Skip to content

Commit d1b58b3

Browse files
committed
Optimize module namespace object property accesses.
1 parent 3f80fc6 commit d1b58b3

File tree

6 files changed

+81
-52
lines changed

6 files changed

+81
-52
lines changed

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/access/HasPropertyCacheNode.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
import com.oracle.truffle.js.runtime.JSRuntime;
5454
import com.oracle.truffle.js.runtime.Strings;
5555
import com.oracle.truffle.js.runtime.builtins.JSAdapter;
56-
import com.oracle.truffle.js.runtime.builtins.JSModuleNamespace;
5756
import com.oracle.truffle.js.runtime.builtins.JSProxy;
5857
import com.oracle.truffle.js.runtime.java.JavaImporter;
5958
import com.oracle.truffle.js.runtime.java.JavaPackage;
@@ -329,8 +328,6 @@ protected HasCacheNode createUndefinedPropertyNode(Object thisObj, Object store,
329328
return new JSAdapterHasPropertyCacheNode(key, createJSClassCheck(thisObj, depth));
330329
} else if (JSProxy.isJSProxy(store)) {
331330
return new JSProxyDispatcherPropertyHasNode(context, key, createJSClassCheck(thisObj, depth), isOwnProperty());
332-
} else if (JSModuleNamespace.isJSModuleNamespace(store)) {
333-
return new UnspecializedHasPropertyCacheNode(createJSClassCheck(thisObj, depth));
334331
} else {
335332
return new AbsentHasPropertyCacheNode(createShapeCheckNode(cacheShape, thisJSObj, depth, false, false));
336333
}

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/access/PropertyGetNode.java

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
import com.oracle.truffle.js.nodes.function.JSFunctionCallNode;
8181
import com.oracle.truffle.js.nodes.interop.ForeignObjectPrototypeNode;
8282
import com.oracle.truffle.js.nodes.interop.ImportValueNode;
83+
import com.oracle.truffle.js.nodes.module.ReadImportBindingNode;
8384
import com.oracle.truffle.js.runtime.Errors;
8485
import com.oracle.truffle.js.runtime.JSArguments;
8586
import com.oracle.truffle.js.runtime.JSConfig;
@@ -98,7 +99,7 @@
9899
import com.oracle.truffle.js.runtime.builtins.JSFunction;
99100
import com.oracle.truffle.js.runtime.builtins.JSFunctionData;
100101
import com.oracle.truffle.js.runtime.builtins.JSFunctionObject;
101-
import com.oracle.truffle.js.runtime.builtins.JSModuleNamespace;
102+
import com.oracle.truffle.js.runtime.builtins.JSModuleNamespaceObject;
102103
import com.oracle.truffle.js.runtime.builtins.JSOrdinary;
103104
import com.oracle.truffle.js.runtime.builtins.JSProxy;
104105
import com.oracle.truffle.js.runtime.builtins.JSRegExp;
@@ -108,6 +109,7 @@
108109
import com.oracle.truffle.js.runtime.java.JavaImporter;
109110
import com.oracle.truffle.js.runtime.java.JavaPackage;
110111
import com.oracle.truffle.js.runtime.objects.Accessor;
112+
import com.oracle.truffle.js.runtime.objects.ExportResolution;
111113
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
112114
import com.oracle.truffle.js.runtime.objects.JSObject;
113115
import com.oracle.truffle.js.runtime.objects.JSObjectUtil;
@@ -1179,6 +1181,26 @@ protected Object getValue(Object thisObj, Object receiver, Object defaultValue,
11791181
}
11801182
}
11811183

