Skip to content

Commit 3f80fc6

Browse files
committed
Use EconomicMap for module namespace exports.
1 parent bad5bc3 commit 3f80fc6

File tree

3 files changed

+51
-39
lines changed

3 files changed

+51
-39
lines changed

graal-js/src/com.oracle.truffle.js.parser/src/com/oracle/truffle/js/parser/GraalJSEvaluator.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import java.util.Deque;
5353
import java.util.HashMap;
5454
import java.util.HashSet;
55-
import java.util.LinkedHashMap;
5655
import java.util.List;
5756
import java.util.Map;
5857
import java.util.Set;
@@ -584,18 +583,17 @@ public JSDynamicObject getModuleNamespace(JSModuleRecord moduleRecord) {
584583

585584
assert moduleRecord.getStatus() != Status.Unlinked;
586585
Collection<TruffleString> exportedNames = getExportedNames(moduleRecord);
587-
List<Pair<TruffleString, ExportResolution>> unambiguousNames = new ArrayList<>();
586+
List<Map.Entry<TruffleString, ExportResolution>> unambiguousNames = new ArrayList<>();
588587
for (TruffleString exportedName : exportedNames) {
589588
ExportResolution resolution = resolveExport(moduleRecord, exportedName);
590589
if (resolution.isNull()) {
591590
throw Errors.createSyntaxError("Could not resolve export");
592591
} else if (!resolution.isAmbiguous()) {
593-
unambiguousNames.add(new Pair<>(exportedName, resolution));
592+
unambiguousNames.add(Map.entry(exportedName, resolution));
594593
}
595594
}
596-
Map<TruffleString, ExportResolution> sortedNames = new LinkedHashMap<>();
597-
unambiguousNames.stream().sorted((a, b) -> a.getFirst().compareCharsUTF16Uncached(b.getFirst())).forEachOrdered(p -> sortedNames.put(p.getFirst(), p.getSecond()));
598-
JSModuleNamespaceObject namespace = JSModuleNamespace.create(moduleRecord.getContext(), JSRealm.get(null), moduleRecord, sortedNames);
595+
unambiguousNames.sort((a, b) -> a.getKey().compareCharsUTF16Uncached(b.getKey()));
596+
JSModuleNamespaceObject namespace = JSModuleNamespace.create(moduleRecord.getContext(), JSRealm.get(null), moduleRecord, unambiguousNames);
599597
moduleRecord.setNamespace(namespace);
600598
return namespace;
601599
}

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

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,17 @@
4545
import java.util.List;
4646
import java.util.Map;
4747

