OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/value-serializer.h" | 5 #include "src/value-serializer.h" |
6 | 6 |
7 #include <type_traits> | 7 #include <type_traits> |
8 | 8 |
9 #include "src/base/logging.h" | 9 #include "src/base/logging.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 kUint16Array = 'W', | 117 kUint16Array = 'W', |
118 kInt32Array = 'd', | 118 kInt32Array = 'd', |
119 kUint32Array = 'D', | 119 kUint32Array = 'D', |
120 kFloat32Array = 'f', | 120 kFloat32Array = 'f', |
121 kFloat64Array = 'F', | 121 kFloat64Array = 'F', |
122 kDataView = '?', | 122 kDataView = '?', |
123 }; | 123 }; |
124 | 124 |
125 } // namespace | 125 } // namespace |
126 | 126 |
| 127 struct ValueSerializer::State { |
| 128 enum Kind { |
| 129 kJSObjectPropertiesSlow, |
| 130 kDenseArrayElementsSlow, |
| 131 kDenseArrayPropertiesSlow, |
| 132 kSparseArrayPropertiesSlow, |
| 133 kJSMap, |
| 134 kJSSet, |
| 135 }; |
| 136 Kind kind; |
| 137 uint32_t index; |
| 138 uint32_t array_length; |
| 139 uint32_t properties_written; |
| 140 Handle<JSObject> receiver; |
| 141 Handle<FixedArray> data; |
| 142 }; |
| 143 |
127 ValueSerializer::ValueSerializer(Isolate* isolate) | 144 ValueSerializer::ValueSerializer(Isolate* isolate) |
128 : isolate_(isolate), | 145 : isolate_(isolate), |
129 zone_(isolate->allocator()), | 146 zone_(isolate->allocator()), |
130 id_map_(isolate->heap(), &zone_), | 147 id_map_(isolate->heap(), &zone_), |
131 array_buffer_transfer_map_(isolate->heap(), &zone_) {} | 148 array_buffer_transfer_map_(isolate->heap(), &zone_), |
| 149 states_(&zone_) {} |
132 | 150 |
133 ValueSerializer::~ValueSerializer() {} | 151 ValueSerializer::~ValueSerializer() {} |
134 | 152 |
135 void ValueSerializer::WriteHeader() { | 153 void ValueSerializer::WriteHeader() { |
136 WriteTag(SerializationTag::kVersion); | 154 WriteTag(SerializationTag::kVersion); |
137 WriteVarint(kLatestVersion); | 155 WriteVarint(kLatestVersion); |
138 } | 156 } |
139 | 157 |
140 void ValueSerializer::WriteTag(SerializationTag tag) { | 158 void ValueSerializer::WriteTag(SerializationTag tag) { |
141 buffer_.push_back(static_cast<uint8_t>(tag)); | 159 buffer_.push_back(static_cast<uint8_t>(tag)); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 buffer_.resize(buffer_.size() + bytes); | 220 buffer_.resize(buffer_.size() + bytes); |
203 return &buffer_[old_size]; | 221 return &buffer_[old_size]; |
204 } | 222 } |
205 | 223 |
206 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, | 224 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, |
207 Handle<JSArrayBuffer> array_buffer) { | 225 Handle<JSArrayBuffer> array_buffer) { |
208 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); | 226 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); |
209 array_buffer_transfer_map_.Set(array_buffer, transfer_id); | 227 array_buffer_transfer_map_.Set(array_buffer, transfer_id); |
210 } | 228 } |
211 | 229 |
212 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 230 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> outer_object) { |
| 231 size_t stack_size = states_.size(); |
| 232 if (!WriteObjectInternal(outer_object).FromMaybe(false)) { |
| 233 return Nothing<bool>(); |
| 234 } |
| 235 while (states_.size() > stack_size) { |
| 236 // Warning: it is illegal to access |state| after invoking |
| 237 // WriteObjectInternal, because the vector may have reallocated. |
| 238 size_t state_index = states_.size() - 1; |
| 239 State& state = states_[state_index]; |
| 240 |
| 241 switch (state.kind) { |
| 242 case State::kJSObjectPropertiesSlow: |
| 243 case State::kDenseArrayPropertiesSlow: |
| 244 case State::kSparseArrayPropertiesSlow: { |
| 245 Handle<FixedArray> keys = state.data; |
| 246 if (state.index >= keys->length()) { |
| 247 DCHECK_EQ(state.index, keys->length()); |
| 248 if (state.kind == State::kJSObjectPropertiesSlow) { |
| 249 WriteTag(SerializationTag::kEndJSObject); |
| 250 WriteVarint<uint32_t>(state.properties_written); |
| 251 } else if (state.kind == State::kDenseArrayPropertiesSlow) { |
| 252 WriteTag(SerializationTag::kEndDenseJSArray); |
| 253 WriteVarint<uint32_t>(state.properties_written); |
| 254 WriteVarint<uint32_t>(state.array_length); |
| 255 } else if (state.kind == State::kSparseArrayPropertiesSlow) { |
| 256 WriteTag(SerializationTag::kEndSparseJSArray); |
| 257 WriteVarint<uint32_t>(state.properties_written); |
| 258 WriteVarint<uint32_t>(state.array_length); |
| 259 } |
| 260 states_.pop_back(); |
| 261 continue; |
| 262 } |
| 263 |
| 264 Handle<Object> key(keys->get(state.index++), isolate_); |
| 265 bool success; |
| 266 LookupIterator it = LookupIterator::PropertyOrElement( |
| 267 isolate_, state.receiver, key, &success, LookupIterator::OWN); |
| 268 DCHECK(success); |
| 269 Handle<Object> value; |
| 270 if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<bool>(); |
| 271 |
| 272 // If the property is no longer found, do not serialize it. |
| 273 // This could happen if a getter deleted the property. |
| 274 if (!it.IsFound()) continue; |
| 275 |
| 276 if (!WriteObjectInternal(key).FromMaybe(false)) return Nothing<bool>(); |
| 277 DCHECK_EQ(states_.size(), state_index + 1); |
| 278 if (!WriteObjectInternal(value).FromMaybe(false)) { |
| 279 return Nothing<bool>(); |
| 280 } |
| 281 states_[state_index].properties_written++; |
| 282 break; |
| 283 } |
| 284 case State::kDenseArrayElementsSlow: { |
| 285 if (state.index >= state.array_length) { |
| 286 DCHECK_EQ(state.index, state.array_length); |
| 287 state.kind = State::kDenseArrayPropertiesSlow; |
| 288 state.index = 0; |
| 289 continue; |
| 290 } |
| 291 LookupIterator it(isolate_, state.receiver, state.index++, |
| 292 state.receiver, LookupIterator::OWN); |
| 293 Handle<Object> element; |
| 294 if (!Object::GetProperty(&it).ToHandle(&element) || |
| 295 !WriteObjectInternal(element).FromMaybe(false)) { |
| 296 return Nothing<bool>(); |
| 297 } |
| 298 break; |
| 299 } |
| 300 case State::kJSMap: |
| 301 case State::kJSSet: { |
| 302 Handle<FixedArray> collection = state.data; |
| 303 if (state.index >= collection->length()) { |
| 304 DCHECK_EQ(state.index, collection->length()); |
| 305 WriteTag(state.kind == State::kJSMap ? SerializationTag::kEndJSMap |
| 306 : SerializationTag::kEndJSSet); |
| 307 WriteVarint<uint32_t>(collection->length()); |
| 308 states_.pop_back(); |
| 309 continue; |
| 310 } |
| 311 Handle<Object> value(collection->get(state.index++), isolate_); |
| 312 if (!WriteObjectInternal(value).FromMaybe(false)) { |
| 313 return Nothing<bool>(); |
| 314 } |
| 315 break; |
| 316 } |
| 317 } |
| 318 } |
| 319 DCHECK_EQ(states_.size(), stack_size); |
| 320 return Just(true); |
| 321 } |
| 322 |
| 323 Maybe<bool> ValueSerializer::WriteObjectInternal(Handle<Object> object) { |
213 if (object->IsSmi()) { | 324 if (object->IsSmi()) { |
214 WriteSmi(Smi::cast(*object)); | 325 WriteSmi(Smi::cast(*object)); |
215 return Just(true); | 326 return Just(true); |
216 } | 327 } |
217 | 328 |
218 DCHECK(object->IsHeapObject()); | 329 DCHECK(object->IsHeapObject()); |
219 switch (HeapObject::cast(*object)->map()->instance_type()) { | 330 switch (HeapObject::cast(*object)->map()->instance_type()) { |
220 case ODDBALL_TYPE: | 331 case ODDBALL_TYPE: |
221 WriteOddball(Oddball::cast(*object)); | 332 WriteOddball(Oddball::cast(*object)); |
222 return Just(true); | 333 return Just(true); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 | 447 |
337 // Eliminate callable and exotic objects, which should not be serialized. | 448 // Eliminate callable and exotic objects, which should not be serialized. |
338 InstanceType instance_type = receiver->map()->instance_type(); | 449 InstanceType instance_type = receiver->map()->instance_type(); |
339 if (receiver->IsCallable() || instance_type <= LAST_SPECIAL_RECEIVER_TYPE) { | 450 if (receiver->IsCallable() || instance_type <= LAST_SPECIAL_RECEIVER_TYPE) { |
340 return Nothing<bool>(); | 451 return Nothing<bool>(); |
341 } | 452 } |
342 | 453 |
343 // If we are at the end of the stack, abort. This function may recurse. | 454 // If we are at the end of the stack, abort. This function may recurse. |
344 if (StackLimitCheck(isolate_).HasOverflowed()) return Nothing<bool>(); | 455 if (StackLimitCheck(isolate_).HasOverflowed()) return Nothing<bool>(); |
345 | 456 |
346 HandleScope scope(isolate_); | |
347 switch (instance_type) { | 457 switch (instance_type) { |
348 case JS_ARRAY_TYPE: | 458 case JS_ARRAY_TYPE: |
349 return WriteJSArray(Handle<JSArray>::cast(receiver)); | 459 return WriteJSArray(Handle<JSArray>::cast(receiver)); |
350 case JS_OBJECT_TYPE: | 460 case JS_OBJECT_TYPE: |
351 case JS_API_OBJECT_TYPE: | 461 case JS_API_OBJECT_TYPE: |
352 return WriteJSObject(Handle<JSObject>::cast(receiver)); | 462 return WriteJSObject(Handle<JSObject>::cast(receiver)); |
353 case JS_DATE_TYPE: | 463 case JS_DATE_TYPE: |
354 WriteJSDate(JSDate::cast(*receiver)); | 464 WriteJSDate(JSDate::cast(*receiver)); |
355 return Just(true); | 465 return Just(true); |
356 case JS_VALUE_TYPE: | 466 case JS_VALUE_TYPE: |
(...skipping 13 matching lines...) Expand all Loading... |
370 default: | 480 default: |
371 UNIMPLEMENTED(); | 481 UNIMPLEMENTED(); |
372 break; | 482 break; |
373 } | 483 } |
374 return Nothing<bool>(); | 484 return Nothing<bool>(); |
375 } | 485 } |
376 | 486 |
377 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { | 487 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { |
378 WriteTag(SerializationTag::kBeginJSObject); | 488 WriteTag(SerializationTag::kBeginJSObject); |
379 Handle<FixedArray> keys; | 489 Handle<FixedArray> keys; |
380 uint32_t properties_written; | |
381 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, | 490 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, |
382 ENUMERABLE_STRINGS) | 491 ENUMERABLE_STRINGS) |
383 .ToHandle(&keys) || | 492 .ToHandle(&keys)) { |
384 !WriteJSObjectProperties(object, keys).To(&properties_written)) { | |
385 return Nothing<bool>(); | 493 return Nothing<bool>(); |
386 } | 494 } |
387 WriteTag(SerializationTag::kEndJSObject); | 495 states_.push_back({State::kJSObjectPropertiesSlow, 0, 0, 0, object, keys}); |
388 WriteVarint<uint32_t>(properties_written); | |
389 return Just(true); | 496 return Just(true); |
390 } | 497 } |
391 | 498 |
392 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) { | 499 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) { |
393 uint32_t length = 0; | 500 uint32_t length = 0; |
394 bool valid_length = array->length()->ToArrayLength(&length); | 501 bool valid_length = array->length()->ToArrayLength(&length); |
395 DCHECK(valid_length); | 502 DCHECK(valid_length); |
396 USE(valid_length); | 503 USE(valid_length); |
397 | 504 |
398 // To keep things simple, for now we decide between dense and sparse | 505 // To keep things simple, for now we decide between dense and sparse |
399 // serialization based on elements kind. A more principled heuristic could | 506 // serialization based on elements kind. A more principled heuristic could |
400 // count the elements, but would need to take care to note which indices | 507 // count the elements, but would need to take care to note which indices |
401 // existed (as only indices which were enumerable own properties at this point | 508 // existed (as only indices which were enumerable own properties at this point |
402 // should be serialized). | 509 // should be serialized). |
403 const bool should_serialize_densely = | 510 const bool should_serialize_densely = |
404 array->HasFastElements() && !array->HasFastHoleyElements(); | 511 array->HasFastElements() && !array->HasFastHoleyElements(); |
405 | 512 |
406 if (should_serialize_densely) { | 513 if (should_serialize_densely) { |
407 // TODO(jbroman): Distinguish between undefined and a hole (this can happen | 514 // TODO(jbroman): Distinguish between undefined and a hole (this can happen |
408 // if serializing one of the elements deletes another). This requires wire | 515 // if serializing one of the elements deletes another). This requires wire |
409 // format changes. | 516 // format changes. |
410 WriteTag(SerializationTag::kBeginDenseJSArray); | 517 WriteTag(SerializationTag::kBeginDenseJSArray); |
411 WriteVarint<uint32_t>(length); | 518 WriteVarint<uint32_t>(length); |
412 for (uint32_t i = 0; i < length; i++) { | |
413 // Serializing the array's elements can have arbitrary side effects, so we | |
414 // cannot rely on still having fast elements, even if it did to begin | |
415 // with. | |
416 Handle<Object> element; | |
417 LookupIterator it(isolate_, array, i, array, LookupIterator::OWN); | |
418 if (!Object::GetProperty(&it).ToHandle(&element) || | |
419 !WriteObject(element).FromMaybe(false)) { | |
420 return Nothing<bool>(); | |
421 } | |
422 } | |
423 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly, | 519 KeyAccumulator accumulator(isolate_, KeyCollectionMode::kOwnOnly, |
424 ENUMERABLE_STRINGS); | 520 ENUMERABLE_STRINGS); |
425 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) { | 521 if (!accumulator.CollectOwnPropertyNames(array, array).FromMaybe(false)) { |
426 return Nothing<bool>(); | 522 return Nothing<bool>(); |
427 } | 523 } |
428 Handle<FixedArray> keys = | 524 Handle<FixedArray> keys = |
429 accumulator.GetKeys(GetKeysConversion::kConvertToString); | 525 accumulator.GetKeys(GetKeysConversion::kConvertToString); |
430 uint32_t properties_written; | 526 states_.push_back( |
431 if (!WriteJSObjectProperties(array, keys).To(&properties_written)) { | 527 {State::kDenseArrayElementsSlow, 0, length, 0, array, keys}); |
432 return Nothing<bool>(); | |
433 } | |
434 WriteTag(SerializationTag::kEndDenseJSArray); | |
435 WriteVarint<uint32_t>(properties_written); | |
436 WriteVarint<uint32_t>(length); | |
437 } else { | 528 } else { |
438 WriteTag(SerializationTag::kBeginSparseJSArray); | 529 WriteTag(SerializationTag::kBeginSparseJSArray); |
439 WriteVarint<uint32_t>(length); | 530 WriteVarint<uint32_t>(length); |
440 Handle<FixedArray> keys; | 531 Handle<FixedArray> keys; |
441 uint32_t properties_written; | 532 uint32_t properties_written; |
442 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly, | 533 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly, |
443 ENUMERABLE_STRINGS) | 534 ENUMERABLE_STRINGS) |
444 .ToHandle(&keys) || | 535 .ToHandle(&keys)) { |
445 !WriteJSObjectProperties(array, keys).To(&properties_written)) { | |
446 return Nothing<bool>(); | 536 return Nothing<bool>(); |
447 } | 537 } |
448 WriteTag(SerializationTag::kEndSparseJSArray); | 538 states_.push_back( |
449 WriteVarint<uint32_t>(properties_written); | 539 {State::kSparseArrayPropertiesSlow, 0, length, 0, array, keys}); |
450 WriteVarint<uint32_t>(length); | |
451 } | 540 } |
452 return Just(true); | 541 return Just(true); |
453 } | 542 } |
454 | 543 |
455 void ValueSerializer::WriteJSDate(JSDate* date) { | 544 void ValueSerializer::WriteJSDate(JSDate* date) { |
456 WriteTag(SerializationTag::kDate); | 545 WriteTag(SerializationTag::kDate); |
457 WriteDouble(date->value()->Number()); | 546 WriteDouble(date->value()->Number()); |
458 } | 547 } |
459 | 548 |
460 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { | 549 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 int capacity = table->UsedCapacity(); | 595 int capacity = table->UsedCapacity(); |
507 int result_index = 0; | 596 int result_index = 0; |
508 for (int i = 0; i < capacity; i++) { | 597 for (int i = 0; i < capacity; i++) { |
509 Object* key = table->KeyAt(i); | 598 Object* key = table->KeyAt(i); |
510 if (key == the_hole) continue; | 599 if (key == the_hole) continue; |
511 entries->set(result_index++, key); | 600 entries->set(result_index++, key); |
512 entries->set(result_index++, table->ValueAt(i)); | 601 entries->set(result_index++, table->ValueAt(i)); |
513 } | 602 } |
514 DCHECK_EQ(result_index, length); | 603 DCHECK_EQ(result_index, length); |
515 } | 604 } |
516 | |
517 // Then write it out. | |
518 WriteTag(SerializationTag::kBeginJSMap); | 605 WriteTag(SerializationTag::kBeginJSMap); |
519 for (int i = 0; i < length; i++) { | 606 states_.push_back({State::kJSMap, 0, 0, 0, map, entries}); |
520 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | |
521 return Nothing<bool>(); | |
522 } | |
523 } | |
524 WriteTag(SerializationTag::kEndJSMap); | |
525 WriteVarint<uint32_t>(length); | |
526 return Just(true); | 607 return Just(true); |
527 } | 608 } |
528 | 609 |
529 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { | 610 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { |
530 // First copy the element pointers, since getters could mutate them. | 611 // First copy the element pointers, since getters could mutate them. |
531 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); | 612 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); |
532 int length = table->NumberOfElements(); | 613 int length = table->NumberOfElements(); |
533 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); | 614 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); |
534 { | 615 { |
535 DisallowHeapAllocation no_gc; | 616 DisallowHeapAllocation no_gc; |
536 Oddball* the_hole = isolate_->heap()->the_hole_value(); | 617 Oddball* the_hole = isolate_->heap()->the_hole_value(); |
537 int capacity = table->UsedCapacity(); | 618 int capacity = table->UsedCapacity(); |
538 int result_index = 0; | 619 int result_index = 0; |
539 for (int i = 0; i < capacity; i++) { | 620 for (int i = 0; i < capacity; i++) { |
540 Object* key = table->KeyAt(i); | 621 Object* key = table->KeyAt(i); |
541 if (key == the_hole) continue; | 622 if (key == the_hole) continue; |
542 entries->set(result_index++, key); | 623 entries->set(result_index++, key); |
543 } | 624 } |
544 DCHECK_EQ(result_index, length); | 625 DCHECK_EQ(result_index, length); |
545 } | 626 } |
546 | |
547 // Then write it out. | |
548 WriteTag(SerializationTag::kBeginJSSet); | 627 WriteTag(SerializationTag::kBeginJSSet); |
549 for (int i = 0; i < length; i++) { | 628 states_.push_back({State::kJSSet, 0, 0, 0, set, entries}); |
550 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { | |
551 return Nothing<bool>(); | |
552 } | |
553 } | |
554 WriteTag(SerializationTag::kEndJSSet); | |
555 WriteVarint<uint32_t>(length); | |
556 return Just(true); | 629 return Just(true); |
557 } | 630 } |
558 | 631 |
559 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { | 632 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(JSArrayBuffer* array_buffer) { |
560 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); | 633 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); |
561 if (transfer_entry) { | 634 if (transfer_entry) { |
562 DCHECK(array_buffer->was_neutered() || array_buffer->is_shared()); | 635 DCHECK(array_buffer->was_neutered() || array_buffer->is_shared()); |
563 WriteTag(array_buffer->is_shared() | 636 WriteTag(array_buffer->is_shared() |
564 ? SerializationTag::kSharedArrayBufferTransfer | 637 ? SerializationTag::kSharedArrayBufferTransfer |
565 : SerializationTag::kArrayBufferTransfer); | 638 : SerializationTag::kArrayBufferTransfer); |
(...skipping 28 matching lines...) Expand all Loading... |
594 } else { | 667 } else { |
595 DCHECK(view->IsJSDataView()); | 668 DCHECK(view->IsJSDataView()); |
596 tag = ArrayBufferViewTag::kDataView; | 669 tag = ArrayBufferViewTag::kDataView; |
597 } | 670 } |
598 WriteVarint(static_cast<uint8_t>(tag)); | 671 WriteVarint(static_cast<uint8_t>(tag)); |
599 WriteVarint(NumberToUint32(view->byte_offset())); | 672 WriteVarint(NumberToUint32(view->byte_offset())); |
600 WriteVarint(NumberToUint32(view->byte_length())); | 673 WriteVarint(NumberToUint32(view->byte_length())); |
601 return Just(true); | 674 return Just(true); |
602 } | 675 } |
603 | 676 |
604 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 677 struct ValueDeserializer::State { |
605 Handle<JSObject> object, Handle<FixedArray> keys) { | 678 enum Kind { |
606 uint32_t properties_written = 0; | 679 kJSObjectProperties, |
607 int length = keys->length(); | 680 kDenseArrayElements, |
608 for (int i = 0; i < length; i++) { | 681 kDenseArrayProperties, |
609 Handle<Object> key(keys->get(i), isolate_); | 682 kSparseArrayProperties, |
610 | 683 kJSMapKey, |
611 bool success; | 684 kJSMapValue, |
612 LookupIterator it = LookupIterator::PropertyOrElement( | 685 kJSSet, |
613 isolate_, object, key, &success, LookupIterator::OWN); | 686 }; |
614 DCHECK(success); | 687 Kind kind; |
615 Handle<Object> value; | 688 uint32_t index; |
616 if (!Object::GetProperty(&it).ToHandle(&value)) return Nothing<uint32_t>(); | 689 uint32_t array_length; |
617 | 690 uint32_t num_properties; |
618 // If the property is no longer found, do not serialize it. | 691 Handle<JSObject> receiver; |
619 // This could happen if a getter deleted the property. | 692 Handle<Object> elements_or_function; |
620 if (!it.IsFound()) continue; | 693 Handle<Object> map_key; |
621 | 694 }; |
622 if (!WriteObject(key).FromMaybe(false) || | |
623 !WriteObject(value).FromMaybe(false)) { | |
624 return Nothing<uint32_t>(); | |
625 } | |
626 | |
627 properties_written++; | |
628 } | |
629 return Just(properties_written); | |
630 } | |
631 | 695 |
632 ValueDeserializer::ValueDeserializer(Isolate* isolate, | 696 ValueDeserializer::ValueDeserializer(Isolate* isolate, |
633 Vector<const uint8_t> data) | 697 Vector<const uint8_t> data) |
634 : isolate_(isolate), | 698 : isolate_(isolate), |
635 position_(data.start()), | 699 position_(data.start()), |
636 end_(data.start() + data.length()), | 700 end_(data.start() + data.length()), |
637 id_map_(Handle<SeededNumberDictionary>::cast( | 701 id_map_(Handle<SeededNumberDictionary>::cast( |
638 isolate->global_handles()->Create( | 702 isolate->global_handles()->Create( |
639 *SeededNumberDictionary::New(isolate, 0)))) {} | 703 *SeededNumberDictionary::New(isolate, 0)))) {} |
640 | 704 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer, | 818 SeededNumberDictionary::AtNumberPut(dictionary, transfer_id, array_buffer, |
755 used_as_prototype); | 819 used_as_prototype); |
756 if (!new_dictionary.is_identical_to(dictionary)) { | 820 if (!new_dictionary.is_identical_to(dictionary)) { |
757 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location()); | 821 GlobalHandles::Destroy(Handle<Object>::cast(dictionary).location()); |
758 array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast( | 822 array_buffer_transfer_map_ = Handle<SeededNumberDictionary>::cast( |
759 isolate_->global_handles()->Create(*new_dictionary)); | 823 isolate_->global_handles()->Create(*new_dictionary)); |
760 } | 824 } |
761 } | 825 } |
762 | 826 |
763 MaybeHandle<Object> ValueDeserializer::ReadObject() { | 827 MaybeHandle<Object> ValueDeserializer::ReadObject() { |
764 MaybeHandle<Object> result = ReadObjectInternal(); | 828 size_t stack_size = states_.size(); |
| 829 Handle<Object> result; |
| 830 if (!ReadObjectInternal().ToHandle(&result)) return MaybeHandle<Object>(); |
765 | 831 |
766 // ArrayBufferView is special in that it consumes the value before it, even | 832 while (states_.size() > stack_size) { |
767 // after format version 0. | 833 size_t state_index = states_.size() - 1; |
768 Handle<Object> object; | 834 State& state = states_[state_index]; |
769 SerializationTag tag; | 835 switch (state.kind) { |
770 if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) && | 836 case State::kJSObjectProperties: |
771 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) { | 837 case State::kDenseArrayProperties: |
772 ConsumeTag(SerializationTag::kArrayBufferView); | 838 case State::kSparseArrayProperties: { |
773 result = ReadJSArrayBufferView(Handle<JSArrayBuffer>::cast(object)); | 839 SerializationTag tag; |
| 840 if (!PeekTag().To(&tag)) return MaybeHandle<Object>(); |
| 841 const SerializationTag expected_tag = |
| 842 state.kind == State::kDenseArrayProperties |
| 843 ? SerializationTag::kEndDenseJSArray |
| 844 : state.kind == State::kSparseArrayProperties |
| 845 ? SerializationTag::kEndSparseJSArray |
| 846 : SerializationTag::kEndJSObject; |
| 847 if (tag == expected_tag) { |
| 848 ConsumeTag(expected_tag); |
| 849 uint32_t expected_num_properties; |
| 850 if (!ReadVarint<uint32_t>().To(&expected_num_properties) || |
| 851 state.num_properties != expected_num_properties) { |
| 852 return MaybeHandle<Object>(); |
| 853 } |
| 854 if (tag != SerializationTag::kEndJSObject) { |
| 855 uint32_t expected_length; |
| 856 if (!ReadVarint<uint32_t>().To(&expected_length) || |
| 857 state.array_length != expected_length) { |
| 858 return MaybeHandle<Object>(); |
| 859 } |
| 860 } |
| 861 states_.pop_back(); |
| 862 continue; |
| 863 } |
| 864 state.num_properties++; |
| 865 Handle<Object> receiver = state.receiver; |
| 866 Handle<Object> key; |
| 867 Handle<Object> value; |
| 868 if (!ReadObjectInternal().ToHandle(&key)) return MaybeHandle<Object>(); |
| 869 DCHECK_EQ(states_.size(), state_index + 1); |
| 870 if (!ReadObjectInternal().ToHandle(&value)) { |
| 871 return MaybeHandle<Object>(); |
| 872 } |
| 873 |
| 874 bool success; |
| 875 LookupIterator it = LookupIterator::PropertyOrElement( |
| 876 isolate_, receiver, key, &success, LookupIterator::OWN); |
| 877 if (!success || |
| 878 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE) |
| 879 .is_null()) { |
| 880 return MaybeHandle<Object>(); |
| 881 } |
| 882 break; |
| 883 } |
| 884 case State::kDenseArrayElements: { |
| 885 if (state.index >= state.array_length) { |
| 886 DCHECK_EQ(state.index, state.array_length); |
| 887 state.kind = State::kDenseArrayProperties; |
| 888 state.index = 0; |
| 889 continue; |
| 890 } |
| 891 Handle<FixedArray> elements = |
| 892 Handle<FixedArray>::cast(state.elements_or_function); |
| 893 uint32_t index = state.index++; |
| 894 Handle<Object> element; |
| 895 if (!ReadObjectInternal().ToHandle(&element)) { |
| 896 return MaybeHandle<Object>(); |
| 897 } |
| 898 // TODO(jbroman): Distinguish between undefined and a hole. |
| 899 if (element->IsUndefined(isolate_)) continue; |
| 900 elements->set(index, *element); |
| 901 break; |
| 902 } |
| 903 case State::kJSMapKey: { |
| 904 SerializationTag tag; |
| 905 if (!PeekTag().To(&tag)) return MaybeHandle<Object>(); |
| 906 if (tag == SerializationTag::kEndJSMap) { |
| 907 ConsumeTag(SerializationTag::kEndJSMap); |
| 908 uint32_t expected_length; |
| 909 if (!ReadVarint<uint32_t>().To(&expected_length) || |
| 910 state.index != expected_length) { |
| 911 return MaybeHandle<Object>(); |
| 912 } |
| 913 states_.pop_back(); |
| 914 continue; |
| 915 } |
| 916 state.index++; |
| 917 Handle<Object> key; |
| 918 if (!ReadObjectInternal().ToHandle(&key)) return MaybeHandle<Object>(); |
| 919 State& new_state = states_[state_index]; |
| 920 new_state.kind = State::kJSMapValue; |
| 921 new_state.map_key = key; |
| 922 break; |
| 923 } |
| 924 case State::kJSMapValue: { |
| 925 state.index++; |
| 926 Handle<JSFunction> map_set = |
| 927 Handle<JSFunction>::cast(state.elements_or_function); |
| 928 Handle<JSMap> map = Handle<JSMap>::cast(state.receiver); |
| 929 Handle<Object> argv[2] = {state.map_key, Handle<Object>()}; |
| 930 state.kind = State::kJSMapKey; |
| 931 state.map_key = Handle<Object>(); |
| 932 if (!ReadObjectInternal().ToHandle(&argv[1]) || |
| 933 Execution::Call(isolate_, map_set, map, arraysize(argv), argv) |
| 934 .is_null()) { |
| 935 return MaybeHandle<Object>(); |
| 936 } |
| 937 break; |
| 938 } |
| 939 case State::kJSSet: { |
| 940 SerializationTag tag; |
| 941 if (!PeekTag().To(&tag)) return MaybeHandle<Object>(); |
| 942 if (tag == SerializationTag::kEndJSSet) { |
| 943 ConsumeTag(SerializationTag::kEndJSSet); |
| 944 uint32_t expected_length; |
| 945 if (!ReadVarint<uint32_t>().To(&expected_length) || |
| 946 state.index != expected_length) { |
| 947 return MaybeHandle<Object>(); |
| 948 } |
| 949 states_.pop_back(); |
| 950 continue; |
| 951 } |
| 952 state.index++; |
| 953 Handle<JSFunction> set_add = |
| 954 Handle<JSFunction>::cast(state.elements_or_function); |
| 955 Handle<JSSet> set = Handle<JSSet>::cast(state.receiver); |
| 956 Handle<Object> argv[1]; |
| 957 if (!ReadObjectInternal().ToHandle(&argv[0]) || |
| 958 Execution::Call(isolate_, set_add, set, arraysize(argv), argv) |
| 959 .is_null()) { |
| 960 return MaybeHandle<Object>(); |
| 961 } |
| 962 break; |
| 963 } |
| 964 } |
774 } | 965 } |
775 | 966 DCHECK_EQ(states_.size(), stack_size); |
776 return result; | 967 return result; |
777 } | 968 } |
778 | 969 |
779 MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() { | 970 MaybeHandle<Object> ValueDeserializer::ReadObjectInternal() { |
| 971 MaybeHandle<Object> result; |
780 SerializationTag tag; | 972 SerializationTag tag; |
781 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); | 973 if (!ReadTag().To(&tag)) return MaybeHandle<Object>(); |
782 switch (tag) { | 974 switch (tag) { |
783 case SerializationTag::kVerifyObjectCount: | 975 case SerializationTag::kVerifyObjectCount: |
784 // Read the count and ignore it. | 976 // Read the count and ignore it. |
785 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); | 977 if (ReadVarint<uint32_t>().IsNothing()) return MaybeHandle<Object>(); |
786 return ReadObject(); | 978 result = ReadObject(); |
| 979 break; |
787 case SerializationTag::kUndefined: | 980 case SerializationTag::kUndefined: |
788 return isolate_->factory()->undefined_value(); | 981 return isolate_->factory()->undefined_value(); |
789 case SerializationTag::kNull: | 982 case SerializationTag::kNull: |
790 return isolate_->factory()->null_value(); | 983 return isolate_->factory()->null_value(); |
791 case SerializationTag::kTrue: | 984 case SerializationTag::kTrue: |
792 return isolate_->factory()->true_value(); | 985 return isolate_->factory()->true_value(); |
793 case SerializationTag::kFalse: | 986 case SerializationTag::kFalse: |
794 return isolate_->factory()->false_value(); | 987 return isolate_->factory()->false_value(); |
795 case SerializationTag::kInt32: { | 988 case SerializationTag::kInt32: { |
796 Maybe<int32_t> number = ReadZigZag<int32_t>(); | 989 Maybe<int32_t> number = ReadZigZag<int32_t>(); |
(...skipping 10 matching lines...) Expand all Loading... |
807 if (number.IsNothing()) return MaybeHandle<Object>(); | 1000 if (number.IsNothing()) return MaybeHandle<Object>(); |
808 return isolate_->factory()->NewNumber(number.FromJust()); | 1001 return isolate_->factory()->NewNumber(number.FromJust()); |
809 } | 1002 } |
810 case SerializationTag::kUtf8String: | 1003 case SerializationTag::kUtf8String: |
811 return ReadUtf8String(); | 1004 return ReadUtf8String(); |
812 case SerializationTag::kTwoByteString: | 1005 case SerializationTag::kTwoByteString: |
813 return ReadTwoByteString(); | 1006 return ReadTwoByteString(); |
814 case SerializationTag::kObjectReference: { | 1007 case SerializationTag::kObjectReference: { |
815 uint32_t id; | 1008 uint32_t id; |
816 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>(); | 1009 if (!ReadVarint<uint32_t>().To(&id)) return MaybeHandle<Object>(); |
817 return GetObjectWithID(id); | 1010 result = GetObjectWithID(id); |
| 1011 break; |
818 } | 1012 } |
819 case SerializationTag::kBeginJSObject: | 1013 case SerializationTag::kBeginJSObject: |
820 return ReadJSObject(); | 1014 return ReadJSObject(); |
821 case SerializationTag::kBeginSparseJSArray: | 1015 case SerializationTag::kBeginSparseJSArray: |
822 return ReadSparseJSArray(); | 1016 return ReadSparseJSArray(); |
823 case SerializationTag::kBeginDenseJSArray: | 1017 case SerializationTag::kBeginDenseJSArray: |
824 return ReadDenseJSArray(); | 1018 return ReadDenseJSArray(); |
825 case SerializationTag::kDate: | 1019 case SerializationTag::kDate: |
826 return ReadJSDate(); | 1020 return ReadJSDate(); |
827 case SerializationTag::kTrueObject: | 1021 case SerializationTag::kTrueObject: |
828 case SerializationTag::kFalseObject: | 1022 case SerializationTag::kFalseObject: |
829 case SerializationTag::kNumberObject: | 1023 case SerializationTag::kNumberObject: |
830 case SerializationTag::kStringObject: | 1024 case SerializationTag::kStringObject: |
831 return ReadJSValue(tag); | 1025 return ReadJSValue(tag); |
832 case SerializationTag::kRegExp: | 1026 case SerializationTag::kRegExp: |
833 return ReadJSRegExp(); | 1027 return ReadJSRegExp(); |
834 case SerializationTag::kBeginJSMap: | 1028 case SerializationTag::kBeginJSMap: |
835 return ReadJSMap(); | 1029 return ReadJSMap(); |
836 case SerializationTag::kBeginJSSet: | 1030 case SerializationTag::kBeginJSSet: |
837 return ReadJSSet(); | 1031 return ReadJSSet(); |
838 case SerializationTag::kArrayBuffer: | 1032 case SerializationTag::kArrayBuffer: |
839 return ReadJSArrayBuffer(); | 1033 result = ReadJSArrayBuffer(); |
| 1034 break; |
840 case SerializationTag::kArrayBufferTransfer: { | 1035 case SerializationTag::kArrayBufferTransfer: { |
841 const bool is_shared = false; | 1036 const bool is_shared = false; |
842 return ReadTransferredJSArrayBuffer(is_shared); | 1037 result = ReadTransferredJSArrayBuffer(is_shared); |
| 1038 break; |
843 } | 1039 } |
844 case SerializationTag::kSharedArrayBufferTransfer: { | 1040 case SerializationTag::kSharedArrayBufferTransfer: { |
845 const bool is_shared = true; | 1041 const bool is_shared = true; |
846 return ReadTransferredJSArrayBuffer(is_shared); | 1042 result = ReadTransferredJSArrayBuffer(is_shared); |
| 1043 break; |
847 } | 1044 } |
848 default: | 1045 default: |
849 return MaybeHandle<Object>(); | 1046 return MaybeHandle<Object>(); |
850 } | 1047 } |
| 1048 |
| 1049 // ArrayBufferView is special in that it consumes the value before it, even |
| 1050 // after format version 0. |
| 1051 Handle<Object> object; |
| 1052 if (result.ToHandle(&object) && V8_UNLIKELY(object->IsJSArrayBuffer()) && |
| 1053 PeekTag().To(&tag) && tag == SerializationTag::kArrayBufferView) { |
| 1054 ConsumeTag(SerializationTag::kArrayBufferView); |
| 1055 return ReadJSArrayBufferView(Handle<JSArrayBuffer>::cast(object)); |
| 1056 } |
| 1057 |
| 1058 return result; |
851 } | 1059 } |
852 | 1060 |
853 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 1061 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
854 uint32_t utf8_length; | 1062 uint32_t utf8_length; |
855 Vector<const uint8_t> utf8_bytes; | 1063 Vector<const uint8_t> utf8_bytes; |
856 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 1064 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
857 utf8_length > | 1065 utf8_length > |
858 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || | 1066 static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) || |
859 !ReadRawBytes(utf8_length).To(&utf8_bytes)) | 1067 !ReadRawBytes(utf8_length).To(&utf8_bytes)) |
860 return MaybeHandle<String>(); | 1068 return MaybeHandle<String>(); |
(...skipping 18 matching lines...) Expand all Loading... |
879 .ToHandle(&string)) | 1087 .ToHandle(&string)) |
880 return MaybeHandle<String>(); | 1088 return MaybeHandle<String>(); |
881 | 1089 |
882 // Copy the bytes directly into the new string. | 1090 // Copy the bytes directly into the new string. |
883 // Warning: this uses host endianness. | 1091 // Warning: this uses host endianness. |
884 memcpy(string->GetChars(), bytes.begin(), bytes.length()); | 1092 memcpy(string->GetChars(), bytes.begin(), bytes.length()); |
885 return string; | 1093 return string; |
886 } | 1094 } |
887 | 1095 |
888 MaybeHandle<JSObject> ValueDeserializer::ReadJSObject() { | 1096 MaybeHandle<JSObject> ValueDeserializer::ReadJSObject() { |
889 // If we are at the end of the stack, abort. This function may recurse. | |
890 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSObject>(); | |
891 | |
892 uint32_t id = next_id_++; | 1097 uint32_t id = next_id_++; |
893 HandleScope scope(isolate_); | |
894 Handle<JSObject> object = | 1098 Handle<JSObject> object = |
895 isolate_->factory()->NewJSObject(isolate_->object_function()); | 1099 isolate_->factory()->NewJSObject(isolate_->object_function()); |
896 AddObjectWithID(id, object); | 1100 AddObjectWithID(id, object); |
897 | 1101 states_.push_back({State::kJSObjectProperties, 0, 0, 0, object, |
898 uint32_t num_properties; | 1102 Handle<FixedArray>(), Handle<Object>()}); |
899 uint32_t expected_num_properties; | 1103 return object; |
900 if (!ReadJSObjectProperties(object, SerializationTag::kEndJSObject) | |
901 .To(&num_properties) || | |
902 !ReadVarint<uint32_t>().To(&expected_num_properties) || | |
903 num_properties != expected_num_properties) { | |
904 return MaybeHandle<JSObject>(); | |
905 } | |
906 | |
907 DCHECK(HasObjectWithID(id)); | |
908 return scope.CloseAndEscape(object); | |
909 } | 1104 } |
910 | 1105 |
911 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() { | 1106 MaybeHandle<JSArray> ValueDeserializer::ReadSparseJSArray() { |
912 // If we are at the end of the stack, abort. This function may recurse. | |
913 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSArray>(); | |
914 | |
915 uint32_t length; | 1107 uint32_t length; |
916 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>(); | 1108 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>(); |
917 | 1109 |
918 uint32_t id = next_id_++; | 1110 uint32_t id = next_id_++; |
919 HandleScope scope(isolate_); | |
920 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); | 1111 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); |
921 JSArray::SetLength(array, length); | 1112 JSArray::SetLength(array, length); |
922 AddObjectWithID(id, array); | 1113 AddObjectWithID(id, array); |
923 | 1114 states_.push_back({State::kSparseArrayProperties, 0, length, 0, array, |
924 uint32_t num_properties; | 1115 Handle<FixedArray>(), Handle<Object>()}); |
925 uint32_t expected_num_properties; | 1116 return array; |
926 uint32_t expected_length; | |
927 if (!ReadJSObjectProperties(array, SerializationTag::kEndSparseJSArray) | |
928 .To(&num_properties) || | |
929 !ReadVarint<uint32_t>().To(&expected_num_properties) || | |
930 !ReadVarint<uint32_t>().To(&expected_length) || | |
931 num_properties != expected_num_properties || length != expected_length) { | |
932 return MaybeHandle<JSArray>(); | |
933 } | |
934 | |
935 DCHECK(HasObjectWithID(id)); | |
936 return scope.CloseAndEscape(array); | |
937 } | 1117 } |
938 | 1118 |
939 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() { | 1119 MaybeHandle<JSArray> ValueDeserializer::ReadDenseJSArray() { |
940 // If we are at the end of the stack, abort. This function may recurse. | |
941 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSArray>(); | |
942 | |
943 uint32_t length; | 1120 uint32_t length; |
944 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>(); | 1121 if (!ReadVarint<uint32_t>().To(&length)) return MaybeHandle<JSArray>(); |
945 | 1122 |
946 uint32_t id = next_id_++; | 1123 uint32_t id = next_id_++; |
947 HandleScope scope(isolate_); | |
948 Handle<JSArray> array = isolate_->factory()->NewJSArray( | 1124 Handle<JSArray> array = isolate_->factory()->NewJSArray( |
949 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); | 1125 FAST_HOLEY_ELEMENTS, length, length, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); |
950 AddObjectWithID(id, array); | 1126 AddObjectWithID(id, array); |
951 | 1127 |
952 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_); | 1128 Handle<FixedArray> elements(FixedArray::cast(array->elements()), isolate_); |
953 for (uint32_t i = 0; i < length; i++) { | 1129 states_.push_back({State::kDenseArrayElements, 0, length, 0, array, elements, |
954 Handle<Object> element; | 1130 Handle<Object>()}); |
955 if (!ReadObject().ToHandle(&element)) return MaybeHandle<JSArray>(); | 1131 return array; |
956 // TODO(jbroman): Distinguish between undefined and a hole. | |
957 if (element->IsUndefined(isolate_)) continue; | |
958 elements->set(i, *element); | |
959 } | |
960 | |
961 uint32_t num_properties; | |
962 uint32_t expected_num_properties; | |
963 uint32_t expected_length; | |
964 if (!ReadJSObjectProperties(array, SerializationTag::kEndDenseJSArray) | |
965 .To(&num_properties) || | |
966 !ReadVarint<uint32_t>().To(&expected_num_properties) || | |
967 !ReadVarint<uint32_t>().To(&expected_length) || | |
968 num_properties != expected_num_properties || length != expected_length) { | |
969 return MaybeHandle<JSArray>(); | |
970 } | |
971 | |
972 DCHECK(HasObjectWithID(id)); | |
973 return scope.CloseAndEscape(array); | |
974 } | 1132 } |
975 | 1133 |
976 MaybeHandle<JSDate> ValueDeserializer::ReadJSDate() { | 1134 MaybeHandle<JSDate> ValueDeserializer::ReadJSDate() { |
977 double value; | 1135 double value; |
978 if (!ReadDouble().To(&value)) return MaybeHandle<JSDate>(); | 1136 if (!ReadDouble().To(&value)) return MaybeHandle<JSDate>(); |
979 uint32_t id = next_id_++; | 1137 uint32_t id = next_id_++; |
980 Handle<JSDate> date; | 1138 Handle<JSDate> date; |
981 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) | 1139 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) |
982 .ToHandle(&date)) { | 1140 .ToHandle(&date)) { |
983 return MaybeHandle<JSDate>(); | 1141 return MaybeHandle<JSDate>(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1034 !ReadVarint<uint32_t>().To(&raw_flags) || | 1192 !ReadVarint<uint32_t>().To(&raw_flags) || |
1035 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) | 1193 !JSRegExp::New(pattern, static_cast<JSRegExp::Flags>(raw_flags)) |
1036 .ToHandle(®exp)) { | 1194 .ToHandle(®exp)) { |
1037 return MaybeHandle<JSRegExp>(); | 1195 return MaybeHandle<JSRegExp>(); |
1038 } | 1196 } |
1039 AddObjectWithID(id, regexp); | 1197 AddObjectWithID(id, regexp); |
1040 return regexp; | 1198 return regexp; |
1041 } | 1199 } |
1042 | 1200 |
1043 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() { | 1201 MaybeHandle<JSMap> ValueDeserializer::ReadJSMap() { |
1044 // If we are at the end of the stack, abort. This function may recurse. | |
1045 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSMap>(); | |
1046 | |
1047 HandleScope scope(isolate_); | |
1048 uint32_t id = next_id_++; | 1202 uint32_t id = next_id_++; |
1049 Handle<JSMap> map = isolate_->factory()->NewJSMap(); | 1203 Handle<JSMap> map = isolate_->factory()->NewJSMap(); |
1050 AddObjectWithID(id, map); | 1204 AddObjectWithID(id, map); |
1051 | 1205 states_.push_back( |
1052 Handle<JSFunction> map_set = isolate_->map_set(); | 1206 {State::kJSMapKey, 0, 0, 0, map, isolate_->map_set(), Handle<Object>()}); |
1053 uint32_t length = 0; | 1207 return map; |
1054 while (true) { | |
1055 SerializationTag tag; | |
1056 if (!PeekTag().To(&tag)) return MaybeHandle<JSMap>(); | |
1057 if (tag == SerializationTag::kEndJSMap) { | |
1058 ConsumeTag(SerializationTag::kEndJSMap); | |
1059 break; | |
1060 } | |
1061 | |
1062 Handle<Object> argv[2]; | |
1063 if (!ReadObject().ToHandle(&argv[0]) || !ReadObject().ToHandle(&argv[1]) || | |
1064 Execution::Call(isolate_, map_set, map, arraysize(argv), argv) | |
1065 .is_null()) { | |
1066 return MaybeHandle<JSMap>(); | |
1067 } | |
1068 length += 2; | |
1069 } | |
1070 | |
1071 uint32_t expected_length; | |
1072 if (!ReadVarint<uint32_t>().To(&expected_length) || | |
1073 length != expected_length) { | |
1074 return MaybeHandle<JSMap>(); | |
1075 } | |
1076 DCHECK(HasObjectWithID(id)); | |
1077 return scope.CloseAndEscape(map); | |
1078 } | 1208 } |
1079 | 1209 |
1080 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() { | 1210 MaybeHandle<JSSet> ValueDeserializer::ReadJSSet() { |
1081 // If we are at the end of the stack, abort. This function may recurse. | |
1082 if (StackLimitCheck(isolate_).HasOverflowed()) return MaybeHandle<JSSet>(); | |
1083 | |
1084 HandleScope scope(isolate_); | |
1085 uint32_t id = next_id_++; | 1211 uint32_t id = next_id_++; |
1086 Handle<JSSet> set = isolate_->factory()->NewJSSet(); | 1212 Handle<JSSet> set = isolate_->factory()->NewJSSet(); |
1087 AddObjectWithID(id, set); | 1213 AddObjectWithID(id, set); |
1088 Handle<JSFunction> set_add = isolate_->set_add(); | 1214 states_.push_back( |
1089 uint32_t length = 0; | 1215 {State::kJSSet, 0, 0, 0, set, isolate_->set_add(), Handle<Object>()}); |
1090 while (true) { | 1216 return set; |
1091 SerializationTag tag; | |
1092 if (!PeekTag().To(&tag)) return MaybeHandle<JSSet>(); | |
1093 if (tag == SerializationTag::kEndJSSet) { | |
1094 ConsumeTag(SerializationTag::kEndJSSet); | |
1095 break; | |
1096 } | |
1097 | |
1098 Handle<Object> argv[1]; | |
1099 if (!ReadObject().ToHandle(&argv[0]) || | |
1100 Execution::Call(isolate_, set_add, set, arraysize(argv), argv) | |
1101 .is_null()) { | |
1102 return MaybeHandle<JSSet>(); | |
1103 } | |
1104 length++; | |
1105 } | |
1106 | |
1107 uint32_t expected_length; | |
1108 if (!ReadVarint<uint32_t>().To(&expected_length) || | |
1109 length != expected_length) { | |
1110 return MaybeHandle<JSSet>(); | |
1111 } | |
1112 DCHECK(HasObjectWithID(id)); | |
1113 return scope.CloseAndEscape(set); | |
1114 } | 1217 } |
1115 | 1218 |
1116 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer() { | 1219 MaybeHandle<JSArrayBuffer> ValueDeserializer::ReadJSArrayBuffer() { |
1117 uint32_t id = next_id_++; | 1220 uint32_t id = next_id_++; |
1118 uint32_t byte_length; | 1221 uint32_t byte_length; |
1119 Vector<const uint8_t> bytes; | 1222 Vector<const uint8_t> bytes; |
1120 if (!ReadVarint<uint32_t>().To(&byte_length) || | 1223 if (!ReadVarint<uint32_t>().To(&byte_length) || |
1121 byte_length > static_cast<size_t>(end_ - position_)) { | 1224 byte_length > static_cast<size_t>(end_ - position_)) { |
1122 return MaybeHandle<JSArrayBuffer>(); | 1225 return MaybeHandle<JSArrayBuffer>(); |
1123 } | 1226 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 } | 1287 } |
1185 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { | 1288 if (byte_offset % element_size != 0 || byte_length % element_size != 0) { |
1186 return MaybeHandle<JSArrayBufferView>(); | 1289 return MaybeHandle<JSArrayBufferView>(); |
1187 } | 1290 } |
1188 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( | 1291 Handle<JSTypedArray> typed_array = isolate_->factory()->NewJSTypedArray( |
1189 external_array_type, buffer, byte_offset, byte_length / element_size); | 1292 external_array_type, buffer, byte_offset, byte_length / element_size); |
1190 AddObjectWithID(id, typed_array); | 1293 AddObjectWithID(id, typed_array); |
1191 return typed_array; | 1294 return typed_array; |
1192 } | 1295 } |
1193 | 1296 |
1194 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | |
1195 Handle<JSObject> object, SerializationTag end_tag) { | |
1196 for (uint32_t num_properties = 0;; num_properties++) { | |
1197 SerializationTag tag; | |
1198 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | |
1199 if (tag == end_tag) { | |
1200 ConsumeTag(end_tag); | |
1201 return Just(num_properties); | |
1202 } | |
1203 | |
1204 Handle<Object> key; | |
1205 if (!ReadObject().ToHandle(&key)) return Nothing<uint32_t>(); | |
1206 Handle<Object> value; | |
1207 if (!ReadObject().ToHandle(&value)) return Nothing<uint32_t>(); | |
1208 | |
1209 bool success; | |
1210 LookupIterator it = LookupIterator::PropertyOrElement( | |
1211 isolate_, object, key, &success, LookupIterator::OWN); | |
1212 if (!success || | |
1213 JSObject::DefineOwnPropertyIgnoreAttributes(&it, value, NONE) | |
1214 .is_null()) { | |
1215 return Nothing<uint32_t>(); | |
1216 } | |
1217 } | |
1218 } | |
1219 | |
1220 bool ValueDeserializer::HasObjectWithID(uint32_t id) { | 1297 bool ValueDeserializer::HasObjectWithID(uint32_t id) { |
1221 return id_map_->Has(isolate_, id); | 1298 return id_map_->Has(isolate_, id); |
1222 } | 1299 } |
1223 | 1300 |
1224 MaybeHandle<JSReceiver> ValueDeserializer::GetObjectWithID(uint32_t id) { | 1301 MaybeHandle<JSReceiver> ValueDeserializer::GetObjectWithID(uint32_t id) { |
1225 int index = id_map_->FindEntry(isolate_, id); | 1302 int index = id_map_->FindEntry(isolate_, id); |
1226 if (index == SeededNumberDictionary::kNotFound) { | 1303 if (index == SeededNumberDictionary::kNotFound) { |
1227 return MaybeHandle<JSReceiver>(); | 1304 return MaybeHandle<JSReceiver>(); |
1228 } | 1305 } |
1229 Object* value = id_map_->ValueAt(index); | 1306 Object* value = id_map_->ValueAt(index); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 } | 1425 } |
1349 #endif | 1426 #endif |
1350 position_ = end_; | 1427 position_ = end_; |
1351 | 1428 |
1352 if (stack.size() != 1) return MaybeHandle<Object>(); | 1429 if (stack.size() != 1) return MaybeHandle<Object>(); |
1353 return scope.CloseAndEscape(stack[0]); | 1430 return scope.CloseAndEscape(stack[0]); |
1354 } | 1431 } |
1355 | 1432 |
1356 } // namespace internal | 1433 } // namespace internal |
1357 } // namespace v8 | 1434 } // namespace v8 |
OLD | NEW |