isolate()->initial_object_prototype(),
Builtins::kIllegal, true, true);
}
+ { // -- W e a k S e t
+ InstallFunction(global, "WeakSet", JS_WEAK_SET_TYPE, JSWeakSet::kSize,
+ isolate()->initial_object_prototype(),
+ Builtins::kIllegal, true, true);
+ }
}
if (FLAG_harmony_array_buffer) {
var $Set = global.Set;
var $Map = global.Map;
var $WeakMap = global.WeakMap;
+var $WeakSet = global.WeakSet;
// Global sentinel to be used instead of undefined keys, which are not
// supported internally but required for Harmony sets and maps.
function WeakMapConstructor() {
if (%_IsConstructCall()) {
- %WeakMapInitialize(this);
+ %WeakCollectionInitialize(this);
} else {
return new $WeakMap();
}
if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
- return %WeakMapGet(this, key);
+ return %WeakCollectionGet(this, key);
}
if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
- return %WeakMapSet(this, key, value);
+ return %WeakCollectionSet(this, key, value);
}
if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
- return %WeakMapHas(this, key);
+ return %WeakCollectionHas(this, key);
}
if (!(IS_SPEC_OBJECT(key) || IS_SYMBOL(key))) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
- return %WeakMapDelete(this, key);
+ return %WeakCollectionDelete(this, key);
}
['WeakMap.prototype.clear', this]);
}
// Replace the internal table with a new empty table.
- %WeakMapInitialize(this);
+ %WeakCollectionInitialize(this);
}
}
SetUpWeakMap();
+
+
+// -------------------------------------------------------------------
+// Harmony WeakSet
+
+function WeakSetConstructor() {
+ if (%_IsConstructCall()) {
+ %WeakCollectionInitialize(this);
+ } else {
+ return new $WeakSet();
+ }
+}
+
+
+function WeakSetAdd(value) {
+ if (!IS_WEAKSET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakSet.prototype.add', this]);
+ }
+ if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
+ throw %MakeTypeError('invalid_weakset_value', [this, value]);
+ }
+ return %WeakCollectionSet(this, value, true);
+}
+
+
+function WeakSetHas(value) {
+ if (!IS_WEAKSET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakSet.prototype.has', this]);
+ }
+ if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
+ throw %MakeTypeError('invalid_weakset_value', [this, value]);
+ }
+ return %WeakCollectionHas(this, value);
+}
+
+
+function WeakSetDelete(value) {
+ if (!IS_WEAKSET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakSet.prototype.delete', this]);
+ }
+ if (!(IS_SPEC_OBJECT(value) || IS_SYMBOL(value))) {
+ throw %MakeTypeError('invalid_weakset_value', [this, value]);
+ }
+ return %WeakCollectionDelete(this, value);
+}
+
+
+function WeakSetClear() {
+ if (!IS_WEAKSET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakSet.prototype.clear', this]);
+ }
+ // Replace the internal table with a new empty table.
+ %WeakCollectionInitialize(this);
+}
+
+
+// -------------------------------------------------------------------
+
+function SetUpWeakSet() {
+ %CheckIsBootstrapping();
+
+ %SetCode($WeakSet, WeakSetConstructor);
+ %FunctionSetPrototype($WeakSet, new $Object());
+ %SetProperty($WeakSet.prototype, "constructor", $WeakSet, DONT_ENUM);
+
+ // Set up the non-enumerable functions on the WeakSet prototype object.
+ InstallFunctions($WeakSet.prototype, DONT_ENUM, $Array(
+ "add", WeakSetAdd,
+ "has", WeakSetHas,
+ "delete", WeakSetDelete,
+ "clear", WeakSetClear
+ ));
+}
+
+SetUpWeakSet();
&ObjectEvacuationStrategy<POINTER_OBJECT>::
Visit);
+ table_.Register(kVisitJSWeakSet,
+ &ObjectEvacuationStrategy<POINTER_OBJECT>::
+ Visit);
+
table_.Register(kVisitJSArrayBuffer,
&ObjectEvacuationStrategy<POINTER_OBJECT>::
Visit);
PrintF("intracompaction_ptrs=%.1f ",
scopes_[Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED]);
PrintF("misc_compaction=%.1f ", scopes_[Scope::MC_UPDATE_MISC_POINTERS]);
- PrintF("weakmap_process=%.1f ", scopes_[Scope::MC_WEAKMAP_PROCESS]);
- PrintF("weakmap_clear=%.1f ", scopes_[Scope::MC_WEAKMAP_CLEAR]);
+ PrintF("weakcollection_process=%.1f ",
+ scopes_[Scope::MC_WEAKCOLLECTION_PROCESS]);
+ PrintF("weakcollection_clear=%.1f ",
+ scopes_[Scope::MC_WEAKCOLLECTION_CLEAR]);
PrintF("total_size_before=%" V8_PTR_PREFIX "d ", start_object_size_);
PrintF("total_size_after=%" V8_PTR_PREFIX "d ", heap_->SizeOfObjects());
MC_UPDATE_POINTERS_TO_EVACUATED,
MC_UPDATE_POINTERS_BETWEEN_EVACUATED,
MC_UPDATE_MISC_POINTERS,
- MC_WEAKMAP_PROCESS,
- MC_WEAKMAP_CLEAR,
+ MC_WEAKCOLLECTION_PROCESS,
+ MC_WEAKCOLLECTION_CLEAR,
MC_FLUSH_CODE,
kNumberOfScopes
};
VisitNativeContext(map, context);
}
- static void VisitJSWeakMap(Map* map, HeapObject* object) {
+ static void VisitWeakCollection(Map* map, HeapObject* object) {
Heap* heap = map->GetHeap();
VisitPointers(heap,
- HeapObject::RawField(object, JSWeakMap::kPropertiesOffset),
- HeapObject::RawField(object, JSWeakMap::kSize));
+ HeapObject::RawField(object,
+ JSWeakCollection::kPropertiesOffset),
+ HeapObject::RawField(object, JSWeakCollection::kSize));
}
static void BeforeVisitingSharedFunctionInfo(HeapObject* object) {}
macro IS_SET(arg) = (%_ClassOf(arg) === 'Set');
macro IS_MAP(arg) = (%_ClassOf(arg) === 'Map');
macro IS_WEAKMAP(arg) = (%_ClassOf(arg) === 'WeakMap');
+macro IS_WEAKSET(arg) = (%_ClassOf(arg) === 'WeakSet');
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
migration_slots_buffer_(NULL),
heap_(NULL),
code_flusher_(NULL),
- encountered_weak_maps_(NULL) { }
+ encountered_weak_collections_(NULL) { }
#ifdef VERIFY_HEAP
// Make sure that Prepare() has been called. The individual steps below will
// update the state as they proceed.
ASSERT(state_ == PREPARE_GC);
- ASSERT(encountered_weak_maps_ == Smi::FromInt(0));
+ ASSERT(encountered_weak_collections_ == Smi::FromInt(0));
MarkLiveObjects();
ASSERT(heap_->incremental_marking()->IsStopped());
if (FLAG_collect_maps) ClearNonLiveReferences();
- ClearWeakMaps();
+ ClearWeakCollections();
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
shared->BeforeVisitingPointers();
}
- static void VisitJSWeakMap(Map* map, HeapObject* object) {
+ static void VisitWeakCollection(Map* map, HeapObject* object) {
MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector();
- JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object);
+ JSWeakCollection* weak_collection =
+ reinterpret_cast<JSWeakCollection*>(object);
// Enqueue weak map in linked list of encountered weak maps.
- if (weak_map->next() == Smi::FromInt(0)) {
- weak_map->set_next(collector->encountered_weak_maps());
- collector->set_encountered_weak_maps(weak_map);
+ if (weak_collection->next() == Smi::FromInt(0)) {
+ weak_collection->set_next(collector->encountered_weak_collections());
+ collector->set_encountered_weak_collections(weak_collection);
}
// Skip visiting the backing hash table containing the mappings.
- int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object);
+ int object_size = JSWeakCollection::BodyDescriptor::SizeOf(map, object);
BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers(
map->GetHeap(),
object,
- JSWeakMap::BodyDescriptor::kStartOffset,
- JSWeakMap::kTableOffset);
+ JSWeakCollection::BodyDescriptor::kStartOffset,
+ JSWeakCollection::kTableOffset);
BodyVisitorBase<MarkCompactMarkingVisitor>::IteratePointers(
map->GetHeap(),
object,
- JSWeakMap::kTableOffset + kPointerSize,
+ JSWeakCollection::kTableOffset + kPointerSize,
object_size);
// Mark the backing hash table without pushing it on the marking stack.
- Object* table_object = weak_map->table();
+ Object* table_object = weak_collection->table();
if (!table_object->IsHashTable()) return;
ObjectHashTable* table = ObjectHashTable::cast(table_object);
Object** table_slot =
- HeapObject::RawField(weak_map, JSWeakMap::kTableOffset);
+ HeapObject::RawField(weak_collection, JSWeakCollection::kTableOffset);
MarkBit table_mark = Marking::MarkBitFrom(table);
collector->RecordSlot(table_slot, table_slot, table);
if (!table_mark.Get()) collector->SetMark(table, table_mark);
isolate()->global_handles()->IterateObjectGroups(
visitor, &IsUnmarkedHeapObjectWithHeap);
MarkImplicitRefGroups();
- ProcessWeakMaps();
+ ProcessWeakCollections();
work_to_do = !marking_deque_.IsEmpty();
ProcessMarkingDeque();
}
}
-void MarkCompactCollector::ProcessWeakMaps() {
- GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKMAP_PROCESS);
- Object* weak_map_obj = encountered_weak_maps();
- while (weak_map_obj != Smi::FromInt(0)) {
- ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj)));
- JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj);
- ObjectHashTable* table = ObjectHashTable::cast(weak_map->table());
+void MarkCompactCollector::ProcessWeakCollections() {
+ GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKCOLLECTION_PROCESS);
+ Object* weak_collection_obj = encountered_weak_collections();
+ while (weak_collection_obj != Smi::FromInt(0)) {
+ ASSERT(MarkCompactCollector::IsMarked(
+ HeapObject::cast(weak_collection_obj)));
+ JSWeakCollection* weak_collection =
+ reinterpret_cast<JSWeakCollection*>(weak_collection_obj);
+ ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table());
Object** anchor = reinterpret_cast<Object**>(table->address());
for (int i = 0; i < table->Capacity(); i++) {
if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) {
this, anchor, value_slot);
}
}
- weak_map_obj = weak_map->next();
+ weak_collection_obj = weak_collection->next();
}
}
-void MarkCompactCollector::ClearWeakMaps() {
- GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKMAP_CLEAR);
- Object* weak_map_obj = encountered_weak_maps();
- while (weak_map_obj != Smi::FromInt(0)) {
- ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj)));
- JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj);
- ObjectHashTable* table = ObjectHashTable::cast(weak_map->table());
+void MarkCompactCollector::ClearWeakCollections() {
+ GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_WEAKCOLLECTION_CLEAR);
+ Object* weak_collection_obj = encountered_weak_collections();
+ while (weak_collection_obj != Smi::FromInt(0)) {
+ ASSERT(MarkCompactCollector::IsMarked(
+ HeapObject::cast(weak_collection_obj)));
+ JSWeakCollection* weak_collection =
+ reinterpret_cast<JSWeakCollection*>(weak_collection_obj);
+ ObjectHashTable* table = ObjectHashTable::cast(weak_collection->table());
for (int i = 0; i < table->Capacity(); i++) {
if (!MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) {
table->RemoveEntry(i);
}
}
- weak_map_obj = weak_map->next();
- weak_map->set_next(Smi::FromInt(0));
+ weak_collection_obj = weak_collection->next();
+ weak_collection->set_next(Smi::FromInt(0));
}
- set_encountered_weak_maps(Smi::FromInt(0));
+ set_encountered_weak_collections(Smi::FromInt(0));
}
bool TryPromoteObject(HeapObject* object, int object_size);
- inline Object* encountered_weak_maps() { return encountered_weak_maps_; }
- inline void set_encountered_weak_maps(Object* weak_map) {
- encountered_weak_maps_ = weak_map;
+ inline Object* encountered_weak_collections() {
+ return encountered_weak_collections_;
+ }
+ inline void set_encountered_weak_collections(Object* weak_collection) {
+ encountered_weak_collections_ = weak_collection;
}
void InvalidateCode(Code* code);
// ClearNonLiveTransitions pass or by calling this function.
void ReattachInitialMaps();
- // Mark all values associated with reachable keys in weak maps encountered
- // so far. This might push new object or even new weak maps onto the
- // marking stack.
- void ProcessWeakMaps();
+ // Mark all values associated with reachable keys in weak collections
+ // encountered so far. This might push new object or even new weak maps onto
+ // the marking stack.
+ void ProcessWeakCollections();
// After all reachable objects have been marked those weak map entries
// with an unreachable key are removed from all encountered weak maps.
// The linked list of all encountered weak maps is destroyed.
- void ClearWeakMaps();
+ void ClearWeakCollections();
// -----------------------------------------------------------------------
// Phase 2: Sweeping to clear mark bits and free non-live objects for
Heap* heap_;
MarkingDeque marking_deque_;
CodeFlusher* code_flusher_;
- Object* encountered_weak_maps_;
+ Object* encountered_weak_collections_;
List<Page*> evacuation_candidates_;
List<Code*> invalidated_code_;
proxy_non_object_prop_names: ["Trap '", "%1", "' returned non-object ", "%0"],
proxy_repeated_prop_name: ["Trap '", "%1", "' returned repeated property name '", "%2", "'"],
invalid_weakmap_key: ["Invalid value used as weak map key"],
+ invalid_weakset_value: ["Invalid value used in weak set"],
not_date_object: ["this is not a Date object."],
observe_non_object: ["Object.", "%0", " cannot ", "%0", " non-object"],
observe_non_function: ["Object.", "%0", " cannot deliver to non-function"],
get: function(key) {
key = %UnwrapGlobalProxy(key);
if (!IS_SPEC_OBJECT(key)) return void 0;
- return %WeakMapGet(this.map_, key);
+ return %WeakCollectionGet(this.map_, key);
},
set: function(key, value) {
key = %UnwrapGlobalProxy(key);
if (!IS_SPEC_OBJECT(key)) return void 0;
- %WeakMapSet(this.map_, key, value);
+ %WeakCollectionSet(this.map_, key, value);
},
has: function(key) {
return !IS_UNDEFINED(this.get(key));
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapVerify();
break;
+ case JS_WEAK_SET_TYPE:
+ JSWeakSet::cast(this)->JSWeakSetVerify();
+ break;
case JS_REGEXP_TYPE:
JSRegExp::cast(this)->JSRegExpVerify();
break;
}
+void JSWeakSet::JSWeakSetVerify() {
+ CHECK(IsJSWeakSet());
+ JSObjectVerify();
+ VerifyHeapPointer(table());
+ CHECK(table()->IsHashTable() || table()->IsUndefined());
+}
+
+
void JSRegExp::JSRegExpVerify() {
JSObjectVerify();
CHECK(data()->IsUndefined() || data()->IsFixedArray());
TYPE_CHECKER(JSSet, JS_SET_TYPE)
TYPE_CHECKER(JSMap, JS_MAP_TYPE)
TYPE_CHECKER(JSWeakMap, JS_WEAK_MAP_TYPE)
+TYPE_CHECKER(JSWeakSet, JS_WEAK_SET_TYPE)
TYPE_CHECKER(JSContextExtensionObject, JS_CONTEXT_EXTENSION_OBJECT_TYPE)
TYPE_CHECKER(Map, MAP_TYPE)
TYPE_CHECKER(FixedArray, FIXED_ARRAY_TYPE)
TYPE_CHECKER(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
+bool Object::IsJSWeakCollection() {
+ return IsJSWeakMap() || IsJSWeakSet();
+}
+
+
bool Object::IsDescriptorArray() {
return IsFixedArray();
}
return JSMap::kSize;
case JS_WEAK_MAP_TYPE:
return JSWeakMap::kSize;
+ case JS_WEAK_SET_TYPE:
+ return JSWeakSet::kSize;
case JS_REGEXP_TYPE:
return JSRegExp::kSize;
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
CAST_ACCESSOR(JSSet)
CAST_ACCESSOR(JSMap)
CAST_ACCESSOR(JSWeakMap)
+CAST_ACCESSOR(JSWeakSet)
CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FreeSpace)
ACCESSORS(JSSet, table, Object, kTableOffset)
ACCESSORS(JSMap, table, Object, kTableOffset)
-ACCESSORS(JSWeakMap, table, Object, kTableOffset)
-ACCESSORS(JSWeakMap, next, Object, kNextOffset)
+ACCESSORS(JSWeakCollection, table, Object, kTableOffset)
+ACCESSORS(JSWeakCollection, next, Object, kNextOffset)
Address Foreign::foreign_address() {
case JS_WEAK_MAP_TYPE:
JSWeakMap::cast(this)->JSWeakMapPrint(out);
break;
+ case JS_WEAK_SET_TYPE:
+ JSWeakSet::cast(this)->JSWeakSetPrint(out);
+ break;
case FOREIGN_TYPE:
Foreign::cast(this)->ForeignPrint(out);
break;
case JS_ARRAY_TYPE: return "JS_ARRAY";
case JS_PROXY_TYPE: return "JS_PROXY";
case JS_WEAK_MAP_TYPE: return "JS_WEAK_MAP";
+ case JS_WEAK_SET_TYPE: return "JS_WEAK_SET";
case JS_REGEXP_TYPE: return "JS_REGEXP";
case JS_VALUE_TYPE: return "JS_VALUE";
case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
}
+void JSWeakSet::JSWeakSetPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "JSWeakSet");
+ PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+ PrintF(out, " - table = ");
+ table()->ShortPrint(out);
+ PrintF(out, "\n");
+}
+
+
void JSArrayBuffer::JSArrayBufferPrint(FILE* out) {
HeapObject::PrintHeader(out, "JSArrayBuffer");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
table_.Register(kVisitJSWeakMap, &JSObjectVisitor::Visit);
+ table_.Register(kVisitJSWeakSet, &JSObjectVisitor::Visit);
+
table_.Register(kVisitJSRegExp, &JSObjectVisitor::Visit);
table_.template RegisterSpecializations<DataObjectVisitor,
table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit);
- table_.Register(kVisitJSWeakMap, &StaticVisitor::VisitJSWeakMap);
+ table_.Register(kVisitJSWeakMap, &StaticVisitor::VisitWeakCollection);
+
+ table_.Register(kVisitJSWeakSet, &StaticVisitor::VisitWeakCollection);
table_.Register(kVisitOddball,
&FixedBodyVisitor<StaticVisitor,
case JS_WEAK_MAP_TYPE:
return kVisitJSWeakMap;
+ case JS_WEAK_SET_TYPE:
+ return kVisitJSWeakSet;
+
case JS_REGEXP_TYPE:
return kVisitJSRegExp;
V(SharedFunctionInfo) \
V(JSFunction) \
V(JSWeakMap) \
+ V(JSWeakSet) \
V(JSArrayBuffer) \
V(JSTypedArray) \
V(JSDataView) \
accumulator->Add("<JS WeakMap>");
break;
}
+ case JS_WEAK_SET_TYPE: {
+ accumulator->Add("<JS WeakSet>");
+ break;
+ }
case JS_REGEXP_TYPE: {
accumulator->Add("<JS RegExp>");
break;
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_WEAK_MAP_TYPE:
+ case JS_WEAK_SET_TYPE:
case JS_REGEXP_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
// - JSArray
// - JSArrayBuffer
// - JSArrayBufferView
-// - JSTypedArray
-// - JSDataView
+// - JSTypedArray
+// - JSDataView
// - JSSet
// - JSMap
-// - JSWeakMap
+// - JSWeakCollection
+// - JSWeakMap
+// - JSWeakSet
// - JSRegExp
// - JSFunction
// - JSGeneratorObject
V(JS_DATA_VIEW_TYPE) \
V(JS_PROXY_TYPE) \
V(JS_WEAK_MAP_TYPE) \
+ V(JS_WEAK_SET_TYPE) \
V(JS_REGEXP_TYPE) \
\
V(JS_FUNCTION_TYPE) \
JS_SET_TYPE,
JS_MAP_TYPE,
JS_WEAK_MAP_TYPE,
+ JS_WEAK_SET_TYPE,
JS_REGEXP_TYPE,
V(JSFunctionProxy) \
V(JSSet) \
V(JSMap) \
+ V(JSWeakCollection) \
V(JSWeakMap) \
+ V(JSWeakSet) \
V(JSRegExp) \
V(HashTable) \
V(Dictionary) \
};
-// The JSWeakMap describes EcmaScript Harmony weak maps
-class JSWeakMap: public JSObject {
+// Base class for both JSWeakMap and JSWeakSet
+class JSWeakCollection: public JSObject {
public:
// [table]: the backing hash table mapping keys to values.
DECL_ACCESSORS(table, Object)
// [next]: linked list of encountered weak maps during GC.
DECL_ACCESSORS(next, Object)
+ static const int kTableOffset = JSObject::kHeaderSize;
+ static const int kNextOffset = kTableOffset + kPointerSize;
+ static const int kSize = kNextOffset + kPointerSize;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakCollection);
+};
+
+
+// The JSWeakMap describes EcmaScript Harmony weak maps
+class JSWeakMap: public JSWeakCollection {
+ public:
// Casting.
static inline JSWeakMap* cast(Object* obj);
DECLARE_PRINTER(JSWeakMap)
DECLARE_VERIFIER(JSWeakMap)
- static const int kTableOffset = JSObject::kHeaderSize;
- static const int kNextOffset = kTableOffset + kPointerSize;
- static const int kSize = kNextOffset + kPointerSize;
-
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakMap);
};
+// The JSWeakSet describes EcmaScript Harmony weak sets
+class JSWeakSet: public JSWeakCollection {
+ public:
+ // Casting.
+ static inline JSWeakSet* cast(Object* obj);
+
+ // Dispatched behavior.
+ DECLARE_PRINTER(JSWeakSet)
+ DECLARE_VERIFIER(JSWeakSet)
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(JSWeakSet);
+};
+
+
class JSArrayBuffer: public JSObject {
public:
// [backing_store]: backing memory for this array
}
-static JSWeakMap* WeakMapInitialize(Isolate* isolate,
- Handle<JSWeakMap> weakmap) {
- ASSERT(weakmap->map()->inobject_properties() == 0);
+static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
+ Handle<JSWeakCollection> weak_collection) {
+ ASSERT(weak_collection->map()->inobject_properties() == 0);
Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
- weakmap->set_table(*table);
- weakmap->set_next(Smi::FromInt(0));
- return *weakmap;
+ weak_collection->set_table(*table);
+ weak_collection->set_next(Smi::FromInt(0));
+ return *weak_collection;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
- return WeakMapInitialize(isolate, weakmap);
+ CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
+ return WeakCollectionInitialize(isolate, weak_collection);
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
+ Handle<ObjectHashTable> table(
+ ObjectHashTable::cast(weak_collection->table()));
Handle<Object> lookup(table->Lookup(*key), isolate);
return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapHas) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
+ Handle<ObjectHashTable> table(
+ ObjectHashTable::cast(weak_collection->table()));
Handle<Object> lookup(table->Lookup(*key), isolate);
return isolate->heap()->ToBoolean(!lookup->IsTheHole());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapDelete) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
HandleScope scope(isolate);
ASSERT(args.length() == 2);
- CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
+ Handle<ObjectHashTable> table(ObjectHashTable::cast(
+ weak_collection->table()));
Handle<Object> lookup(table->Lookup(*key), isolate);
Handle<ObjectHashTable> new_table =
PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
- weakmap->set_table(*new_table);
+ weak_collection->set_table(*new_table);
return isolate->heap()->ToBoolean(!lookup->IsTheHole());
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
Handle<Object> value(args[2], isolate);
- Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
+ Handle<ObjectHashTable> table(
+ ObjectHashTable::cast(weak_collection->table()));
Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
- weakmap->set_table(*new_table);
+ weak_collection->set_table(*new_table);
return isolate->heap()->undefined_value();
}
isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
Handle<JSWeakMap> weakmap =
Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
- return WeakMapInitialize(isolate, weakmap);
+ return WeakCollectionInitialize(isolate, weakmap);
}
F(MapSet, 3, 1) \
F(MapGetSize, 1, 1) \
\
- /* Harmony weakmaps */ \
- F(WeakMapInitialize, 1, 1) \
- F(WeakMapGet, 2, 1) \
- F(WeakMapHas, 2, 1) \
- F(WeakMapDelete, 2, 1) \
- F(WeakMapSet, 3, 1) \
+ /* Harmony weak maps and sets */ \
+ F(WeakCollectionInitialize, 1, 1) \
+ F(WeakCollectionGet, 2, 1) \
+ F(WeakCollectionHas, 2, 1) \
+ F(WeakCollectionDelete, 2, 1) \
+ F(WeakCollectionSet, 3, 1) \
\
/* Harmony observe */ \
F(IsObserved, 1, 1) \
case JS_SET_TYPE:
case JS_MAP_TYPE:
case JS_WEAK_MAP_TYPE:
+ case JS_WEAK_SET_TYPE:
if (map->is_undetectable()) return kUndetectable;
return kOtherObject;
case JS_ARRAY_TYPE:
'test-utils.cc',
'test-version.cc',
'test-weakmaps.cc',
+ 'test-weaksets.cc',
'test-weaktypedarrays.cc'
],
'conditions': [
# We do not yet shrink weak maps after they have been emptied by the GC
test-weakmaps/Shrinking: FAIL
+test-weaksets/WeakSet_Shrinking: FAIL
# Deferred stack trace formatting is temporarily disabled.
test-heap/ReleaseStackTraceData: PASS || FAIL
--- /dev/null
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "global-handles.h"
+#include "snapshot.h"
+#include "cctest.h"
+
+using namespace v8::internal;
+
+
+static Isolate* GetIsolateFrom(LocalContext* context) {
+ return reinterpret_cast<Isolate*>((*context)->GetIsolate());
+}
+
+
+static Handle<JSWeakSet> AllocateJSWeakSet(Isolate* isolate) {
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ Handle<Map> map = factory->NewMap(JS_WEAK_SET_TYPE, JSWeakSet::kSize);
+ Handle<JSObject> weakset_obj = factory->NewJSObjectFromMap(map);
+ Handle<JSWeakSet> weakset(JSWeakSet::cast(*weakset_obj));
+ // Do not use handles for the hash table, it would make entries strong.
+ Object* table_obj = ObjectHashTable::Allocate(heap, 1)->ToObjectChecked();
+ ObjectHashTable* table = ObjectHashTable::cast(table_obj);
+ weakset->set_table(table);
+ weakset->set_next(Smi::FromInt(0));
+ return weakset;
+}
+
+static void PutIntoWeakSet(Handle<JSWeakSet> weakset,
+ Handle<JSObject> key,
+ Handle<Object> value) {
+ Handle<ObjectHashTable> table = PutIntoObjectHashTable(
+ Handle<ObjectHashTable>(ObjectHashTable::cast(weakset->table())),
+ Handle<JSObject>(JSObject::cast(*key)),
+ value);
+ weakset->set_table(*table);
+}
+
+static int NumberOfWeakCalls = 0;
+static void WeakPointerCallback(v8::Isolate* isolate,
+ v8::Persistent<v8::Value>* handle,
+ void* id) {
+ ASSERT(id == reinterpret_cast<void*>(1234));
+ NumberOfWeakCalls++;
+ handle->Dispose(isolate);
+}
+
+
+TEST(WeakSet_Weakness) {
+ FLAG_incremental_marking = false;
+ LocalContext context;
+ Isolate* isolate = GetIsolateFrom(&context);
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ HandleScope scope(isolate);
+ Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
+ GlobalHandles* global_handles = isolate->global_handles();
+
+ // Keep global reference to the key.
+ Handle<Object> key;
+ {
+ HandleScope scope(isolate);
+ Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+ key = global_handles->Create(*object);
+ }
+ CHECK(!global_handles->IsWeak(key.location()));
+
+ // Put entry into weak set.
+ {
+ HandleScope scope(isolate);
+ PutIntoWeakSet(weakset,
+ Handle<JSObject>(JSObject::cast(*key)),
+ Handle<Smi>(Smi::FromInt(23), isolate));
+ }
+ CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+
+ // Force a full GC.
+ heap->CollectAllGarbage(false);
+ CHECK_EQ(0, NumberOfWeakCalls);
+ CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+ CHECK_EQ(
+ 0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
+
+ // Make the global reference to the key weak.
+ {
+ HandleScope scope(isolate);
+ global_handles->MakeWeak(key.location(),
+ reinterpret_cast<void*>(1234),
+ &WeakPointerCallback);
+ }
+ CHECK(global_handles->IsWeak(key.location()));
+
+ // Force a full GC.
+ // Perform two consecutive GCs because the first one will only clear
+ // weak references whereas the second one will also clear weak sets.
+ heap->CollectAllGarbage(false);
+ CHECK_EQ(1, NumberOfWeakCalls);
+ CHECK_EQ(1, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+ CHECK_EQ(
+ 0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
+ heap->CollectAllGarbage(false);
+ CHECK_EQ(1, NumberOfWeakCalls);
+ CHECK_EQ(0, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+ CHECK_EQ(
+ 1, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
+}
+
+
+TEST(WeakSet_Shrinking) {
+ LocalContext context;
+ Isolate* isolate = GetIsolateFrom(&context);
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ HandleScope scope(isolate);
+ Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
+
+ // Check initial capacity.
+ CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->Capacity());
+
+ // Fill up weak set to trigger capacity change.
+ {
+ HandleScope scope(isolate);
+ Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
+ for (int i = 0; i < 32; i++) {
+ Handle<JSObject> object = factory->NewJSObjectFromMap(map);
+ PutIntoWeakSet(weakset, object, Handle<Smi>(Smi::FromInt(i), isolate));
+ }
+ }
+
+ // Check increased capacity.
+ CHECK_EQ(128, ObjectHashTable::cast(weakset->table())->Capacity());
+
+ // Force a full GC.
+ CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+ CHECK_EQ(
+ 0, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
+ heap->CollectAllGarbage(false);
+ CHECK_EQ(0, ObjectHashTable::cast(weakset->table())->NumberOfElements());
+ CHECK_EQ(
+ 32, ObjectHashTable::cast(weakset->table())->NumberOfDeletedElements());
+
+ // Check shrunk capacity.
+ CHECK_EQ(32, ObjectHashTable::cast(weakset->table())->Capacity());
+}
+
+
+// Test that weak set values on an evacuation candidate which are not reachable
+// by other paths are correctly recorded in the slots buffer.
+TEST(WeakSet_Regress2060a) {
+ FLAG_always_compact = true;
+ LocalContext context;
+ Isolate* isolate = GetIsolateFrom(&context);
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ HandleScope scope(isolate);
+ Handle<JSFunction> function =
+ factory->NewFunction(factory->function_string(), factory->null_value());
+ Handle<JSObject> key = factory->NewJSObject(function);
+ Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
+
+ // Start second old-space page so that values land on evacuation candidate.
+ Page* first_page = heap->old_pointer_space()->anchor()->next_page();
+ factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+
+ // Fill up weak set with values on an evacuation candidate.
+ {
+ HandleScope scope(isolate);
+ for (int i = 0; i < 32; i++) {
+ Handle<JSObject> object = factory->NewJSObject(function, TENURED);
+ CHECK(!heap->InNewSpace(object->address()));
+ CHECK(!first_page->Contains(object->address()));
+ PutIntoWeakSet(weakset, key, object);
+ }
+ }
+
+ // Force compacting garbage collection.
+ CHECK(FLAG_always_compact);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+}
+
+
+// Test that weak set keys on an evacuation candidate which are reachable by
+// other strong paths are correctly recorded in the slots buffer.
+TEST(WeakSet_Regress2060b) {
+ FLAG_always_compact = true;
+#ifdef VERIFY_HEAP
+ FLAG_verify_heap = true;
+#endif
+
+ LocalContext context;
+ Isolate* isolate = GetIsolateFrom(&context);
+ Factory* factory = isolate->factory();
+ Heap* heap = isolate->heap();
+ HandleScope scope(isolate);
+ Handle<JSFunction> function =
+ factory->NewFunction(factory->function_string(), factory->null_value());
+
+ // Start second old-space page so that keys land on evacuation candidate.
+ Page* first_page = heap->old_pointer_space()->anchor()->next_page();
+ factory->NewFixedArray(900 * KB / kPointerSize, TENURED);
+
+ // Fill up weak set with keys on an evacuation candidate.
+ Handle<JSObject> keys[32];
+ for (int i = 0; i < 32; i++) {
+ keys[i] = factory->NewJSObject(function, TENURED);
+ CHECK(!heap->InNewSpace(keys[i]->address()));
+ CHECK(!first_page->Contains(keys[i]->address()));
+ }
+ Handle<JSWeakSet> weakset = AllocateJSWeakSet(isolate);
+ for (int i = 0; i < 32; i++) {
+ PutIntoWeakSet(weakset,
+ keys[i],
+ Handle<Smi>(Smi::FromInt(i), isolate));
+ }
+
+ // Force compacting garbage collection. The subsequent collections are used
+ // to verify that key references were actually updated.
+ CHECK(FLAG_always_compact);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+ heap->CollectAllGarbage(Heap::kNoGCFlags);
+}
assertDoesNotThrow(function () { m.delete(new Object) });
}
TestValidSetCalls(new Set);
+TestValidSetCalls(new WeakSet);
// Test valid getter and setter calls on Maps and WeakMaps
}
}
TestSetBehavior(new Set);
+TestSet(new WeakSet, new Object);
// Test expected mapping behavior for Maps and WeakMaps
TestEnumerable(Set);
TestEnumerable(Map);
TestEnumerable(WeakMap);
+TestEnumerable(WeakSet);
// Test arbitrary properties on Maps and WeakMaps
assertTrue(Set() instanceof Set);
assertTrue(Map() instanceof Map);
assertTrue(WeakMap() instanceof WeakMap);
+assertTrue(WeakSet() instanceof WeakSet);
// Test whether NaN values as keys are treated correctly.
assertTrue(Set.prototype.add instanceof Function)
assertTrue(Set.prototype.has instanceof Function)
assertTrue(Set.prototype.delete instanceof Function)
+assertTrue(Set.prototype.clear instanceof Function)
// Test some common JavaScript idioms for Maps
assertTrue(Map.prototype.get instanceof Function)
assertTrue(Map.prototype.has instanceof Function)
assertTrue(Map.prototype.delete instanceof Function)
+assertTrue(Map.prototype.clear instanceof Function)
// Test some common JavaScript idioms for WeakMaps
assertTrue(WeakMap.prototype.get instanceof Function)
assertTrue(WeakMap.prototype.has instanceof Function)
assertTrue(WeakMap.prototype.delete instanceof Function)
+assertTrue(WeakMap.prototype.clear instanceof Function)
-// Test class of the Set, Map and WeakMap instance and prototype.
+// Test some common JavaScript idioms for WeakSets
+var s = new WeakSet;
+assertTrue(s instanceof WeakSet);
+assertTrue(WeakSet.prototype.add instanceof Function)
+assertTrue(WeakSet.prototype.has instanceof Function)
+assertTrue(WeakSet.prototype.delete instanceof Function)
+assertTrue(WeakSet.prototype.clear instanceof Function)
+
+
+// Test class of instance and prototype.
assertEquals("Set", %_ClassOf(new Set))
assertEquals("Object", %_ClassOf(Set.prototype))
assertEquals("Map", %_ClassOf(new Map))
assertEquals("Object", %_ClassOf(Map.prototype))
assertEquals("WeakMap", %_ClassOf(new WeakMap))
assertEquals("Object", %_ClassOf(WeakMap.prototype))
+assertEquals("WeakSet", %_ClassOf(new WeakSet))
+assertEquals("Object", %_ClassOf(WeakMap.prototype))
+
+
+// Test name of constructor.
+assertEquals("Set", Set.name);
+assertEquals("Map", Map.name);
+assertEquals("WeakMap", WeakMap.name);
+assertEquals("WeakSet", WeakSet.name);
-// Test constructor property of the Set, Map and WeakMap prototype.
+// Test constructor property of the Set, Map, WeakMap and WeakSet prototype.
function TestConstructor(C) {
assertFalse(C === Object.prototype.constructor);
assertSame(C, C.prototype.constructor);
TestConstructor(Set);
TestConstructor(Map);
TestConstructor(WeakMap);
+TestConstructor(WeakSet);
+
+
+function TestDescriptor(global, C) {
+ assertEquals({
+ value: C,
+ writable: true,
+ enumerable: false,
+ configurable: true
+ }, Object.getOwnPropertyDescriptor(global, C.name));
+}
+TestDescriptor(this, Set);
+TestDescriptor(this, Map);
+TestDescriptor(this, WeakMap);
+TestDescriptor(this, WeakSet);
// Regression test for WeakMap prototype.
var bogusReceiversTestSet = [
{ proto: Set.prototype,
funcs: [ 'add', 'has', 'delete' ],
- receivers: alwaysBogus.concat([ new Map, new WeakMap ]),
+ receivers: alwaysBogus.concat([ new Map, new WeakMap, new WeakSet ]),
},
{ proto: Map.prototype,
funcs: [ 'get', 'set', 'has', 'delete' ],
- receivers: alwaysBogus.concat([ new Set, new WeakMap ]),
+ receivers: alwaysBogus.concat([ new Set, new WeakMap, new WeakSet ]),
},
{ proto: WeakMap.prototype,
funcs: [ 'get', 'set', 'has', 'delete' ],
- receivers: alwaysBogus.concat([ new Set, new Map ]),
+ receivers: alwaysBogus.concat([ new Set, new Map, new WeakSet ]),
+ },
+ { proto: WeakSet.prototype,
+ funcs: [ 'add', 'has', 'delete' ],
+ receivers: alwaysBogus.concat([ new Set, new Map, new WeakMap ]),
},
];
function TestBogusReceivers(testSet) {
assertFalse(w.has(k));
assertEquals(undefined, w.get(k));
})();
+
+
+// Test WeakSet clear
+(function() {
+ var k = new Object();
+ var w = new WeakSet();
+ w.add(k);
+ assertTrue(w.has(k));
+ w.clear();
+ assertFalse(w.has(k));
+})();
\ No newline at end of file
180: "JS_ARRAY_TYPE",
171: "JS_PROXY_TYPE",
183: "JS_WEAK_MAP_TYPE",
- 184: "JS_REGEXP_TYPE",
- 185: "JS_FUNCTION_TYPE",
+ 184: "JS_WEAK_SET_TYPE",
+ 185: "JS_REGEXP_TYPE",
+ 186: "JS_FUNCTION_TYPE",
170: "JS_FUNCTION_PROXY_TYPE",
165: "DEBUG_INFO_TYPE",
166: "BREAK_POINT_INFO_TYPE",