1184+
public static final class ModuleNamespacePropertyGetNode extends LinkedPropertyGetNode {
1185+
1186+
private final Location location;
1187+
@Child ReadImportBindingNode readBindingNode;
1188+
1189+
public ModuleNamespacePropertyGetNode(Property property, ReceiverCheckNode receiverCheck) {
1190+
super(receiverCheck);
1191+
assert JSProperty.isModuleNamespaceExport(property);
1192+
this.location = property.getLocation();
1193+
this.readBindingNode = ReadImportBindingNode.create();
1194+
}
1195+
1196+
@Override
1197+
protected Object getValue(Object thisObj, Object receiver, Object defaultValue, PropertyGetNode root, boolean guard) {
1198+
JSModuleNamespaceObject store = (JSModuleNamespaceObject) receiverCheck.getStore(thisObj);
1199+
ExportResolution.Resolved exportResolution = (ExportResolution.Resolved) location.get(store, guard);
1200+
return readBindingNode.execute(exportResolution);
1201+
}
1202+
}
1203+
11821204
public static final class UnspecializedPropertyGetNode extends LinkedPropertyGetNode {
11831205
public UnspecializedPropertyGetNode(ReceiverCheckNode receiverCheck) {
11841206
super(receiverCheck);
@@ -1916,37 +1938,37 @@ private GetCacheNode createCachedPropertyNodeNotJSObject(Property property, Obje
19161938
}
19171939

19181940
private static GetCacheNode createSpecializationFromDataProperty(Property property, ReceiverCheckNode receiverCheck, JSContext context) {
1919-
Property dataProperty = property;
1920-
19211941
if (property.getLocation() instanceof com.oracle.truffle.api.object.IntLocation) {
1922-
return new IntPropertyGetNode(dataProperty, receiverCheck);
1942+
return new IntPropertyGetNode(property, receiverCheck);
19231943
} else if (property.getLocation() instanceof com.oracle.truffle.api.object.DoubleLocation) {
1924-
return new DoublePropertyGetNode(dataProperty, receiverCheck);
1944+
return new DoublePropertyGetNode(property, receiverCheck);
19251945
} else if (property.getLocation() instanceof com.oracle.truffle.api.object.BooleanLocation) {
1926-
return new BooleanPropertyGetNode(dataProperty, receiverCheck);
1946+
return new BooleanPropertyGetNode(property, receiverCheck);
19271947
} else if (property.getLocation() instanceof com.oracle.truffle.api.object.LongLocation) {
1928-
return new LongPropertyGetNode(dataProperty, receiverCheck);
1948+
return new LongPropertyGetNode(property, receiverCheck);
1949+
} else if (JSProperty.isModuleNamespaceExport(property)) {
1950+
return new ModuleNamespacePropertyGetNode(property, receiverCheck);
19291951
} else if (JSProperty.isProxy(property)) {
19301952
if (isArrayLengthProperty(property)) {
1931-
return new ArrayLengthPropertyGetNode(dataProperty, receiverCheck);
1953+
return new ArrayLengthPropertyGetNode(property, receiverCheck);
19321954
} else if (isFunctionLengthProperty(property)) {
1933-
return new FunctionLengthPropertyGetNode(dataProperty, receiverCheck);
1955+
return new FunctionLengthPropertyGetNode(property, receiverCheck);
19341956
} else if (isFunctionNameProperty(property)) {
1935-
return new FunctionNamePropertyGetNode(dataProperty, receiverCheck);
1957+
return new FunctionNamePropertyGetNode(property, receiverCheck);
19361958
} else if (isClassPrototypeProperty(property)) {
1937-
return new ClassPrototypePropertyGetNode(dataProperty, receiverCheck, context);
1959+
return new ClassPrototypePropertyGetNode(property, receiverCheck, context);
19381960
} else if (isStringLengthProperty(property)) {
1939-
return new StringObjectLengthPropertyGetNode(dataProperty, receiverCheck);
1961+
return new StringObjectLengthPropertyGetNode(property, receiverCheck);
19401962
} else if (isLazyRegexResultIndexProperty(property)) {
1941-
return new LazyRegexResultIndexPropertyGetNode(dataProperty, receiverCheck);
1963+
return new LazyRegexResultIndexPropertyGetNode(property, receiverCheck);
19421964
} else if (isLazyNamedCaptureGroupProperty(property)) {
19431965
int groupIndex = ((JSRegExp.LazyNamedCaptureGroupProperty) JSProperty.getConstantProxy(property)).getGroupIndex();
1944-
return new LazyNamedCaptureGroupPropertyGetNode(dataProperty, receiverCheck, groupIndex, context);
1966+
return new LazyNamedCaptureGroupPropertyGetNode(property, receiverCheck, groupIndex, context);
19451967
} else {
1946-
return new ProxyPropertyGetNode(dataProperty, receiverCheck);
1968+
return new ProxyPropertyGetNode(property, receiverCheck);
19471969
}
19481970
} else {
1949-
return new ObjectPropertyGetNode(dataProperty, receiverCheck);
1971+
return new ObjectPropertyGetNode(property, receiverCheck);
19501972
}
19511973
}
19521974

@@ -2018,8 +2040,6 @@ protected GetCacheNode createUndefinedPropertyNode(Object thisObj, Object store,
20182040
return new JSAdapterPropertyGetNode(createJSClassCheck(thisObj, depth));
20192041
} else if (JSProxy.isJSProxy(store) && JSRuntime.isPropertyKey(key)) {
20202042
return createJSProxyCache(createJSClassCheck(thisObj, depth));
2021-
} else if (JSModuleNamespace.isJSModuleNamespace(store)) {
2022-
return new UnspecializedPropertyGetNode(createJSClassCheck(thisObj, depth));
20232043
} else {
20242044
return createUndefinedJSObjectPropertyNode(jsobject, depth);
20252045
}

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/access/PropertySetNode.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ private SetCacheNode createCachedPropertyNodeJSObject(Property property, JSDynam
10421042

10431043
private SetCacheNode createCachedDataPropertyNodeJSObject(JSDynamicObject thisObj, int depth, Object value, AbstractShapeCheckNode shapeCheck, Property property) {
10441044
assert !JSProperty.isConst(property) || (depth == 0 && isGlobal() && property.getLocation().isConstant() && property.getLocation().getConstantValue() == Dead.instance()) : "const assignment";
1045-
if (!JSProperty.isWritable(property)) {
1045+
if (!JSProperty.isWritable(property) || JSProperty.isModuleNamespaceExport(property)) {
10461046
return new ReadOnlyPropertySetNode(shapeCheck, isStrict());
10471047
} else if (superProperty) {
10481048
// define the property on the receiver; currently not handled, rewrite to generic
@@ -1058,7 +1058,7 @@ private SetCacheNode createCachedDataPropertyNodeJSObject(JSDynamicObject thisOb
10581058
}
10591059
return new PropertyProxySetNode(property, shapeCheck, isStrict());
10601060
} else {
1061-
assert JSProperty.isWritable(property) && depth == 0 && !JSProperty.isProxy(property);
1061+
assert JSProperty.isWritable(property) && !JSProperty.isModuleNamespaceExport(property) && depth == 0 && !JSProperty.isProxy(property);
10621062
if (property.getLocation().isConstant() || !property.getLocation().canStore(value)) {
10631063
return createRedefinePropertyNode(key, shapeCheck, shapeCheck.getShape(), property);
10641064
}

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/module/ReadImportBindingNode.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
import java.util.Set;
4444

45+
import com.oracle.truffle.api.CompilerDirectives;
4546
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4647
import com.oracle.truffle.api.dsl.Cached;
4748
import com.oracle.truffle.api.dsl.Executed;
@@ -52,6 +53,7 @@
5253
import com.oracle.truffle.api.frame.FrameSlotKind;
5354
import com.oracle.truffle.api.frame.MaterializedFrame;
5455
import com.oracle.truffle.api.instrumentation.Tag;
56+
import com.oracle.truffle.api.profiles.BranchProfile;
5557
import com.oracle.truffle.api.strings.TruffleString;
5658
import com.oracle.truffle.js.nodes.JavaScriptNode;
5759
import com.oracle.truffle.js.nodes.access.JSReadFrameSlotNode;
@@ -80,7 +82,15 @@ public static JavaScriptNode create(JavaScriptNode resolutionNode) {
8082
return ReadImportBindingNodeGen.create(resolutionNode);
8183
}
8284

83-
@Specialization(guards = {"frameDescriptor == resolution.getModule().getFrameDescriptor()", "equals(equalNode, bindingName, resolution.getBindingName())"}, limit = "1")
85+
public static ReadImportBindingNode create() {
86+
return ReadImportBindingNodeGen.create(null);
87+
}
88+
89+
public abstract Object execute(ExportResolution resolution);
90+
91+
@Specialization(guards = {"!resolution.isNamespace()",
92+
"frameDescriptor == resolution.getModule().getFrameDescriptor()",
93+
"equals(equalNode, bindingName, resolution.getBindingName())"}, limit = "1")
8494
static Object doCached(ExportResolution.Resolved resolution,
8595
@Cached("resolution.getModule().getFrameDescriptor()") @SuppressWarnings("unused") FrameDescriptor frameDescriptor,
8696
@Cached("resolution.getBindingName()") @SuppressWarnings("unused") TruffleString bindingName,
@@ -95,7 +105,7 @@ static Object doCached(ExportResolution.Resolved resolution,
95105
}
96106

97107
@TruffleBoundary
98-
@Specialization(replaces = {"doCached"})
108+
@Specialization(guards = {"!resolution.isNamespace()"}, replaces = {"doCached"})
99109
final Object doUncached(ExportResolution.Resolved resolution) {
100110
JSModuleRecord module = resolution.getModule();
101111
assert module.getStatus().compareTo(Status.Linked) >= 0 : module.getStatus();
@@ -117,6 +127,19 @@ static int findImportedSlotIndex(TruffleString bindingName, JSModuleRecord modul
117127
return JSFrameUtil.findRequiredFrameSlotIndex(module.getFrameDescriptor(), bindingName);
118128
}
119129

130+
@Specialization(guards = {"resolution.isNamespace()"})
131+
final Object doGetNamespace(ExportResolution.Resolved resolution,
132+
@Cached BranchProfile slowPath) {
133+
JSModuleRecord module = resolution.getModule();
134+
assert module.getStatus().compareTo(Status.Linked) >= 0 : module.getStatus();
135+
if (CompilerDirectives.injectBranchProbability(CompilerDirectives.FASTPATH_PROBABILITY, module.getNamespace() != null)) {
136+
return module.getNamespace();
137+
} else {
138+
slowPath.enter();
139+
return getLanguage().getJSContext().getEvaluator().getModuleNamespace(module);
140+
}
141+
}
142+
120143
@Specialization
121144
static Object doNamespace(JSModuleNamespaceObject namespace) {
122145
return namespace;

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSModuleNamespace.java

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
*/
4141
package com.oracle.truffle.js.runtime.builtins;
4242

43-
import java.util.ArrayList;
44-
import java.util.Collections;
4543
import java.util.List;
4644
import java.util.Map;
4745

@@ -61,6 +59,7 @@
6159
import com.oracle.truffle.js.runtime.JSFrameUtil;
6260
import com.oracle.truffle.js.runtime.JSRealm;
6361
import com.oracle.truffle.js.runtime.JSRuntime;
62+
import com.oracle.truffle.js.runtime.Properties;
6463
import com.oracle.truffle.js.runtime.Strings;
6564
import com.oracle.truffle.js.runtime.Symbol;
6665
import com.oracle.truffle.js.runtime.ToDisplayStringFormat;
@@ -69,6 +68,7 @@
6968
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
7069
import com.oracle.truffle.js.runtime.objects.JSModuleRecord;
7170
import com.oracle.truffle.js.runtime.objects.JSObject;
71+
import com.oracle.truffle.js.runtime.objects.JSProperty;
7272
import com.oracle.truffle.js.runtime.objects.JSShape;
7373
import com.oracle.truffle.js.runtime.objects.Null;
7474
import com.oracle.truffle.js.runtime.objects.PropertyDescriptor;
@@ -111,11 +111,12 @@ public static UnmodifiableEconomicMap<TruffleString, ExportResolution> getExport
111111
public static JSModuleNamespaceObject create(JSContext context, JSRealm realm, JSModuleRecord module, List<Map.Entry<TruffleString, ExportResolution>> sortedExports) {
112112
CompilerAsserts.neverPartOfCompilation();
113113
EconomicMap<TruffleString, ExportResolution> exportResolutionMap = EconomicMap.create(sortedExports.size());
114+
JSObjectFactory factory = context.getModuleNamespaceFactory();
115+
JSModuleNamespaceObject obj = JSModuleNamespaceObject.create(realm, factory, module, exportResolutionMap);
114116
for (Map.Entry<TruffleString, ExportResolution> entry : sortedExports) {
117+
Properties.putWithFlagsUncached(obj, entry.getKey(), entry.getValue(), JSProperty.MODULE_NAMESPACE_EXPORT | JSAttributes.notConfigurableEnumerableWritable());
115118
exportResolutionMap.put(entry.getKey(), entry.getValue());
116119
}
117-
JSObjectFactory factory = context.getModuleNamespaceFactory();
118-
JSModuleNamespaceObject obj = JSModuleNamespaceObject.create(realm, factory, module, exportResolutionMap);
119120
assert !JSObject.isExtensible(obj);
120121
return context.trackAllocation(obj);
121122
}
@@ -267,28 +268,6 @@ public static boolean isJSModuleNamespace(Object obj) {
267268
return obj instanceof JSModuleNamespaceObject;
268269
}
269270

270-
@TruffleBoundary
271-
@Override
272-
public List<Object> getOwnPropertyKeys(JSDynamicObject thisObj, boolean strings, boolean symbols) {
273-
List<Object> symbolKeys = symbols ? symbolKeys(thisObj) : Collections.emptyList();
274-
if (!strings) {
275-
return symbolKeys;
276-
}
277-
UnmodifiableEconomicMap<TruffleString, ExportResolution> exports = getExports(thisObj);
278-
List<Object> keys = new ArrayList<>(exports.size() + symbolKeys.size());
279-
// TODO: convert these keys earlier
280-
for (TruffleString k : exports.getKeys()) {
281-
keys.add(k);
282-
}
283-
keys.addAll(symbolKeys);
284-
return keys;
285-
}
286-
287-
private static List<Object> symbolKeys(JSDynamicObject thisObj) {
288-
// Module Namespace objects only have symbol keys in their shapes.
289-
return thisObj.getShape().getKeyList();
290-
}
291-
292271
@Override
293272
@TruffleBoundary
294273
public boolean setIntegrityLevel(JSDynamicObject obj, boolean freeze, boolean doThrow) {

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/objects/JSProperty.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ public class JSProperty {
6767

6868
public static final int CONST = 1 << 5;
6969

70+
public static final int MODULE_NAMESPACE_EXPORT = 1 << 6 | PROXY;
71+
7072
@TruffleBoundary
7173
public String toString(Property property) {
7274
return "\"" + property.getKey() + "\"" + getAttributeString(property) + ":" + property.getLocation();
@@ -189,6 +191,10 @@ public static boolean isConst(Property property) {
189191
return (property.getFlags() & CONST) != 0;
190192
}
191193

194+
public static boolean isModuleNamespaceExport(Property property) {
195+
return isModuleNamespaceExport(property.getFlags());
196+
}
197+
192198
public static boolean isConfigurable(int flags) {
193199
return (flags & NOT_CONFIGURABLE) == 0;
194200
}
@@ -214,7 +220,11 @@ public static boolean isData(int flags) {
214220
}
215221

216222
public static boolean isConst(int flags) {
217-
return (flags & CONST) == 0;
223+
return (flags & CONST) != 0;
224+
}
225+
226+
public static boolean isModuleNamespaceExport(int flags) {
227+
return (flags & MODULE_NAMESPACE_EXPORT) == MODULE_NAMESPACE_EXPORT;
218228
}
219229

220230
public static PropertyProxy getConstantProxy(Property proxyProperty) {

0 commit comments

Comments
 (0)