Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Unified Diff: src/collection.js

Issue 947683002: Reimplement Maps and Sets in JS (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Disable one more test Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/hydrogen.h » ('j') | src/hydrogen.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/collection.js
diff --git a/src/collection.js b/src/collection.js
index 9b5716687bcc14ed06e628afd15de795b07c1a14..3033907afd8548c3bbc53550922e7166da4703e0 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -2,303 +2,456 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-"use strict";
-
// This file relies on the fact that the following declaration has been made
// in runtime.js:
+// var $Object = global.Object;
// var $Array = global.Array;
var $Set = global.Set;
var $Map = global.Map;
-// -------------------------------------------------------------------
-// Harmony Set
+(function() {
+ "use strict";
+
-function SetConstructor(iterable) {
- if (!%_IsConstructCall()) {
- throw MakeTypeError('constructor_not_function', ['Set']);
+ function HashToBucket(hash, numBuckets) {
+ return hash & (numBuckets - 1);
}
+ %SetInlineBuiltinFlag(HashToBucket);
- var iter, adder;
- if (!IS_NULL_OR_UNDEFINED(iterable)) {
- iter = GetIterator(iterable);
- adder = this.add;
- if (!IS_SPEC_FUNCTION(adder)) {
- throw MakeTypeError('property_not_function', ['add', this]);
+ function HashToEntry(table, hash, numBuckets) {
+ var bucket = HashToBucket(hash, numBuckets);
+ return %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket);
+ }
+ %SetInlineBuiltinFlag(HashToEntry);
+
+
+ function SetFindEntry(table, numBuckets, key, hash) {
+ var keyIsNaN = IS_NUMBER(key) && NUMBER_IS_NAN(key);
+ for (var entry = HashToEntry(table, hash, numBuckets);
+ entry !== NOT_FOUND;
+ entry = SET_CHAIN_AT(table, entry, numBuckets)) {
+ var candidate = SET_KEY_AT(table, entry, numBuckets);
+ if (key === candidate) {
+ return entry;
+ }
+ if (keyIsNaN && IS_NUMBER(candidate) && NUMBER_IS_NAN(candidate)) {
arv (Not doing code reviews) 2015/02/21 16:20:16 Nice optimization to get around the NaN SameValueZ
arv (Not doing code reviews) 2015/02/21 16:20:16 Nice optimization to get around the NaN SameValueZ
+ return entry;
+ }
}
+ return NOT_FOUND;
+ }
+ %SetInlineBuiltinFlag(SetFindEntry);
+
+
+ function MapFindEntry(table, numBuckets, key, hash) {
+ var keyIsNaN = IS_NUMBER(key) && NUMBER_IS_NAN(key);
+ for (var entry = HashToEntry(table, hash, numBuckets);
+ entry !== NOT_FOUND;
+ entry = MAP_CHAIN_AT(table, entry, numBuckets)) {
+ var candidate = MAP_KEY_AT(table, entry, numBuckets);
+ if (key === candidate) {
+ return entry;
+ }
+ if (keyIsNaN && IS_NUMBER(candidate) && NUMBER_IS_NAN(candidate)) {
+ return entry;
+ }
+ }
+ return NOT_FOUND;
+ }
+ %SetInlineBuiltinFlag(MapFindEntry);
+
+
+ function GetHash(key) {
+ if (%_IsSmi(key)) return %_SmiHash(key);
+ if (IS_STRING(key)) return %_StringHash(key);
+ return %GenericHash(key);
}
+ %SetInlineBuiltinFlag(GetHash);
- %_SetInitialize(this);
- if (IS_UNDEFINED(iter)) return;
+ // -------------------------------------------------------------------
+ // Harmony Set
- var next, done;
- while (!(next = iter.next()).done) {
- if (!IS_SPEC_OBJECT(next)) {
- throw MakeTypeError('iterator_result_not_an_object', [next]);
+ function SetConstructor(iterable) {
+ if (!%_IsConstructCall()) {
+ throw MakeTypeError('constructor_not_function', ['Set']);
}
- %_CallFunction(this, next.value, adder);
- }
-}
+ var iter, adder;
-function SetAddJS(key) {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.add', this]);
- }
- // Normalize -0 to +0 as required by the spec.
- // Even though we use SameValueZero as the comparison for the keys we don't
- // want to ever store -0 as the key since the key is directly exposed when
- // doing iteration.
- if (key === 0) {
- key = 0;
- }
- return %_SetAdd(this, key);
-}
+ if (!IS_NULL_OR_UNDEFINED(iterable)) {
+ iter = GetIterator(iterable);
+ adder = this.add;
+ if (!IS_SPEC_FUNCTION(adder)) {
+ throw MakeTypeError('property_not_function', ['add', this]);
+ }
+ }
+
+ %_SetInitialize(this);
+ if (IS_UNDEFINED(iter)) return;
-function SetHasJS(key) {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.has', this]);
+ var next, done;
+ while (!(next = iter.next()).done) {
+ if (!IS_SPEC_OBJECT(next)) {
+ throw MakeTypeError('iterator_result_not_an_object', [next]);
+ }
+ %_CallFunction(this, next.value, adder);
+ }
}
- return %_SetHas(this, key);
-}
-function SetDeleteJS(key) {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.delete', this]);
+ function SetAdd(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.add', this]);
+ }
+ // Normalize -0 to +0 as required by the spec.
+ // Even though we use SameValueZero as the comparison for the keys we don't
+ // want to ever store -0 as the key since the key is directly exposed when
+ // doing iteration.
+ if (IS_NUMBER(key) && key === 0) {
+ key = 0;
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ if (SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND) return this;
+
+ var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX);
+ var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX);
+ var capacity = numBuckets << 1;
+ if ((nof + nod) >= capacity) {
+ // Need to grow, bail out to runtime.
+ %SetGrow(this);
+ // Re-enter...TODO(adamk) Fix this
+ return %_CallFunction(this, key, SetAdd);
+ }
+ var entry = nof + nod;
+ var index = SET_ENTRY_TO_INDEX(entry, numBuckets);
+ var bucket = HashToBucket(hash, numBuckets);
+ var chainEntry = %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket);
+ %_FixedArraySet(table, HASH_TABLE_START_INDEX + bucket, entry);
+ %_FixedArraySet(table, index + SET_CHAIN_OFFSET, chainEntry);
+ %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof + 1);
+ %_FixedArraySet(table, index, key);
+ return this;
}
- return %_SetDelete(this, key);
-}
-function SetGetSizeJS() {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.size', this]);
+ function SetHas(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.has', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ return SetFindEntry(table, numBuckets, key, hash) !== NOT_FOUND;
}
- return %_SetGetSize(this);
-}
-function SetClearJS() {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.clear', this]);
+ function SetDelete(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.delete', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ var entry = SetFindEntry(table, numBuckets, key, hash);
+ if (entry === NOT_FOUND) return false;
+
+ var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX) - 1;
+ var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX) + 1;
+ var index = SET_ENTRY_TO_INDEX(entry, numBuckets);
+ %_FixedArraySetTheHole(table, index);
+ %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof);
+ %_FixedArraySet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX, nod);
+ if (nof < (numBuckets >> 1)) %SetShrink(this);
+ return true;
}
- %_SetClear(this);
-}
-function SetForEach(f, receiver) {
- if (!IS_SET(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Set.prototype.forEach', this]);
+ function SetGetSize() {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.size', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ return %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX);
}
- if (!IS_SPEC_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [f]);
- }
- var needs_wrapper = false;
- if (IS_NULL_OR_UNDEFINED(receiver)) {
- receiver = %GetDefaultReceiver(f) || receiver;
- } else {
- needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
- }
- var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
- var key;
- var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
- var value_array = [UNDEFINED];
- while (%SetIteratorNext(iterator, value_array)) {
- if (stepping) %DebugPrepareStepInIfStepping(f);
- key = value_array[0];
- var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
- %_CallFunction(new_receiver, key, key, this, f);
+ function SetClearJS() {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.clear', this]);
+ }
+ %_SetClear(this);
}
-}
-// -------------------------------------------------------------------
+ function SetForEach(f, receiver) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.forEach', this]);
+ }
-function SetUpSet() {
- %CheckIsBootstrapping();
+ if (!IS_SPEC_FUNCTION(f)) {
+ throw MakeTypeError('called_non_callable', [f]);
+ }
+ var needs_wrapper = false;
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ } else {
+ needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
+ }
- %SetCode($Set, SetConstructor);
- %FunctionSetPrototype($Set, new $Object());
- %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
- %AddNamedProperty(
- $Set.prototype, symbolToStringTag, "Set", DONT_ENUM | READ_ONLY);
+ var iterator = new SetIterator(this, ITERATOR_KIND_VALUES);
+ var key;
+ var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
+ var value_array = [UNDEFINED];
+ while (%SetIteratorNext(iterator, value_array)) {
arv (Not doing code reviews) 2015/02/21 16:20:16 This one can get much faster now that we have acce
adamk 2015/02/23 18:43:34 Yeah, there are definitely opportunities to speed
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ key = value_array[0];
+ var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
+ %_CallFunction(new_receiver, key, key, this, f);
+ }
+ }
- %FunctionSetLength(SetForEach, 1);
- // Set up the non-enumerable functions on the Set prototype object.
- InstallGetter($Set.prototype, "size", SetGetSizeJS);
- InstallFunctions($Set.prototype, DONT_ENUM, $Array(
- "add", SetAddJS,
- "has", SetHasJS,
- "delete", SetDeleteJS,
- "clear", SetClearJS,
- "forEach", SetForEach
- ));
-}
+ // -------------------------------------------------------------------
-SetUpSet();
+ function SetUpSet() {
+ %CheckIsBootstrapping();
+ %SetCode($Set, SetConstructor);
+ %FunctionSetPrototype($Set, new $Object());
+ %AddNamedProperty($Set.prototype, "constructor", $Set, DONT_ENUM);
+ %AddNamedProperty(
+ $Set.prototype, symbolToStringTag, "Set", DONT_ENUM | READ_ONLY);
-// -------------------------------------------------------------------
-// Harmony Map
+ %FunctionSetLength(SetForEach, 1);
-function MapConstructor(iterable) {
- if (!%_IsConstructCall()) {
- throw MakeTypeError('constructor_not_function', ['Map']);
+ // Set up the non-enumerable functions on the Set prototype object.
+ InstallGetter($Set.prototype, "size", SetGetSize);
+ InstallFunctions($Set.prototype, DONT_ENUM, $Array(
+ "add", SetAdd,
+ "has", SetHas,
+ "delete", SetDelete,
+ "clear", SetClearJS,
+ "forEach", SetForEach
+ ));
}
- var iter, adder;
+ SetUpSet();
- if (!IS_NULL_OR_UNDEFINED(iterable)) {
- iter = GetIterator(iterable);
- adder = this.set;
- if (!IS_SPEC_FUNCTION(adder)) {
- throw MakeTypeError('property_not_function', ['set', this]);
- }
- }
- %_MapInitialize(this);
+ // -------------------------------------------------------------------
+ // Harmony Map
+
+ function MapConstructor(iterable) {
+ if (!%_IsConstructCall()) {
+ throw MakeTypeError('constructor_not_function', ['Map']);
+ }
- if (IS_UNDEFINED(iter)) return;
+ var iter, adder;
- var next, done, nextItem;
- while (!(next = iter.next()).done) {
- if (!IS_SPEC_OBJECT(next)) {
- throw MakeTypeError('iterator_result_not_an_object', [next]);
+ if (!IS_NULL_OR_UNDEFINED(iterable)) {
+ iter = GetIterator(iterable);
+ adder = this.set;
+ if (!IS_SPEC_FUNCTION(adder)) {
+ throw MakeTypeError('property_not_function', ['set', this]);
+ }
}
- nextItem = next.value;
- if (!IS_SPEC_OBJECT(nextItem)) {
- throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
+
+ %_MapInitialize(this);
+
+ if (IS_UNDEFINED(iter)) return;
+
+ var next, done, nextItem;
+ while (!(next = iter.next()).done) {
+ if (!IS_SPEC_OBJECT(next)) {
+ throw MakeTypeError('iterator_result_not_an_object', [next]);
+ }
+ nextItem = next.value;
+ if (!IS_SPEC_OBJECT(nextItem)) {
+ throw MakeTypeError('iterator_value_not_an_object', [nextItem]);
+ }
+ %_CallFunction(this, nextItem[0], nextItem[1], adder);
}
- %_CallFunction(this, nextItem[0], nextItem[1], adder);
}
-}
-function MapGetJS(key) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.get', this]);
+ function MapGet(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.get', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ var entry = MapFindEntry(table, numBuckets, key, hash);
+ if (entry === NOT_FOUND) return UNDEFINED;
+ return MAP_VALUE_AT(table, entry, numBuckets);
}
- return %_MapGet(this, key);
-}
-function MapSetJS(key, value) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.set', this]);
- }
- // Normalize -0 to +0 as required by the spec.
- // Even though we use SameValueZero as the comparison for the keys we don't
- // want to ever store -0 as the key since the key is directly exposed when
- // doing iteration.
- if (key === 0) {
- key = 0;
- }
- return %_MapSet(this, key, value);
-}
+ function MapSet(key, value) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.set', this]);
+ }
+ // Normalize -0 to +0 as required by the spec.
+ // Even though we use SameValueZero as the comparison for the keys we don't
+ // want to ever store -0 as the key since the key is directly exposed when
+ // doing iteration.
+ if (IS_NUMBER(key) && key === 0) {
+ key = 0;
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ var entry = MapFindEntry(table, numBuckets, key, hash);
+ if (entry !== NOT_FOUND) {
+ var existingIndex = MAP_ENTRY_TO_INDEX(entry, numBuckets);
+ %_FixedArraySet(table, existingIndex + 1, value);
+ return this;
+ }
-function MapHasJS(key) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.has', this]);
+ var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX);
+ var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX);
+ var capacity = numBuckets << 1;
+ if ((nof + nod) >= capacity) {
+ // Need to grow, bail out to runtime.
+ %MapGrow(this);
+ // Re-enter...TODO(adamk) Fix this
+ return %_CallFunction(this, key, value, MapSet);
+ }
+ entry = nof + nod;
+ var index = MAP_ENTRY_TO_INDEX(entry, numBuckets);
+ var bucket = HashToBucket(hash, numBuckets);
+ var chainEntry = %_FixedArrayGet(table, HASH_TABLE_START_INDEX + bucket);
+ %_FixedArraySet(table, HASH_TABLE_START_INDEX + bucket, entry);
+ %_FixedArraySet(table, index + MAP_CHAIN_OFFSET, chainEntry);
+ %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof + 1);
+ %_FixedArraySet(table, index, key);
+ %_FixedArraySet(table, index + 1, value);
+ return this;
}
- return %_MapHas(this, key);
-}
-function MapDeleteJS(key) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.delete', this]);
+ function MapHas(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.has', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ return MapFindEntry(table, numBuckets, key, hash) !== NOT_FOUND;
}
- return %_MapDelete(this, key);
-}
-function MapGetSizeJS() {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.size', this]);
+ function MapDelete(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.delete', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ var numBuckets = %_FixedArrayGet(table, NUMBER_OF_BUCKETS_INDEX);
+ var hash = GetHash(key);
+ var entry = MapFindEntry(table, numBuckets, key, hash);
+ if (entry === NOT_FOUND) return false;
+
+ var nof = %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX) - 1;
+ var nod = %_FixedArrayGet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX) + 1;
+ var index = MAP_ENTRY_TO_INDEX(entry, numBuckets);
+ %_FixedArraySetTheHole(table, index);
+ %_FixedArraySetTheHole(table, index + 1);
+ %_FixedArraySet(table, NUMBER_OF_ELEMENTS_INDEX, nof);
+ %_FixedArraySet(table, NUMBER_OF_DELETED_ELEMENTS_INDEX, nod);
+ if (nof < (numBuckets >> 1)) %MapShrink(this);
+ return true;
}
- return %_MapGetSize(this);
-}
-function MapClearJS() {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.clear', this]);
+ function MapGetSize() {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.size', this]);
+ }
+ var table = %_JSCollectionGetTable(this);
+ return %_FixedArrayGet(table, NUMBER_OF_ELEMENTS_INDEX);
}
- %_MapClear(this);
-}
-function MapForEach(f, receiver) {
- if (!IS_MAP(this)) {
- throw MakeTypeError('incompatible_method_receiver',
- ['Map.prototype.forEach', this]);
+ function MapClearJS() {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.clear', this]);
+ }
+ %_MapClear(this);
}
- if (!IS_SPEC_FUNCTION(f)) {
- throw MakeTypeError('called_non_callable', [f]);
- }
- var needs_wrapper = false;
- if (IS_NULL_OR_UNDEFINED(receiver)) {
- receiver = %GetDefaultReceiver(f) || receiver;
- } else {
- needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
- }
- var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
- var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
- var value_array = [UNDEFINED, UNDEFINED];
- while (%MapIteratorNext(iterator, value_array)) {
- if (stepping) %DebugPrepareStepInIfStepping(f);
- var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
- %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
+ function MapForEach(f, receiver) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.forEach', this]);
+ }
+
+ if (!IS_SPEC_FUNCTION(f)) {
+ throw MakeTypeError('called_non_callable', [f]);
+ }
+ var needs_wrapper = false;
+ if (IS_NULL_OR_UNDEFINED(receiver)) {
+ receiver = %GetDefaultReceiver(f) || receiver;
+ } else {
+ needs_wrapper = SHOULD_CREATE_WRAPPER(f, receiver);
+ }
+
+ var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES);
+ var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f);
+ var value_array = [UNDEFINED, UNDEFINED];
+ while (%MapIteratorNext(iterator, value_array)) {
+ if (stepping) %DebugPrepareStepInIfStepping(f);
+ var new_receiver = needs_wrapper ? ToObject(receiver) : receiver;
+ %_CallFunction(new_receiver, value_array[1], value_array[0], this, f);
+ }
}
-}
-// -------------------------------------------------------------------
+ // -------------------------------------------------------------------
+
+ function SetUpMap() {
+ %CheckIsBootstrapping();
-function SetUpMap() {
- %CheckIsBootstrapping();
+ %SetCode($Map, MapConstructor);
+ %FunctionSetPrototype($Map, new $Object());
+ %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
+ %AddNamedProperty(
+ $Map.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY);
- %SetCode($Map, MapConstructor);
- %FunctionSetPrototype($Map, new $Object());
- %AddNamedProperty($Map.prototype, "constructor", $Map, DONT_ENUM);
- %AddNamedProperty(
- $Map.prototype, symbolToStringTag, "Map", DONT_ENUM | READ_ONLY);
+ %FunctionSetLength(MapForEach, 1);
- %FunctionSetLength(MapForEach, 1);
+ // Set up the non-enumerable functions on the Map prototype object.
+ InstallGetter($Map.prototype, "size", MapGetSize);
+ InstallFunctions($Map.prototype, DONT_ENUM, $Array(
+ "get", MapGet,
+ "set", MapSet,
+ "has", MapHas,
+ "delete", MapDelete,
+ "clear", MapClearJS,
+ "forEach", MapForEach
+ ));
+ }
- // Set up the non-enumerable functions on the Map prototype object.
- InstallGetter($Map.prototype, "size", MapGetSizeJS);
- InstallFunctions($Map.prototype, DONT_ENUM, $Array(
- "get", MapGetJS,
- "set", MapSetJS,
- "has", MapHasJS,
- "delete", MapDeleteJS,
- "clear", MapClearJS,
- "forEach", MapForEach
- ));
-}
+ SetUpMap();
-SetUpMap();
+})();
« no previous file with comments | « no previous file | src/hydrogen.h » ('j') | src/hydrogen.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698