OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef VM_OBJECT_H_ | 5 #ifndef VM_OBJECT_H_ |
6 #define VM_OBJECT_H_ | 6 #define VM_OBJECT_H_ |
7 | 7 |
8 #include "include/dart_api.h" | 8 #include "include/dart_api.h" |
9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
10 #include "platform/utils.h" | 10 #include "platform/utils.h" |
(...skipping 3529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3540 RawArray* arguments_descriptor() const { | 3540 RawArray* arguments_descriptor() const { |
3541 return raw_ptr()->args_descriptor_; | 3541 return raw_ptr()->args_descriptor_; |
3542 } | 3542 } |
3543 | 3543 |
3544 intptr_t NumArgsTested() const; | 3544 intptr_t NumArgsTested() const; |
3545 | 3545 |
3546 intptr_t deopt_id() const { | 3546 intptr_t deopt_id() const { |
3547 return raw_ptr()->deopt_id_; | 3547 return raw_ptr()->deopt_id_; |
3548 } | 3548 } |
3549 | 3549 |
3550 uint32_t range_feedback() const { | |
3551 return raw_ptr()->range_feedback_; | |
3552 } | |
3553 | |
3550 #define DEOPT_REASONS(V) \ | 3554 #define DEOPT_REASONS(V) \ |
3551 V(Unknown) \ | 3555 V(Unknown) \ |
3552 V(InstanceGetter) \ | 3556 V(InstanceGetter) \ |
3553 V(PolymorphicInstanceCallTestFail) \ | 3557 V(PolymorphicInstanceCallTestFail) \ |
3554 V(InstanceCallNoICData) \ | 3558 V(InstanceCallNoICData) \ |
3555 V(IntegerToDouble) \ | 3559 V(IntegerToDouble) \ |
3556 V(BinarySmiOp) \ | 3560 V(BinarySmiOp) \ |
3557 V(BinaryMintOp) \ | 3561 V(BinaryMintOp) \ |
3558 V(UnaryMintOp) \ | 3562 V(UnaryMintOp) \ |
3559 V(ShiftMintOp) \ | 3563 V(ShiftMintOp) \ |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3634 } | 3638 } |
3635 | 3639 |
3636 static intptr_t ic_data_offset() { | 3640 static intptr_t ic_data_offset() { |
3637 return OFFSET_OF(RawICData, ic_data_); | 3641 return OFFSET_OF(RawICData, ic_data_); |
3638 } | 3642 } |
3639 | 3643 |
3640 static intptr_t owner_offset() { | 3644 static intptr_t owner_offset() { |
3641 return OFFSET_OF(RawICData, owner_); | 3645 return OFFSET_OF(RawICData, owner_); |
3642 } | 3646 } |
3643 | 3647 |
3648 static intptr_t range_feedback_offset() { | |
3649 return OFFSET_OF(RawICData, range_feedback_); | |
3650 } | |
3651 | |
3644 // Used for unoptimized static calls when no class-ids are checked. | 3652 // Used for unoptimized static calls when no class-ids are checked. |
3645 void AddTarget(const Function& target) const; | 3653 void AddTarget(const Function& target) const; |
3646 | 3654 |
3647 // Adding checks. | 3655 // Adding checks. |
3648 | 3656 |
3649 // Adds one more class test to ICData. Length of 'classes' must be equal to | 3657 // Adds one more class test to ICData. Length of 'classes' must be equal to |
3650 // the number of arguments tested. Use only for num_args_tested > 1. | 3658 // the number of arguments tested. Use only for num_args_tested > 1. |
3651 void AddCheck(const GrowableArray<intptr_t>& class_ids, | 3659 void AddCheck(const GrowableArray<intptr_t>& class_ids, |
3652 const Function& target) const; | 3660 const Function& target) const; |
3653 // Adds sorted so that Smi is the first class-id. Use only for | 3661 // Adds sorted so that Smi is the first class-id. Use only for |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3708 | 3716 |
3709 static intptr_t CountIndexFor(intptr_t num_args) { | 3717 static intptr_t CountIndexFor(intptr_t num_args) { |
3710 return (num_args + 1); | 3718 return (num_args + 1); |
3711 } | 3719 } |
3712 | 3720 |
3713 bool IsUsedAt(intptr_t i) const; | 3721 bool IsUsedAt(intptr_t i) const; |
3714 | 3722 |
3715 void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, | 3723 void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, |
3716 GrowableArray<intptr_t>* second) const; | 3724 GrowableArray<intptr_t>* second) const; |
3717 | 3725 |
3726 // Range feedback tracking functionality. | |
3727 | |
3728 // For arithmetic operations we store range information for inputs and the | |
3729 // result. The goal is to discover: | |
3730 // | |
3731 // - on 32-bit platforms: | |
3732 // - when Mint operation is actually a int32/uint32 operation; | |
3733 // - when Smi operation produces non-smi results; | |
3734 // | |
3735 // - on 64-bit platforms: | |
3736 // - when Smi operation is actually int32/uint32 operation; | |
3737 // - when Mint operation produces non-smi results; | |
3738 // | |
3739 enum RangeFeedback { | |
3740 kSmiRange, | |
3741 kInt32Range, | |
3742 kUint32Range, | |
3743 kInt64Range | |
3744 }; | |
3745 | |
3746 // We use 4 bits per operand/result feedback. Our lattice allows us to | |
3747 // express the following states: | |
3748 // | |
3749 // - usmi 0000 [used only on 32bit platforms] | |
3750 // - smi 0001 | |
3751 // - uint31 0010 | |
3752 // - int32 0011 | |
3753 // - uint32 0100 | |
3754 // - int33 x1x1 | |
3755 // - int64 1xxx | |
3756 // | |
3757 // DecodeRangeFeedbackAt() helper maps these states into the RangeFeedback | |
3758 // enumeration. | |
3759 enum { | |
3760 kSignBit = 1 << 0, | |
3761 kInt32Bit = 1 << 1, | |
3762 kUint32Bit = 1 << 2, | |
3763 kInt64Bit = 1 << 3, | |
3764 kBitsPerRangeFeedback = 4, | |
3765 kRangeFeedbackMask = (1 << kBitsPerRangeFeedback) - 1 | |
3766 }; | |
3767 | |
3768 static bool IsValidRangeFeedbackIndex(intptr_t index) { | |
3769 return (0 <= index) && (index < 3); | |
3770 } | |
3771 | |
3772 static const char* RangeFeedbackToString(RangeFeedback feedback) { | |
3773 switch (feedback) { | |
3774 case kSmiRange: | |
3775 return "smi"; | |
3776 case kInt32Range: | |
3777 return "int32"; | |
3778 case kUint32Range: | |
3779 return "uint32"; | |
3780 case kInt64Range: | |
3781 return "int64"; | |
3782 default: | |
3783 UNREACHABLE(); | |
3784 return "?"; | |
3785 } | |
3786 } | |
3787 | |
3788 // It is only meaningful to interptret range feedback stored in the ICData | |
3789 // when all checks are Mint or Smi. | |
3790 bool HasRangeFeedback() const; | |
3791 RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const; | |
3792 | |
3718 private: | 3793 private: |
3719 RawArray* ic_data() const { | 3794 RawArray* ic_data() const { |
3720 return raw_ptr()->ic_data_; | 3795 return raw_ptr()->ic_data_; |
3721 } | 3796 } |
3722 | 3797 |
3723 void set_owner(const Function& value) const; | 3798 void set_owner(const Function& value) const; |
3724 void set_target_name(const String& value) const; | 3799 void set_target_name(const String& value) const; |
3725 void set_arguments_descriptor(const Array& value) const; | 3800 void set_arguments_descriptor(const Array& value) const; |
3726 void set_deopt_id(intptr_t value) const; | 3801 void set_deopt_id(intptr_t value) const; |
3727 void SetNumArgsTested(intptr_t value) const; | 3802 void SetNumArgsTested(intptr_t value) const; |
3728 void set_ic_data(const Array& value) const; | 3803 void set_ic_data(const Array& value) const; |
3729 void set_state_bits(uint32_t bits) const; | 3804 void set_state_bits(uint32_t bits) const; |
3805 void set_range_feedback(uint32_t feedback); | |
3730 | 3806 |
3731 enum { | 3807 enum { |
3732 kNumArgsTestedPos = 0, | 3808 kNumArgsTestedPos = 0, |
3733 kNumArgsTestedSize = 2, | 3809 kNumArgsTestedSize = 2, |
3734 kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize, | 3810 kDeoptReasonPos = kNumArgsTestedPos + kNumArgsTestedSize, |
3735 kDeoptReasonSize = kDeoptNumReasons, | 3811 kDeoptReasonSize = kDeoptNumReasons, |
3736 kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize, | 3812 kIssuedJSWarningBit = kDeoptReasonPos + kDeoptReasonSize, |
zra
2014/12/15 16:01:41
If we didn't need to encode so many deopt reasons,
Vyacheslav Egorov (Google)
2014/12/15 17:20:05
We actually don't need most of the deopt reasons.
| |
3737 }; | 3813 }; |
3738 | 3814 |
3739 class NumArgsTestedBits : public BitField<uint32_t, | 3815 class NumArgsTestedBits : public BitField<uint32_t, |
3740 kNumArgsTestedPos, kNumArgsTestedSize> {}; // NOLINT | 3816 kNumArgsTestedPos, kNumArgsTestedSize> {}; // NOLINT |
3741 class DeoptReasonBits : public BitField<uint32_t, | 3817 class DeoptReasonBits : public BitField<uint32_t, |
3742 ICData::kDeoptReasonPos, ICData::kDeoptReasonSize> {}; // NOLINT | 3818 ICData::kDeoptReasonPos, ICData::kDeoptReasonSize> {}; // NOLINT |
3743 class IssuedJSWarningBit : public BitField<bool, kIssuedJSWarningBit, 1> {}; | 3819 class IssuedJSWarningBit : public BitField<bool, kIssuedJSWarningBit, 1> {}; |
3744 | 3820 |
3745 #if defined(DEBUG) | 3821 #if defined(DEBUG) |
3746 // Used in asserts to verify that a check is not added twice. | 3822 // Used in asserts to verify that a check is not added twice. |
(...skipping 3845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7592 | 7668 |
7593 | 7669 |
7594 RawObject* MegamorphicCache::GetTargetFunction(const Array& array, | 7670 RawObject* MegamorphicCache::GetTargetFunction(const Array& array, |
7595 intptr_t index) { | 7671 intptr_t index) { |
7596 return array.At((index * kEntryLength) + kTargetFunctionIndex); | 7672 return array.At((index * kEntryLength) + kTargetFunctionIndex); |
7597 } | 7673 } |
7598 | 7674 |
7599 } // namespace dart | 7675 } // namespace dart |
7600 | 7676 |
7601 #endif // VM_OBJECT_H_ | 7677 #endif // VM_OBJECT_H_ |
OLD | NEW |