| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/code-factory.h" |
| 8 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 9 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| 10 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
| 11 #include "src/compiler/js-operator.h" | 12 #include "src/compiler/js-operator.h" |
| 13 #include "src/compiler/linkage.h" |
| 12 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
| 13 #include "src/contexts.h" | 15 #include "src/contexts.h" |
| 14 #include "src/field-index-inl.h" | 16 #include "src/field-index-inl.h" |
| 15 #include "src/lookup.h" | 17 #include "src/lookup.h" |
| 16 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 18 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 17 #include "src/type-cache.h" | 19 #include "src/type-cache.h" |
| 18 #include "src/type-feedback-vector.h" | 20 #include "src/type-feedback-vector.h" |
| 19 | 21 |
| 20 namespace v8 { | 22 namespace v8 { |
| 21 namespace internal { | 23 namespace internal { |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 this_receiver = jsgraph()->Constant(holder); | 418 this_receiver = jsgraph()->Constant(holder); |
| 417 } | 419 } |
| 418 Node* this_storage = this_receiver; | 420 Node* this_storage = this_receiver; |
| 419 if (!field_index.is_inobject()) { | 421 if (!field_index.is_inobject()) { |
| 420 this_storage = this_effect = graph()->NewNode( | 422 this_storage = this_effect = graph()->NewNode( |
| 421 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), | 423 simplified()->LoadField(AccessBuilder::ForJSObjectProperties()), |
| 422 this_storage, this_effect, this_control); | 424 this_storage, this_effect, this_control); |
| 423 } | 425 } |
| 424 FieldAccess field_access = {kTaggedBase, field_index.offset(), name, | 426 FieldAccess field_access = {kTaggedBase, field_index.offset(), name, |
| 425 field_type, kMachAnyTagged}; | 427 field_type, kMachAnyTagged}; |
| 426 if (field_type->Is(Type::UntaggedFloat64())) { | 428 if (access_mode == PropertyAccessMode::kLoad) { |
| 427 if (!field_index.is_inobject() || field_index.is_hidden_field() || | 429 if (field_type->Is(Type::UntaggedFloat64())) { |
| 428 !FLAG_unbox_double_fields) { | 430 if (!field_index.is_inobject() || field_index.is_hidden_field() || |
| 429 this_storage = this_effect = | 431 !FLAG_unbox_double_fields) { |
| 430 graph()->NewNode(simplified()->LoadField(field_access), | 432 this_storage = this_effect = |
| 431 this_storage, this_effect, this_control); | 433 graph()->NewNode(simplified()->LoadField(field_access), |
| 432 field_access.offset = HeapNumber::kValueOffset; | 434 this_storage, this_effect, this_control); |
| 433 field_access.name = MaybeHandle<Name>(); | 435 field_access.offset = HeapNumber::kValueOffset; |
| 436 field_access.name = MaybeHandle<Name>(); |
| 437 } |
| 438 field_access.machine_type = kMachFloat64; |
| 434 } | 439 } |
| 435 field_access.machine_type = kMachFloat64; | |
| 436 } | |
| 437 if (access_mode == PropertyAccessMode::kLoad) { | |
| 438 this_value = this_effect = | 440 this_value = this_effect = |
| 439 graph()->NewNode(simplified()->LoadField(field_access), | 441 graph()->NewNode(simplified()->LoadField(field_access), |
| 440 this_storage, this_effect, this_control); | 442 this_storage, this_effect, this_control); |
| 441 } else { | 443 } else { |
| 442 DCHECK_EQ(PropertyAccessMode::kStore, access_mode); | 444 DCHECK_EQ(PropertyAccessMode::kStore, access_mode); |
| 443 if (field_type->Is(Type::UntaggedFloat64())) { | 445 if (field_type->Is(Type::UntaggedFloat64())) { |
| 444 Node* check = | 446 Node* check = |
| 445 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); | 447 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); |
| 446 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 448 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 447 check, this_control); | 449 check, this_control); |
| 448 exit_controls.push_back( | 450 exit_controls.push_back( |
| 449 graph()->NewNode(common()->IfFalse(), branch)); | 451 graph()->NewNode(common()->IfFalse(), branch)); |
| 450 this_control = graph()->NewNode(common()->IfTrue(), branch); | 452 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 451 this_value = graph()->NewNode(common()->Guard(Type::Number()), | 453 this_value = graph()->NewNode(common()->Guard(Type::Number()), |
| 452 this_value, this_control); | 454 this_value, this_control); |
| 455 |
| 456 if (!field_index.is_inobject() || field_index.is_hidden_field() || |
| 457 !FLAG_unbox_double_fields) { |
| 458 if (access_info.HasTransitionMap()) { |
| 459 // Allocate a MutableHeapNumber for the new property. |
| 460 Callable callable = |
| 461 CodeFactory::AllocateMutableHeapNumber(isolate()); |
| 462 CallDescriptor* desc = Linkage::GetStubCallDescriptor( |
| 463 isolate(), jsgraph()->zone(), callable.descriptor(), 0, |
| 464 CallDescriptor::kNoFlags, Operator::kNoThrow); |
| 465 Node* this_box = this_effect = graph()->NewNode( |
| 466 common()->Call(desc), |
| 467 jsgraph()->HeapConstant(callable.code()), |
| 468 jsgraph()->NoContextConstant(), this_effect, this_control); |
| 469 this_effect = graph()->NewNode( |
| 470 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), |
| 471 this_box, this_value, this_effect, this_control); |
| 472 this_value = this_box; |
| 473 |
| 474 field_access.type = Type::TaggedPointer(); |
| 475 } else { |
| 476 // We just store directly to the MutableHeapNumber. |
| 477 this_storage = this_effect = |
| 478 graph()->NewNode(simplified()->LoadField(field_access), |
| 479 this_storage, this_effect, this_control); |
| 480 field_access.offset = HeapNumber::kValueOffset; |
| 481 field_access.name = MaybeHandle<Name>(); |
| 482 field_access.machine_type = kMachFloat64; |
| 483 } |
| 484 } else { |
| 485 // Unboxed double field, we store directly to the field. |
| 486 field_access.machine_type = kMachFloat64; |
| 487 } |
| 453 } else if (field_type->Is(Type::TaggedSigned())) { | 488 } else if (field_type->Is(Type::TaggedSigned())) { |
| 454 Node* check = | 489 Node* check = |
| 455 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); | 490 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); |
| 456 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 491 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), |
| 457 check, this_control); | 492 check, this_control); |
| 458 exit_controls.push_back( | 493 exit_controls.push_back( |
| 459 graph()->NewNode(common()->IfFalse(), branch)); | 494 graph()->NewNode(common()->IfFalse(), branch)); |
| 460 this_control = graph()->NewNode(common()->IfTrue(), branch); | 495 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 461 } else if (field_type->Is(Type::TaggedPointer())) { | 496 } else if (field_type->Is(Type::TaggedPointer())) { |
| 462 Node* check = | 497 Node* check = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 Handle<Map> transition_map; | 533 Handle<Map> transition_map; |
| 499 if (access_info.transition_map().ToHandle(&transition_map)) { | 534 if (access_info.transition_map().ToHandle(&transition_map)) { |
| 500 this_effect = graph()->NewNode(common()->BeginRegion(), this_effect); | 535 this_effect = graph()->NewNode(common()->BeginRegion(), this_effect); |
| 501 this_effect = graph()->NewNode( | 536 this_effect = graph()->NewNode( |
| 502 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver, | 537 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver, |
| 503 jsgraph()->Constant(transition_map), this_effect, this_control); | 538 jsgraph()->Constant(transition_map), this_effect, this_control); |
| 504 } | 539 } |
| 505 this_effect = graph()->NewNode(simplified()->StoreField(field_access), | 540 this_effect = graph()->NewNode(simplified()->StoreField(field_access), |
| 506 this_storage, this_value, this_effect, | 541 this_storage, this_value, this_effect, |
| 507 this_control); | 542 this_control); |
| 508 if (!access_info.transition_map().is_null()) { | 543 if (access_info.HasTransitionMap()) { |
| 509 this_effect = | 544 this_effect = |
| 510 graph()->NewNode(common()->FinishRegion(), | 545 graph()->NewNode(common()->FinishRegion(), |
| 511 jsgraph()->UndefinedConstant(), this_effect); | 546 jsgraph()->UndefinedConstant(), this_effect); |
| 512 } | 547 } |
| 513 } | 548 } |
| 514 } | 549 } |
| 515 | 550 |
| 516 // Remember the final state for this property access. | 551 // Remember the final state for this property access. |
| 517 values.push_back(this_value); | 552 values.push_back(this_value); |
| 518 effects.push_back(this_effect); | 553 effects.push_back(this_effect); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 } | 721 } |
| 687 | 722 |
| 688 | 723 |
| 689 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 724 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 690 return jsgraph()->simplified(); | 725 return jsgraph()->simplified(); |
| 691 } | 726 } |
| 692 | 727 |
| 693 } // namespace compiler | 728 } // namespace compiler |
| 694 } // namespace internal | 729 } // namespace internal |
| 695 } // namespace v8 | 730 } // namespace v8 |
| OLD | NEW |