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