From 7a77daf24344db7942e34c962b0f1ee729ab7af5 Mon Sep 17 00:00:00 2001 From: Michaƫl Zasso Date: Tue, 14 Feb 2017 11:27:26 +0100 Subject: deps: update V8 to 5.6.326.55 PR-URL: https://github.com/nodejs/node/pull/10992 Reviewed-By: Ben Noordhuis --- deps/v8/src/snapshot/code-serializer.cc | 30 ++++++++++++--- deps/v8/src/snapshot/code-serializer.h | 60 ++++++++++++++++-------------- deps/v8/src/snapshot/deserializer.cc | 32 ++++++++++++++-- deps/v8/src/snapshot/deserializer.h | 1 + deps/v8/src/snapshot/partial-serializer.cc | 48 ++++++++++++++++++++++-- deps/v8/src/snapshot/partial-serializer.h | 7 +++- deps/v8/src/snapshot/serializer-common.cc | 47 ++++++++++++----------- deps/v8/src/snapshot/serializer-common.h | 14 +++---- deps/v8/src/snapshot/serializer.cc | 6 +++ deps/v8/src/snapshot/startup-serializer.h | 13 ++++--- 10 files changed, 184 insertions(+), 74 deletions(-) (limited to 'deps/v8/src/snapshot') diff --git a/deps/v8/src/snapshot/code-serializer.cc b/deps/v8/src/snapshot/code-serializer.cc index 16044a5059..86a91643d2 100644 --- a/deps/v8/src/snapshot/code-serializer.cc +++ b/deps/v8/src/snapshot/code-serializer.cc @@ -12,6 +12,8 @@ #include "src/snapshot/deserializer.h" #include "src/snapshot/snapshot.h" #include "src/version.h" +#include "src/wasm/wasm-module.h" +#include "src/wasm/wasm-objects.h" namespace v8 { namespace internal { @@ -99,8 +101,8 @@ void CodeSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, } if (ElideObject(obj)) { - return SerializeObject(*isolate()->factory()->undefined_value(), - how_to_code, where_to_point, skip); + return SerializeObject(isolate()->heap()->undefined_value(), how_to_code, + where_to_point, skip); } // Past this point we should not see any (context-specific) maps anymore. CHECK(!obj->IsMap()); @@ -217,15 +219,19 @@ MaybeHandle CodeSerializer::Deserialize( } std::unique_ptr WasmCompiledModuleSerializer::SerializeWasmModule( - Isolate* isolate, Handle compiled_module) { + Isolate* isolate, Handle input) { + Handle compiled_module = + Handle::cast(input); WasmCompiledModuleSerializer wasm_cs(isolate, 0); wasm_cs.reference_map()->AddAttachedReference(*isolate->native_context()); + wasm_cs.reference_map()->AddAttachedReference( + *compiled_module->module_bytes()); ScriptData* data = wasm_cs.Serialize(compiled_module); return std::unique_ptr(data); } MaybeHandle WasmCompiledModuleSerializer::DeserializeWasmModule( - Isolate* isolate, ScriptData* data) { + Isolate* isolate, ScriptData* data, Vector wire_bytes) { SerializedCodeData::SanityCheckResult sanity_check_result = SerializedCodeData::CHECK_SUCCESS; MaybeHandle nothing; @@ -239,6 +245,15 @@ MaybeHandle WasmCompiledModuleSerializer::DeserializeWasmModule( Deserializer deserializer(&scd, true); deserializer.AddAttachedObject(isolate->native_context()); + MaybeHandle maybe_wire_bytes_as_string = + isolate->factory()->NewStringFromOneByte(wire_bytes, TENURED); + Handle wire_bytes_as_string; + if (!maybe_wire_bytes_as_string.ToHandle(&wire_bytes_as_string)) { + return nothing; + } + deserializer.AddAttachedObject( + handle(SeqOneByteString::cast(*wire_bytes_as_string))); + Vector stub_keys = scd.CodeStubKeys(); for (int i = 0; i < stub_keys.length(); ++i) { deserializer.AddAttachedObject( @@ -247,7 +262,11 @@ MaybeHandle WasmCompiledModuleSerializer::DeserializeWasmModule( MaybeHandle obj = deserializer.DeserializeObject(isolate); if (obj.is_null() || !obj.ToHandleChecked()->IsFixedArray()) return nothing; - return Handle::cast(obj.ToHandleChecked()); + Handle compiled_module = + Handle::cast(obj.ToHandleChecked()); + + WasmCompiledModule::RecreateModuleWrapper(isolate, compiled_module); + return compiled_module; } class Checksum { @@ -340,6 +359,7 @@ SerializedCodeData::SerializedCodeData(const List* payload, SerializedCodeData::SanityCheckResult SerializedCodeData::SanityCheck( Isolate* isolate, uint32_t expected_source_hash) const { + if (this->size_ < kHeaderSize) return INVALID_HEADER; uint32_t magic_number = GetMagicNumber(); if (magic_number != ComputeMagicNumber(isolate)) return MAGIC_NUMBER_MISMATCH; uint32_t version_hash = GetHeaderValue(kVersionHashOffset); diff --git a/deps/v8/src/snapshot/code-serializer.h b/deps/v8/src/snapshot/code-serializer.h index b3c54d1c84..15757379f0 100644 --- a/deps/v8/src/snapshot/code-serializer.h +++ b/deps/v8/src/snapshot/code-serializer.h @@ -59,8 +59,8 @@ class WasmCompiledModuleSerializer : public CodeSerializer { public: static std::unique_ptr SerializeWasmModule( Isolate* isolate, Handle compiled_module); - static MaybeHandle DeserializeWasmModule(Isolate* isolate, - ScriptData* data); + static MaybeHandle DeserializeWasmModule( + Isolate* isolate, ScriptData* data, Vector wire_bytes); protected: void SerializeCodeObject(Code* code_object, HowToCode how_to_code, @@ -74,7 +74,9 @@ class WasmCompiledModuleSerializer : public CodeSerializer { } } - bool ElideObject(Object* obj) override { return obj->IsWeakCell(); }; + bool ElideObject(Object* obj) override { + return obj->IsWeakCell() || obj->IsForeign(); + }; private: WasmCompiledModuleSerializer(Isolate* isolate, uint32_t source_hash) @@ -92,9 +94,35 @@ class SerializedCodeData : public SerializedData { SOURCE_MISMATCH = 3, CPU_FEATURES_MISMATCH = 4, FLAGS_MISMATCH = 5, - CHECKSUM_MISMATCH = 6 + CHECKSUM_MISMATCH = 6, + INVALID_HEADER = 7 }; + // The data header consists of uint32_t-sized entries: + // [0] magic number and external reference count + // [1] version hash + // [2] source hash + // [3] cpu features + // [4] flag hash + // [5] number of code stub keys + // [6] number of reservation size entries + // [7] payload length + // [8] payload checksum part 1 + // [9] payload checksum part 2 + // ... reservations + // ... code stub keys + // ... serialized payload + static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; + static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; + static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; + static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size; + static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size; + static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size; + static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size; + static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size; + static const int kChecksum2Offset = kChecksum1Offset + kInt32Size; + static const int kHeaderSize = kChecksum2Offset + kInt32Size; + // Used when consuming. static const SerializedCodeData FromCachedData( Isolate* isolate, ScriptData* cached_data, uint32_t expected_source_hash, @@ -124,30 +152,6 @@ class SerializedCodeData : public SerializedData { SanityCheckResult SanityCheck(Isolate* isolate, uint32_t expected_source_hash) const; - // The data header consists of uint32_t-sized entries: - // [0] magic number and external reference count - // [1] version hash - // [2] source hash - // [3] cpu features - // [4] flag hash - // [5] number of code stub keys - // [6] number of reservation size entries - // [7] payload length - // [8] payload checksum part 1 - // [9] payload checksum part 2 - // ... reservations - // ... code stub keys - // ... serialized payload - static const int kVersionHashOffset = kMagicNumberOffset + kInt32Size; - static const int kSourceHashOffset = kVersionHashOffset + kInt32Size; - static const int kCpuFeaturesOffset = kSourceHashOffset + kInt32Size; - static const int kFlagHashOffset = kCpuFeaturesOffset + kInt32Size; - static const int kNumReservationsOffset = kFlagHashOffset + kInt32Size; - static const int kNumCodeStubKeysOffset = kNumReservationsOffset + kInt32Size; - static const int kPayloadLengthOffset = kNumCodeStubKeysOffset + kInt32Size; - static const int kChecksum1Offset = kPayloadLengthOffset + kInt32Size; - static const int kChecksum2Offset = kChecksum1Offset + kInt32Size; - static const int kHeaderSize = kChecksum2Offset + kInt32Size; }; } // namespace internal diff --git a/deps/v8/src/snapshot/deserializer.cc b/deps/v8/src/snapshot/deserializer.cc index b90a2c5b10..aabd806b7a 100644 --- a/deps/v8/src/snapshot/deserializer.cc +++ b/deps/v8/src/snapshot/deserializer.cc @@ -99,7 +99,7 @@ void Deserializer::Deserialize(Isolate* isolate) { isolate_->heap()->undefined_value()); // The allocation site list is build during root iteration, but if no sites // were encountered then it needs to be initialized to undefined. - if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { + if (isolate_->heap()->allocation_sites_list() == Smi::kZero) { isolate_->heap()->set_allocation_sites_list( isolate_->heap()->undefined_value()); } @@ -128,6 +128,7 @@ MaybeHandle Deserializer::DeserializePartial( Object* root; VisitPointer(&root); DeserializeDeferredObjects(); + DeserializeInternalFields(); isolate->heap()->RegisterReservationsForBlackAllocation(reservations_); @@ -212,6 +213,31 @@ void Deserializer::DeserializeDeferredObjects() { } } +void Deserializer::DeserializeInternalFields() { + if (!source_.HasMore() || source_.Get() != kInternalFieldsData) return; + DisallowHeapAllocation no_gc; + DisallowJavascriptExecution no_js(isolate_); + DisallowCompilation no_compile(isolate_); + v8::DeserializeInternalFieldsCallback callback = + isolate_->deserialize_internal_fields_callback(); + DCHECK_NOT_NULL(callback); + for (int code = source_.Get(); code != kSynchronize; code = source_.Get()) { + HandleScope scope(isolate_); + int space = code & kSpaceMask; + DCHECK(space <= kNumberOfSpaces); + DCHECK(code - space == kNewObject); + Handle obj(JSObject::cast(GetBackReferencedObject(space)), + isolate_); + int index = source_.GetInt(); + int size = source_.GetInt(); + byte* data = new byte[size]; + source_.CopyRaw(data, size); + callback(v8::Utils::ToLocal(obj), index, + {reinterpret_cast(data), size}); + delete[] data; + } +} + // Used to insert a deserialized internalized string into the string table. class StringTableInsertionKey : public HashTableKey { public: @@ -277,7 +303,7 @@ HeapObject* Deserializer::PostProcessNewObject(HeapObject* obj, int space) { // TODO(mvstanton): consider treating the heap()->allocation_sites_list() // as a (weak) root. If this root is relocated correctly, this becomes // unnecessary. - if (isolate_->heap()->allocation_sites_list() == Smi::FromInt(0)) { + if (isolate_->heap()->allocation_sites_list() == Smi::kZero) { site->set_weak_next(isolate_->heap()->undefined_value()); } else { site->set_weak_next(isolate_->heap()->allocation_sites_list()); @@ -502,7 +528,7 @@ bool Deserializer::ReadData(Object** current, Object** limit, int source_space, int skip = source_.GetInt(); \ current = reinterpret_cast( \ reinterpret_cast
(current) + skip); \ - int reference_id = source_.GetInt(); \ + uint32_t reference_id = static_cast(source_.GetInt()); \ Address address = external_reference_table_->address(reference_id); \ new_object = reinterpret_cast(address); \ } else if (where == kAttachedReference) { \ diff --git a/deps/v8/src/snapshot/deserializer.h b/deps/v8/src/snapshot/deserializer.h index 634d80e3ab..db7996297d 100644 --- a/deps/v8/src/snapshot/deserializer.h +++ b/deps/v8/src/snapshot/deserializer.h @@ -88,6 +88,7 @@ class Deserializer : public SerializerDeserializer { } void DeserializeDeferredObjects(); + void DeserializeInternalFields(); void FlushICacheForNewIsolate(); void FlushICacheForNewCodeObjectsAndRecordEmbeddedObjects(); diff --git a/deps/v8/src/snapshot/partial-serializer.cc b/deps/v8/src/snapshot/partial-serializer.cc index b46f6755f0..e89f44f6e2 100644 --- a/deps/v8/src/snapshot/partial-serializer.cc +++ b/deps/v8/src/snapshot/partial-serializer.cc @@ -10,9 +10,12 @@ namespace v8 { namespace internal { -PartialSerializer::PartialSerializer(Isolate* isolate, - StartupSerializer* startup_serializer) - : Serializer(isolate), startup_serializer_(startup_serializer) { +PartialSerializer::PartialSerializer( + Isolate* isolate, StartupSerializer* startup_serializer, + v8::SerializeInternalFieldsCallback callback) + : Serializer(isolate), + startup_serializer_(startup_serializer), + serialize_internal_fields_(callback) { InitializeCodeAddressMap(); } @@ -33,10 +36,14 @@ void PartialSerializer::Serialize(Object** o) { context->set(Context::NEXT_CONTEXT_LINK, isolate_->heap()->undefined_value()); DCHECK(!context->global_object()->IsUndefined(context->GetIsolate())); + // 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()); } } VisitPointer(o); SerializeDeferredObjects(); + SerializeInternalFields(); Pad(); } @@ -93,6 +100,11 @@ void PartialSerializer::SerializeObject(HeapObject* obj, HowToCode how_to_code, function->ClearTypeFeedbackInfo(); } + if (obj->IsJSObject()) { + JSObject* jsobj = JSObject::cast(obj); + if (jsobj->GetInternalFieldCount() > 0) internal_field_holders_.Add(jsobj); + } + // Object has not yet been serialized. Serialize it here. ObjectSerializer serializer(this, obj, &sink_, how_to_code, where_to_point); serializer.Serialize(); @@ -106,9 +118,39 @@ bool PartialSerializer::ShouldBeInThePartialSnapshotCache(HeapObject* o) { DCHECK(!o->IsScript()); return o->IsName() || o->IsSharedFunctionInfo() || o->IsHeapNumber() || o->IsCode() || o->IsScopeInfo() || o->IsAccessorInfo() || + o->IsTemplateInfo() || o->map() == startup_serializer_->isolate()->heap()->fixed_cow_array_map(); } +void PartialSerializer::SerializeInternalFields() { + int count = internal_field_holders_.length(); + if (count == 0) return; + DisallowHeapAllocation no_gc; + DisallowJavascriptExecution no_js(isolate()); + DisallowCompilation no_compile(isolate()); + DCHECK_NOT_NULL(serialize_internal_fields_); + sink_.Put(kInternalFieldsData, "internal fields data"); + while (internal_field_holders_.length() > 0) { + HandleScope scope(isolate()); + Handle obj(internal_field_holders_.RemoveLast(), isolate()); + SerializerReference reference = reference_map_.Lookup(*obj); + DCHECK(reference.is_back_reference()); + int internal_fields_count = obj->GetInternalFieldCount(); + for (int i = 0; i < internal_fields_count; i++) { + if (obj->GetInternalField(i)->IsHeapObject()) continue; + StartupData data = serialize_internal_fields_(v8::Utils::ToLocal(obj), i); + sink_.Put(kNewObject + reference.space(), "internal field holder"); + PutBackReference(*obj, reference); + sink_.PutInt(i, "internal field index"); + sink_.PutInt(data.raw_size, "internal fields data size"); + sink_.PutRaw(reinterpret_cast(data.data), data.raw_size, + "internal fields data"); + delete[] data.data; + } + } + sink_.Put(kSynchronize, "Finished with internal fields data"); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/src/snapshot/partial-serializer.h b/deps/v8/src/snapshot/partial-serializer.h index 282f76e78f..45d64e431e 100644 --- a/deps/v8/src/snapshot/partial-serializer.h +++ b/deps/v8/src/snapshot/partial-serializer.h @@ -15,7 +15,8 @@ class StartupSerializer; class PartialSerializer : public Serializer { public: - PartialSerializer(Isolate* isolate, StartupSerializer* startup_serializer); + PartialSerializer(Isolate* isolate, StartupSerializer* startup_serializer, + v8::SerializeInternalFieldsCallback callback); ~PartialSerializer() override; @@ -28,7 +29,11 @@ class PartialSerializer : public Serializer { bool ShouldBeInThePartialSnapshotCache(HeapObject* o); + void SerializeInternalFields(); + StartupSerializer* startup_serializer_; + List internal_field_holders_; + v8::SerializeInternalFieldsCallback serialize_internal_fields_; DISALLOW_COPY_AND_ASSIGN(PartialSerializer); }; diff --git a/deps/v8/src/snapshot/serializer-common.cc b/deps/v8/src/snapshot/serializer-common.cc index adfd6e4f64..f188793419 100644 --- a/deps/v8/src/snapshot/serializer-common.cc +++ b/deps/v8/src/snapshot/serializer-common.cc @@ -13,37 +13,42 @@ namespace internal { ExternalReferenceEncoder::ExternalReferenceEncoder(Isolate* isolate) { map_ = isolate->external_reference_map(); - if (map_ != NULL) return; - map_ = new base::HashMap(); +#ifdef DEBUG + table_ = ExternalReferenceTable::instance(isolate); +#endif // DEBUG + if (map_ != nullptr) return; + map_ = new AddressToIndexHashMap(); ExternalReferenceTable* table = ExternalReferenceTable::instance(isolate); - for (int i = 0; i < table->size(); ++i) { + for (uint32_t i = 0; i < table->size(); ++i) { Address addr = table->address(i); - if (addr == ExternalReferenceTable::NotAvailable()) continue; - // We expect no duplicate external references entries in the table. - // AccessorRefTable getter may have duplicates, indicated by an empty string - // as name. - DCHECK(table->name(i)[0] == '\0' || - map_->Lookup(addr, Hash(addr)) == nullptr); - map_->LookupOrInsert(addr, Hash(addr))->value = reinterpret_cast(i); + DCHECK(map_->Get(addr).IsNothing() || + strncmp(table->name(i), "Redirect to ", 12) == 0); + map_->Set(addr, i); + DCHECK(map_->Get(addr).IsJust()); } isolate->set_external_reference_map(map_); } uint32_t ExternalReferenceEncoder::Encode(Address address) const { - DCHECK_NOT_NULL(address); - base::HashMap::Entry* entry = - const_cast(map_)->Lookup(address, Hash(address)); - DCHECK_NOT_NULL(entry); - return static_cast(reinterpret_cast(entry->value)); + Maybe maybe_index = map_->Get(address); + if (maybe_index.IsNothing()) { + void* addr = address; + v8::base::OS::PrintError("Unknown external reference %p.\n", addr); + v8::base::OS::PrintError("%s", ExternalReferenceTable::ResolveSymbol(addr)); + v8::base::OS::Abort(); + } +#ifdef DEBUG + table_->increment_count(maybe_index.FromJust()); +#endif // DEBUG + return maybe_index.FromJust(); } const char* ExternalReferenceEncoder::NameOfAddress(Isolate* isolate, Address address) const { - base::HashMap::Entry* entry = - const_cast(map_)->Lookup(address, Hash(address)); - if (entry == NULL) return ""; - uint32_t i = static_cast(reinterpret_cast(entry->value)); - return ExternalReferenceTable::instance(isolate)->name(i); + Maybe maybe_index = map_->Get(address); + if (maybe_index.IsNothing()) return ""; + return ExternalReferenceTable::instance(isolate)->name( + maybe_index.FromJust()); } void SerializedData::AllocateData(int size) { @@ -64,7 +69,7 @@ void SerializerDeserializer::Iterate(Isolate* isolate, ObjectVisitor* visitor) { List* cache = isolate->partial_snapshot_cache(); for (int i = 0;; ++i) { // Extend the array ready to get a value when deserializing. - if (cache->length() <= i) cache->Add(Smi::FromInt(0)); + if (cache->length() <= i) cache->Add(Smi::kZero); // During deserialization, the visitor populates the partial snapshot cache // and eventually terminates the cache with undefined. visitor->VisitPointer(&cache->at(i)); diff --git a/deps/v8/src/snapshot/serializer-common.h b/deps/v8/src/snapshot/serializer-common.h index 74b0218073..201ac4e039 100644 --- a/deps/v8/src/snapshot/serializer-common.h +++ b/deps/v8/src/snapshot/serializer-common.h @@ -23,12 +23,10 @@ class ExternalReferenceEncoder { const char* NameOfAddress(Isolate* isolate, Address address) const; private: - static uint32_t Hash(Address key) { - return static_cast(reinterpret_cast(key) >> - kPointerSizeLog2); - } - - base::HashMap* map_; + AddressToIndexHashMap* map_; +#ifdef DEBUG + ExternalReferenceTable* table_; +#endif // DEBUG DISALLOW_COPY_AND_ASSIGN(ExternalReferenceEncoder); }; @@ -172,6 +170,8 @@ class SerializerDeserializer : public ObjectVisitor { // Used for the source code for compiled stubs, which is in the executable, // but is referred to from external strings in the snapshot. static const int kExtraNativesStringResource = 0x1e; + // Used for embedder-provided serialization data for internal fields. + static const int kInternalFieldsData = 0x1f; // 8 hot (recently seen or back-referenced) objects with optional skip. static const int kNumberOfHotObjects = 8; @@ -182,7 +182,7 @@ class SerializerDeserializer : public ObjectVisitor { static const int kHotObjectWithSkip = 0x58; static const int kHotObjectMask = 0x07; - // 0x1f, 0x35..0x37, 0x55..0x57, 0x75..0x7f unused. + // 0x35..0x37, 0x55..0x57, 0x75..0x7f unused. // ---------- byte code range 0x80..0xff ---------- // First 32 root array items. diff --git a/deps/v8/src/snapshot/serializer.cc b/deps/v8/src/snapshot/serializer.cc index f622a5b8d2..2e971e3407 100644 --- a/deps/v8/src/snapshot/serializer.cc +++ b/deps/v8/src/snapshot/serializer.cc @@ -212,6 +212,11 @@ void Serializer::PutRoot(int root_index, HeapObject* object, PrintF("\n"); } + // Assert that the first 32 root array items are a conscious choice. They are + // chosen so that the most common ones can be encoded more efficiently. + STATIC_ASSERT(Heap::kEmptyDescriptorArrayRootIndex == + kNumberOfRootArrayConstants - 1); + if (how_to_code == kPlain && where_to_point == kStartOfObject && root_index < kNumberOfRootArrayConstants && !isolate()->heap()->InNewSpace(object)) { @@ -618,6 +623,7 @@ void Serializer::ObjectSerializer::VisitExternalReference(RelocInfo* rinfo) { sink_->Put(kExternalReference + how_to_code + kStartOfObject, "ExternalRef"); sink_->PutInt(skip, "SkipB4ExternalRef"); Address target = rinfo->target_external_reference(); + DCHECK_NOT_NULL(target); // Code does not reference null. sink_->PutInt(serializer_->EncodeExternalReference(target), "reference id"); bytes_processed_so_far_ += rinfo->target_address_size(); } diff --git a/deps/v8/src/snapshot/startup-serializer.h b/deps/v8/src/snapshot/startup-serializer.h index 9c1c3b904c..ac75c5d163 100644 --- a/deps/v8/src/snapshot/startup-serializer.h +++ b/deps/v8/src/snapshot/startup-serializer.h @@ -30,25 +30,26 @@ class StartupSerializer : public Serializer { int PartialSnapshotCacheIndex(HeapObject* o); private: - class PartialCacheIndexMap : public AddressMapBase { + class PartialCacheIndexMap { public: PartialCacheIndexMap() : map_(), next_index_(0) {} // Lookup object in the map. Return its index if found, or create // a new entry with new_index as value, and return kInvalidIndex. bool LookupOrInsert(HeapObject* obj, int* index_out) { - base::HashMap::Entry* entry = LookupEntry(&map_, obj, false); - if (entry != NULL) { - *index_out = GetValue(entry); + Maybe maybe_index = map_.Get(obj); + if (maybe_index.IsJust()) { + *index_out = maybe_index.FromJust(); return true; } *index_out = next_index_; - SetValue(LookupEntry(&map_, obj, true), next_index_++); + map_.Set(obj, next_index_++); return false; } private: - base::HashMap map_; + DisallowHeapAllocation no_allocation_; + HeapObjectToIndexHashMap map_; int next_index_; DISALLOW_COPY_AND_ASSIGN(PartialCacheIndexMap); -- cgit v1.2.3