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

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

Issue 2643723010: [d8] Use ValueSerializer for postMessage (instead of ad-hoc serializer) (Closed)
Patch Set: fix Created 3 years, 11 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
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 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t)); 210 WriteRawBytes(chars.begin(), chars.length() * sizeof(uint8_t));
211 } 211 }
212 212
213 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) { 213 void ValueSerializer::WriteTwoByteString(Vector<const uc16> chars) {
214 // Warning: this uses host endianness. 214 // Warning: this uses host endianness.
215 WriteVarint<uint32_t>(chars.length() * sizeof(uc16)); 215 WriteVarint<uint32_t>(chars.length() * sizeof(uc16));
216 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16)); 216 WriteRawBytes(chars.begin(), chars.length() * sizeof(uc16));
217 } 217 }
218 218
219 void ValueSerializer::WriteRawBytes(const void* source, size_t length) { 219 void ValueSerializer::WriteRawBytes(const void* source, size_t length) {
220 memcpy(ReserveRawBytes(length), source, length); 220 uint8_t* dest;
221 if (ReserveRawBytes(length).To(&dest)) {
222 memcpy(dest, source, length);
223 }
221 } 224 }
222 225
223 uint8_t* ValueSerializer::ReserveRawBytes(size_t bytes) { 226 Maybe<uint8_t*> ValueSerializer::ReserveRawBytes(size_t bytes) {
224 size_t old_size = buffer_size_; 227 size_t old_size = buffer_size_;
225 size_t new_size = old_size + bytes; 228 size_t new_size = old_size + bytes;
226 if (new_size > buffer_capacity_) ExpandBuffer(new_size); 229 if (new_size > buffer_capacity_) {
230 bool ok;
231 if (!ExpandBuffer(new_size).To(&ok)) {
232 return Nothing<uint8_t*>();
233 }
234 }
227 buffer_size_ = new_size; 235 buffer_size_ = new_size;
228 return &buffer_[old_size]; 236 return Just(&buffer_[old_size]);
229 } 237 }
230 238
231 void ValueSerializer::ExpandBuffer(size_t required_capacity) { 239 Maybe<bool> ValueSerializer::ExpandBuffer(size_t required_capacity) {
232 DCHECK_GT(required_capacity, buffer_capacity_); 240 DCHECK_GT(required_capacity, buffer_capacity_);
233 size_t requested_capacity = 241 size_t requested_capacity =
234 std::max(required_capacity, buffer_capacity_ * 2) + 64; 242 std::max(required_capacity, buffer_capacity_ * 2) + 64;
235 size_t provided_capacity = 0; 243 size_t provided_capacity = 0;
236 void* new_buffer = nullptr; 244 void* new_buffer = nullptr;
237 if (delegate_) { 245 if (delegate_) {
238 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity, 246 new_buffer = delegate_->ReallocateBufferMemory(buffer_, requested_capacity,
239 &provided_capacity); 247 &provided_capacity);
240 } else { 248 } else {
241 new_buffer = realloc(buffer_, requested_capacity); 249 new_buffer = realloc(buffer_, requested_capacity);
242 provided_capacity = requested_capacity; 250 provided_capacity = requested_capacity;
243 } 251 }
244 DCHECK_GE(provided_capacity, requested_capacity); 252 if (new_buffer && provided_capacity >= requested_capacity) {
jbroman 2017/01/26 21:53:03 It seems odd to need to check both of these. Can w
binji 2017/01/27 19:33:21 Done.
245 buffer_ = reinterpret_cast<uint8_t*>(new_buffer); 253 buffer_ = reinterpret_cast<uint8_t*>(new_buffer);
246 buffer_capacity_ = provided_capacity; 254 buffer_capacity_ = provided_capacity;
255 return Just(true);
256 } else {
257 out_of_memory_ = true;
258 return Nothing<bool>();
259 }
247 } 260 }
248 261
249 void ValueSerializer::WriteUint32(uint32_t value) { 262 void ValueSerializer::WriteUint32(uint32_t value) {
250 WriteVarint<uint32_t>(value); 263 WriteVarint<uint32_t>(value);
251 } 264 }
252 265
253 void ValueSerializer::WriteUint64(uint64_t value) { 266 void ValueSerializer::WriteUint64(uint64_t value) {
254 WriteVarint<uint64_t>(value); 267 WriteVarint<uint64_t>(value);
255 } 268 }
256 269
(...skipping 10 matching lines...) Expand all
267 } 280 }
268 281
269 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id, 282 void ValueSerializer::TransferArrayBuffer(uint32_t transfer_id,
270 Handle<JSArrayBuffer> array_buffer) { 283 Handle<JSArrayBuffer> array_buffer) {
271 DCHECK(!array_buffer_transfer_map_.Find(array_buffer)); 284 DCHECK(!array_buffer_transfer_map_.Find(array_buffer));
272 DCHECK(!array_buffer->is_shared()); 285 DCHECK(!array_buffer->is_shared());
273 array_buffer_transfer_map_.Set(array_buffer, transfer_id); 286 array_buffer_transfer_map_.Set(array_buffer, transfer_id);
274 } 287 }
275 288
276 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) { 289 Maybe<bool> ValueSerializer::WriteObject(Handle<Object> object) {
290 out_of_memory_ = false;
277 if (object->IsSmi()) { 291 if (object->IsSmi()) {
278 WriteSmi(Smi::cast(*object)); 292 WriteSmi(Smi::cast(*object));
279 return Just(true); 293 return ThrowIfOutOfMemory();
280 } 294 }
281 295
282 DCHECK(object->IsHeapObject()); 296 DCHECK(object->IsHeapObject());
283 switch (HeapObject::cast(*object)->map()->instance_type()) { 297 switch (HeapObject::cast(*object)->map()->instance_type()) {
284 case ODDBALL_TYPE: 298 case ODDBALL_TYPE:
285 WriteOddball(Oddball::cast(*object)); 299 WriteOddball(Oddball::cast(*object));
286 return Just(true); 300 return ThrowIfOutOfMemory();
287 case HEAP_NUMBER_TYPE: 301 case HEAP_NUMBER_TYPE:
288 case MUTABLE_HEAP_NUMBER_TYPE: 302 case MUTABLE_HEAP_NUMBER_TYPE:
289 WriteHeapNumber(HeapNumber::cast(*object)); 303 WriteHeapNumber(HeapNumber::cast(*object));
290 return Just(true); 304 return ThrowIfOutOfMemory();
291 case JS_TYPED_ARRAY_TYPE: 305 case JS_TYPED_ARRAY_TYPE:
292 case JS_DATA_VIEW_TYPE: { 306 case JS_DATA_VIEW_TYPE: {
293 // Despite being JSReceivers, these have their wrapped buffer serialized 307 // Despite being JSReceivers, these have their wrapped buffer serialized
294 // first. That makes this logic a little quirky, because it needs to 308 // first. That makes this logic a little quirky, because it needs to
295 // happen before we assign object IDs. 309 // happen before we assign object IDs.
296 // TODO(jbroman): It may be possible to avoid materializing a typed 310 // TODO(jbroman): It may be possible to avoid materializing a typed
297 // array's buffer here. 311 // array's buffer here.
298 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object); 312 Handle<JSArrayBufferView> view = Handle<JSArrayBufferView>::cast(object);
299 if (!id_map_.Find(view)) { 313 if (!id_map_.Find(view)) {
300 Handle<JSArrayBuffer> buffer( 314 Handle<JSArrayBuffer> buffer(
301 view->IsJSTypedArray() 315 view->IsJSTypedArray()
302 ? Handle<JSTypedArray>::cast(view)->GetBuffer() 316 ? Handle<JSTypedArray>::cast(view)->GetBuffer()
303 : handle(JSArrayBuffer::cast(view->buffer()), isolate_)); 317 : handle(JSArrayBuffer::cast(view->buffer()), isolate_));
304 if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>(); 318 if (!WriteJSReceiver(buffer).FromMaybe(false)) return Nothing<bool>();
305 } 319 }
306 return WriteJSReceiver(view); 320 return WriteJSReceiver(view);
307 } 321 }
308 default: 322 default:
309 if (object->IsString()) { 323 if (object->IsString()) {
310 WriteString(Handle<String>::cast(object)); 324 WriteString(Handle<String>::cast(object));
311 return Just(true); 325 return ThrowIfOutOfMemory();
312 } else if (object->IsJSReceiver()) { 326 } else if (object->IsJSReceiver()) {
313 return WriteJSReceiver(Handle<JSReceiver>::cast(object)); 327 return WriteJSReceiver(Handle<JSReceiver>::cast(object));
314 } else { 328 } else {
315 ThrowDataCloneError(MessageTemplate::kDataCloneError, object); 329 ThrowDataCloneError(MessageTemplate::kDataCloneError, object);
316 return Nothing<bool>(); 330 return Nothing<bool>();
317 } 331 }
318 } 332 }
319 } 333 }
320 334
321 void ValueSerializer::WriteOddball(Oddball* oddball) { 335 void ValueSerializer::WriteOddball(Oddball* oddball) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 // TODO(jbroman): In a future format version, consider adding a tag for 376 // TODO(jbroman): In a future format version, consider adding a tag for
363 // Latin-1 strings, so that this can be skipped. 377 // Latin-1 strings, so that this can be skipped.
364 WriteTag(SerializationTag::kUtf8String); 378 WriteTag(SerializationTag::kUtf8String);
365 Vector<const uint8_t> chars = flat.ToOneByteVector(); 379 Vector<const uint8_t> chars = flat.ToOneByteVector();
366 if (String::IsAscii(chars.begin(), chars.length())) { 380 if (String::IsAscii(chars.begin(), chars.length())) {
367 WriteOneByteString(chars); 381 WriteOneByteString(chars);
368 } else { 382 } else {
369 v8::Local<v8::String> api_string = Utils::ToLocal(string); 383 v8::Local<v8::String> api_string = Utils::ToLocal(string);
370 uint32_t utf8_length = api_string->Utf8Length(); 384 uint32_t utf8_length = api_string->Utf8Length();
371 WriteVarint(utf8_length); 385 WriteVarint(utf8_length);
372 api_string->WriteUtf8( 386 uint8_t* dest;
373 reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), utf8_length, 387 if (ReserveRawBytes(utf8_length).To(&dest)) {
374 nullptr, v8::String::NO_NULL_TERMINATION); 388 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length,
389 nullptr, v8::String::NO_NULL_TERMINATION);
390 }
375 } 391 }
376 } else if (flat.IsTwoByte()) { 392 } else if (flat.IsTwoByte()) {
377 Vector<const uc16> chars = flat.ToUC16Vector(); 393 Vector<const uc16> chars = flat.ToUC16Vector();
378 uint32_t byte_length = chars.length() * sizeof(uc16); 394 uint32_t byte_length = chars.length() * sizeof(uc16);
379 // The existing reading code expects 16-byte strings to be aligned. 395 // The existing reading code expects 16-byte strings to be aligned.
380 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1) 396 if ((buffer_size_ + 1 + BytesNeededForVarint(byte_length)) & 1)
381 WriteTag(SerializationTag::kPadding); 397 WriteTag(SerializationTag::kPadding);
382 WriteTag(SerializationTag::kTwoByteString); 398 WriteTag(SerializationTag::kTwoByteString);
383 WriteTwoByteString(chars); 399 WriteTwoByteString(chars);
384 } else { 400 } else {
385 UNREACHABLE(); 401 UNREACHABLE();
386 } 402 }
387 } 403 }
388 404
389 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) { 405 Maybe<bool> ValueSerializer::WriteJSReceiver(Handle<JSReceiver> receiver) {
390 // If the object has already been serialized, just write its ID. 406 // If the object has already been serialized, just write its ID.
391 uint32_t* id_map_entry = id_map_.Get(receiver); 407 uint32_t* id_map_entry = id_map_.Get(receiver);
392 if (uint32_t id = *id_map_entry) { 408 if (uint32_t id = *id_map_entry) {
393 WriteTag(SerializationTag::kObjectReference); 409 WriteTag(SerializationTag::kObjectReference);
394 WriteVarint(id - 1); 410 WriteVarint(id - 1);
395 return Just(true); 411 return ThrowIfOutOfMemory();
396 } 412 }
397 413
398 // Otherwise, allocate an ID for it. 414 // Otherwise, allocate an ID for it.
399 uint32_t id = next_id_++; 415 uint32_t id = next_id_++;
400 *id_map_entry = id + 1; 416 *id_map_entry = id + 1;
401 417
402 // Eliminate callable and exotic objects, which should not be serialized. 418 // Eliminate callable and exotic objects, which should not be serialized.
403 InstanceType instance_type = receiver->map()->instance_type(); 419 InstanceType instance_type = receiver->map()->instance_type();
404 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) && 420 if (receiver->IsCallable() || (IsSpecialReceiverInstanceType(instance_type) &&
405 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) { 421 instance_type != JS_SPECIAL_API_OBJECT_TYPE)) {
(...skipping 19 matching lines...) Expand all
425 } else if (JSObject::GetInternalFieldCount(map)) { 441 } else if (JSObject::GetInternalFieldCount(map)) {
426 return WriteHostObject(js_object); 442 return WriteHostObject(js_object);
427 } else { 443 } else {
428 return WriteJSObject(js_object); 444 return WriteJSObject(js_object);
429 } 445 }
430 } 446 }
431 case JS_SPECIAL_API_OBJECT_TYPE: 447 case JS_SPECIAL_API_OBJECT_TYPE:
432 return WriteHostObject(Handle<JSObject>::cast(receiver)); 448 return WriteHostObject(Handle<JSObject>::cast(receiver));
433 case JS_DATE_TYPE: 449 case JS_DATE_TYPE:
434 WriteJSDate(JSDate::cast(*receiver)); 450 WriteJSDate(JSDate::cast(*receiver));
435 return Just(true); 451 return ThrowIfOutOfMemory();
436 case JS_VALUE_TYPE: 452 case JS_VALUE_TYPE:
437 return WriteJSValue(Handle<JSValue>::cast(receiver)); 453 return WriteJSValue(Handle<JSValue>::cast(receiver));
438 case JS_REGEXP_TYPE: 454 case JS_REGEXP_TYPE:
439 WriteJSRegExp(JSRegExp::cast(*receiver)); 455 WriteJSRegExp(JSRegExp::cast(*receiver));
440 return Just(true); 456 return ThrowIfOutOfMemory();
441 case JS_MAP_TYPE: 457 case JS_MAP_TYPE:
442 return WriteJSMap(Handle<JSMap>::cast(receiver)); 458 return WriteJSMap(Handle<JSMap>::cast(receiver));
443 case JS_SET_TYPE: 459 case JS_SET_TYPE:
444 return WriteJSSet(Handle<JSSet>::cast(receiver)); 460 return WriteJSSet(Handle<JSSet>::cast(receiver));
445 case JS_ARRAY_BUFFER_TYPE: 461 case JS_ARRAY_BUFFER_TYPE:
446 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver)); 462 return WriteJSArrayBuffer(Handle<JSArrayBuffer>::cast(receiver));
447 case JS_TYPED_ARRAY_TYPE: 463 case JS_TYPED_ARRAY_TYPE:
448 case JS_DATA_VIEW_TYPE: 464 case JS_DATA_VIEW_TYPE:
449 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver)); 465 return WriteJSArrayBufferView(JSArrayBufferView::cast(*receiver));
450 default: 466 default:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 507
492 if (!WriteObject(key).FromMaybe(false) || 508 if (!WriteObject(key).FromMaybe(false) ||
493 !WriteObject(value).FromMaybe(false)) { 509 !WriteObject(value).FromMaybe(false)) {
494 return Nothing<bool>(); 510 return Nothing<bool>();
495 } 511 }
496 properties_written++; 512 properties_written++;
497 } 513 }
498 514
499 WriteTag(SerializationTag::kEndJSObject); 515 WriteTag(SerializationTag::kEndJSObject);
500 WriteVarint<uint32_t>(properties_written); 516 WriteVarint<uint32_t>(properties_written);
501 return Just(true); 517 return ThrowIfOutOfMemory();
502 } 518 }
503 519
504 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) { 520 Maybe<bool> ValueSerializer::WriteJSObjectSlow(Handle<JSObject> object) {
505 WriteTag(SerializationTag::kBeginJSObject); 521 WriteTag(SerializationTag::kBeginJSObject);
506 Handle<FixedArray> keys; 522 Handle<FixedArray> keys;
507 uint32_t properties_written; 523 uint32_t properties_written;
508 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, 524 if (!KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly,
509 ENUMERABLE_STRINGS) 525 ENUMERABLE_STRINGS)
510 .ToHandle(&keys) || 526 .ToHandle(&keys) ||
511 !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) { 527 !WriteJSObjectPropertiesSlow(object, keys).To(&properties_written)) {
512 return Nothing<bool>(); 528 return Nothing<bool>();
513 } 529 }
514 WriteTag(SerializationTag::kEndJSObject); 530 WriteTag(SerializationTag::kEndJSObject);
515 WriteVarint<uint32_t>(properties_written); 531 WriteVarint<uint32_t>(properties_written);
516 return Just(true); 532 return ThrowIfOutOfMemory();
517 } 533 }
518 534
519 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) { 535 Maybe<bool> ValueSerializer::WriteJSArray(Handle<JSArray> array) {
520 uint32_t length = 0; 536 uint32_t length = 0;
521 bool valid_length = array->length()->ToArrayLength(&length); 537 bool valid_length = array->length()->ToArrayLength(&length);
522 DCHECK(valid_length); 538 DCHECK(valid_length);
523 USE(valid_length); 539 USE(valid_length);
524 540
525 // To keep things simple, for now we decide between dense and sparse 541 // To keep things simple, for now we decide between dense and sparse
526 // serialization based on elements kind. A more principled heuristic could 542 // serialization based on elements kind. A more principled heuristic could
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly, 627 if (!KeyAccumulator::GetKeys(array, KeyCollectionMode::kOwnOnly,
612 ENUMERABLE_STRINGS) 628 ENUMERABLE_STRINGS)
613 .ToHandle(&keys) || 629 .ToHandle(&keys) ||
614 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) { 630 !WriteJSObjectPropertiesSlow(array, keys).To(&properties_written)) {
615 return Nothing<bool>(); 631 return Nothing<bool>();
616 } 632 }
617 WriteTag(SerializationTag::kEndSparseJSArray); 633 WriteTag(SerializationTag::kEndSparseJSArray);
618 WriteVarint<uint32_t>(properties_written); 634 WriteVarint<uint32_t>(properties_written);
619 WriteVarint<uint32_t>(length); 635 WriteVarint<uint32_t>(length);
620 } 636 }
621 return Just(true); 637 return ThrowIfOutOfMemory();
622 } 638 }
623 639
624 void ValueSerializer::WriteJSDate(JSDate* date) { 640 void ValueSerializer::WriteJSDate(JSDate* date) {
625 WriteTag(SerializationTag::kDate); 641 WriteTag(SerializationTag::kDate);
626 WriteDouble(date->value()->Number()); 642 WriteDouble(date->value()->Number());
627 } 643 }
628 644
629 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) { 645 Maybe<bool> ValueSerializer::WriteJSValue(Handle<JSValue> value) {
630 Object* inner_value = value->value(); 646 Object* inner_value = value->value();
631 if (inner_value->IsTrue(isolate_)) { 647 if (inner_value->IsTrue(isolate_)) {
632 WriteTag(SerializationTag::kTrueObject); 648 WriteTag(SerializationTag::kTrueObject);
633 } else if (inner_value->IsFalse(isolate_)) { 649 } else if (inner_value->IsFalse(isolate_)) {
634 WriteTag(SerializationTag::kFalseObject); 650 WriteTag(SerializationTag::kFalseObject);
635 } else if (inner_value->IsNumber()) { 651 } else if (inner_value->IsNumber()) {
636 WriteTag(SerializationTag::kNumberObject); 652 WriteTag(SerializationTag::kNumberObject);
637 WriteDouble(inner_value->Number()); 653 WriteDouble(inner_value->Number());
638 } else if (inner_value->IsString()) { 654 } else if (inner_value->IsString()) {
639 // TODO(jbroman): Replace UTF-8 encoding with the same options available for 655 // TODO(jbroman): Replace UTF-8 encoding with the same options available for
640 // ordinary strings. 656 // ordinary strings.
641 WriteTag(SerializationTag::kStringObject); 657 WriteTag(SerializationTag::kStringObject);
642 v8::Local<v8::String> api_string = 658 v8::Local<v8::String> api_string =
643 Utils::ToLocal(handle(String::cast(inner_value), isolate_)); 659 Utils::ToLocal(handle(String::cast(inner_value), isolate_));
644 uint32_t utf8_length = api_string->Utf8Length(); 660 uint32_t utf8_length = api_string->Utf8Length();
645 WriteVarint(utf8_length); 661 WriteVarint(utf8_length);
646 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), 662 uint8_t* dest;
647 utf8_length, nullptr, 663 if (ReserveRawBytes(utf8_length).To(&dest)) {
648 v8::String::NO_NULL_TERMINATION); 664 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr,
665 v8::String::NO_NULL_TERMINATION);
666 }
649 } else { 667 } else {
650 DCHECK(inner_value->IsSymbol()); 668 DCHECK(inner_value->IsSymbol());
651 ThrowDataCloneError(MessageTemplate::kDataCloneError, value); 669 ThrowDataCloneError(MessageTemplate::kDataCloneError, value);
652 return Nothing<bool>(); 670 return Nothing<bool>();
653 } 671 }
654 return Just(true); 672 return ThrowIfOutOfMemory();
655 } 673 }
656 674
657 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) { 675 void ValueSerializer::WriteJSRegExp(JSRegExp* regexp) {
658 WriteTag(SerializationTag::kRegExp); 676 WriteTag(SerializationTag::kRegExp);
659 v8::Local<v8::String> api_string = 677 v8::Local<v8::String> api_string =
660 Utils::ToLocal(handle(regexp->Pattern(), isolate_)); 678 Utils::ToLocal(handle(regexp->Pattern(), isolate_));
661 uint32_t utf8_length = api_string->Utf8Length(); 679 uint32_t utf8_length = api_string->Utf8Length();
662 WriteVarint(utf8_length); 680 WriteVarint(utf8_length);
663 api_string->WriteUtf8(reinterpret_cast<char*>(ReserveRawBytes(utf8_length)), 681 uint8_t* dest;
664 utf8_length, nullptr, v8::String::NO_NULL_TERMINATION); 682 if (ReserveRawBytes(utf8_length).To(&dest)) {
683 api_string->WriteUtf8(reinterpret_cast<char*>(dest), utf8_length, nullptr,
684 v8::String::NO_NULL_TERMINATION);
685 }
665 WriteVarint(static_cast<uint32_t>(regexp->GetFlags())); 686 WriteVarint(static_cast<uint32_t>(regexp->GetFlags()));
666 } 687 }
667 688
668 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) { 689 Maybe<bool> ValueSerializer::WriteJSMap(Handle<JSMap> map) {
669 // First copy the key-value pairs, since getters could mutate them. 690 // First copy the key-value pairs, since getters could mutate them.
670 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table())); 691 Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
671 int length = table->NumberOfElements() * 2; 692 int length = table->NumberOfElements() * 2;
672 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); 693 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
673 { 694 {
674 DisallowHeapAllocation no_gc; 695 DisallowHeapAllocation no_gc;
(...skipping 11 matching lines...) Expand all
686 707
687 // Then write it out. 708 // Then write it out.
688 WriteTag(SerializationTag::kBeginJSMap); 709 WriteTag(SerializationTag::kBeginJSMap);
689 for (int i = 0; i < length; i++) { 710 for (int i = 0; i < length; i++) {
690 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { 711 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
691 return Nothing<bool>(); 712 return Nothing<bool>();
692 } 713 }
693 } 714 }
694 WriteTag(SerializationTag::kEndJSMap); 715 WriteTag(SerializationTag::kEndJSMap);
695 WriteVarint<uint32_t>(length); 716 WriteVarint<uint32_t>(length);
696 return Just(true); 717 return ThrowIfOutOfMemory();
697 } 718 }
698 719
699 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) { 720 Maybe<bool> ValueSerializer::WriteJSSet(Handle<JSSet> set) {
700 // First copy the element pointers, since getters could mutate them. 721 // First copy the element pointers, since getters could mutate them.
701 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table())); 722 Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
702 int length = table->NumberOfElements(); 723 int length = table->NumberOfElements();
703 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length); 724 Handle<FixedArray> entries = isolate_->factory()->NewFixedArray(length);
704 { 725 {
705 DisallowHeapAllocation no_gc; 726 DisallowHeapAllocation no_gc;
706 Oddball* the_hole = isolate_->heap()->the_hole_value(); 727 Oddball* the_hole = isolate_->heap()->the_hole_value();
707 int capacity = table->UsedCapacity(); 728 int capacity = table->UsedCapacity();
708 int result_index = 0; 729 int result_index = 0;
709 for (int i = 0; i < capacity; i++) { 730 for (int i = 0; i < capacity; i++) {
710 Object* key = table->KeyAt(i); 731 Object* key = table->KeyAt(i);
711 if (key == the_hole) continue; 732 if (key == the_hole) continue;
712 entries->set(result_index++, key); 733 entries->set(result_index++, key);
713 } 734 }
714 DCHECK_EQ(result_index, length); 735 DCHECK_EQ(result_index, length);
715 } 736 }
716 737
717 // Then write it out. 738 // Then write it out.
718 WriteTag(SerializationTag::kBeginJSSet); 739 WriteTag(SerializationTag::kBeginJSSet);
719 for (int i = 0; i < length; i++) { 740 for (int i = 0; i < length; i++) {
720 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) { 741 if (!WriteObject(handle(entries->get(i), isolate_)).FromMaybe(false)) {
721 return Nothing<bool>(); 742 return Nothing<bool>();
722 } 743 }
723 } 744 }
724 WriteTag(SerializationTag::kEndJSSet); 745 WriteTag(SerializationTag::kEndJSSet);
725 WriteVarint<uint32_t>(length); 746 WriteVarint<uint32_t>(length);
726 return Just(true); 747 return ThrowIfOutOfMemory();
727 } 748 }
728 749
729 Maybe<bool> ValueSerializer::WriteJSArrayBuffer( 750 Maybe<bool> ValueSerializer::WriteJSArrayBuffer(
730 Handle<JSArrayBuffer> array_buffer) { 751 Handle<JSArrayBuffer> array_buffer) {
731 if (array_buffer->is_shared()) { 752 if (array_buffer->is_shared()) {
732 if (!delegate_) { 753 if (!delegate_) {
733 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); 754 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
734 return Nothing<bool>(); 755 return Nothing<bool>();
735 } 756 }
736 757
737 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); 758 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
738 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId( 759 Maybe<uint32_t> index = delegate_->GetSharedArrayBufferId(
739 v8_isolate, Utils::ToLocalShared(array_buffer)); 760 v8_isolate, Utils::ToLocalShared(array_buffer));
740 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>()); 761 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate_, Nothing<bool>());
741 762
742 WriteTag(SerializationTag::kSharedArrayBuffer); 763 WriteTag(SerializationTag::kSharedArrayBuffer);
743 WriteVarint(index.FromJust()); 764 WriteVarint(index.FromJust());
744 return Just(true); 765 return ThrowIfOutOfMemory();
745 } 766 }
746 767
747 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer); 768 uint32_t* transfer_entry = array_buffer_transfer_map_.Find(array_buffer);
748 if (transfer_entry) { 769 if (transfer_entry) {
749 WriteTag(SerializationTag::kArrayBufferTransfer); 770 WriteTag(SerializationTag::kArrayBufferTransfer);
750 WriteVarint(*transfer_entry); 771 WriteVarint(*transfer_entry);
751 return Just(true); 772 return ThrowIfOutOfMemory();
752 } 773 }
753 if (array_buffer->was_neutered()) { 774 if (array_buffer->was_neutered()) {
754 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer); 775 ThrowDataCloneError(MessageTemplate::kDataCloneErrorNeuteredArrayBuffer);
755 return Nothing<bool>(); 776 return Nothing<bool>();
756 } 777 }
757 double byte_length = array_buffer->byte_length()->Number(); 778 double byte_length = array_buffer->byte_length()->Number();
758 if (byte_length > std::numeric_limits<uint32_t>::max()) { 779 if (byte_length > std::numeric_limits<uint32_t>::max()) {
759 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer); 780 ThrowDataCloneError(MessageTemplate::kDataCloneError, array_buffer);
760 return Nothing<bool>(); 781 return Nothing<bool>();
761 } 782 }
762 WriteTag(SerializationTag::kArrayBuffer); 783 WriteTag(SerializationTag::kArrayBuffer);
763 WriteVarint<uint32_t>(byte_length); 784 WriteVarint<uint32_t>(byte_length);
764 WriteRawBytes(array_buffer->backing_store(), byte_length); 785 WriteRawBytes(array_buffer->backing_store(), byte_length);
765 return Just(true); 786 return ThrowIfOutOfMemory();
766 } 787 }
767 788
768 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) { 789 Maybe<bool> ValueSerializer::WriteJSArrayBufferView(JSArrayBufferView* view) {
769 WriteTag(SerializationTag::kArrayBufferView); 790 WriteTag(SerializationTag::kArrayBufferView);
770 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array; 791 ArrayBufferViewTag tag = ArrayBufferViewTag::kInt8Array;
771 if (view->IsJSTypedArray()) { 792 if (view->IsJSTypedArray()) {
772 switch (JSTypedArray::cast(view)->type()) { 793 switch (JSTypedArray::cast(view)->type()) {
773 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 794 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
774 case kExternal##Type##Array: \ 795 case kExternal##Type##Array: \
775 tag = ArrayBufferViewTag::k##Type##Array; \ 796 tag = ArrayBufferViewTag::k##Type##Array; \
776 break; 797 break;
777 TYPED_ARRAYS(TYPED_ARRAY_CASE) 798 TYPED_ARRAYS(TYPED_ARRAY_CASE)
778 #undef TYPED_ARRAY_CASE 799 #undef TYPED_ARRAY_CASE
779 } 800 }
780 } else { 801 } else {
781 DCHECK(view->IsJSDataView()); 802 DCHECK(view->IsJSDataView());
782 tag = ArrayBufferViewTag::kDataView; 803 tag = ArrayBufferViewTag::kDataView;
783 } 804 }
784 WriteVarint(static_cast<uint8_t>(tag)); 805 WriteVarint(static_cast<uint8_t>(tag));
785 WriteVarint(NumberToUint32(view->byte_offset())); 806 WriteVarint(NumberToUint32(view->byte_offset()));
786 WriteVarint(NumberToUint32(view->byte_length())); 807 WriteVarint(NumberToUint32(view->byte_length()));
787 return Just(true); 808 return ThrowIfOutOfMemory();
788 } 809 }
789 810
790 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) { 811 Maybe<bool> ValueSerializer::WriteWasmModule(Handle<JSObject> object) {
791 Handle<WasmCompiledModule> compiled_part( 812 Handle<WasmCompiledModule> compiled_part(
792 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_); 813 WasmCompiledModule::cast(object->GetInternalField(0)), isolate_);
793 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes; 814 WasmEncodingTag encoding_tag = WasmEncodingTag::kRawBytes;
794 WriteTag(SerializationTag::kWasmModule); 815 WriteTag(SerializationTag::kWasmModule);
795 WriteRawBytes(&encoding_tag, sizeof(encoding_tag)); 816 WriteRawBytes(&encoding_tag, sizeof(encoding_tag));
796 817
797 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_); 818 Handle<String> wire_bytes(compiled_part->module_bytes(), isolate_);
798 int wire_bytes_length = wire_bytes->length(); 819 int wire_bytes_length = wire_bytes->length();
799 WriteVarint<uint32_t>(wire_bytes_length); 820 WriteVarint<uint32_t>(wire_bytes_length);
800 uint8_t* destination = ReserveRawBytes(wire_bytes_length); 821 uint8_t* destination;
801 String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length); 822 if (ReserveRawBytes(wire_bytes_length).To(&destination)) {
823 String::WriteToFlat(*wire_bytes, destination, 0, wire_bytes_length);
824 }
802 825
803 std::unique_ptr<ScriptData> script_data = 826 std::unique_ptr<ScriptData> script_data =
804 WasmCompiledModuleSerializer::SerializeWasmModule(isolate_, 827 WasmCompiledModuleSerializer::SerializeWasmModule(isolate_,
805 compiled_part); 828 compiled_part);
806 int script_data_length = script_data->length(); 829 int script_data_length = script_data->length();
807 WriteVarint<uint32_t>(script_data_length); 830 WriteVarint<uint32_t>(script_data_length);
808 WriteRawBytes(script_data->data(), script_data_length); 831 WriteRawBytes(script_data->data(), script_data_length);
809 832
810 return Just(true); 833 return ThrowIfOutOfMemory();
811 } 834 }
812 835
813 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) { 836 Maybe<bool> ValueSerializer::WriteHostObject(Handle<JSObject> object) {
814 if (!delegate_) { 837 if (!delegate_) {
815 isolate_->Throw(*isolate_->factory()->NewError( 838 isolate_->Throw(*isolate_->factory()->NewError(
816 isolate_->error_function(), MessageTemplate::kDataCloneError, object)); 839 isolate_->error_function(), MessageTemplate::kDataCloneError, object));
817 return Nothing<bool>(); 840 return Nothing<bool>();
818 } 841 }
819 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_); 842 v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
820 Maybe<bool> result = 843 Maybe<bool> result =
(...skipping 30 matching lines...) Expand all
851 } 874 }
852 return Just(properties_written); 875 return Just(properties_written);
853 } 876 }
854 877
855 void ValueSerializer::ThrowDataCloneError( 878 void ValueSerializer::ThrowDataCloneError(
856 MessageTemplate::Template template_index) { 879 MessageTemplate::Template template_index) {
857 return ThrowDataCloneError(template_index, 880 return ThrowDataCloneError(template_index,
858 isolate_->factory()->empty_string()); 881 isolate_->factory()->empty_string());
859 } 882 }
860 883
884 Maybe<bool> ValueSerializer::ThrowIfOutOfMemory() {
885 if (out_of_memory_) {
886 ThrowDataCloneError(MessageTemplate::kDataCloneErrorOutOfMemory);
887 return Nothing<bool>();
888 }
889 return Just(true);
890 }
891
861 void ValueSerializer::ThrowDataCloneError( 892 void ValueSerializer::ThrowDataCloneError(
862 MessageTemplate::Template template_index, Handle<Object> arg0) { 893 MessageTemplate::Template template_index, Handle<Object> arg0) {
863 Handle<String> message = 894 Handle<String> message =
864 MessageTemplate::FormatMessage(isolate_, template_index, arg0); 895 MessageTemplate::FormatMessage(isolate_, template_index, arg0);
865 if (delegate_) { 896 if (delegate_) {
866 delegate_->ThrowDataCloneError(Utils::ToLocal(message)); 897 delegate_->ThrowDataCloneError(Utils::ToLocal(message));
867 } else { 898 } else {
868 isolate_->Throw( 899 isolate_->Throw(
869 *isolate_->factory()->NewError(isolate_->error_function(), message)); 900 *isolate_->factory()->NewError(isolate_->error_function(), message));
870 } 901 }
(...skipping 1008 matching lines...) Expand 10 before | Expand all | Expand 10 after
1879 if (stack.size() != 1) { 1910 if (stack.size() != 1) {
1880 isolate_->Throw(*isolate_->factory()->NewError( 1911 isolate_->Throw(*isolate_->factory()->NewError(
1881 MessageTemplate::kDataCloneDeserializationError)); 1912 MessageTemplate::kDataCloneDeserializationError));
1882 return MaybeHandle<Object>(); 1913 return MaybeHandle<Object>();
1883 } 1914 }
1884 return scope.CloseAndEscape(stack[0]); 1915 return scope.CloseAndEscape(stack[0]);
1885 } 1916 }
1886 1917
1887 } // namespace internal 1918 } // namespace internal
1888 } // namespace v8 1919 } // namespace v8
OLDNEW
« src/d8.cc ('K') | « src/value-serializer.h ('k') | test/mjsunit/d8-worker.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698