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 |