48+
import org.graalvm.collections.EconomicMap;
49+
import org.graalvm.collections.UnmodifiableEconomicMap;
50+
51+
import com.oracle.truffle.api.CompilerAsserts;
4852
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
4953
import com.oracle.truffle.api.frame.FrameDescriptor;
5054
import com.oracle.truffle.api.frame.FrameSlotKind;
5155
import com.oracle.truffle.api.frame.MaterializedFrame;
5256
import com.oracle.truffle.api.nodes.Node;
5357
import com.oracle.truffle.api.object.Shape;
5458
import com.oracle.truffle.api.strings.TruffleString;
55-
import com.oracle.truffle.js.runtime.Boundaries;
5659
import com.oracle.truffle.js.runtime.Errors;
5760
import com.oracle.truffle.js.runtime.JSContext;
5861
import com.oracle.truffle.js.runtime.JSFrameUtil;
@@ -100,14 +103,19 @@ public static JSModuleRecord getModule(JSDynamicObject obj) {
100103
* object. The list is ordered as if an Array of those String values had been sorted using
101104
* Array.prototype.sort using SortCompare as comparefn.
102105
*/
103-
public static Map<TruffleString, ExportResolution> getExports(JSDynamicObject obj) {
106+
public static UnmodifiableEconomicMap<TruffleString, ExportResolution> getExports(JSDynamicObject obj) {
104107
assert isJSModuleNamespace(obj);
105108
return ((JSModuleNamespaceObject) obj).getExports();
106109
}
107110

108-
public static JSModuleNamespaceObject create(JSContext context, JSRealm realm, JSModuleRecord module, Map<TruffleString, ExportResolution> exports) {
111+
public static JSModuleNamespaceObject create(JSContext context, JSRealm realm, JSModuleRecord module, List<Map.Entry<TruffleString, ExportResolution>> sortedExports) {
112+
CompilerAsserts.neverPartOfCompilation();
113+
EconomicMap<TruffleString, ExportResolution> exportResolutionMap = EconomicMap.create(sortedExports.size());
114+
for (Map.Entry<TruffleString, ExportResolution> entry : sortedExports) {
115+
exportResolutionMap.put(entry.getKey(), entry.getValue());
116+
}
109117
JSObjectFactory factory = context.getModuleNamespaceFactory();
110-
JSModuleNamespaceObject obj = JSModuleNamespaceObject.create(realm, factory, module, exports);
118+
JSModuleNamespaceObject obj = JSModuleNamespaceObject.create(realm, factory, module, exportResolutionMap);
111119
assert !JSObject.isExtensible(obj);
112120
return context.trackAllocation(obj);
113121
}
@@ -145,8 +153,7 @@ public Object getOwnHelper(JSDynamicObject store, Object thisObj, Object key, No
145153
if (!Strings.isTString(key)) {
146154
return super.getOwnHelper(store, thisObj, key, encapsulatingNode);
147155
}
148-
Map<TruffleString, ExportResolution> exports = getExports(store);
149-
ExportResolution binding = exports.get(key);
156+
ExportResolution binding = getExports(store).get((TruffleString) key);
150157
if (binding != null) {
151158
return getBindingValue(binding);
152159
} else {
@@ -155,6 +162,7 @@ public Object getOwnHelper(JSDynamicObject store, Object thisObj, Object key, No
155162
}
156163

157164
static Object getBindingValue(ExportResolution binding) {
165+
CompilerAsserts.neverPartOfCompilation();
158166
TruffleString bindingName = binding.getBindingName();
159167
JSModuleRecord targetModule = binding.getModule();
160168
MaterializedFrame targetEnv = targetModule.getEnvironment();
@@ -174,13 +182,13 @@ static Object getBindingValue(ExportResolution binding) {
174182
return targetEnv.getValue(slot);
175183
}
176184

185+
@TruffleBoundary
177186
@Override
178187
public boolean hasProperty(JSDynamicObject thisObj, Object key) {
179188
if (!Strings.isTString(key)) {
180189
return super.hasProperty(thisObj, key);
181190
}
182-
Map<TruffleString, ExportResolution> exports = getExports(thisObj);
183-
return Boundaries.mapContainsKey(exports, (TruffleString) key);
191+
return getExports(thisObj).containsKey((TruffleString) key);
184192
}
185193

186194
@Override
@@ -189,8 +197,7 @@ public boolean hasOwnProperty(JSDynamicObject thisObj, Object key) {
189197
if (!Strings.isTString(key)) {
190198
return super.hasOwnProperty(thisObj, key);
191199
}
192-
Map<TruffleString, ExportResolution> exports = getExports(thisObj);
193-
ExportResolution binding = exports.get(key);
200+
ExportResolution binding = getExports(thisObj).get((TruffleString) key);
194201
if (binding != null) {
195202
// checks for uninitialized bindings
196203
getBindingValue(binding);
@@ -205,12 +212,13 @@ public boolean delete(JSDynamicObject thisObj, long index, boolean isStrict) {
205212
return true;
206213
}
207214

215+
@TruffleBoundary
208216
@Override
209217
public boolean delete(JSDynamicObject thisObj, Object key, boolean isStrict) {
210218
if (!Strings.isTString(key)) {
211219
return super.delete(thisObj, key, isStrict);
212220
}
213-
if (Boundaries.mapContainsKey(getExports(thisObj), (TruffleString) key)) {
221+
if (getExports(thisObj).containsKey((TruffleString) key)) {
214222
if (isStrict) {
215223
throw Errors.createTypeErrorNotConfigurableProperty(key);
216224
} else {
@@ -226,6 +234,7 @@ public boolean setPrototypeOf(JSDynamicObject thisObj, JSDynamicObject newProtot
226234
return newPrototype == Null.instance;
227235
}
228236

237+
@TruffleBoundary
229238
@Override
230239
public boolean defineOwnProperty(JSDynamicObject thisObj, Object key, PropertyDescriptor desc, boolean doThrow) {
231240
if (!Strings.isTString(key)) {
@@ -245,8 +254,7 @@ public PropertyDescriptor getOwnProperty(JSDynamicObject thisObj, Object key) {
245254
if (!Strings.isTString(key)) {
246255
return super.getOwnProperty(thisObj, key);
247256
}
248-
Map<TruffleString, ExportResolution> exports = getExports(thisObj);
249-
ExportResolution binding = exports.get(key);
257+
ExportResolution binding = getExports(thisObj).get((TruffleString) key);
250258
if (binding != null) {
251259
Object value = getBindingValue(binding);
252260
return PropertyDescriptor.createData(value, true, true, false);
@@ -266,10 +274,12 @@ public List<Object> getOwnPropertyKeys(JSDynamicObject thisObj, boolean strings,
266274
if (!strings) {
267275
return symbolKeys;
268276
}
269-
Map<TruffleString, ExportResolution> exports = getExports(thisObj);
277+
UnmodifiableEconomicMap<TruffleString, ExportResolution> exports = getExports(thisObj);
270278
List<Object> keys = new ArrayList<>(exports.size() + symbolKeys.size());
271279
// TODO: convert these keys earlier
272-
keys.addAll(exports.keySet());
280+
for (TruffleString k : exports.getKeys()) {
281+
keys.add(k);
282+
}
273283
keys.addAll(symbolKeys);
274284
return keys;
275285
}
@@ -282,21 +292,25 @@ private static List<Object> symbolKeys(JSDynamicObject thisObj) {
282292
@Override
283293
@TruffleBoundary
284294
public boolean setIntegrityLevel(JSDynamicObject obj, boolean freeze, boolean doThrow) {
285-
if (freeze) {
286-
Map<TruffleString, ExportResolution> exports = getExports(obj);
287-
if (!exports.isEmpty()) {
288-
ExportResolution firstBinding = exports.values().iterator().next();
289-
// Throw ReferenceError if the first binding is uninitialized,
290-
// throw TypeError otherwise
291-
// checks for an uninitialized binding
292-
getBindingValue(firstBinding);
295+
for (ExportResolution binding : getExports(obj).getValues()) {
296+
// Check for uninitialized binding (throws ReferenceError)
297+
getBindingValue(binding);
298+
if (freeze) {
299+
// ReferenceError if the first binding is uninitialized, TypeError otherwise
293300
throw Errors.createTypeError("not allowed to freeze a namespace object");
294301
}
295-
} else {
296-
// Check for uninitialized bindings
297-
for (ExportResolution binding : getExports(obj).values()) {
298-
// can throw ReferenceError
299-
getBindingValue(binding);
302+
}
303+
return true;
304+
}
305+
306+
@TruffleBoundary
307+
@Override
308+
public boolean testIntegrityLevel(JSDynamicObject obj, boolean frozen) {
309+
for (ExportResolution binding : getExports(obj).getValues()) {
310+
// Check for uninitialized binding (throws ReferenceError)
311+
getBindingValue(binding);
312+
if (frozen) {
313+
return false;
300314
}
301315
}
302316
return true;

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

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

43-
import java.util.Map;
43+
import org.graalvm.collections.UnmodifiableEconomicMap;
4444

4545
import com.oracle.truffle.api.object.Shape;
4646
import com.oracle.truffle.api.strings.TruffleString;
@@ -66,9 +66,9 @@ public final class JSModuleNamespaceObject extends JSNonProxyObject {
6666
* object. The list is ordered as if an Array of those String values had been sorted using
6767
* Array.prototype.sort using SortCompare as comparefn.
6868
*/
69-
private final Map<TruffleString, ExportResolution> exports;
69+
private final UnmodifiableEconomicMap<TruffleString, ExportResolution> exports;
7070

71-
protected JSModuleNamespaceObject(Shape shape, JSModuleRecord module, Map<TruffleString, ExportResolution> exports) {
71+
protected JSModuleNamespaceObject(Shape shape, JSModuleRecord module, UnmodifiableEconomicMap<TruffleString, ExportResolution> exports) {
7272
super(shape);
7373
this.module = module;
7474
this.exports = exports;
@@ -78,11 +78,11 @@ public JSModuleRecord getModule() {
7878
return module;
7979
}
8080

81-
public Map<TruffleString, ExportResolution> getExports() {
81+
public UnmodifiableEconomicMap<TruffleString, ExportResolution> getExports() {
8282
return exports;
8383
}
8484

85-
public static JSModuleNamespaceObject create(JSRealm realm, JSObjectFactory factory, JSModuleRecord module, Map<TruffleString, ExportResolution> exports) {
85+
public static JSModuleNamespaceObject create(JSRealm realm, JSObjectFactory factory, JSModuleRecord module, UnmodifiableEconomicMap<TruffleString, ExportResolution> exports) {
8686
return factory.initProto(new JSModuleNamespaceObject(factory.getShape(realm), module, exports), realm);
8787
}
8888

0 commit comments

Comments
 (0)