Snapshot: support rehashing property and element dictionaries.
This change - adds new maps for elements, global, and named dictionaries. - adds support to embed these dictionaries in the startup snapshot. - adds support to embed these dictionaries in the code cache. - refactors the rehashing logic. R=ishell@chromium.org, jgruber@chromium.org, mstarzinger@chromium.org Bug: v8:6593 Change-Id: I8d9a7ba7145f1af4e6e15301a4d5611f07c77f33 Reviewed-on: https://chromium-review.googlesource.com/753323 Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#49155}
This commit is contained in:
parent
0afe2524c0
commit
3877bf6f4b
@ -2394,8 +2394,8 @@ Node* CodeStubAssembler::AllocateNameDictionaryWithCapacity(Node* capacity) {
|
||||
Node* result = AllocateInNewSpace(store_size);
|
||||
Comment("Initialize NameDictionary");
|
||||
// Initialize FixedArray fields.
|
||||
DCHECK(Heap::RootIsImmortalImmovable(Heap::kHashTableMapRootIndex));
|
||||
StoreMapNoWriteBarrier(result, Heap::kHashTableMapRootIndex);
|
||||
DCHECK(Heap::RootIsImmortalImmovable(Heap::kNameDictionaryMapRootIndex));
|
||||
StoreMapNoWriteBarrier(result, Heap::kNameDictionaryMapRootIndex);
|
||||
StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
|
||||
SmiFromWord(length));
|
||||
// Initialized HashTable fields.
|
||||
|
@ -2262,7 +2262,7 @@ Reduction JSBuiltinReducer::ReduceObjectCreate(Node* node) {
|
||||
Node* properties = jsgraph()->EmptyFixedArrayConstant();
|
||||
if (instance_map->is_dictionary_map()) {
|
||||
// Allocated an empty NameDictionary as backing store for the properties.
|
||||
Handle<Map> map(isolate()->heap()->hash_table_map(), isolate());
|
||||
Handle<Map> map(isolate()->heap()->name_dictionary_map(), isolate());
|
||||
int capacity =
|
||||
NameDictionary::ComputeCapacity(NameDictionary::kInitialCapacity);
|
||||
DCHECK(base::bits::IsPowerOfTwo(capacity));
|
||||
|
@ -515,7 +515,9 @@ ScriptCompiler::CachedData* CompileForCachedData(
|
||||
}
|
||||
Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = Shell::array_buffer_allocator;
|
||||
i::FLAG_hash_seed ^= 1337; // Use a different hash seed.
|
||||
Isolate* temp_isolate = Isolate::New(create_params);
|
||||
i::FLAG_hash_seed ^= 1337; // Restore old hash seed.
|
||||
temp_isolate->SetHostImportModuleDynamicallyCallback(
|
||||
Shell::HostImportModuleDynamically);
|
||||
temp_isolate->SetHostInitializeImportMetaObjectCallback(
|
||||
|
@ -104,6 +104,9 @@ using v8::MemoryPressureLevel;
|
||||
V(Map, fixed_double_array_map, FixedDoubleArrayMap) \
|
||||
V(Map, mutable_heap_number_map, MutableHeapNumberMap) \
|
||||
V(Map, ordered_hash_table_map, OrderedHashTableMap) \
|
||||
V(Map, name_dictionary_map, NameDictionaryMap) \
|
||||
V(Map, global_dictionary_map, GlobalDictionaryMap) \
|
||||
V(Map, seeded_number_dictionary_map, SeededNumberDictionaryMap) \
|
||||
V(Map, unseeded_number_dictionary_map, UnseededNumberDictionaryMap) \
|
||||
V(Map, sloppy_arguments_elements_map, SloppyArgumentsElementsMap) \
|
||||
V(Map, small_ordered_hash_map_map, SmallOrderedHashMapMap) \
|
||||
@ -311,6 +314,7 @@ using v8::MemoryPressureLevel;
|
||||
V(ForeignMap) \
|
||||
V(FreeSpaceMap) \
|
||||
V(FunctionContextMap) \
|
||||
V(GlobalDictionaryMap) \
|
||||
V(GlobalPropertyCellMap) \
|
||||
V(HashTableMap) \
|
||||
V(HeapNumberMap) \
|
||||
@ -327,6 +331,7 @@ using v8::MemoryPressureLevel;
|
||||
V(ModuleContextMap) \
|
||||
V(ModuleInfoMap) \
|
||||
V(MutableHeapNumberMap) \
|
||||
V(NameDictionaryMap) \
|
||||
V(NanValue) \
|
||||
V(NativeContextMap) \
|
||||
V(NoClosuresCellMap) \
|
||||
@ -337,12 +342,13 @@ using v8::MemoryPressureLevel;
|
||||
V(OptimizedOut) \
|
||||
V(OrderedHashTableMap) \
|
||||
V(PropertyArrayMap) \
|
||||
V(SmallOrderedHashMapMap) \
|
||||
V(SmallOrderedHashSetMap) \
|
||||
V(ScopeInfoMap) \
|
||||
V(ScriptContextMap) \
|
||||
V(SeededNumberDictionaryMap) \
|
||||
V(SharedFunctionInfoMap) \
|
||||
V(SloppyArgumentsElementsMap) \
|
||||
V(SmallOrderedHashMapMap) \
|
||||
V(SmallOrderedHashSetMap) \
|
||||
V(SpeciesProtector) \
|
||||
V(StaleRegister) \
|
||||
V(StringLengthProtector) \
|
||||
@ -358,6 +364,7 @@ using v8::MemoryPressureLevel;
|
||||
V(UndefinedValue) \
|
||||
V(UninitializedMap) \
|
||||
V(UninitializedValue) \
|
||||
V(UnseededNumberDictionaryMap) \
|
||||
V(WeakCellMap) \
|
||||
V(WithContextMap) \
|
||||
PRIVATE_SYMBOL_LIST(V)
|
||||
|
@ -288,6 +288,9 @@ bool Heap::CreateInitialMaps() {
|
||||
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, hash_table)
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, ordered_hash_table)
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, name_dictionary)
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, global_dictionary)
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, seeded_number_dictionary)
|
||||
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, unseeded_number_dictionary)
|
||||
|
||||
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context)
|
||||
|
@ -139,7 +139,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
// Check that the properties array is a dictionary.
|
||||
__ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
Register tmp = properties;
|
||||
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
||||
__ LoadRoot(tmp, Heap::kNameDictionaryMapRootIndex);
|
||||
__ cmp(map, tmp);
|
||||
__ b(ne, miss_label);
|
||||
|
||||
|
@ -76,7 +76,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
FieldMemOperand(receiver, JSObject::kPropertiesOrHashOffset));
|
||||
// Check that the properties array is a dictionary.
|
||||
__ Ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
__ JumpIfNotRoot(map, Heap::kHashTableMapRootIndex, miss_label);
|
||||
__ JumpIfNotRoot(map, Heap::kNameDictionaryMapRootIndex, miss_label);
|
||||
|
||||
NameDictionaryLookupStub::GenerateNegativeLookup(
|
||||
masm, miss_label, &done, receiver, properties, name, scratch1);
|
||||
|
@ -88,7 +88,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
|
||||
// Check that the properties array is a dictionary.
|
||||
__ cmp(FieldOperand(properties, HeapObject::kMapOffset),
|
||||
Immediate(masm->isolate()->factory()->hash_table_map()));
|
||||
Immediate(masm->isolate()->factory()->name_dictionary_map()));
|
||||
__ j(not_equal, miss_label);
|
||||
|
||||
Label done;
|
||||
|
@ -131,7 +131,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
// Check that the properties array is a dictionary.
|
||||
__ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
Register tmp = properties;
|
||||
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
||||
__ LoadRoot(tmp, Heap::kNameDictionaryMapRootIndex);
|
||||
__ Branch(miss_label, ne, map, Operand(tmp));
|
||||
|
||||
// Restore the temporarily used register.
|
||||
|
@ -131,7 +131,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
// Check that the properties array is a dictionary.
|
||||
__ Ld(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
Register tmp = properties;
|
||||
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
||||
__ LoadRoot(tmp, Heap::kNameDictionaryMapRootIndex);
|
||||
__ Branch(miss_label, ne, map, Operand(tmp));
|
||||
|
||||
// Restore the temporarily used register.
|
||||
|
@ -133,7 +133,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
// Check that the properties array is a dictionary.
|
||||
__ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
Register tmp = properties;
|
||||
__ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
||||
__ LoadRoot(tmp, Heap::kNameDictionaryMapRootIndex);
|
||||
__ cmp(map, tmp);
|
||||
__ bne(miss_label);
|
||||
|
||||
|
@ -129,7 +129,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
FieldMemOperand(receiver, JSObject::kPropertiesOrHashOffset));
|
||||
// Check that the properties array is a dictionary.
|
||||
__ LoadP(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
||||
__ CompareRoot(map, Heap::kHashTableMapRootIndex);
|
||||
__ CompareRoot(map, Heap::kNameDictionaryMapRootIndex);
|
||||
__ bne(miss_label);
|
||||
|
||||
// Restore the temporarily used register.
|
||||
|
@ -74,7 +74,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||
|
||||
// Check that the properties array is a dictionary.
|
||||
__ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset),
|
||||
Heap::kHashTableMapRootIndex);
|
||||
Heap::kNameDictionaryMapRootIndex);
|
||||
__ j(not_equal, miss_label);
|
||||
|
||||
Label done;
|
||||
|
@ -424,11 +424,17 @@ bool HeapObject::IsDictionary() const {
|
||||
return IsHashTable() && this != GetHeap()->string_table();
|
||||
}
|
||||
|
||||
bool Object::IsNameDictionary() const { return IsDictionary(); }
|
||||
bool HeapObject::IsGlobalDictionary() const {
|
||||
return map() == GetHeap()->global_dictionary_map();
|
||||
}
|
||||
|
||||
bool Object::IsGlobalDictionary() const { return IsDictionary(); }
|
||||
bool HeapObject::IsNameDictionary() const {
|
||||
return map() == GetHeap()->name_dictionary_map();
|
||||
}
|
||||
|
||||
bool Object::IsSeededNumberDictionary() const { return IsDictionary(); }
|
||||
bool HeapObject::IsSeededNumberDictionary() const {
|
||||
return map() == GetHeap()->seeded_number_dictionary_map();
|
||||
}
|
||||
|
||||
bool HeapObject::IsUnseededNumberDictionary() const {
|
||||
return map() == GetHeap()->unseeded_number_dictionary_map();
|
||||
@ -1957,6 +1963,19 @@ AllocationAlignment HeapObject::RequiredAlignment() const {
|
||||
return kWordAligned;
|
||||
}
|
||||
|
||||
bool HeapObject::NeedsRehashing() const {
|
||||
switch (map()->instance_type()) {
|
||||
case HASH_TABLE_TYPE:
|
||||
return !IsUnseededNumberDictionary();
|
||||
case TRANSITION_ARRAY_TYPE:
|
||||
return TransitionArray::cast(this)->number_of_entries() > 1;
|
||||
case SMALL_ORDERED_HASH_MAP_TYPE:
|
||||
case SMALL_ORDERED_HASH_SET_TYPE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FixedArray::set(int index,
|
||||
Object* value,
|
||||
@ -4779,8 +4798,16 @@ Object* GlobalDictionaryShape::Unwrap(Object* object) {
|
||||
return PropertyCell::cast(object)->name();
|
||||
}
|
||||
|
||||
Map* GlobalDictionaryShape::GetMap(Isolate* isolate) {
|
||||
return isolate->heap()->global_dictionary_map();
|
||||
}
|
||||
|
||||
Name* NameDictionary::NameAt(int entry) { return Name::cast(KeyAt(entry)); }
|
||||
|
||||
Map* NameDictionaryShape::GetMap(Isolate* isolate) {
|
||||
return isolate->heap()->name_dictionary_map();
|
||||
}
|
||||
|
||||
PropertyCell* GlobalDictionary::CellAt(int entry) {
|
||||
DCHECK(KeyAt(entry)->IsPropertyCell());
|
||||
return PropertyCell::cast(KeyAt(entry));
|
||||
@ -4841,6 +4868,9 @@ uint32_t SeededNumberDictionaryShape::HashForObject(Isolate* isolate,
|
||||
isolate->heap()->HashSeed());
|
||||
}
|
||||
|
||||
Map* SeededNumberDictionaryShape::GetMap(Isolate* isolate) {
|
||||
return isolate->heap()->seeded_number_dictionary_map();
|
||||
}
|
||||
|
||||
Handle<Object> NumberDictionaryShape::AsHandle(Isolate* isolate, uint32_t key) {
|
||||
return isolate->factory()->NewNumberFromUint(key);
|
||||
|
@ -3630,6 +3630,55 @@ String* JSReceiver::class_name() {
|
||||
return GetHeap()->Object_string();
|
||||
}
|
||||
|
||||
bool HeapObject::CanBeRehashed() const {
|
||||
DCHECK(NeedsRehashing());
|
||||
switch (map()->instance_type()) {
|
||||
case HASH_TABLE_TYPE:
|
||||
return IsNameDictionary() || IsGlobalDictionary() ||
|
||||
IsSeededNumberDictionary();
|
||||
case TRANSITION_ARRAY_TYPE:
|
||||
return true;
|
||||
case SMALL_ORDERED_HASH_MAP_TYPE:
|
||||
return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
|
||||
case SMALL_ORDERED_HASH_SET_TYPE:
|
||||
return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HeapObject::RehashBasedOnMap() {
|
||||
switch (map()->instance_type()) {
|
||||
case HASH_TABLE_TYPE:
|
||||
if (IsNameDictionary()) {
|
||||
NameDictionary::cast(this)->Rehash();
|
||||
} else if (IsSeededNumberDictionary()) {
|
||||
SeededNumberDictionary::cast(this)->Rehash();
|
||||
} else if (IsGlobalDictionary()) {
|
||||
GlobalDictionary::cast(this)->Rehash();
|
||||
} else {
|
||||
// TODO(6593): Some hash tables cannot yet be rehashed based on the map,
|
||||
// and are handled explicitly in StartupDeserializer::RehashHeap.
|
||||
if (this == GetHeap()->empty_ordered_hash_table()) break;
|
||||
if (this == GetHeap()->weak_object_to_code_table()) break;
|
||||
if (this == GetHeap()->string_table()) break;
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
case TRANSITION_ARRAY_TYPE:
|
||||
TransitionArray::cast(this)->Sort();
|
||||
break;
|
||||
case SMALL_ORDERED_HASH_MAP_TYPE:
|
||||
DCHECK_EQ(0, SmallOrderedHashMap::cast(this)->NumberOfElements());
|
||||
break;
|
||||
case SMALL_ORDERED_HASH_SET_TYPE:
|
||||
DCHECK_EQ(0, SmallOrderedHashSet::cast(this)->NumberOfElements());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
|
||||
@ -6436,10 +6485,14 @@ int GetIdentityHashHelper(Isolate* isolate, JSReceiver* object) {
|
||||
return PropertyArray::cast(properties)->Hash();
|
||||
}
|
||||
|
||||
if (properties->IsDictionary()) {
|
||||
if (properties->IsNameDictionary()) {
|
||||
return NameDictionary::cast(properties)->Hash();
|
||||
}
|
||||
|
||||
if (properties->IsGlobalDictionary()) {
|
||||
return GlobalDictionary::cast(properties)->Hash();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
FixedArray* empty_fixed_array = isolate->heap()->empty_fixed_array();
|
||||
FixedArray* empty_property_dictionary =
|
||||
|
@ -1013,6 +1013,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(FrameArray) \
|
||||
V(FreeSpace) \
|
||||
V(Function) \
|
||||
V(GlobalDictionary) \
|
||||
V(HandlerTable) \
|
||||
V(HeapNumber) \
|
||||
V(InternalizedString) \
|
||||
@ -1056,6 +1057,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(ModuleInfo) \
|
||||
V(MutableHeapNumber) \
|
||||
V(Name) \
|
||||
V(NameDictionary) \
|
||||
V(NativeContext) \
|
||||
V(NormalizedMapCache) \
|
||||
V(ObjectHashSet) \
|
||||
@ -1069,6 +1071,7 @@ template <class C> inline bool Is(Object* obj);
|
||||
V(RegExpMatchInfo) \
|
||||
V(ScopeInfo) \
|
||||
V(ScriptContextTable) \
|
||||
V(SeededNumberDictionary) \
|
||||
V(SeqOneByteString) \
|
||||
V(SeqString) \
|
||||
V(SeqTwoByteString) \
|
||||
@ -1182,9 +1185,6 @@ class Object {
|
||||
// ES6, #sec-isarray. NOT to be confused with %_IsArray.
|
||||
INLINE(MUST_USE_RESULT static Maybe<bool> IsArray(Handle<Object> object));
|
||||
|
||||
INLINE(bool IsNameDictionary() const);
|
||||
INLINE(bool IsGlobalDictionary() const);
|
||||
INLINE(bool IsSeededNumberDictionary() const);
|
||||
INLINE(bool IsOrderedHashSet() const);
|
||||
INLINE(bool IsOrderedHashMap() const);
|
||||
INLINE(bool IsSmallOrderedHashTable() const);
|
||||
@ -1816,6 +1816,19 @@ class HeapObject: public Object {
|
||||
|
||||
inline AllocationAlignment RequiredAlignment() const;
|
||||
|
||||
// Whether the object needs rehashing. That is the case if the object's
|
||||
// content depends on FLAG_hash_seed. When the object is deserialized into
|
||||
// a heap with a different hash seed, these objects need to adapt.
|
||||
inline bool NeedsRehashing() const;
|
||||
|
||||
// Rehashing support is not implemented for all objects that need rehashing.
|
||||
// With objects that need rehashing but cannot be rehashed, rehashing has to
|
||||
// be disabled.
|
||||
bool CanBeRehashed() const;
|
||||
|
||||
// Rehash the object based on the layout inferred from its map.
|
||||
void RehashBasedOnMap();
|
||||
|
||||
// Layout description.
|
||||
// First field in a heap object is map.
|
||||
static const int kMapOffset = Object::kHeaderSize;
|
||||
|
@ -112,6 +112,7 @@ class NameDictionaryShape : public BaseDictionaryShape<Handle<Name>> {
|
||||
static inline uint32_t Hash(Isolate* isolate, Handle<Name> key);
|
||||
static inline uint32_t HashForObject(Isolate* isolate, Object* object);
|
||||
static inline Handle<Object> AsHandle(Isolate* isolate, Handle<Name> key);
|
||||
static inline Map* GetMap(Isolate* isolate);
|
||||
static const int kPrefixSize = 2;
|
||||
static const int kEntrySize = 3;
|
||||
static const int kEntryValueIndex = 1;
|
||||
@ -207,6 +208,7 @@ class GlobalDictionaryShape : public NameDictionaryShape {
|
||||
static inline Object* Unwrap(Object* key);
|
||||
static inline bool IsKey(Isolate* isolate, Object* k);
|
||||
static inline bool IsLive(Isolate* isolate, Object* key);
|
||||
static inline Map* GetMap(Isolate* isolate);
|
||||
};
|
||||
|
||||
class GlobalDictionary
|
||||
@ -235,6 +237,8 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape {
|
||||
|
||||
static inline uint32_t Hash(Isolate* isolate, uint32_t key);
|
||||
static inline uint32_t HashForObject(Isolate* isolate, Object* object);
|
||||
|
||||
static inline Map* GetMap(Isolate* isolate);
|
||||
};
|
||||
|
||||
class UnseededNumberDictionaryShape : public NumberDictionaryShape {
|
||||
|
@ -123,8 +123,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
CHECK(!obj->IsMap());
|
||||
// There should be no references to the global object embedded.
|
||||
CHECK(!obj->IsJSGlobalProxy() && !obj->IsJSGlobalObject());
|
||||
// There should be no hash table embedded. They would require rehashing.
|
||||
CHECK(!obj->IsHashTable());
|
||||
// Embedded FixedArrays that need rehashing must support rehashing.
|
||||
CHECK_IMPLIES(obj->NeedsRehashing(), obj->CanBeRehashed());
|
||||
// We expect no instantiated function objects or contexts.
|
||||
CHECK(!obj->IsJSFunction() && !obj->IsContext());
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include "src/assembler-inl.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/objects/hash-table.h"
|
||||
#include "src/objects/string.h"
|
||||
#include "src/snapshot/builtin-deserializer-allocator.h"
|
||||
#include "src/snapshot/natives.h"
|
||||
@ -38,6 +39,18 @@ bool Deserializer<AllocatorT>::IsLazyDeserializationEnabled() const {
|
||||
return FLAG_lazy_deserialization && !isolate()->serializer_enabled();
|
||||
}
|
||||
|
||||
template <class AllocatorT>
|
||||
void Deserializer<AllocatorT>::Rehash() {
|
||||
DCHECK(can_rehash() || deserializing_user_code());
|
||||
for (const auto& item : to_rehash_) item->RehashBasedOnMap();
|
||||
for (const auto& address : allocator()->GetAllocatedMaps()) {
|
||||
Map* map = Map::cast(HeapObject::FromAddress(address));
|
||||
if (map->instance_descriptors()->number_of_descriptors() > 1) {
|
||||
map->instance_descriptors()->Sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class AllocatorT>
|
||||
Deserializer<AllocatorT>::~Deserializer() {
|
||||
#ifdef DEBUG
|
||||
@ -126,11 +139,19 @@ uint32_t StringTableInsertionKey::ComputeHashField(String* string) {
|
||||
template <class AllocatorT>
|
||||
HeapObject* Deserializer<AllocatorT>::PostProcessNewObject(HeapObject* obj,
|
||||
int space) {
|
||||
if ((FLAG_rehash_snapshot && can_rehash_) || deserializing_user_code()) {
|
||||
if (obj->IsString()) {
|
||||
// Uninitialize hash field as we need to recompute the hash.
|
||||
String* string = String::cast(obj);
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
} else if (obj->NeedsRehashing()) {
|
||||
to_rehash_.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (deserializing_user_code()) {
|
||||
if (obj->IsString()) {
|
||||
String* string = String::cast(obj);
|
||||
// Uninitialize hash field as the hash seed may have changed.
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
if (string->IsInternalizedString()) {
|
||||
// Canonicalize the internalized string. If it already exists in the
|
||||
// string table, set it to forward to the existing one.
|
||||
@ -203,20 +224,9 @@ HeapObject* Deserializer<AllocatorT>::PostProcessNewObject(HeapObject* obj,
|
||||
if (fta->base_pointer() == nullptr) {
|
||||
Smi* store_index = reinterpret_cast<Smi*>(fta->external_pointer());
|
||||
void* backing_store = off_heap_backing_stores_[store_index->value()];
|
||||
|
||||
fta->set_external_pointer(backing_store);
|
||||
}
|
||||
}
|
||||
if (FLAG_rehash_snapshot && can_rehash_ && !deserializing_user_code()) {
|
||||
if (obj->IsString()) {
|
||||
// Uninitialize hash field as we are going to reinitialize the hash seed.
|
||||
String* string = String::cast(obj);
|
||||
string->set_hash_field(String::kEmptyHashField);
|
||||
} else if (obj->IsTransitionArray() &&
|
||||
TransitionArray::cast(obj)->number_of_entries() > 1) {
|
||||
transition_arrays_.push_back(TransitionArray::cast(obj));
|
||||
}
|
||||
}
|
||||
// Check alignment.
|
||||
DCHECK_EQ(0, Heap::GetFillToAlign(obj->address(), obj->RequiredAlignment()));
|
||||
return obj;
|
||||
@ -258,16 +268,6 @@ HeapObject* Deserializer<AllocatorT>::GetBackReferencedObject(int space) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <class AllocatorT>
|
||||
void Deserializer<AllocatorT>::SortMapDescriptors() {
|
||||
for (const auto& address : allocator()->GetAllocatedMaps()) {
|
||||
Map* map = Map::cast(HeapObject::FromAddress(address));
|
||||
if (map->instance_descriptors()->number_of_descriptors() > 1) {
|
||||
map->instance_descriptors()->Sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This routine writes the new object into the pointer provided and then
|
||||
// returns true if the new object was in young space and false otherwise.
|
||||
// The reason for this strange interface is that otherwise the object is
|
||||
|
@ -88,9 +88,6 @@ class Deserializer : public SerializerDeserializer {
|
||||
const std::vector<Handle<Script>>& new_scripts() const {
|
||||
return new_scripts_;
|
||||
}
|
||||
const std::vector<TransitionArray*>& transition_arrays() const {
|
||||
return transition_arrays_;
|
||||
}
|
||||
|
||||
AllocatorT* allocator() { return &allocator_; }
|
||||
bool deserializing_user_code() const { return deserializing_user_code_; }
|
||||
@ -98,6 +95,8 @@ class Deserializer : public SerializerDeserializer {
|
||||
|
||||
bool IsLazyDeserializationEnabled() const;
|
||||
|
||||
void Rehash();
|
||||
|
||||
private:
|
||||
void VisitRootPointers(Root root, Object** start, Object** end) override;
|
||||
|
||||
@ -147,7 +146,6 @@ class Deserializer : public SerializerDeserializer {
|
||||
std::vector<CallHandlerInfo*> call_handler_infos_;
|
||||
std::vector<Handle<String>> new_internalized_strings_;
|
||||
std::vector<Handle<Script>> new_scripts_;
|
||||
std::vector<TransitionArray*> transition_arrays_;
|
||||
std::vector<byte*> off_heap_backing_stores_;
|
||||
|
||||
AllocatorT allocator_;
|
||||
@ -155,6 +153,7 @@ class Deserializer : public SerializerDeserializer {
|
||||
|
||||
// TODO(6593): generalize rehashing, and remove this flag.
|
||||
bool can_rehash_;
|
||||
std::vector<HeapObject*> to_rehash_;
|
||||
|
||||
#ifdef DEBUG
|
||||
uint32_t num_api_references_;
|
||||
|
@ -79,6 +79,7 @@ MaybeHandle<HeapObject> ObjectDeserializer::Deserialize(Isolate* isolate) {
|
||||
DeserializeDeferredObjects();
|
||||
FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects();
|
||||
result = Handle<HeapObject>(HeapObject::cast(root));
|
||||
Rehash();
|
||||
allocator()->RegisterDeserializedObjectsForBlackAllocation();
|
||||
}
|
||||
CommitPostProcessedObjects();
|
||||
|
@ -53,7 +53,7 @@ MaybeHandle<Object> PartialDeserializer::Deserialize(
|
||||
// new code, which also has to be flushed from instruction cache.
|
||||
CHECK_EQ(start_address, code_space->top());
|
||||
|
||||
if (FLAG_rehash_snapshot && can_rehash()) RehashContext(Context::cast(root));
|
||||
if (FLAG_rehash_snapshot && can_rehash()) Rehash();
|
||||
|
||||
return Handle<Object>(root, isolate);
|
||||
}
|
||||
@ -84,13 +84,5 @@ void PartialDeserializer::DeserializeEmbedderFields(
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void PartialDeserializer::RehashContext(Context* context) {
|
||||
DCHECK(can_rehash());
|
||||
for (const auto& array : transition_arrays()) array->Sort();
|
||||
context->global_object()->global_dictionary()->Rehash();
|
||||
SortMapDescriptors();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -33,9 +33,6 @@ class PartialDeserializer final : public Deserializer<> {
|
||||
|
||||
void DeserializeEmbedderFields(
|
||||
v8::DeserializeEmbedderFieldsCallback embedder_fields_deserializer);
|
||||
|
||||
// Rehash after deserializing a context.
|
||||
void RehashContext(Context* context);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -17,7 +17,6 @@ PartialSerializer::PartialSerializer(
|
||||
: Serializer(isolate),
|
||||
startup_serializer_(startup_serializer),
|
||||
serialize_embedder_fields_(callback),
|
||||
rehashable_global_dictionary_(nullptr),
|
||||
can_be_rehashed_(true) {
|
||||
InitializeCodeAddressMap();
|
||||
}
|
||||
@ -42,8 +41,6 @@ void PartialSerializer::Serialize(Object** o, bool include_global_proxy) {
|
||||
// Reset math random cache to get fresh random numbers.
|
||||
context->set_math_random_index(Smi::kZero);
|
||||
context->set_math_random_cache(isolate()->heap()->undefined_value());
|
||||
DCHECK_NULL(rehashable_global_dictionary_);
|
||||
rehashable_global_dictionary_ = context->global_object()->global_dictionary();
|
||||
|
||||
VisitRootPointer(Root::kPartialSnapshotCache, o);
|
||||
SerializeDeferredObjects();
|
||||
@ -104,7 +101,7 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->IsHashTable()) CheckRehashability(obj);
|
||||
CheckRehashability(obj);
|
||||
|
||||
// Object has not yet been serialized. Serialize it here.
|
||||
ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point);
|
||||
@ -155,17 +152,10 @@ void PartialSerializer::SerializeEmbedderFields() {
|
||||
sink_.Put(kSynchronize, "Finished with embedder fields data");
|
||||
}
|
||||
|
||||
void PartialSerializer::CheckRehashability(HeapObject* table) {
|
||||
DCHECK(table->IsHashTable());
|
||||
void PartialSerializer::CheckRehashability(HeapObject* obj) {
|
||||
if (!can_be_rehashed_) return;
|
||||
if (table->IsUnseededNumberDictionary()) return;
|
||||
if (table->IsOrderedHashMap() &&
|
||||
OrderedHashMap::cast(table)->NumberOfElements() == 0) {
|
||||
return;
|
||||
}
|
||||
// We can only correctly rehash if the global dictionary is the only hash
|
||||
// table that we deserialize.
|
||||
if (table == rehashable_global_dictionary_) return;
|
||||
if (!obj->NeedsRehashing()) return;
|
||||
if (obj->CanBeRehashed()) return;
|
||||
can_be_rehashed_ = false;
|
||||
}
|
||||
|
||||
|
@ -33,12 +33,11 @@ class PartialSerializer : public Serializer<> {
|
||||
|
||||
void SerializeEmbedderFields();
|
||||
|
||||
void CheckRehashability(HeapObject* table);
|
||||
void CheckRehashability(HeapObject* obj);
|
||||
|
||||
StartupSerializer* startup_serializer_;
|
||||
std::vector<JSObject*> embedder_field_holders_;
|
||||
v8::SerializeEmbedderFieldsCallback serialize_embedder_fields_;
|
||||
GlobalDictionary* rehashable_global_dictionary_;
|
||||
// Indicates whether we only serialized hash tables that we can rehash.
|
||||
// TODO(yangguo): generalize rehashing, and remove this flag.
|
||||
bool can_be_rehashed_;
|
||||
|
@ -73,7 +73,7 @@ void StartupDeserializer::DeserializeInto(Isolate* isolate) {
|
||||
// to display the builtin names.
|
||||
PrintDisassembledCodeObjects();
|
||||
|
||||
if (FLAG_rehash_snapshot && can_rehash()) Rehash();
|
||||
if (FLAG_rehash_snapshot && can_rehash()) RehashHeap();
|
||||
}
|
||||
|
||||
void StartupDeserializer::FlushICacheForNewIsolate() {
|
||||
@ -105,12 +105,12 @@ void StartupDeserializer::PrintDisassembledCodeObjects() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartupDeserializer::Rehash() {
|
||||
void StartupDeserializer::RehashHeap() {
|
||||
DCHECK(FLAG_rehash_snapshot && can_rehash());
|
||||
isolate()->heap()->InitializeHashSeed();
|
||||
isolate()->heap()->string_table()->Rehash();
|
||||
isolate()->heap()->weak_object_to_code_table()->Rehash();
|
||||
SortMapDescriptors();
|
||||
Rehash();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -26,7 +26,7 @@ class StartupDeserializer final : public Deserializer<> {
|
||||
void PrintDisassembledCodeObjects();
|
||||
|
||||
// Rehash after deserializing an isolate.
|
||||
void Rehash();
|
||||
void RehashHeap();
|
||||
|
||||
const BuiltinSnapshotData* builtin_data_;
|
||||
};
|
||||
|
@ -81,7 +81,7 @@ void StartupSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code,
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->IsHashTable()) CheckRehashability(obj);
|
||||
CheckRehashability(obj);
|
||||
|
||||
// Object has not yet been serialized. Serialize it here.
|
||||
ObjectSerializer object_serializer(this, obj, &sink_, how_to_code,
|
||||
@ -182,17 +182,15 @@ bool StartupSerializer::RootShouldBeSkipped(int root_index) {
|
||||
serializing_immortal_immovables_roots_;
|
||||
}
|
||||
|
||||
void StartupSerializer::CheckRehashability(HeapObject* table) {
|
||||
DCHECK(table->IsHashTable());
|
||||
void StartupSerializer::CheckRehashability(HeapObject* obj) {
|
||||
if (!can_be_rehashed_) return;
|
||||
if (!obj->NeedsRehashing()) return;
|
||||
if (obj->CanBeRehashed()) return;
|
||||
// We can only correctly rehash if the four hash tables below are the only
|
||||
// ones that we deserialize.
|
||||
if (table->IsUnseededNumberDictionary()) return;
|
||||
if (table == isolate()->heap()->empty_ordered_hash_table()) return;
|
||||
if (table == isolate()->heap()->empty_slow_element_dictionary()) return;
|
||||
if (table == isolate()->heap()->empty_property_dictionary()) return;
|
||||
if (table == isolate()->heap()->weak_object_to_code_table()) return;
|
||||
if (table == isolate()->heap()->string_table()) return;
|
||||
if (obj == isolate()->heap()->empty_ordered_hash_table()) return;
|
||||
if (obj == isolate()->heap()->weak_object_to_code_table()) return;
|
||||
if (obj == isolate()->heap()->string_table()) return;
|
||||
can_be_rehashed_ = false;
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class StartupSerializer : public Serializer<> {
|
||||
// roots. In the second pass, we serialize the rest.
|
||||
bool RootShouldBeSkipped(int root_index);
|
||||
|
||||
void CheckRehashability(HeapObject* hashtable);
|
||||
void CheckRehashability(HeapObject* obj);
|
||||
|
||||
const bool clear_function_code_;
|
||||
bool serializing_immortal_immovables_roots_;
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
#include "src/ic/handler-configuration-inl.h"
|
||||
|
||||
// Has to be the last include (doesn't have include guards):
|
||||
#include "src/objects/object-macros.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
@ -31,12 +34,7 @@ TransitionArray* TransitionsAccessor::transitions() {
|
||||
return TransitionArray::cast(raw_transitions_);
|
||||
}
|
||||
|
||||
// static
|
||||
TransitionArray* TransitionArray::cast(Object* object) {
|
||||
DCHECK(object->IsTransitionArray());
|
||||
return reinterpret_cast<TransitionArray*>(object);
|
||||
}
|
||||
|
||||
CAST_ACCESSOR(TransitionArray)
|
||||
|
||||
bool TransitionArray::HasPrototypeTransitions() {
|
||||
return get(kPrototypeTransitionsIndex) != Smi::kZero;
|
||||
@ -215,4 +213,6 @@ void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#include "src/objects/object-macros-undef.h"
|
||||
|
||||
#endif // V8_TRANSITIONS_INL_H_
|
||||
|
@ -12,6 +12,9 @@
|
||||
#include "src/objects/map.h"
|
||||
#include "src/objects/name.h"
|
||||
|
||||
// Has to be the last include (doesn't have include guards):
|
||||
#include "src/objects/object-macros.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
@ -205,7 +208,7 @@ class TransitionsAccessor {
|
||||
// [3 + number of transitions * kTransitionSize]: start of slack
|
||||
class TransitionArray : public FixedArray {
|
||||
public:
|
||||
inline static TransitionArray* cast(Object* object);
|
||||
DECL_CAST(TransitionArray)
|
||||
|
||||
inline FixedArray* GetPrototypeTransitions();
|
||||
inline Object** GetPrototypeTransitionsSlot();
|
||||
@ -227,7 +230,7 @@ class TransitionArray : public FixedArray {
|
||||
return GetKey(transition_number);
|
||||
}
|
||||
int GetSortedKeyIndex(int transition_number) { return transition_number; }
|
||||
inline int number_of_entries() { return number_of_transitions(); }
|
||||
inline int number_of_entries() const { return number_of_transitions(); }
|
||||
#ifdef DEBUG
|
||||
bool IsSortedNoDuplicates(int valid_entries = -1);
|
||||
#endif
|
||||
@ -326,7 +329,7 @@ class TransitionArray : public FixedArray {
|
||||
int SearchDetails(int transition, PropertyKind kind,
|
||||
PropertyAttributes attributes, int* out_insertion_index);
|
||||
|
||||
int number_of_transitions() {
|
||||
int number_of_transitions() const {
|
||||
if (length() < kFirstIndex) return 0;
|
||||
return Smi::ToInt(get(kTransitionLengthIndex));
|
||||
}
|
||||
@ -362,8 +365,9 @@ class TransitionArray : public FixedArray {
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(TransitionArray);
|
||||
};
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#include "src/objects/object-macros-undef.h"
|
||||
|
||||
#endif // V8_TRANSITIONS_H_
|
||||
|
@ -2721,7 +2721,7 @@ TEST(SnapshotCreatorIncludeGlobalProxy) {
|
||||
delete[] blob.data;
|
||||
}
|
||||
|
||||
UNINITIALIZED_TEST(ReinitializeStringHashSeedNotRehashable) {
|
||||
UNINITIALIZED_TEST(ReinitializeHashSeedNotRehashable) {
|
||||
DisableAlwaysOpt();
|
||||
i::FLAG_rehash_snapshot = true;
|
||||
i::FLAG_hash_seed = 42;
|
||||
@ -2734,13 +2734,12 @@ UNINITIALIZED_TEST(ReinitializeStringHashSeedNotRehashable) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
// Create dictionary mode object.
|
||||
// Create an object with an ordered hash table.
|
||||
CompileRun(
|
||||
"var a = {};"
|
||||
"a.b = 1;"
|
||||
"a.c = 2;"
|
||||
"delete a.b;");
|
||||
ExpectInt32("a.c", 2);
|
||||
"var m = new Map();"
|
||||
"m.set('a', 1);"
|
||||
"m.set('b', 2);");
|
||||
ExpectInt32("m.get('b')", 2);
|
||||
creator.SetDefaultContext(context);
|
||||
}
|
||||
blob =
|
||||
@ -2760,7 +2759,74 @@ UNINITIALIZED_TEST(ReinitializeStringHashSeedNotRehashable) {
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
CHECK(!context.IsEmpty());
|
||||
v8::Context::Scope context_scope(context);
|
||||
ExpectInt32("a.c", 2);
|
||||
ExpectInt32("m.get('b')", 2);
|
||||
}
|
||||
isolate->Dispose();
|
||||
delete[] blob.data;
|
||||
}
|
||||
|
||||
UNINITIALIZED_TEST(ReinitializeHashSeedRehashable) {
|
||||
DisableAlwaysOpt();
|
||||
i::FLAG_rehash_snapshot = true;
|
||||
i::FLAG_hash_seed = 42;
|
||||
i::FLAG_allow_natives_syntax = true;
|
||||
v8::StartupData blob;
|
||||
{
|
||||
v8::SnapshotCreator creator;
|
||||
v8::Isolate* isolate = creator.GetIsolate();
|
||||
{
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
v8::Context::Scope context_scope(context);
|
||||
// Create dictionary mode object.
|
||||
CompileRun(
|
||||
"var a = new Array(10000);"
|
||||
"%NormalizeElements(a);"
|
||||
"a[133] = 1;"
|
||||
"a[177] = 2;"
|
||||
"a[971] = 3;"
|
||||
"a[7997] = 4;"
|
||||
"a[2111] = 5;"
|
||||
"var o = {};"
|
||||
"%OptimizeObjectForAddingMultipleProperties(o, 3);"
|
||||
"o.a = 1;"
|
||||
"o.b = 2;"
|
||||
"o.c = 3;");
|
||||
i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
|
||||
i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
|
||||
CHECK(i_a->IsJSArray());
|
||||
CHECK(i_a->IsJSObject());
|
||||
CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
|
||||
CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
|
||||
ExpectInt32("a[2111]", 5);
|
||||
ExpectInt32("o.c", 3);
|
||||
creator.SetDefaultContext(context);
|
||||
}
|
||||
blob =
|
||||
creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear);
|
||||
}
|
||||
|
||||
i::FLAG_hash_seed = 1337;
|
||||
v8::Isolate::CreateParams create_params;
|
||||
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
||||
create_params.snapshot_blob = &blob;
|
||||
v8::Isolate* isolate = v8::Isolate::New(create_params);
|
||||
{
|
||||
// Check that rehashing has been performed.
|
||||
CHECK_EQ(1337, reinterpret_cast<i::Isolate*>(isolate)->heap()->HashSeed());
|
||||
v8::Isolate::Scope isolate_scope(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Context> context = v8::Context::New(isolate);
|
||||
CHECK(!context.IsEmpty());
|
||||
v8::Context::Scope context_scope(context);
|
||||
i::Handle<i::Object> i_a = v8::Utils::OpenHandle(*CompileRun("a"));
|
||||
i::Handle<i::Object> i_o = v8::Utils::OpenHandle(*CompileRun("o"));
|
||||
CHECK(i_a->IsJSArray());
|
||||
CHECK(i_a->IsJSObject());
|
||||
CHECK(!i::Handle<i::JSArray>::cast(i_a)->HasFastElements());
|
||||
CHECK(!i::Handle<i::JSObject>::cast(i_o)->HasFastProperties());
|
||||
ExpectInt32("a[2111]", 5);
|
||||
ExpectInt32("o.c", 3);
|
||||
}
|
||||
isolate->Dispose();
|
||||
delete[] blob.data;
|
||||
|
@ -202,74 +202,77 @@ KNOWN_MAPS = {
|
||||
0x02de1: (148, "FixedDoubleArrayMap"),
|
||||
0x02e31: (134, "MutableHeapNumberMap"),
|
||||
0x02e81: (172, "OrderedHashTableMap"),
|
||||
0x02ed1: (171, "SloppyArgumentsElementsMap"),
|
||||
0x02f21: (180, "SmallOrderedHashMapMap"),
|
||||
0x02f71: (181, "SmallOrderedHashSetMap"),
|
||||
0x02fc1: (189, "JSMessageObjectMap"),
|
||||
0x03011: (137, "BytecodeArrayMap"),
|
||||
0x03061: (171, "ModuleInfoMap"),
|
||||
0x030b1: (177, "NoClosuresCellMap"),
|
||||
0x03101: (177, "OneClosureCellMap"),
|
||||
0x03151: (177, "ManyClosuresCellMap"),
|
||||
0x031a1: (175, "PropertyArrayMap"),
|
||||
0x031f1: (130, "BigIntMap"),
|
||||
0x03241: (64, "StringMap"),
|
||||
0x03291: (73, "ConsOneByteStringMap"),
|
||||
0x032e1: (65, "ConsStringMap"),
|
||||
0x03331: (77, "ThinOneByteStringMap"),
|
||||
0x03381: (69, "ThinStringMap"),
|
||||
0x033d1: (67, "SlicedStringMap"),
|
||||
0x03421: (75, "SlicedOneByteStringMap"),
|
||||
0x03471: (66, "ExternalStringMap"),
|
||||
0x034c1: (82, "ExternalStringWithOneByteDataMap"),
|
||||
0x03511: (74, "ExternalOneByteStringMap"),
|
||||
0x03561: (98, "ShortExternalStringMap"),
|
||||
0x035b1: (114, "ShortExternalStringWithOneByteDataMap"),
|
||||
0x03601: (0, "InternalizedStringMap"),
|
||||
0x03651: (2, "ExternalInternalizedStringMap"),
|
||||
0x036a1: (18, "ExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x036f1: (10, "ExternalOneByteInternalizedStringMap"),
|
||||
0x03741: (34, "ShortExternalInternalizedStringMap"),
|
||||
0x03791: (50, "ShortExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x037e1: (42, "ShortExternalOneByteInternalizedStringMap"),
|
||||
0x03831: (106, "ShortExternalOneByteStringMap"),
|
||||
0x03881: (140, "FixedUint8ArrayMap"),
|
||||
0x038d1: (139, "FixedInt8ArrayMap"),
|
||||
0x03921: (142, "FixedUint16ArrayMap"),
|
||||
0x03971: (141, "FixedInt16ArrayMap"),
|
||||
0x039c1: (144, "FixedUint32ArrayMap"),
|
||||
0x03a11: (143, "FixedInt32ArrayMap"),
|
||||
0x03a61: (145, "FixedFloat32ArrayMap"),
|
||||
0x03ab1: (146, "FixedFloat64ArrayMap"),
|
||||
0x03b01: (147, "FixedUint8ClampedArrayMap"),
|
||||
0x03b51: (158, "ScriptMap"),
|
||||
0x03ba1: (182, "CodeDataContainerMap"),
|
||||
0x03bf1: (173, "FeedbackVectorMap"),
|
||||
0x03c41: (171, "DebugEvaluateContextMap"),
|
||||
0x03c91: (171, "ScriptContextTableMap"),
|
||||
0x03ce1: (172, "UnseededNumberDictionaryMap"),
|
||||
0x03d31: (192, "ExternalMap"),
|
||||
0x03d81: (106, "NativeSourceStringMap"),
|
||||
0x03dd1: (165, "Tuple2Map"),
|
||||
0x03e21: (153, "InterceptorInfoMap"),
|
||||
0x03e71: (150, "AccessorInfoMap"),
|
||||
0x03ec1: (151, "AccessorPairMap"),
|
||||
0x03f11: (152, "AccessCheckInfoMap"),
|
||||
0x03f61: (154, "FunctionTemplateInfoMap"),
|
||||
0x03fb1: (155, "ObjectTemplateInfoMap"),
|
||||
0x04001: (156, "AllocationSiteMap"),
|
||||
0x04051: (157, "AllocationMementoMap"),
|
||||
0x040a1: (159, "AliasedArgumentsEntryMap"),
|
||||
0x040f1: (160, "PromiseResolveThenableJobInfoMap"),
|
||||
0x04141: (161, "PromiseReactionJobInfoMap"),
|
||||
0x04191: (162, "DebugInfoMap"),
|
||||
0x041e1: (163, "StackFrameInfoMap"),
|
||||
0x04231: (164, "PrototypeInfoMap"),
|
||||
0x04281: (166, "Tuple3Map"),
|
||||
0x042d1: (167, "ContextExtensionMap"),
|
||||
0x04321: (168, "ModuleMap"),
|
||||
0x04371: (169, "ModuleInfoEntryMap"),
|
||||
0x043c1: (170, "AsyncGeneratorRequestMap"),
|
||||
0x02ed1: (172, "NameDictionaryMap"),
|
||||
0x02f21: (172, "GlobalDictionaryMap"),
|
||||
0x02f71: (172, "SeededNumberDictionaryMap"),
|
||||
0x02fc1: (172, "UnseededNumberDictionaryMap"),
|
||||
0x03011: (171, "SloppyArgumentsElementsMap"),
|
||||
0x03061: (180, "SmallOrderedHashMapMap"),
|
||||
0x030b1: (181, "SmallOrderedHashSetMap"),
|
||||
0x03101: (189, "JSMessageObjectMap"),
|
||||
0x03151: (137, "BytecodeArrayMap"),
|
||||
0x031a1: (171, "ModuleInfoMap"),
|
||||
0x031f1: (177, "NoClosuresCellMap"),
|
||||
0x03241: (177, "OneClosureCellMap"),
|
||||
0x03291: (177, "ManyClosuresCellMap"),
|
||||
0x032e1: (175, "PropertyArrayMap"),
|
||||
0x03331: (130, "BigIntMap"),
|
||||
0x03381: (64, "StringMap"),
|
||||
0x033d1: (73, "ConsOneByteStringMap"),
|
||||
0x03421: (65, "ConsStringMap"),
|
||||
0x03471: (77, "ThinOneByteStringMap"),
|
||||
0x034c1: (69, "ThinStringMap"),
|
||||
0x03511: (67, "SlicedStringMap"),
|
||||
0x03561: (75, "SlicedOneByteStringMap"),
|
||||
0x035b1: (66, "ExternalStringMap"),
|
||||
0x03601: (82, "ExternalStringWithOneByteDataMap"),
|
||||
0x03651: (74, "ExternalOneByteStringMap"),
|
||||
0x036a1: (98, "ShortExternalStringMap"),
|
||||
0x036f1: (114, "ShortExternalStringWithOneByteDataMap"),
|
||||
0x03741: (0, "InternalizedStringMap"),
|
||||
0x03791: (2, "ExternalInternalizedStringMap"),
|
||||
0x037e1: (18, "ExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x03831: (10, "ExternalOneByteInternalizedStringMap"),
|
||||
0x03881: (34, "ShortExternalInternalizedStringMap"),
|
||||
0x038d1: (50, "ShortExternalInternalizedStringWithOneByteDataMap"),
|
||||
0x03921: (42, "ShortExternalOneByteInternalizedStringMap"),
|
||||
0x03971: (106, "ShortExternalOneByteStringMap"),
|
||||
0x039c1: (140, "FixedUint8ArrayMap"),
|
||||
0x03a11: (139, "FixedInt8ArrayMap"),
|
||||
0x03a61: (142, "FixedUint16ArrayMap"),
|
||||
0x03ab1: (141, "FixedInt16ArrayMap"),
|
||||
0x03b01: (144, "FixedUint32ArrayMap"),
|
||||
0x03b51: (143, "FixedInt32ArrayMap"),
|
||||
0x03ba1: (145, "FixedFloat32ArrayMap"),
|
||||
0x03bf1: (146, "FixedFloat64ArrayMap"),
|
||||
0x03c41: (147, "FixedUint8ClampedArrayMap"),
|
||||
0x03c91: (158, "ScriptMap"),
|
||||
0x03ce1: (182, "CodeDataContainerMap"),
|
||||
0x03d31: (173, "FeedbackVectorMap"),
|
||||
0x03d81: (171, "DebugEvaluateContextMap"),
|
||||
0x03dd1: (171, "ScriptContextTableMap"),
|
||||
0x03e21: (192, "ExternalMap"),
|
||||
0x03e71: (106, "NativeSourceStringMap"),
|
||||
0x03ec1: (165, "Tuple2Map"),
|
||||
0x03f11: (153, "InterceptorInfoMap"),
|
||||
0x03f61: (150, "AccessorInfoMap"),
|
||||
0x03fb1: (151, "AccessorPairMap"),
|
||||
0x04001: (152, "AccessCheckInfoMap"),
|
||||
0x04051: (154, "FunctionTemplateInfoMap"),
|
||||
0x040a1: (155, "ObjectTemplateInfoMap"),
|
||||
0x040f1: (156, "AllocationSiteMap"),
|
||||
0x04141: (157, "AllocationMementoMap"),
|
||||
0x04191: (159, "AliasedArgumentsEntryMap"),
|
||||
0x041e1: (160, "PromiseResolveThenableJobInfoMap"),
|
||||
0x04231: (161, "PromiseReactionJobInfoMap"),
|
||||
0x04281: (162, "DebugInfoMap"),
|
||||
0x042d1: (163, "StackFrameInfoMap"),
|
||||
0x04321: (164, "PrototypeInfoMap"),
|
||||
0x04371: (166, "Tuple3Map"),
|
||||
0x043c1: (167, "ContextExtensionMap"),
|
||||
0x04411: (168, "ModuleMap"),
|
||||
0x04461: (169, "ModuleInfoEntryMap"),
|
||||
0x044b1: (170, "AsyncGeneratorRequestMap"),
|
||||
}
|
||||
|
||||
# List of known V8 objects.
|
||||
|
Loading…
Reference in New Issue
Block a user