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
3 // found in the LICENSE file.
8 #include "src/macro-assembler.h"
14 const int kMaxKeyedPolymorphism = 4;
17 class ICUtility : public AllStatic {
19 // Clear the inline cache to initial state.
20 static void Clear(Isolate* isolate, Address address,
21 ConstantPoolArray* constant_pool);
22 // Clear a vector-based inline cache to initial state.
23 template <class Nexus>
24 static void Clear(Isolate* isolate, Code::Kind kind, Code* host,
29 class CallICState FINAL BASE_EMBEDDED {
31 explicit CallICState(ExtraICState extra_ic_state);
33 enum CallType { METHOD, FUNCTION };
35 CallICState(int argc, CallType call_type)
36 : argc_(argc), call_type_(call_type) {}
38 ExtraICState GetExtraICState() const;
40 static void GenerateAheadOfTime(Isolate*,
41 void (*Generate)(Isolate*,
44 int arg_count() const { return argc_; }
45 CallType call_type() const { return call_type_; }
47 bool CallAsMethod() const { return call_type_ == METHOD; }
50 class ArgcBits : public BitField<int, 0, Code::kArgumentsBits> {};
51 class CallTypeBits : public BitField<CallType, Code::kArgumentsBits, 1> {};
54 const CallType call_type_;
58 std::ostream& operator<<(std::ostream& os, const CallICState& s);
61 // Mode to overwrite BinaryExpression values.
62 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
64 class BinaryOpICState FINAL BASE_EMBEDDED {
66 BinaryOpICState(Isolate* isolate, ExtraICState extra_ic_state);
68 BinaryOpICState(Isolate* isolate, Token::Value op, OverwriteMode mode)
75 DCHECK_LE(FIRST_TOKEN, op);
76 DCHECK_LE(op, LAST_TOKEN);
79 InlineCacheState GetICState() const {
80 if (Max(left_kind_, right_kind_) == NONE) {
81 return ::v8::internal::UNINITIALIZED;
83 if (Max(left_kind_, right_kind_) == GENERIC) {
84 return ::v8::internal::MEGAMORPHIC;
86 if (Min(left_kind_, right_kind_) == GENERIC) {
87 return ::v8::internal::GENERIC;
89 return ::v8::internal::MONOMORPHIC;
92 ExtraICState GetExtraICState() const;
94 static void GenerateAheadOfTime(Isolate*,
95 void (*Generate)(Isolate*,
96 const BinaryOpICState&));
98 bool CanReuseDoubleBox() const {
99 return (result_kind_ > SMI && result_kind_ <= NUMBER) &&
100 ((mode_ == OVERWRITE_LEFT && left_kind_ > SMI &&
101 left_kind_ <= NUMBER) ||
102 (mode_ == OVERWRITE_RIGHT && right_kind_ > SMI &&
103 right_kind_ <= NUMBER));
106 // Returns true if the IC _could_ create allocation mementos.
107 bool CouldCreateAllocationMementos() const {
108 if (left_kind_ == STRING || right_kind_ == STRING) {
109 DCHECK_EQ(Token::ADD, op_);
115 // Returns true if the IC _should_ create allocation mementos.
116 bool ShouldCreateAllocationMementos() const {
117 return FLAG_allocation_site_pretenuring && CouldCreateAllocationMementos();
120 bool HasSideEffects() const {
121 return Max(left_kind_, right_kind_) == GENERIC;
124 // Returns true if the IC should enable the inline smi code (i.e. if either
125 // parameter may be a smi).
126 bool UseInlinedSmiCode() const {
127 return KindMaybeSmi(left_kind_) || KindMaybeSmi(right_kind_);
130 static const int FIRST_TOKEN = Token::BIT_OR;
131 static const int LAST_TOKEN = Token::MOD;
133 Token::Value op() const { return op_; }
134 OverwriteMode mode() const { return mode_; }
135 Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
137 Type* GetLeftType(Zone* zone) const { return KindToType(left_kind_, zone); }
138 Type* GetRightType(Zone* zone) const { return KindToType(right_kind_, zone); }
139 Type* GetResultType(Zone* zone) const;
141 void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result);
143 Isolate* isolate() const { return isolate_; }
146 friend std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
148 enum Kind { NONE, SMI, INT32, NUMBER, STRING, GENERIC };
150 Kind UpdateKind(Handle<Object> object, Kind kind) const;
152 static const char* KindToString(Kind kind);
153 static Type* KindToType(Kind kind, Zone* zone);
154 static bool KindMaybeSmi(Kind kind) {
155 return (kind >= SMI && kind <= NUMBER) || kind == GENERIC;
158 // We truncate the last bit of the token.
159 STATIC_ASSERT(LAST_TOKEN - FIRST_TOKEN < (1 << 4));
160 class OpField : public BitField<int, 0, 4> {};
161 class OverwriteModeField : public BitField<OverwriteMode, 4, 2> {};
162 class ResultKindField : public BitField<Kind, 6, 3> {};
163 class LeftKindField : public BitField<Kind, 9, 3> {};
164 // When fixed right arg is set, we don't need to store the right kind.
165 // Thus the two fields can overlap.
166 class HasFixedRightArgField : public BitField<bool, 12, 1> {};
167 class FixedRightArgValueField : public BitField<int, 13, 4> {};
168 class RightKindField : public BitField<Kind, 13, 3> {};
175 Maybe<int> fixed_right_arg_;
180 std::ostream& operator<<(std::ostream& os, const BinaryOpICState& s);
183 class CompareICState {
185 // The type/state lattice is defined by the following inequations:
186 // UNINITIALIZED < ...
189 // INTERNALIZED_STRING < STRING
190 // KNOWN_OBJECT < OBJECT
197 UNIQUE_NAME, // Symbol or InternalizedString
199 KNOWN_OBJECT, // JSObject with specific map (faster check)
203 static Type* StateToType(Zone* zone, State state,
204 Handle<Map> map = Handle<Map>());
206 static State NewInputState(State old_state, Handle<Object> value);
208 static const char* GetStateName(CompareICState::State state);
210 static State TargetState(State old_state, State old_left, State old_right,
211 Token::Value op, bool has_inlined_smi_code,
212 Handle<Object> x, Handle<Object> y);
216 class LoadICState FINAL BASE_EMBEDDED {
218 explicit LoadICState(ExtraICState extra_ic_state) : state_(extra_ic_state) {}
220 explicit LoadICState(ContextualMode mode)
221 : state_(ContextualModeBits::encode(mode)) {}
223 ExtraICState GetExtraICState() const { return state_; }
225 ContextualMode contextual_mode() const {
226 return ContextualModeBits::decode(state_);
229 static ContextualMode GetContextualMode(ExtraICState state) {
230 return LoadICState(state).contextual_mode();
234 class ContextualModeBits : public BitField<ContextualMode, 0, 1> {};
235 STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
237 const ExtraICState state_;
242 #endif // V8_IC_STATE_H_