Chromium Code Reviews| 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/factory.h" | 10 #include "src/factory.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 kBeginSparseJSArray = 'a', | 65 kBeginSparseJSArray = 'a', |
| 66 // End of a sparse JS array. numProperties:uint32_t length:uint32_t | 66 // End of a sparse JS array. numProperties:uint32_t length:uint32_t |
| 67 kEndSparseJSArray = '@', | 67 kEndSparseJSArray = '@', |
| 68 // Beginning of a dense JS array. length:uint32_t | 68 // Beginning of a dense JS array. length:uint32_t |
| 69 // |length| elements, followed by properties as key/value pairs | 69 // |length| elements, followed by properties as key/value pairs |
| 70 kBeginDenseJSArray = 'A', | 70 kBeginDenseJSArray = 'A', |
| 71 // End of a dense JS array. numProperties:uint32_t length:uint32_t | 71 // End of a dense JS array. numProperties:uint32_t length:uint32_t |
| 72 kEndDenseJSArray = '$', | 72 kEndDenseJSArray = '$', |
| 73 // Date. millisSinceEpoch:double | 73 // Date. millisSinceEpoch:double |
| 74 kDate = 'D', | 74 kDate = 'D', |
| 75 // Boolean object. No data. | |
| 76 kTrueObject = 'y', | |
| 77 kFalseObject = 'x', | |
| 78 // Number object. value:double | |
| 79 kNumberObject = 'n', | |
| 80 // String object, UTF-8 encoding. byteLength:uint32_t, then raw data. | |
| 81 kStringObject = 's', | |
| 75 }; | 82 }; |
| 76 | 83 |
| 77 ValueSerializer::ValueSerializer(Isolate* isolate) | 84 ValueSerializer::ValueSerializer(Isolate* isolate) |
| 78 : isolate_(isolate), | 85 : isolate_(isolate), |
| 79 zone_(isolate->allocator()), | 86 zone_(isolate->allocator()), |
| 80 id_map_(isolate->heap(), &zone_) {} | 87 id_map_(isolate->heap(), &zone_) {} |
| 81 | 88 |
| 82 ValueSerializer::~ValueSerializer() {} | 89 ValueSerializer::~ValueSerializer() {} |
| 83 | 90 |
| 84 void ValueSerializer::WriteHeader() { | 91 void ValueSerializer::WriteHeader() { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 } | 141 } |
| 135 | 142 |
| 136 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { | 143 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { |
| 137 // Warning: this uses host endianness. | 144 // Warning: this uses host endianness. |
| 138 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); | 145 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); |
| 139 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), | 146 buffer_.insert(buffer_.end(), reinterpret_cast<const uint8_t*>(chars.begin()), |
| 140 reinterpret_cast<const uint8_t*>(chars.end())); | 147 reinterpret_cast<const uint8_t*>(chars.end())); |
| 141 } | 148 } |
| 142 | 149 |
| 143 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { | 150 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { |
| 151 if (!bytes) return nullptr; | |
|
jbroman
2016/08/19 19:11:16
This sometimes triggered the debug std::vector che
| |
| 144 auto old_size = buffer_.size(); | 152 auto old_size = buffer_.size(); |
| 145 buffer_.resize(buffer_.size() + bytes); | 153 buffer_.resize(buffer_.size() + bytes); |
| 146 return &buffer_[old_size]; | 154 return &buffer_[old_size]; |
| 147 } | 155 } |
| 148 | 156 |
| 149 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { | 157 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { |
| 150 if (object->IsSmi()) { | 158 if (object->IsSmi()) { |
| 151 WriteSmi(Smi::cast(*object)); | 159 WriteSmi(Smi::cast(*object)); |
| 152 return Just(true); | 160 return Just(true); |
| 153 } | 161 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 HandleScope scope(isolate_); | 274 HandleScope scope(isolate_); |
| 267 switch (instance_type) { | 275 switch (instance_type) { |
| 268 case JS_ARRAY_TYPE: | 276 case JS_ARRAY_TYPE: |
| 269 return WriteJSArray(Handle<JSArray>::cast(receiver)); | 277 return WriteJSArray(Handle<JSArray>::cast(receiver)); |
| 270 case JS_OBJECT_TYPE: | 278 case JS_OBJECT_TYPE: |
| 271 case JS_API_OBJECT_TYPE: | 279 case JS_API_OBJECT_TYPE: |
| 272 return WriteJSObject(Handle<JSObject>::cast(receiver)); | 280 return WriteJSObject(Handle<JSObject>::cast(receiver)); |
| 273 case JS_DATE_TYPE: | 281 case JS_DATE_TYPE: |
| 274 WriteJSDate(JSDate::cast(*receiver)); | 282 WriteJSDate(JSDate::cast(*receiver)); |
| 275 return Just(true); | 283 return Just(true); |
| 284 case JS_VALUE_TYPE: | |
| 285 return WriteJSValue(Handle<JSValue>::cast(receiver)); | |
| 276 default: | 286 default: |
| 277 UNIMPLEMENTED(); | 287 UNIMPLEMENTED(); |
| 278 break; | 288 break; |
| 279 } | 289 } |
| 280 return Nothing<bool>(); | 290 return Nothing<bool>(); |
| 281 } | 291 } |
| 282 | 292 |
| 283 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { | 293 Maybe<bool> ValueSerializer::WriteJSObject(Handle<JSObject> object) { |
| 284 WriteTag(SerializationTag::kBeginJSObject); | 294 WriteTag(SerializationTag::kBeginJSObject); |
| 285 Handle<FixedArray> keys; | 295 Handle<FixedArray> keys; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 356 WriteVarint<uint32_t>(length); | 366 WriteVarint<uint32_t>(length); |
| 357 } | 367 } |
| 358 return Just(true); | 368 return Just(true); |
| 359 } | 369 } |
| 360 | 370 |
| 361 void ValueSerializer::WriteJSDate(JSDate* date) { | 371 void ValueSerializer::WriteJSDate(JSDate* date) { |
| 362 WriteTag(SerializationTag::kDate); | 372 WriteTag(SerializationTag::kDate); |
| 363 WriteDouble(date->value()->Number()); | 373 WriteDouble(date->value()->Number()); |
| 364 } | 374 } |
| 365 | 375 |
| 376 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { | |
| 377 Object* inner_value = value->value(); | |
| 378 if (value->HasSpecificClassOf(isolate_->heap()->Boolean_string())) { | |
| 379 if (inner_value->IsTrue(isolate_)) { | |
| 380 WriteTag(SerializationTag::kTrueObject); | |
| 381 } else { | |
| 382 DCHECK(inner_value->IsFalse(isolate_)); | |
| 383 WriteTag(SerializationTag::kFalseObject); | |
| 384 } | |
| 385 } else if (value->HasSpecificClassOf(isolate_->heap()->Number_string())) { | |
| 386 DCHECK(inner_value->IsNumber()); | |
| 387 WriteTag(SerializationTag::kNumberObject); | |
| 388 WriteDouble(inner_value->Number()); | |
| 389 } else if (value->HasSpecificClassOf(isolate_->heap()->String_string())) { | |
| 390 DCHECK(inner_value->IsString()); | |
| 391 // TODO(jbroman): Replace UTF-8 encoding with the same options available for | |
| 392 // ordinary strings. | |
| 393 WriteTag(SerializationTag::kStringObject); | |
| 394 v8::Local<v8::String> api_string = | |
| 395 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); | |
| 396 uint32_t utf8_length = api_string->Utf8Length(); | |
| 397 WriteVarint(utf8_length); | |
| 398 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), | |
| 399 utf8_length, nullptr, | |
| 400 v8::String::NO_NULL_TERMINATION); | |
| 401 } else { | |
| 402 return Nothing<bool>(); | |
| 403 } | |
| 404 return Just(true); | |
| 405 } | |
| 406 | |
| 366 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( | 407 Maybe<uint32_t> ValueSerializer::WriteJSObjectProperties( |
| 367 Handle<JSObject> object, Handle<FixedArray> keys) { | 408 Handle<JSObject> object, Handle<FixedArray> keys) { |
| 368 uint32_t properties_written = 0; | 409 uint32_t properties_written = 0; |
| 369 int length = keys->length(); | 410 int length = keys->length(); |
| 370 for (int i = 0; i < length; i++) { | 411 for (int i = 0; i < length; i++) { |
| 371 Handle<Object> key(keys->get(i), isolate_); | 412 Handle<Object> key(keys->get(i), isolate_); |
| 372 | 413 |
| 373 bool success; | 414 bool success; |
| 374 LookupIterator it = LookupIterator::PropertyOrElement( | 415 LookupIterator it = LookupIterator::PropertyOrElement( |
| 375 isolate_, object, key, &success, LookupIterator::OWN); | 416 isolate_, object, key, &success, LookupIterator::OWN); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 return GetObjectWithID(id); | 579 return GetObjectWithID(id); |
| 539 } | 580 } |
| 540 case SerializationTag::kBeginJSObject: | 581 case SerializationTag::kBeginJSObject: |
| 541 return ReadJSObject(); | 582 return ReadJSObject(); |
| 542 case SerializationTag::kBeginSparseJSArray: | 583 case SerializationTag::kBeginSparseJSArray: |
| 543 return ReadSparseJSArray(); | 584 return ReadSparseJSArray(); |
| 544 case SerializationTag::kBeginDenseJSArray: | 585 case SerializationTag::kBeginDenseJSArray: |
| 545 return ReadDenseJSArray(); | 586 return ReadDenseJSArray(); |
| 546 case SerializationTag::kDate: | 587 case SerializationTag::kDate: |
| 547 return ReadJSDate(); | 588 return ReadJSDate(); |
| 589 case SerializationTag::kTrueObject: | |
| 590 case SerializationTag::kFalseObject: | |
| 591 case SerializationTag::kNumberObject: | |
| 592 case SerializationTag::kStringObject: | |
| 593 return ReadJSValue(tag); | |
| 548 default: | 594 default: |
| 549 return MaybeHandle<Object>(); | 595 return MaybeHandle<Object>(); |
| 550 } | 596 } |
| 551 } | 597 } |
| 552 | 598 |
| 553 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { | 599 MaybeHandle<String> ValueDeserializer::ReadUtf8String() { |
| 554 uint32_t utf8_length; | 600 uint32_t utf8_length; |
| 555 Vector<const uint8_t> utf8_bytes; | 601 Vector<const uint8_t> utf8_bytes; |
| 556 if (!ReadVarint<uint32_t>().To(&utf8_length) || | 602 if (!ReadVarint<uint32_t>().To(&utf8_length) || |
| 557 utf8_length > | 603 utf8_length > |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 679 uint32_t id = next_id_++; | 725 uint32_t id = next_id_++; |
| 680 Handle<JSDate> date; | 726 Handle<JSDate> date; |
| 681 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) | 727 if (!JSDate::New(isolate_->date_function(), isolate_->date_function(), value) |
| 682 .ToHandle(&date)) { | 728 .ToHandle(&date)) { |
| 683 return MaybeHandle<JSDate>(); | 729 return MaybeHandle<JSDate>(); |
| 684 } | 730 } |
| 685 AddObjectWithID(id, date); | 731 AddObjectWithID(id, date); |
| 686 return date; | 732 return date; |
| 687 } | 733 } |
| 688 | 734 |
| 735 MaybeHandle<JSValue> ValueDeserializer::ReadJSValue(SerializationTag tag) { | |
| 736 uint32_t id = next_id_++; | |
| 737 Handle<JSValue> value; | |
| 738 switch (tag) { | |
| 739 case SerializationTag::kTrueObject: | |
| 740 value = Handle<JSValue>::cast( | |
| 741 isolate_->factory()->NewJSObject(isolate_->boolean_function())); | |
| 742 value->set_value(isolate_->heap()->true_value()); | |
| 743 break; | |
| 744 case SerializationTag::kFalseObject: | |
| 745 value = Handle<JSValue>::cast( | |
| 746 isolate_->factory()->NewJSObject(isolate_->boolean_function())); | |
| 747 value->set_value(isolate_->heap()->false_value()); | |
| 748 break; | |
| 749 case SerializationTag::kNumberObject: { | |
| 750 double number; | |
| 751 if (!ReadDouble().To(&number)) return MaybeHandle<JSValue>(); | |
| 752 value = Handle<JSValue>::cast( | |
| 753 isolate_->factory()->NewJSObject(isolate_->number_function())); | |
| 754 value->set_value(*isolate_->factory()->NewNumber(number)); | |
| 755 break; | |
| 756 } | |
| 757 case SerializationTag::kStringObject: { | |
| 758 Handle<String> string; | |
| 759 if (!ReadUtf8String().ToHandle(&string)) return MaybeHandle<JSValue>(); | |
| 760 value = Handle<JSValue>::cast( | |
| 761 isolate_->factory()->NewJSObject(isolate_->string_function())); | |
| 762 value->set_value(*string); | |
| 763 break; | |
| 764 } | |
| 765 default: | |
| 766 return MaybeHandle<JSValue>(); | |
| 767 } | |
| 768 AddObjectWithID(id, value); | |
| 769 return value; | |
| 770 } | |
| 771 | |
| 689 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( | 772 Maybe<uint32_t> ValueDeserializer::ReadJSObjectProperties( |
| 690 Handle<JSObject> object, SerializationTag end_tag) { | 773 Handle<JSObject> object, SerializationTag end_tag) { |
| 691 for (uint32_t num_properties = 0;; num_properties++) { | 774 for (uint32_t num_properties = 0;; num_properties++) { |
| 692 SerializationTag tag; | 775 SerializationTag tag; |
| 693 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); | 776 if (!PeekTag().To(&tag)) return Nothing<uint32_t>(); |
| 694 if (tag == end_tag) { | 777 if (tag == end_tag) { |
| 695 ConsumeTag(end_tag); | 778 ConsumeTag(end_tag); |
| 696 return Just(num_properties); | 779 return Just(num_properties); |
| 697 } | 780 } |
| 698 | 781 |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 843 } | 926 } |
| 844 #endif | 927 #endif |
| 845 position_ = end_; | 928 position_ = end_; |
| 846 | 929 |
| 847 if (stack.size() != 1) return MaybeHandle<Object>(); | 930 if (stack.size() != 1) return MaybeHandle<Object>(); |
| 848 return scope.CloseAndEscape(stack[0]); | 931 return scope.CloseAndEscape(stack[0]); |
| 849 } | 932 } |
| 850 | 933 |
| 851 } // namespace internal | 934 } // namespace internal |
| 852 } // namespace v8 | 935 } // namespace v8 |
| OLD | NEW |