diff --git a/src/objects/value-serializer.cc b/src/objects/value-serializer.cc index c1cf33bb3d..3ca63f848c 100644 --- a/src/objects/value-serializer.cc +++ b/src/objects/value-serializer.cc @@ -418,7 +418,8 @@ Maybe ValueSerializer::WriteObject(Handle object) { } DCHECK(object->IsHeapObject()); - InstanceType instance_type = HeapObject::cast(*object).map().instance_type(); + InstanceType instance_type = + HeapObject::cast(*object).map(isolate_).instance_type(); switch (instance_type) { case ODDBALL_TYPE: WriteOddball(Oddball::cast(*object)); @@ -457,8 +458,7 @@ Maybe ValueSerializer::WriteObject(Handle object) { } else if (InstanceTypeChecker::IsJSReceiver(instance_type)) { return WriteJSReceiver(Handle::cast(object)); } else { - ThrowDataCloneError(MessageTemplate::kDataCloneError, object); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, object); } } } @@ -539,8 +539,7 @@ Maybe ValueSerializer::WriteJSReceiver(Handle receiver) { InstanceType instance_type = receiver->map().instance_type(); if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) && instance_type != JS_SPECIAL_API_OBJECT_TYPE)) { - ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); } // If we are at the end of the stack, abort. This function may recurse. @@ -563,7 +562,7 @@ Maybe ValueSerializer::WriteJSReceiver(Handle receiver) { case JS_TYPED_ARRAY_PROTOTYPE_TYPE: case JS_API_OBJECT_TYPE: { Handle js_object = Handle::cast(receiver); - if (JSObject::GetEmbedderFieldCount(js_object->map())) { + if (JSObject::GetEmbedderFieldCount(js_object->map(isolate_))) { return WriteHostObject(js_object); } else { return WriteJSObject(js_object); @@ -606,14 +605,13 @@ Maybe ValueSerializer::WriteJSReceiver(Handle receiver) { break; } - ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver); } Maybe ValueSerializer::WriteJSObject(Handle object) { DCHECK(!object->map().IsCustomElementsReceiverMap()); const bool can_serialize_fast = - object->HasFastProperties() && object->elements().length() == 0; + object->HasFastProperties(isolate_) && object->elements().length() == 0; if (!can_serialize_fast) return WriteJSObjectSlow(object); Handle map(object->map(), isolate_); @@ -625,7 +623,7 @@ Maybe ValueSerializer::WriteJSObject(Handle object) { bool map_changed = false; for (InternalIndex i : map->IterateOwnDescriptors()) { Handle key(map->instance_descriptors(isolate_).GetKey(i), isolate_); - if (!key->IsString()) continue; + if (!key->IsString(isolate_)) continue; PropertyDetails details = map->instance_descriptors(isolate_).GetDetails(i); if (details.IsDontEnum()) continue; @@ -794,24 +792,28 @@ void ValueSerializer::WriteJSDate(JSDate date) { Maybe ValueSerializer::WriteJSPrimitiveWrapper( Handle value) { - Object inner_value = value->value(); - if (inner_value.IsTrue(isolate_)) { - WriteTag(SerializationTag::kTrueObject); - } else if (inner_value.IsFalse(isolate_)) { - WriteTag(SerializationTag::kFalseObject); - } else if (inner_value.IsNumber()) { - WriteTag(SerializationTag::kNumberObject); - WriteDouble(inner_value.Number()); - } else if (inner_value.IsBigInt()) { - WriteTag(SerializationTag::kBigIntObject); - WriteBigIntContents(BigInt::cast(inner_value)); - } else if (inner_value.IsString()) { - WriteTag(SerializationTag::kStringObject); - WriteString(handle(String::cast(inner_value), isolate_)); - } else { - DCHECK(inner_value.IsSymbol()); - ThrowDataCloneError(MessageTemplate::kDataCloneError, value); - return Nothing(); + PtrComprCageBase cage_base(isolate_); + { + DisallowGarbageCollection no_gc; + Object inner_value = value->value(); + if (inner_value.IsTrue(isolate_)) { + WriteTag(SerializationTag::kTrueObject); + } else if (inner_value.IsFalse(isolate_)) { + WriteTag(SerializationTag::kFalseObject); + } else if (inner_value.IsNumber(cage_base)) { + WriteTag(SerializationTag::kNumberObject); + WriteDouble(inner_value.Number()); + } else if (inner_value.IsBigInt(cage_base)) { + WriteTag(SerializationTag::kBigIntObject); + WriteBigIntContents(BigInt::cast(inner_value)); + } else if (inner_value.IsString(cage_base)) { + WriteTag(SerializationTag::kStringObject); + WriteString(handle(String::cast(inner_value), isolate_)); + } else { + AllowGarbageCollection allow_gc; + DCHECK(inner_value.IsSymbol()); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, value); + } } return ThrowIfOutOfMemory(); } @@ -822,20 +824,22 @@ void ValueSerializer::WriteJSRegExp(Handle regexp) { WriteVarint(static_cast(regexp->flags())); } -Maybe ValueSerializer::WriteJSMap(Handle map) { +Maybe ValueSerializer::WriteJSMap(Handle js_map) { // First copy the key-value pairs, since getters could mutate them. - Handle table(OrderedHashMap::cast(map->table()), isolate_); + Handle table(OrderedHashMap::cast(js_map->table()), isolate_); int length = table->NumberOfElements() * 2; Handle entries = isolate_->factory()->NewFixedArray(length); { DisallowGarbageCollection no_gc; + OrderedHashMap raw_table = *table; + FixedArray raw_entries = *entries; Oddball the_hole = ReadOnlyRoots(isolate_).the_hole_value(); int result_index = 0; - for (InternalIndex entry : table->IterateEntries()) { - Object key = table->KeyAt(entry); + for (InternalIndex entry : raw_table.IterateEntries()) { + Object key = raw_table.KeyAt(entry); if (key == the_hole) continue; - entries->set(result_index++, key); - entries->set(result_index++, table->ValueAt(entry)); + raw_entries.set(result_index++, key); + raw_entries.set(result_index++, raw_table.ValueAt(entry)); } DCHECK_EQ(result_index, length); } @@ -852,19 +856,21 @@ Maybe ValueSerializer::WriteJSMap(Handle map) { return ThrowIfOutOfMemory(); } -Maybe ValueSerializer::WriteJSSet(Handle set) { +Maybe ValueSerializer::WriteJSSet(Handle js_set) { // First copy the element pointers, since getters could mutate them. - Handle table(OrderedHashSet::cast(set->table()), isolate_); + Handle table(OrderedHashSet::cast(js_set->table()), isolate_); int length = table->NumberOfElements(); Handle entries = isolate_->factory()->NewFixedArray(length); { DisallowGarbageCollection no_gc; + OrderedHashSet raw_table = *table; + FixedArray raw_entries = *entries; Oddball the_hole = ReadOnlyRoots(isolate_).the_hole_value(); int result_index = 0; - for (InternalIndex entry : table->IterateEntries()) { - Object key = table->KeyAt(entry); + for (InternalIndex entry : raw_table.IterateEntries()) { + Object key = raw_table.KeyAt(entry); if (key == the_hole) continue; - entries->set(result_index++, key); + raw_entries.set(result_index++, key); } DCHECK_EQ(result_index, length); } @@ -885,8 +891,8 @@ Maybe ValueSerializer::WriteJSArrayBuffer( Handle array_buffer) { if (array_buffer->is_shared()) { if (!delegate_) { - ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, + array_buffer); } v8::Isolate* v8_isolate = reinterpret_cast(isolate_); @@ -899,9 +905,8 @@ Maybe ValueSerializer::WriteJSArrayBuffer( return ThrowIfOutOfMemory(); } if (!array_buffer->is_detachable()) { - ThrowDataCloneError( + return ThrowDataCloneError( MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer); - return Nothing(); } uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); @@ -911,13 +916,12 @@ Maybe ValueSerializer::WriteJSArrayBuffer( return ThrowIfOutOfMemory(); } if (array_buffer->was_detached()) { - ThrowDataCloneError(MessageTemplate::kDataCloneErrorDetachedArrayBuffer); - return Nothing(); + return ThrowDataCloneError( + MessageTemplate::kDataCloneErrorDetachedArrayBuffer); } double byte_length = array_buffer->byte_length(); if (byte_length > std::numeric_limits::max()) { - ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); } WriteTag(SerializationTag::kArrayBuffer); WriteVarint(byte_length); @@ -1024,8 +1028,7 @@ Maybe ValueSerializer::WriteJSError(Handle error) { #if V8_ENABLE_WEBASSEMBLY Maybe ValueSerializer::WriteWasmModule(Handle object) { if (delegate_ == nullptr) { - ThrowDataCloneError(MessageTemplate::kDataCloneError, object); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, object); } // TODO(titzer): introduce a Utils::ToLocal for WasmModuleObject. @@ -1045,8 +1048,7 @@ Maybe ValueSerializer::WriteWasmModule(Handle object) { Maybe ValueSerializer::WriteWasmMemory(Handle object) { if (!object->array_buffer().is_shared()) { - ThrowDataCloneError(MessageTemplate::kDataCloneError, object); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneError, object); } GlobalBackingStoreRegistry::Register( @@ -1118,21 +1120,21 @@ Maybe ValueSerializer::WriteJSObjectPropertiesSlow( return Just(properties_written); } -void ValueSerializer::ThrowDataCloneError(MessageTemplate template_index) { - return ThrowDataCloneError(template_index, - isolate_->factory()->empty_string()); -} - Maybe ValueSerializer::ThrowIfOutOfMemory() { if (out_of_memory_) { - ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory); - return Nothing(); + return ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory); } return Just(true); } -void ValueSerializer::ThrowDataCloneError(MessageTemplate index, - Handle arg0) { +Maybe ValueSerializer::ThrowDataCloneError( + MessageTemplate template_index) { + return ThrowDataCloneError(template_index, + isolate_->factory()->empty_string()); +} + +Maybe ValueSerializer::ThrowDataCloneError(MessageTemplate index, + Handle arg0) { Handle message = MessageFormatter::Format(isolate_, index, arg0); if (delegate_) { delegate_->ThrowDataCloneError(Utils::ToLocal(message)); @@ -1143,6 +1145,7 @@ void ValueSerializer::ThrowDataCloneError(MessageTemplate index, if (isolate_->has_scheduled_exception()) { isolate_->PromoteScheduledException(); } + return Nothing(); } ValueDeserializer::ValueDeserializer(Isolate* isolate, @@ -1222,6 +1225,53 @@ Maybe ValueDeserializer::ReadVarint() { // most significant 7 bits. Each byte, except the last, has the MSB set. // If the varint is larger than T, any more significant bits are discarded. // See also https://developers.google.com/protocol-buffers/docs/encoding + static_assert(std::is_integral::value && std::is_unsigned::value, + "Only unsigned integer types can be read as varints."); + if (sizeof(T) > 4) return ReadVarintLoop(); + auto max_read_position = position_ + sizeof(T) + 1; + if (V8_UNLIKELY(max_read_position >= end_)) return ReadVarintLoop(); +#ifdef DEBUG + // DCHECK code to make sure the manually unrolled loop yields the exact + // same end state and result. + auto previous_position = position_; + T expected_value = ReadVarintLoop().ToChecked(); + auto expected_position = position_; + position_ = previous_position; +#endif // DEBUG +#define EXIT_DCHECK() \ + DCHECK_LE(position_, end_); \ + DCHECK_EQ(position_, expected_position); \ + DCHECK_EQ(value, expected_value) + + T value = 0; +#define ITERATION_SHIFTED(shift) \ + if (shift < sizeof(T) * 8) { \ + uint8_t byte = *position_; \ + position_++; \ + if (byte < 0x80) { \ + value |= static_cast(byte) << shift; \ + EXIT_DCHECK(); \ + return Just(value); \ + } else { \ + value |= static_cast(byte & 0x7F) << shift; \ + } \ + } + // Manually unroll the loop to achieve the best measured peformance. + // This is ~15% faster than ReadVarintLoop. + ITERATION_SHIFTED(0); + ITERATION_SHIFTED(7); + ITERATION_SHIFTED(14); + ITERATION_SHIFTED(21); + ITERATION_SHIFTED(28); + + EXIT_DCHECK(); + return Just(value); +#undef ITERATION_SHIFTED +#undef EXIT_DCHECK +} + +template +Maybe ValueDeserializer::ReadVarintLoop() { static_assert(std::is_integral::value && std::is_unsigned::value, "Only unsigned integer types can be read as varints."); T value = 0; @@ -1230,11 +1280,13 @@ Maybe ValueDeserializer::ReadVarint() { do { if (position_ >= end_) return Nothing(); uint8_t byte = *position_; + has_another_byte = byte & 0x80; if (V8_LIKELY(shift < sizeof(T) * 8)) { value |= static_cast(byte & 0x7F) << shift; shift += 7; + } else { + DCHECK(!has_another_byte); } - has_another_byte = byte & 0x80; position_++; } while (has_another_byte); return Just(value); @@ -1259,8 +1311,9 @@ template EXPORT_TEMPLATE_DEFINE( Maybe ValueDeserializer::ReadDouble() { // Warning: this uses host endianness. - if (sizeof(double) > static_cast(end_ - position_)) + if (sizeof(double) > static_cast(end_ - position_)) { return Nothing(); + } double value; memcpy(&value, position_, sizeof(double)); position_ += sizeof(double); @@ -1268,8 +1321,11 @@ Maybe ValueDeserializer::ReadDouble() { return Just(value); } -Maybe> ValueDeserializer::ReadRawBytes(int size) { - if (size > end_ - position_) return Nothing>(); +Maybe> ValueDeserializer::ReadRawBytes( + size_t size) { + if (size > static_cast(end_ - position_)) { + return Nothing>(); + } const uint8_t* start = position_; position_ += size; return Just(base::Vector(start, size)); @@ -1442,7 +1498,7 @@ MaybeHandle ValueDeserializer::ReadObjectInternal() { MaybeHandle ValueDeserializer::ReadString() { if (version_ < 12) return ReadUtf8String(); Handle object; - if (!ReadObject().ToHandle(&object) || !object->IsString()) { + if (!ReadObject().ToHandle(&object) || !object->IsString(isolate_)) { return MaybeHandle(); } return Handle::cast(object); @@ -1459,38 +1515,34 @@ MaybeHandle ValueDeserializer::ReadBigInt() { return BigInt::FromSerializedDigits(isolate_, bitfield, digits_storage); } -MaybeHandle ValueDeserializer::ReadUtf8String() { +MaybeHandle ValueDeserializer::ReadUtf8String( + AllocationType allocation) { uint32_t utf8_length; + if (!ReadVarint().To(&utf8_length)) return {}; + // utf8_length is checked in ReadRawBytes. base::Vector utf8_bytes; - if (!ReadVarint().To(&utf8_length) || - utf8_length > - static_cast(std::numeric_limits::max()) || - !ReadRawBytes(utf8_length).To(&utf8_bytes)) { - return MaybeHandle(); - } + if (!ReadRawBytes(utf8_length).To(&utf8_bytes)) return {}; return isolate_->factory()->NewStringFromUtf8( - base::Vector::cast(utf8_bytes)); + base::Vector::cast(utf8_bytes), allocation); } -MaybeHandle ValueDeserializer::ReadOneByteString() { +MaybeHandle ValueDeserializer::ReadOneByteString( + AllocationType allocation) { uint32_t byte_length; base::Vector bytes; - if (!ReadVarint().To(&byte_length) || - byte_length > - static_cast(std::numeric_limits::max()) || - !ReadRawBytes(byte_length).To(&bytes)) { - return MaybeHandle(); - } - return isolate_->factory()->NewStringFromOneByte(bytes); + if (!ReadVarint().To(&byte_length)) return {}; + // byte_length is checked in ReadRawBytes. + if (!ReadRawBytes(byte_length).To(&bytes)) return {}; + return isolate_->factory()->NewStringFromOneByte(bytes, allocation); } -MaybeHandle ValueDeserializer::ReadTwoByteString() { +MaybeHandle ValueDeserializer::ReadTwoByteString( + AllocationType allocation) { uint32_t byte_length; base::Vector bytes; - if (!ReadVarint().To(&byte_length) || - byte_length > - static_cast(std::numeric_limits::max()) || - byte_length % sizeof(base::uc16) != 0 || + if (!ReadVarint().To(&byte_length)) return {}; + // byte_length is checked in ReadRawBytes. + if (byte_length % sizeof(base::uc16) != 0 || !ReadRawBytes(byte_length).To(&bytes)) { return MaybeHandle(); } @@ -1500,7 +1552,7 @@ MaybeHandle ValueDeserializer::ReadTwoByteString() { if (byte_length == 0) return isolate_->factory()->empty_string(); Handle string; if (!isolate_->factory() - ->NewRawTwoByteString(byte_length / sizeof(base::uc16)) + ->NewRawTwoByteString(byte_length / sizeof(base::uc16), allocation) .ToHandle(&string)) { return MaybeHandle(); } @@ -1520,10 +1572,13 @@ bool ValueDeserializer::ReadExpectedString(Handle expected) { SerializationTag tag; uint32_t byte_length; base::Vector bytes; - if (!ReadTag().To(&tag) || !ReadVarint().To(&byte_length) || - byte_length > - static_cast(std::numeric_limits::max()) || - !ReadRawBytes(byte_length).To(&bytes)) { + if (!ReadTag().To(&tag) || !ReadVarint().To(&byte_length)) { + return {}; + } + // Length is also checked in ReadRawBytes. + DCHECK_LE(byte_length, + static_cast(std::numeric_limits::max())); + if (!ReadRawBytes(byte_length).To(&bytes)) { position_ = original_position; return false; } @@ -1631,6 +1686,7 @@ MaybeHandle ValueDeserializer::ReadDenseJSArray() { AddObjectWithID(id, array); Handle elements(FixedArray::cast(array->elements()), isolate_); + auto elements_length = static_cast(elements->length()); for (uint32_t i = 0; i < length; i++) { SerializationTag tag; if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) { @@ -1647,9 +1703,7 @@ MaybeHandle ValueDeserializer::ReadDenseJSArray() { if (version_ < 11 && element->IsUndefined(isolate_)) continue; // Safety check. - if (i >= static_cast(elements->length())) { - return MaybeHandle(); - } + if (i >= elements_length) return MaybeHandle(); elements->set(i, *element); } @@ -2127,8 +2181,11 @@ static void CommitProperties(Handle object, Handle map, } } -static bool IsValidObjectKey(Handle value) { - return value->IsName() || value->IsNumber(); +static bool IsValidObjectKey(Object value, Isolate* isolate) { + if (value.IsSmi()) return true; + auto instance_type = HeapObject::cast(value).map(isolate).instance_type(); + return InstanceTypeChecker::IsName(instance_type) || + InstanceTypeChecker::IsHeapNumber(instance_type); } Maybe ValueDeserializer::ReadJSObjectProperties( @@ -2167,10 +2224,10 @@ Maybe ValueDeserializer::ReadJSObjectProperties( key = expected_key; target = transitions.ExpectedTransitionTarget(); } else { - if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) { + if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(*key, isolate_)) { return Nothing(); } - if (key->IsString()) { + if (key->IsString(isolate_)) { key = isolate_->factory()->InternalizeString(Handle::cast(key)); // Don't reuse |transitions| because it could be stale. @@ -2251,7 +2308,7 @@ Maybe ValueDeserializer::ReadJSObjectProperties( } Handle key; - if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) { + if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(*key, isolate_)) { return Nothing(); } Handle value; @@ -2302,7 +2359,7 @@ static Maybe SetPropertiesFromKeyValuePairs(Isolate* isolate, uint32_t num_properties) { for (unsigned i = 0; i < 2 * num_properties; i += 2) { Handle key = data[i]; - if (!IsValidObjectKey(key)) return Nothing(); + if (!IsValidObjectKey(*key, isolate)) return Nothing(); Handle value = data[i + 1]; PropertyKey lookup_key(isolate, key); LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN); diff --git a/src/objects/value-serializer.h b/src/objects/value-serializer.h index 853b7168cb..a3ab32b2cd 100644 --- a/src/objects/value-serializer.h +++ b/src/objects/value-serializer.h @@ -153,9 +153,11 @@ class ValueSerializer { * Asks the delegate to handle an error that occurred during data cloning, by * throwing an exception appropriate for the host. */ - void ThrowDataCloneError(MessageTemplate template_index); - V8_NOINLINE void ThrowDataCloneError(MessageTemplate template_index, - Handle arg0); + V8_NOINLINE Maybe ThrowDataCloneError(MessageTemplate template_index) + V8_WARN_UNUSED_RESULT; + V8_NOINLINE Maybe ThrowDataCloneError(MessageTemplate template_index, + Handle arg0) + V8_WARN_UNUSED_RESULT; Maybe ThrowIfOutOfMemory(); @@ -243,11 +245,13 @@ class ValueDeserializer { void ConsumeTag(SerializationTag peeked_tag); Maybe ReadTag() V8_WARN_UNUSED_RESULT; template - Maybe ReadVarint() V8_WARN_UNUSED_RESULT; + V8_INLINE Maybe ReadVarint() V8_WARN_UNUSED_RESULT; + template + V8_NOINLINE Maybe ReadVarintLoop() V8_WARN_UNUSED_RESULT; template Maybe ReadZigZag() V8_WARN_UNUSED_RESULT; Maybe ReadDouble() V8_WARN_UNUSED_RESULT; - Maybe> ReadRawBytes(int size) + Maybe> ReadRawBytes(size_t size) V8_WARN_UNUSED_RESULT; // Reads a string if it matches the one provided. @@ -266,9 +270,12 @@ class ValueDeserializer { // Reading V8 objects of specific kinds. // The tag is assumed to have already been read. MaybeHandle ReadBigInt() V8_WARN_UNUSED_RESULT; - MaybeHandle ReadUtf8String() V8_WARN_UNUSED_RESULT; - MaybeHandle ReadOneByteString() V8_WARN_UNUSED_RESULT; - MaybeHandle ReadTwoByteString() V8_WARN_UNUSED_RESULT; + MaybeHandle ReadUtf8String( + AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT; + MaybeHandle ReadOneByteString( + AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT; + MaybeHandle ReadTwoByteString( + AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT; MaybeHandle ReadJSObject() V8_WARN_UNUSED_RESULT; MaybeHandle ReadSparseJSArray() V8_WARN_UNUSED_RESULT; MaybeHandle ReadDenseJSArray() V8_WARN_UNUSED_RESULT; diff --git a/src/web-snapshot/web-snapshot.cc b/src/web-snapshot/web-snapshot.cc index dd95d2a021..9e0620d84c 100644 --- a/src/web-snapshot/web-snapshot.cc +++ b/src/web-snapshot/web-snapshot.cc @@ -1239,7 +1239,8 @@ void WebSnapshotDeserializer::DeserializeStrings() { strings_handle_ = isolate_->factory()->NewFixedArray(string_count_); strings_ = *strings_handle_; for (uint32_t i = 0; i < string_count_; ++i) { - MaybeHandle maybe_string = deserializer_.ReadUtf8String(); + MaybeHandle maybe_string = + deserializer_.ReadUtf8String(AllocationType::kOld); Handle string; if (!maybe_string.ToHandle(&string)) { Throw("Malformed string"); @@ -1257,7 +1258,7 @@ String WebSnapshotDeserializer::ReadString(bool internalize) { return ReadOnlyRoots(isolate_).empty_string(); } String string = String::cast(strings_.get(string_id)); - if (internalize && !string.IsInternalizedString()) { + if (internalize && !string.IsInternalizedString(isolate_)) { string = *isolate_->factory()->InternalizeString(handle(string, isolate_)); strings_.set(string_id, string); }