Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: src/value-serializer.cc

Issue 2302023002: DO NOT SUBMIT: switch to an on-heap stack for nested object serialization/deserialization
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/value-serializer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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(&regexp)) { 1194 .ToHandle(&regexp)) {
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
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
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
OLDNEW
« no previous file with comments | « src/value-serializer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698