Skip to content

[js_runtime] Use ES6 Map and Set for Dart LinkedHashMap and LinkedHashSet #53162

Open
@rakudrama

Description

@rakudrama

ES6 Maps and Sets can't be used directly for Dart LinkedHashMap and LinkedHashSet but they could be used in a way that is more efficient that the current implementation that uses Object.create(null) dictionaries.

The current implementation uses three object dictionaries - one for Strings, one for small-ish non-negative integers and a final one for hash-buckets. The object dictionaries cannot be relied on to maintain insertion order, and even if they could, elements are spread between the String and small-integer dictionaries and the hash buckets, so the elements are maintained in a double-linked list.

An implementation based on ES6 Maps could use one or two maps. The first Map could be used for primitive objects (strings, numbers), and keys that don't override hashCode and ==, which includes a lot of useful types like enums. The second map would be used to map hashCode values to buckets.

The reliable ES6 Map insertion order could be exploited by having two modes - a direct mode where only the first Map is active, and the map stores the values directly associated with the keys, and a linked mode more like the current implementation where the key-value pairs are in a double-linked list to maintain the insertion order between the first Map and the hash buckets. The implementation would transition from direct mode to linked mode only when an insertion key is presented that does not meet the criteria for using the first set.

In direct mode an Iterator like .keys.iterator would use the JavaScript iterator. In linked mode the iterator would walk the double-linked list. it might be worthwhile to transition to linked mode for certain operations, for example, .keys.last can't be done on a direct ES6 Map without iterating all the keys.

Detecting whether an object overrides hashCode can probably be done with some special compiler support to compare the get$hashCode property with that on Object. If this turns out to be infeasible, direct mode could still be used for primitive values. This should still be substantially better when the keys are numbers.

ES6 Maps treat null and undefined as different keys so this would have to be handled by the implementation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-web-jsIssues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop.dart2js-runtime-libraryIssues related to runtime library for dart2js (sdk/lib/_internal/js_runtime)web-dart2js

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions