Index: src/ic.h |
diff --git a/src/ic.h b/src/ic.h |
index b1a47e2b2171b3d52de6d00e7d0c17aec60e3a63..e018d402bbc2777eacd2f6f49b79f0e445c99d3f 100644 |
--- a/src/ic.h |
+++ b/src/ic.h |
@@ -810,25 +810,114 @@ class KeyedStoreIC: public StoreIC { |
}; |
+// Mode to overwrite BinaryExpression values. |
+enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT }; |
+ |
// Type Recording BinaryOpIC, that records the types of the inputs and outputs. |
class BinaryOpIC: public IC { |
public: |
- enum TypeInfo { |
- UNINITIALIZED, |
- SMI, |
- INT32, |
- NUMBER, |
- ODDBALL, |
- STRING, // Only used for addition operation. |
- GENERIC |
+ class State V8_FINAL BASE_EMBEDDED { |
+ public: |
+ explicit State(ExtraICState extra_ic_state); |
+ |
+ State(Token::Value op, OverwriteMode mode) |
+ : op_(op), mode_(mode), left_kind_(NONE), right_kind_(NONE), |
+ result_kind_(NONE) { |
+ ASSERT_LE(FIRST_TOKEN, op); |
+ ASSERT_LE(op, LAST_TOKEN); |
+ } |
+ |
+ InlineCacheState GetICState() const { |
+ if (Max(left_kind_, right_kind_) == NONE) { |
+ return ::v8::internal::UNINITIALIZED; |
+ } |
+ if (Max(left_kind_, right_kind_) == GENERIC) { |
+ return ::v8::internal::MEGAMORPHIC; |
+ } |
+ if (Min(left_kind_, right_kind_) == GENERIC) { |
+ return ::v8::internal::GENERIC; |
+ } |
+ return ::v8::internal::MONOMORPHIC; |
+ } |
+ |
+ ExtraICState GetExtraICState() const; |
+ |
+ static void GenerateAheadOfTime( |
+ Isolate*, void (*Generate)(Isolate*, const State&)); |
+ |
+ bool CanReuseDoubleBox() const { |
+ return (result_kind_ > SMI && result_kind_ <= NUMBER) && |
+ ((mode_ == OVERWRITE_LEFT && |
+ left_kind_ > SMI && left_kind_ <= NUMBER) || |
+ (mode_ == OVERWRITE_RIGHT && |
+ right_kind_ > SMI && right_kind_ <= NUMBER)); |
+ } |
+ |
+ bool HasSideEffects() const { |
+ return Max(left_kind_, right_kind_) == GENERIC; |
+ } |
+ |
+ bool UseInlinedSmiCode() const { |
+ return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_); |
+ } |
+ |
+ static const int FIRST_TOKEN = Token::BIT_OR; |
+ static const int LAST_TOKEN = Token::MOD; |
+ |
+ Token::Value op() const { return op_; } |
+ OverwriteMode mode() const { return mode_; } |
+ Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } |
+ |
+ Handle<Type> GetLeftType(Isolate* isolate) const { |
+ return KindToType(left_kind_, isolate); |
+ } |
+ Handle<Type> GetRightType(Isolate* isolate) const { |
+ return KindToType(right_kind_, isolate); |
+ } |
+ Handle<Type> GetResultType(Isolate* isolate) const; |
+ |
+ void Print(StringStream* stream) const; |
+ |
+ void Update(Handle<Object> left, |
+ Handle<Object> right, |
+ Handle<Object> result); |
+ |
+ private: |
+ enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC }; |
+ |
+ Kind UpdateKind(Handle<Object> object, Kind kind) const; |
+ |
+ static const char* KindToString(Kind kind); |
+ static Handle<Type> KindToType(Kind kind, Isolate* isolate); |
+ static bool KindMaybeSmi(Kind kind) { |
+ return (kind >= SMI && kind <= NUMBER) || kind == GENERIC; |
+ } |
+ |
+ // We truncate the last bit of the token. |
+ STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4)); |
+ class OpField: public BitField<int, 0, 4> {}; |
+ class OverwriteModeField: public BitField<OverwriteMode, 4, 2> {}; |
+ class SSE2Field: public BitField<bool, 6, 1> {}; |
+ class ResultKindField: public BitField<Kind, 7, 3> {}; |
+ class LeftKindField: public BitField<Kind, 10, 3> {}; |
+ // When fixed right arg is set, we don't need to store the right kind. |
+ // Thus the two fields can overlap. |
+ class HasFixedRightArgField: public BitField<bool, 13, 1> {}; |
+ class FixedRightArgValueField: public BitField<int, 14, 4> {}; |
+ class RightKindField: public BitField<Kind, 14, 3> {}; |
+ |
+ Token::Value op_; |
+ OverwriteMode mode_; |
+ Kind left_kind_; |
+ Kind right_kind_; |
+ Kind result_kind_; |
+ Maybe<int> fixed_right_arg_; |
}; |
explicit BinaryOpIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { } |
static Builtins::JavaScript TokenToJSBuiltin(Token::Value op); |
- static const char* GetName(TypeInfo type_info); |
- |
MUST_USE_RESULT MaybeObject* Transition(Handle<Object> left, |
Handle<Object> right); |
}; |