[serializer][web snapshot] Speed up ValueDeserializer

- Unroll loop in ReadVarInt to skip checks for uncommon branches and
  improve by ~15%
- Use cage_base more aggressively
- Use more dehandlified code if possible
- Allow allocating strings directly in old-space to avoid filling up the
  new space when deserialising web-snapshots

Cleanup:
- ThrowDataCloneError now returns Nothing<bool>() for more consistency

Bug: v8:11525
Change-Id: I69ac635e2bcab83e92fba5ab34603146fa21f043
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3437049
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#78999}
This commit is contained in:
Camillo Bruni 2022-02-04 14:53:05 +01:00 committed by V8 LUCI CQ
parent 0823b36d35
commit 8d6e5bc9c7
3 changed files with 175 additions and 110 deletions

View File

@ -418,7 +418,8 @@ Maybe<bool> ValueSerializer::WriteObject(Handle<Object> 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<bool> ValueSerializer::WriteObject(Handle<Object> object) {
} else if (InstanceTypeChecker::IsJSReceiver(instance_type)) {
return WriteJSReceiver(Handle<JSReceiver>::cast(object));
} else {
ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
}
}
}
@ -539,8 +539,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> 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<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
}
// If we are at the end of the stack, abort. This function may recurse.
@ -563,7 +562,7 @@ Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
case JS_API_OBJECT_TYPE: {
Handle<JSObject> js_object = Handle<JSObject>::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<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
break;
}
ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, receiver);
}
Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> 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> map(object->map(), isolate_);
@ -625,7 +623,7 @@ Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) {
bool map_changed = false;
for (InternalIndex i : map->IterateOwnDescriptors()) {
Handle<Name> 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<bool> ValueSerializer::WriteJSPrimitiveWrapper(
Handle<JSPrimitiveWrapper> 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<bool>();
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<JSRegExp> regexp) {
WriteVarint(static_cast<uint32_t>(regexp->flags()));
}
Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> js_map) {
// First copy the key-value pairs, since getters could mutate them.
Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate_);
Handle<OrderedHashMap> table(OrderedHashMap::cast(js_map->table()), isolate_);
int length = table->NumberOfElements() * 2;
Handle<FixedArray> 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<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
return ThrowIfOutOfMemory();
}
Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) {
Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> js_set) {
// First copy the element pointers, since getters could mutate them.
Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate_);
Handle<OrderedHashSet> table(OrderedHashSet::cast(js_set->table()), isolate_);
int length = table->NumberOfElements();
Handle<FixedArray> 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<bool> ValueSerializer::WriteJSArrayBuffer(
Handle<JSArrayBuffer> array_buffer) {
if (array_buffer->is_shared()) {
if (!delegate_) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError,
array_buffer);
}
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
@ -899,9 +905,8 @@ Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
return ThrowIfOutOfMemory();
}
if (!array_buffer->is_detachable()) {
ThrowDataCloneError(
return ThrowDataCloneError(
MessageTemplate::kDataCloneErrorNonDetachableArrayBuffer);
return Nothing<bool>();
}
uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
@ -911,13 +916,12 @@ Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
return ThrowIfOutOfMemory();
}
if (array_buffer->was_detached()) {
ThrowDataCloneError(MessageTemplate::kDataCloneErrorDetachedArrayBuffer);
return Nothing<bool>();
return ThrowDataCloneError(
MessageTemplate::kDataCloneErrorDetachedArrayBuffer);
}
double byte_length = array_buffer->byte_length();
if (byte_length > std::numeric_limits<uint32_t>::max()) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
}
WriteTag(SerializationTag::kArrayBuffer);
WriteVarint<uint32_t>(byte_length);
@ -1024,8 +1028,7 @@ Maybe<bool> ValueSerializer::WriteJSError(Handle<JSObject> error) {
#if V8_ENABLE_WEBASSEMBLY
Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
if (delegate_ == nullptr) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
}
// TODO(titzer): introduce a Utils::ToLocal for WasmModuleObject.
@ -1045,8 +1048,7 @@ Maybe<bool> ValueSerializer::WriteWasmModule(Handle<WasmModuleObject> object) {
Maybe<bool> ValueSerializer::WriteWasmMemory(Handle<WasmMemoryObject> object) {
if (!object->array_buffer().is_shared()) {
ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
}
GlobalBackingStoreRegistry::Register(
@ -1118,21 +1120,21 @@ Maybe<uint32_t> ValueSerializer::WriteJSObjectPropertiesSlow(
return Just(properties_written);
}
void ValueSerializer::ThrowDataCloneError(MessageTemplate template_index) {
return ThrowDataCloneError(template_index,
isolate_->factory()->empty_string());
}
Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() {
if (out_of_memory_) {
ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
return Nothing<bool>();
return ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
}
return Just(true);
}
void ValueSerializer::ThrowDataCloneError(MessageTemplate index,
Handle<Object> arg0) {
Maybe<bool> ValueSerializer::ThrowDataCloneError(
MessageTemplate template_index) {
return ThrowDataCloneError(template_index,
isolate_->factory()->empty_string());
}
Maybe<bool> ValueSerializer::ThrowDataCloneError(MessageTemplate index,
Handle<Object> arg0) {
Handle<String> 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<bool>();
}
ValueDeserializer::ValueDeserializer(Isolate* isolate,
@ -1222,6 +1225,53 @@ Maybe<T> 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<T>::value && std::is_unsigned<T>::value,
"Only unsigned integer types can be read as varints.");
if (sizeof(T) > 4) return ReadVarintLoop<T>();
auto max_read_position = position_ + sizeof(T) + 1;
if (V8_UNLIKELY(max_read_position >= end_)) return ReadVarintLoop<T>();
#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<T>().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<T>(byte) << shift; \
EXIT_DCHECK(); \
return Just(value); \
} else { \
value |= static_cast<T>(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 <typename T>
Maybe<T> ValueDeserializer::ReadVarintLoop() {
static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
"Only unsigned integer types can be read as varints.");
T value = 0;
@ -1230,11 +1280,13 @@ Maybe<T> ValueDeserializer::ReadVarint() {
do {
if (position_ >= end_) return Nothing<T>();
uint8_t byte = *position_;
has_another_byte = byte & 0x80;
if (V8_LIKELY(shift < sizeof(T) * 8)) {
value |= static_cast<T>(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<double> ValueDeserializer::ReadDouble() {
// Warning: this uses host endianness.
if (sizeof(double) > static_cast<unsigned>(end_ - position_))
if (sizeof(double) > static_cast<unsigned>(end_ - position_)) {
return Nothing<double>();
}
double value;
memcpy(&value, position_, sizeof(double));
position_ += sizeof(double);
@ -1268,8 +1321,11 @@ Maybe<double> ValueDeserializer::ReadDouble() {
return Just(value);
}
Maybe<base::Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(int size) {
if (size > end_ - position_) return Nothing<base::Vector<const uint8_t>>();
Maybe<base::Vector<const uint8_t>> ValueDeserializer::ReadRawBytes(
size_t size) {
if (size > static_cast<size_t>(end_ - position_)) {
return Nothing<base::Vector<const uint8_t>>();
}
const uint8_t* start = position_;
position_ += size;
return Just(base::Vector<const uint8_t>(start, size));
@ -1442,7 +1498,7 @@ MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() {
MaybeHandle<String> ValueDeserializer::ReadString() {
if (version_ < 12) return ReadUtf8String();
Handle<Object> object;
if (!ReadObject().ToHandle(&object) || !object->IsString()) {
if (!ReadObject().ToHandle(&object) || !object->IsString(isolate_)) {
return MaybeHandle<String>();
}
return Handle<String>::cast(object);
@ -1459,38 +1515,34 @@ MaybeHandle<BigInt> ValueDeserializer::ReadBigInt() {
return BigInt::FromSerializedDigits(isolate_, bitfield, digits_storage);
}
MaybeHandle<String> ValueDeserializer::ReadUtf8String() {
MaybeHandle<String> ValueDeserializer::ReadUtf8String(
AllocationType allocation) {
uint32_t utf8_length;
if (!ReadVarint<uint32_t>().To(&utf8_length)) return {};
// utf8_length is checked in ReadRawBytes.
base::Vector<const uint8_t> utf8_bytes;
if (!ReadVarint<uint32_t>().To(&utf8_length) ||
utf8_length >
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
!ReadRawBytes(utf8_length).To(&utf8_bytes)) {
return MaybeHandle<String>();
}
if (!ReadRawBytes(utf8_length).To(&utf8_bytes)) return {};
return isolate_->factory()->NewStringFromUtf8(
base::Vector<const char>::cast(utf8_bytes));
base::Vector<const char>::cast(utf8_bytes), allocation);
}
MaybeHandle<String> ValueDeserializer::ReadOneByteString() {
MaybeHandle<String> ValueDeserializer::ReadOneByteString(
AllocationType allocation) {
uint32_t byte_length;
base::Vector<const uint8_t> bytes;
if (!ReadVarint<uint32_t>().To(&byte_length) ||
byte_length >
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
!ReadRawBytes(byte_length).To(&bytes)) {
return MaybeHandle<String>();
}
return isolate_->factory()->NewStringFromOneByte(bytes);
if (!ReadVarint<uint32_t>().To(&byte_length)) return {};
// byte_length is checked in ReadRawBytes.
if (!ReadRawBytes(byte_length).To(&bytes)) return {};
return isolate_->factory()->NewStringFromOneByte(bytes, allocation);
}
MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
MaybeHandle<String> ValueDeserializer::ReadTwoByteString(
AllocationType allocation) {
uint32_t byte_length;
base::Vector<const uint8_t> bytes;
if (!ReadVarint<uint32_t>().To(&byte_length) ||
byte_length >
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
byte_length % sizeof(base::uc16) != 0 ||
if (!ReadVarint<uint32_t>().To(&byte_length)) return {};
// byte_length is checked in ReadRawBytes.
if (byte_length % sizeof(base::uc16) != 0 ||
!ReadRawBytes(byte_length).To(&bytes)) {
return MaybeHandle<String>();
}
@ -1500,7 +1552,7 @@ MaybeHandle<String> ValueDeserializer::ReadTwoByteString() {
if (byte_length == 0) return isolate_->factory()->empty_string();
Handle<SeqTwoByteString> string;
if (!isolate_->factory()
->NewRawTwoByteString(byte_length / sizeof(base::uc16))
->NewRawTwoByteString(byte_length / sizeof(base::uc16), allocation)
.ToHandle(&string)) {
return MaybeHandle<String>();
}
@ -1520,10 +1572,13 @@ bool ValueDeserializer::ReadExpectedString(Handle<String> expected) {
SerializationTag tag;
uint32_t byte_length;
base::Vector<const uint8_t> bytes;
if (!ReadTag().To(&tag) || !ReadVarint<uint32_t>().To(&byte_length) ||
byte_length >
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) ||
!ReadRawBytes(byte_length).To(&bytes)) {
if (!ReadTag().To(&tag) || !ReadVarint<uint32_t>().To(&byte_length)) {
return {};
}
// Length is also checked in ReadRawBytes.
DCHECK_LE(byte_length,
static_cast<uint32_t>(std::numeric_limits<int32_t>::max()));
if (!ReadRawBytes(byte_length).To(&bytes)) {
position_ = original_position;
return false;
}
@ -1631,6 +1686,7 @@ MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
AddObjectWithID(id, array);
Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_);
auto elements_length = static_cast<uint32_t>(elements->length());
for (uint32_t i = 0; i < length; i++) {
SerializationTag tag;
if (PeekTag().To(&tag) && tag == SerializationTag::kTheHole) {
@ -1647,9 +1703,7 @@ MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() {
if (version_ < 11 && element->IsUndefined(isolate_)) continue;
// Safety check.
if (i >= static_cast<uint32_t>(elements->length())) {
return MaybeHandle<JSArray>();
}
if (i >= elements_length) return MaybeHandle<JSArray>();
elements->set(i, *element);
}
@ -2127,8 +2181,11 @@ static void CommitProperties(Handle<JSObject> object, Handle<Map> map,
}
}
static bool IsValidObjectKey(Handle<Object> 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<uint32_t> ValueDeserializer::ReadJSObjectProperties(
@ -2167,10 +2224,10 @@ Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
key = expected_key;
target = transitions.ExpectedTransitionTarget();
} else {
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(*key, isolate_)) {
return Nothing<uint32_t>();
}
if (key->IsString()) {
if (key->IsString(isolate_)) {
key =
isolate_->factory()->InternalizeString(Handle<String>::cast(key));
// Don't reuse |transitions| because it could be stale.
@ -2251,7 +2308,7 @@ Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties(
}
Handle<Object> key;
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(key)) {
if (!ReadObject().ToHandle(&key) || !IsValidObjectKey(*key, isolate_)) {
return Nothing<uint32_t>();
}
Handle<Object> value;
@ -2302,7 +2359,7 @@ static Maybe<bool> SetPropertiesFromKeyValuePairs(Isolate* isolate,
uint32_t num_properties) {
for (unsigned i = 0; i < 2 * num_properties; i += 2) {
Handle<Object> key = data[i];
if (!IsValidObjectKey(key)) return Nothing<bool>();
if (!IsValidObjectKey(*key, isolate)) return Nothing<bool>();
Handle<Object> value = data[i + 1];
PropertyKey lookup_key(isolate, key);
LookupIterator it(isolate, object, lookup_key, LookupIterator::OWN);

View File

@ -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<Object> arg0);
V8_NOINLINE Maybe<bool> ThrowDataCloneError(MessageTemplate template_index)
V8_WARN_UNUSED_RESULT;
V8_NOINLINE Maybe<bool> ThrowDataCloneError(MessageTemplate template_index,
Handle<Object> arg0)
V8_WARN_UNUSED_RESULT;
Maybe<bool> ThrowIfOutOfMemory();
@ -243,11 +245,13 @@ class ValueDeserializer {
void ConsumeTag(SerializationTag peeked_tag);
Maybe<SerializationTag> ReadTag() V8_WARN_UNUSED_RESULT;
template <typename T>
Maybe<T> ReadVarint() V8_WARN_UNUSED_RESULT;
V8_INLINE Maybe<T> ReadVarint() V8_WARN_UNUSED_RESULT;
template <typename T>
V8_NOINLINE Maybe<T> ReadVarintLoop() V8_WARN_UNUSED_RESULT;
template <typename T>
Maybe<T> ReadZigZag() V8_WARN_UNUSED_RESULT;
Maybe<double> ReadDouble() V8_WARN_UNUSED_RESULT;
Maybe<base::Vector<const uint8_t>> ReadRawBytes(int size)
Maybe<base::Vector<const uint8_t>> 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<BigInt> ReadBigInt() V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadUtf8String() V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadOneByteString() V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadTwoByteString() V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadUtf8String(
AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadOneByteString(
AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT;
MaybeHandle<String> ReadTwoByteString(
AllocationType allocation = AllocationType::kYoung) V8_WARN_UNUSED_RESULT;
MaybeHandle<JSObject> ReadJSObject() V8_WARN_UNUSED_RESULT;
MaybeHandle<JSArray> ReadSparseJSArray() V8_WARN_UNUSED_RESULT;
MaybeHandle<JSArray> ReadDenseJSArray() V8_WARN_UNUSED_RESULT;

View File

@ -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<String> maybe_string = deserializer_.ReadUtf8String();
MaybeHandle<String> maybe_string =
deserializer_.ReadUtf8String(AllocationType::kOld);
Handle<String> 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);
}