Index: runtime/vm/object.h |
diff --git a/runtime/vm/object.h b/runtime/vm/object.h |
index cdf9ddb515c0212cd24dd0a2446c5f6802c7f57b..c4e75f2e210b64eed239c9ae5bac29096c612ec9 100644 |
--- a/runtime/vm/object.h |
+++ b/runtime/vm/object.h |
@@ -3547,6 +3547,10 @@ class ICData : public Object { |
return raw_ptr()->deopt_id_; |
} |
+ uint32_t range_feedback() const { |
+ return raw_ptr()->range_feedback_; |
+ } |
+ |
#define DEOPT_REASONS(V) \ |
V(Unknown) \ |
V(InstanceGetter) \ |
@@ -3641,6 +3645,10 @@ class ICData : public Object { |
return OFFSET_OF(RawICData, owner_); |
} |
+ static intptr_t range_feedback_offset() { |
+ return OFFSET_OF(RawICData, range_feedback_); |
+ } |
+ |
// Used for unoptimized static calls when no class-ids are checked. |
void AddTarget(const Function& target) const; |
@@ -3715,6 +3723,73 @@ class ICData : public Object { |
void GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, |
GrowableArray<intptr_t>* second) const; |
+ // Range feedback tracking functionality. |
+ |
+ // For arithmetic operations we store range information for inputs and the |
+ // result. The goal is to discover: |
+ // |
+ // - on 32-bit platforms: |
+ // - when Mint operation is actually a int32/uint32 operation; |
+ // - when Smi operation produces non-smi results; |
+ // |
+ // - on 64-bit platforms: |
+ // - when Smi operation is actually int32/uint32 operation; |
+ // - when Mint operation produces non-smi results; |
+ // |
+ enum RangeFeedback { |
+ kSmiRange, |
+ kInt32Range, |
+ kUint32Range, |
+ kInt64Range |
+ }; |
+ |
+ // We use 4 bits per operand/result feedback. Our lattice allows us to |
+ // express the following states: |
+ // |
+ // - usmi 0000 [used only on 32bit platforms] |
+ // - smi 0001 |
+ // - uint31 0010 |
+ // - int32 0011 |
+ // - uint32 0100 |
+ // - int33 x1x1 |
+ // - int64 1xxx |
+ // |
+ // DecodeRangeFeedbackAt() helper maps these states into the RangeFeedback |
+ // enumeration. |
+ enum { |
+ kSignedRangeBit = 1 << 0, |
+ kInt32RangeBit = 1 << 1, |
+ kUint32RangeBit = 1 << 2, |
+ kInt64RangeBit = 1 << 3, |
+ kBitsPerRangeFeedback = 4, |
+ kRangeFeedbackMask = (1 << kBitsPerRangeFeedback) - 1 |
+ }; |
+ |
+ static bool IsValidRangeFeedbackIndex(intptr_t index) { |
+ return (0 <= index) && (index < 3); |
+ } |
+ |
+ static const char* RangeFeedbackToString(RangeFeedback feedback) { |
+ switch (feedback) { |
+ case kSmiRange: |
+ return "smi"; |
+ case kInt32Range: |
+ return "int32"; |
+ case kUint32Range: |
+ return "uint32"; |
+ case kInt64Range: |
+ return "int64"; |
+ default: |
+ UNREACHABLE(); |
+ return "?"; |
+ } |
+ } |
+ |
+ // It is only meaningful to interptret range feedback stored in the ICData |
+ // when all checks are Mint or Smi. |
+ bool HasRangeFeedback() const; |
+ RangeFeedback DecodeRangeFeedbackAt(intptr_t idx) const; |
+ |
private: |
RawArray* ic_data() const { |
return raw_ptr()->ic_data_; |
@@ -3727,6 +3802,7 @@ class ICData : public Object { |
void SetNumArgsTested(intptr_t value) const; |
void set_ic_data(const Array& value) const; |
void set_state_bits(uint32_t bits) const; |
+ void set_range_feedback(uint32_t feedback); |
enum { |
kNumArgsTestedPos = 0, |