OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ | 5 #ifndef V8_HYDROGEN_INSTRUCTIONS_H_ |
6 #define V8_HYDROGEN_INSTRUCTIONS_H_ | 6 #define V8_HYDROGEN_INSTRUCTIONS_H_ |
7 | 7 |
8 #include "v8.h" | 8 #include "v8.h" |
9 | 9 |
10 #include "allocation.h" | 10 #include "allocation.h" |
(...skipping 2726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2737 | 2737 |
2738 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 2738 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
2739 | 2739 |
2740 const Heap::RootListIndex index_; | 2740 const Heap::RootListIndex index_; |
2741 }; | 2741 }; |
2742 | 2742 |
2743 | 2743 |
2744 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> { | 2744 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> { |
2745 public: | 2745 public: |
2746 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value, | 2746 static HCheckMaps* New(Zone* zone, HValue* context, HValue* value, |
2747 Handle<Map> map, CompilationInfo* info, | 2747 Handle<Map> map, HValue* typecheck = NULL) { |
2748 HValue* typecheck = NULL); | 2748 return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>( |
| 2749 Unique<Map>::CreateImmovable(map), zone), typecheck); |
| 2750 } |
2749 static HCheckMaps* New(Zone* zone, HValue* context, | 2751 static HCheckMaps* New(Zone* zone, HValue* context, |
2750 HValue* value, SmallMapList* map_list, | 2752 HValue* value, SmallMapList* map_list, |
2751 HValue* typecheck = NULL) { | 2753 HValue* typecheck = NULL) { |
2752 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone); | 2754 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(map_list->length(), zone); |
2753 for (int i = 0; i < map_list->length(); ++i) { | 2755 for (int i = 0; i < map_list->length(); ++i) { |
2754 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone); | 2756 maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone); |
2755 } | 2757 } |
2756 return new(zone) HCheckMaps(value, maps, typecheck); | 2758 return new(zone) HCheckMaps(value, maps, typecheck); |
2757 } | 2759 } |
2758 | 2760 |
2759 bool CanOmitMapChecks() { return omit_; } | 2761 bool IsStabilityCheck() const { return is_stability_check_; } |
| 2762 void MarkAsStabilityCheck() { |
| 2763 has_migration_target_ = false; |
| 2764 is_stability_check_ = true; |
| 2765 ClearChangesFlag(kNewSpacePromotion); |
| 2766 ClearDependsOnFlag(kElementsKind); |
| 2767 ClearDependsOnFlag(kMaps); |
| 2768 } |
2760 | 2769 |
2761 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } | 2770 virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } |
2762 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { | 2771 virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE { |
2763 return Representation::Tagged(); | 2772 return Representation::Tagged(); |
2764 } | 2773 } |
2765 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; | 2774 virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; |
2766 | 2775 |
2767 HValue* value() { return OperandAt(0); } | 2776 HValue* value() { return OperandAt(0); } |
2768 HValue* typecheck() { return OperandAt(1); } | 2777 HValue* typecheck() { return OperandAt(1); } |
2769 | 2778 |
2770 const UniqueSet<Map>* maps() const { return maps_; } | 2779 const UniqueSet<Map>* maps() const { return maps_; } |
2771 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; } | 2780 void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; } |
2772 | 2781 |
2773 bool has_migration_target() const { | 2782 bool maps_are_stable() const { return maps_are_stable_; } |
2774 return has_migration_target_; | 2783 |
2775 } | 2784 bool HasMigrationTarget() const { return has_migration_target_; } |
| 2785 |
| 2786 virtual HValue* Canonicalize() V8_OVERRIDE; |
2776 | 2787 |
2777 DECLARE_CONCRETE_INSTRUCTION(CheckMaps) | 2788 DECLARE_CONCRETE_INSTRUCTION(CheckMaps) |
2778 | 2789 |
2779 protected: | 2790 protected: |
2780 virtual bool DataEquals(HValue* other) V8_OVERRIDE { | 2791 virtual bool DataEquals(HValue* other) V8_OVERRIDE { |
2781 return this->maps()->Equals(HCheckMaps::cast(other)->maps()); | 2792 return this->maps()->Equals(HCheckMaps::cast(other)->maps()); |
2782 } | 2793 } |
2783 | 2794 |
2784 virtual int RedefinedOperandIndex() { return 0; } | 2795 virtual int RedefinedOperandIndex() { return 0; } |
2785 | 2796 |
2786 private: | 2797 private: |
2787 // Clients should use one of the static New* methods above. | 2798 // Clients should use one of the static New* methods above. |
2788 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck) | 2799 HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck) |
2789 : HTemplateInstruction<2>(value->type()), maps_(maps), | 2800 : HTemplateInstruction<2>(value->type()), maps_(maps), |
2790 omit_(false), has_migration_target_(false) { | 2801 has_migration_target_(false), is_stability_check_(false), |
| 2802 maps_are_stable_(true) { |
2791 ASSERT_NE(0, maps->size()); | 2803 ASSERT_NE(0, maps->size()); |
2792 SetOperandAt(0, value); | 2804 SetOperandAt(0, value); |
2793 // Use the object value for the dependency if NULL is passed. | 2805 // Use the object value for the dependency if NULL is passed. |
2794 SetOperandAt(1, typecheck ? typecheck : value); | 2806 SetOperandAt(1, typecheck ? typecheck : value); |
2795 set_representation(Representation::Tagged()); | 2807 set_representation(Representation::Tagged()); |
2796 SetFlag(kUseGVN); | 2808 SetFlag(kUseGVN); |
2797 SetDependsOnFlag(kMaps); | 2809 SetDependsOnFlag(kMaps); |
2798 SetDependsOnFlag(kElementsKind); | 2810 SetDependsOnFlag(kElementsKind); |
2799 for (int i = 0; i < maps->size(); ++i) { | 2811 for (int i = 0; i < maps->size(); ++i) { |
2800 if (maps->at(i).handle()->is_migration_target()) { | 2812 Handle<Map> map = maps->at(i).handle(); |
2801 SetChangesFlag(kNewSpacePromotion); | 2813 if (map->is_migration_target()) has_migration_target_ = true; |
2802 has_migration_target_ = true; | 2814 if (!map->is_stable()) maps_are_stable_ = false; |
2803 break; | |
2804 } | |
2805 } | 2815 } |
| 2816 if (has_migration_target_) SetChangesFlag(kNewSpacePromotion); |
2806 } | 2817 } |
2807 | 2818 |
2808 const UniqueSet<Map>* maps_; | 2819 const UniqueSet<Map>* maps_; |
2809 bool omit_ : 1; | |
2810 bool has_migration_target_ : 1; | 2820 bool has_migration_target_ : 1; |
| 2821 bool is_stability_check_ : 1; |
| 2822 bool maps_are_stable_ : 1; |
2811 }; | 2823 }; |
2812 | 2824 |
2813 | 2825 |
2814 class HCheckValue V8_FINAL : public HUnaryOperation { | 2826 class HCheckValue V8_FINAL : public HUnaryOperation { |
2815 public: | 2827 public: |
2816 static HCheckValue* New(Zone* zone, HValue* context, | 2828 static HCheckValue* New(Zone* zone, HValue* context, |
2817 HValue* value, Handle<JSFunction> func) { | 2829 HValue* value, Handle<JSFunction> func) { |
2818 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func); | 2830 bool in_new_space = zone->isolate()->heap()->InNewSpace(*func); |
2819 // NOTE: We create an uninitialized Unique and initialize it later. | 2831 // NOTE: We create an uninitialized Unique and initialize it later. |
2820 // This is because a JSFunction can move due to GC during graph creation. | 2832 // This is because a JSFunction can move due to GC during graph creation. |
(...skipping 631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3452 | 3464 |
3453 static HConstant* CreateAndInsertBefore(Zone* zone, | 3465 static HConstant* CreateAndInsertBefore(Zone* zone, |
3454 Unique<Object> unique, | 3466 Unique<Object> unique, |
3455 bool is_not_in_new_space, | 3467 bool is_not_in_new_space, |
3456 HInstruction* instruction) { | 3468 HInstruction* instruction) { |
3457 return instruction->Prepend(new(zone) HConstant( | 3469 return instruction->Prepend(new(zone) HConstant( |
3458 unique, Representation::Tagged(), HType::Tagged(), | 3470 unique, Representation::Tagged(), HType::Tagged(), |
3459 is_not_in_new_space, false, false, kUnknownInstanceType)); | 3471 is_not_in_new_space, false, false, kUnknownInstanceType)); |
3460 } | 3472 } |
3461 | 3473 |
| 3474 static HConstant* CreateAndInsertAfter(Zone* zone, |
| 3475 Unique<Map> unique, |
| 3476 HInstruction* instruction) { |
| 3477 return instruction->Append(new(zone) HConstant( |
| 3478 unique, Representation::Tagged(), HType::Tagged(), |
| 3479 true, false, false, MAP_TYPE)); |
| 3480 } |
| 3481 |
3462 Handle<Object> handle(Isolate* isolate) { | 3482 Handle<Object> handle(Isolate* isolate) { |
3463 if (object_.handle().is_null()) { | 3483 if (object_.handle().is_null()) { |
3464 // Default arguments to is_not_in_new_space depend on this heap number | 3484 // Default arguments to is_not_in_new_space depend on this heap number |
3465 // to be tenured so that it's guaranteed not to be located in new space. | 3485 // to be tenured so that it's guaranteed not to be located in new space. |
3466 object_ = Unique<Object>::CreateUninitialized( | 3486 object_ = Unique<Object>::CreateUninitialized( |
3467 isolate->factory()->NewNumber(double_value_, TENURED)); | 3487 isolate->factory()->NewNumber(double_value_, TENURED)); |
3468 } | 3488 } |
3469 AllowDeferredHandleDereference smi_check; | 3489 AllowDeferredHandleDereference smi_check; |
3470 ASSERT(has_int32_value_ || !object_.handle()->IsSmi()); | 3490 ASSERT(has_int32_value_ || !object_.handle()->IsSmi()); |
3471 return object_.handle(); | 3491 return object_.handle(); |
3472 } | 3492 } |
3473 | 3493 |
3474 bool HasMap(Handle<Map> map) { | |
3475 Handle<Object> constant_object = handle(map->GetIsolate()); | |
3476 return constant_object->IsHeapObject() && | |
3477 Handle<HeapObject>::cast(constant_object)->map() == *map; | |
3478 } | |
3479 | |
3480 bool IsSpecialDouble() const { | 3494 bool IsSpecialDouble() const { |
3481 return has_double_value_ && | 3495 return has_double_value_ && |
3482 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || | 3496 (BitCast<int64_t>(double_value_) == BitCast<int64_t>(-0.0) || |
3483 FixedDoubleArray::is_the_hole_nan(double_value_) || | 3497 FixedDoubleArray::is_the_hole_nan(double_value_) || |
3484 std::isnan(double_value_)); | 3498 std::isnan(double_value_)); |
3485 } | 3499 } |
3486 | 3500 |
3487 bool NotInNewSpace() const { | 3501 bool NotInNewSpace() const { |
3488 return is_not_in_new_space_; | 3502 return is_not_in_new_space_; |
3489 } | 3503 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3554 } | 3568 } |
3555 ExternalReference ExternalReferenceValue() const { | 3569 ExternalReference ExternalReferenceValue() const { |
3556 return external_reference_value_; | 3570 return external_reference_value_; |
3557 } | 3571 } |
3558 | 3572 |
3559 bool HasBooleanValue() const { return type_.IsBoolean(); } | 3573 bool HasBooleanValue() const { return type_.IsBoolean(); } |
3560 bool BooleanValue() const { return boolean_value_; } | 3574 bool BooleanValue() const { return boolean_value_; } |
3561 bool IsUndetectable() const { return is_undetectable_; } | 3575 bool IsUndetectable() const { return is_undetectable_; } |
3562 InstanceType GetInstanceType() const { return instance_type_; } | 3576 InstanceType GetInstanceType() const { return instance_type_; } |
3563 | 3577 |
| 3578 bool HasObjectMap() const { return !object_map_.IsNull(); } |
| 3579 Unique<Map> ObjectMap() const { |
| 3580 ASSERT(HasObjectMap()); |
| 3581 return object_map_; |
| 3582 } |
| 3583 bool ObjectMapIsStable() const { |
| 3584 ASSERT(HasObjectMap()); |
| 3585 return object_map_is_stable_; |
| 3586 } |
| 3587 |
3564 virtual intptr_t Hashcode() V8_OVERRIDE { | 3588 virtual intptr_t Hashcode() V8_OVERRIDE { |
3565 if (has_int32_value_) { | 3589 if (has_int32_value_) { |
3566 return static_cast<intptr_t>(int32_value_); | 3590 return static_cast<intptr_t>(int32_value_); |
3567 } else if (has_double_value_) { | 3591 } else if (has_double_value_) { |
3568 return static_cast<intptr_t>(BitCast<int64_t>(double_value_)); | 3592 return static_cast<intptr_t>(BitCast<int64_t>(double_value_)); |
3569 } else if (has_external_reference_value_) { | 3593 } else if (has_external_reference_value_) { |
3570 return reinterpret_cast<intptr_t>(external_reference_value_.address()); | 3594 return reinterpret_cast<intptr_t>(external_reference_value_.address()); |
3571 } else { | 3595 } else { |
3572 ASSERT(!object_.handle().is_null()); | 3596 ASSERT(!object_.handle().is_null()); |
3573 return object_.Hashcode(); | 3597 return object_.Hashcode(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3646 void Initialize(Representation r); | 3670 void Initialize(Representation r); |
3647 | 3671 |
3648 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 3672 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
3649 | 3673 |
3650 // If this is a numerical constant, object_ either points to the | 3674 // If this is a numerical constant, object_ either points to the |
3651 // HeapObject the constant originated from or is null. If the | 3675 // HeapObject the constant originated from or is null. If the |
3652 // constant is non-numeric, object_ always points to a valid | 3676 // constant is non-numeric, object_ always points to a valid |
3653 // constant HeapObject. | 3677 // constant HeapObject. |
3654 Unique<Object> object_; | 3678 Unique<Object> object_; |
3655 | 3679 |
| 3680 // If this is a heap object, this points to the Map of the object. |
| 3681 Unique<Map> object_map_; |
| 3682 bool object_map_is_stable_ : 1; |
| 3683 |
3656 // We store the HConstant in the most specific form safely possible. | 3684 // We store the HConstant in the most specific form safely possible. |
3657 // The two flags, has_int32_value_ and has_double_value_ tell us if | 3685 // The two flags, has_int32_value_ and has_double_value_ tell us if |
3658 // int32_value_ and double_value_ hold valid, safe representations | 3686 // int32_value_ and double_value_ hold valid, safe representations |
3659 // of the constant. has_int32_value_ implies has_double_value_ but | 3687 // of the constant. has_int32_value_ implies has_double_value_ but |
3660 // not the converse. | 3688 // not the converse. |
3661 bool has_smi_value_ : 1; | 3689 bool has_smi_value_ : 1; |
3662 bool has_int32_value_ : 1; | 3690 bool has_int32_value_ : 1; |
3663 bool has_double_value_ : 1; | 3691 bool has_double_value_ : 1; |
3664 bool has_external_reference_value_ : 1; | 3692 bool has_external_reference_value_ : 1; |
3665 bool is_not_in_new_space_ : 1; | 3693 bool is_not_in_new_space_ : 1; |
(...skipping 3890 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7556 virtual bool IsDeletable() const V8_OVERRIDE { return true; } | 7584 virtual bool IsDeletable() const V8_OVERRIDE { return true; } |
7557 }; | 7585 }; |
7558 | 7586 |
7559 | 7587 |
7560 #undef DECLARE_INSTRUCTION | 7588 #undef DECLARE_INSTRUCTION |
7561 #undef DECLARE_CONCRETE_INSTRUCTION | 7589 #undef DECLARE_CONCRETE_INSTRUCTION |
7562 | 7590 |
7563 } } // namespace v8::internal | 7591 } } // namespace v8::internal |
7564 | 7592 |
7565 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ | 7593 #endif // V8_HYDROGEN_INSTRUCTIONS_H_ |
OLD | NEW |