summaryrefslogtreecommitdiff
path: root/deps/v8/src/ic.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ic.h')
-rw-r--r--deps/v8/src/ic.h592
1 files changed, 305 insertions, 287 deletions
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
index fde4bc77a5..fce585f6d7 100644
--- a/deps/v8/src/ic.h
+++ b/deps/v8/src/ic.h
@@ -29,26 +29,24 @@
#define V8_IC_H_
#include "macro-assembler.h"
-#include "type-info.h"
namespace v8 {
namespace internal {
+const int kMaxKeyedPolymorphism = 4;
+
+
// IC_UTIL_LIST defines all utility functions called from generated
// inline caching code. The argument for the macro, ICU, is the function name.
#define IC_UTIL_LIST(ICU) \
ICU(LoadIC_Miss) \
ICU(KeyedLoadIC_Miss) \
- ICU(KeyedLoadIC_MissForceGeneric) \
- ICU(CallIC_Miss) \
- ICU(KeyedCallIC_Miss) \
ICU(StoreIC_Miss) \
ICU(StoreIC_ArrayLength) \
ICU(StoreIC_Slow) \
ICU(SharedStoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
- ICU(KeyedStoreIC_MissForceGeneric) \
ICU(KeyedStoreIC_Slow) \
/* Utilities for IC stubs. */ \
ICU(StoreCallbackProperty) \
@@ -63,8 +61,7 @@ namespace internal {
ICU(Unreachable) \
ICU(ToBooleanIC_Miss)
//
-// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
-// and KeyedStoreIC.
+// IC is the base class for LoadIC, StoreIC, KeyedLoadIC, and KeyedStoreIC.
//
class IC {
public:
@@ -94,10 +91,6 @@ class IC {
IC(FrameDepth depth, Isolate* isolate);
virtual ~IC() {}
- // Get the call-site target; used for determining the state.
- Handle<Code> target() const { return target_; }
- Code* raw_target() const { return GetTargetAtAddress(address()); }
-
State state() const { return state_; }
inline Address address() const;
@@ -110,40 +103,66 @@ class IC {
// Clear the inline cache to initial state.
static void Clear(Isolate* isolate, Address address);
- // Computes the reloc info for this IC. This is a fairly expensive
- // operation as it has to search through the heap to find the code
- // object that contains this IC site.
- RelocInfo::Mode ComputeMode();
-
- // Returns if this IC is for contextual (no explicit receiver)
- // access to properties.
- bool IsUndeclaredGlobal(Handle<Object> receiver) {
- if (receiver->IsGlobalObject()) {
- return SlowIsUndeclaredGlobal();
- } else {
- ASSERT(!SlowIsUndeclaredGlobal());
- return false;
- }
+#ifdef DEBUG
+ bool IsLoadStub() const {
+ return target()->is_load_stub() || target()->is_keyed_load_stub();
}
- bool SlowIsUndeclaredGlobal() {
- return ComputeMode() == RelocInfo::CODE_TARGET_CONTEXT;
+ bool IsStoreStub() const {
+ return target()->is_store_stub() || target()->is_keyed_store_stub();
}
+#endif
// Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null.
- static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object,
- JSObject* holder);
- static inline JSObject* GetCodeCacheHolder(Isolate* isolate,
- Object* object,
- InlineCacheHolderFlag holder);
+ static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
+ // TODO(verwaest): This currently returns a HeapObject rather than JSObject*
+ // since loading the IC for loading the length from strings are stored on
+ // the string map directly, rather than on the JSObject-typed prototype.
+ static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
+ Object* object,
+ InlineCacheHolderFlag holder);
+
+ static inline InlineCacheHolderFlag GetCodeCacheFlag(HeapType* type);
+ static inline Handle<Map> GetCodeCacheHolder(InlineCacheHolderFlag flag,
+ HeapType* type,
+ Isolate* isolate);
static bool IsCleared(Code* code) {
InlineCacheState state = code->ic_state();
return state == UNINITIALIZED || state == PREMONOMORPHIC;
}
+ // Utility functions to convert maps to types and back. There are two special
+ // cases:
+ // - The heap_number_map is used as a marker which includes heap numbers as
+ // well as smis.
+ // - The oddball map is only used for booleans.
+ static Handle<Map> TypeToMap(HeapType* type, Isolate* isolate);
+ template <class T>
+ static typename T::TypeHandle MapToType(Handle<Map> map,
+ typename T::Region* region);
+
+ static Handle<HeapType> CurrentTypeOf(Handle<Object> object,
+ Isolate* isolate);
+
protected:
+ // Get the call-site target; used for determining the state.
+ Handle<Code> target() const { return target_; }
+
+ TypeHandleList* types() { return &types_; }
+ CodeHandleList* handlers() { return &handlers_; }
+ Map* first_map() {
+ return types_.length() == 0 ? NULL : *TypeToMap(*types_.at(0), isolate_);
+ }
+ Code* first_handler() {
+ return handlers_.length() == 0 ? NULL : *handlers_.at(0);
+ }
+ void GetMapsFromTypes(MapHandleList* maps) {
+ for (int i = 0; i < types_.length(); ++i) {
+ maps->Add(TypeToMap(*types_.at(i), isolate_));
+ }
+ }
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; }
@@ -180,30 +199,33 @@ class IC {
// Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> value) {
+ Handle<Object> value,
+ InlineCacheHolderFlag cache_holder) {
UNREACHABLE();
return Handle<Code>::null();
}
- void UpdateMonomorphicIC(Handle<HeapObject> receiver,
+
+ void UpdateMonomorphicIC(Handle<HeapType> type,
Handle<Code> handler,
Handle<String> name);
- bool UpdatePolymorphicIC(Handle<HeapObject> receiver,
+ bool UpdatePolymorphicIC(Handle<HeapType> type,
Handle<String> name,
Handle<Code> code);
+ virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code);
+
void CopyICToMegamorphicCache(Handle<String> name);
- bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
- void PatchCache(Handle<HeapObject> receiver,
+ bool IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map);
+ void PatchCache(Handle<HeapType> type,
Handle<String> name,
Handle<Code> code);
- virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
virtual Code::Kind kind() const {
UNREACHABLE();
return Code::STUB;
@@ -220,12 +242,19 @@ class IC {
UNREACHABLE();
return Handle<Code>::null();
}
- virtual StrictModeFlag strict_mode() const { return kNonStrictMode; }
+
bool TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
Handle<String> name);
void TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name);
+ ExtraICState extra_ic_state() const { return extra_ic_state_; }
+ void set_extra_ic_state(ExtraICState state) {
+ extra_ic_state_ = state;
+ }
+
private:
+ Code* raw_target() const { return GetTargetAtAddress(address()); }
+
// Frame pointer for the frame that uses (calls) the IC.
Address fp_;
@@ -242,6 +271,11 @@ class IC {
State state_;
bool target_set_;
+ ExtraICState extra_ic_state_;
+
+ TypeHandleList types_;
+ CodeHandleList handlers_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
};
@@ -262,133 +296,38 @@ class IC_Utility {
};
-class CallICBase: public IC {
- public:
- class Contextual: public BitField<bool, 0, 1> {};
- class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
-
- // Returns a JSFunction or a Failure.
- MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
- Handle<String> name);
-
- protected:
- CallICBase(Code::Kind kind, Isolate* isolate)
- : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
-
- virtual Code::ExtraICState extra_ic_state() { return Code::kNoExtraICState; }
-
- // Compute a monomorphic stub if possible, otherwise return a null handle.
- Handle<Code> ComputeMonomorphicStub(LookupResult* lookup,
- Handle<Object> object,
- Handle<String> name);
-
- // Update the inline cache and the global stub cache based on the lookup
- // result.
- void UpdateCaches(LookupResult* lookup,
- Handle<Object> object,
- Handle<String> name);
-
- // Returns a JSFunction if the object can be called as a function, and
- // patches the stack to be ready for the call. Otherwise, it returns the
- // undefined value.
- Handle<Object> TryCallAsFunction(Handle<Object> object);
-
- void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
-
- static void Clear(Address address, Code* target);
-
- // Platform-specific code generation functions used by both call and
- // keyed call.
- static void GenerateMiss(MacroAssembler* masm,
- int argc,
- IC::UtilityId id,
- Code::ExtraICState extra_state);
-
- static void GenerateNormal(MacroAssembler* masm, int argc);
-
- static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
- int argc,
- Code::Kind kind,
- Code::ExtraICState extra_state);
-
- virtual Handle<Code> megamorphic_stub();
- virtual Handle<Code> pre_monomorphic_stub();
-
- Code::Kind kind_;
-
- friend class IC;
-};
-
-
-class CallIC: public CallICBase {
+class LoadIC: public IC {
public:
- explicit CallIC(Isolate* isolate)
- : CallICBase(Code::CALL_IC, isolate),
- extra_ic_state_(target()->extra_ic_state()) {
- ASSERT(target()->is_call_stub());
- }
-
- // Code generator routines.
- static void GenerateInitialize(MacroAssembler* masm,
- int argc,
- Code::ExtraICState extra_state) {
- GenerateMiss(masm, argc, extra_state);
- }
+ // ExtraICState bits
+ class ContextualModeBits: public BitField<ContextualMode, 0, 1> {};
+ STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
- static void GenerateMiss(MacroAssembler* masm,
- int argc,
- Code::ExtraICState extra_state) {
- CallICBase::GenerateMiss(masm, argc, IC::kCallIC_Miss, extra_state);
+ static ExtraICState ComputeExtraICState(ContextualMode contextual_mode) {
+ return ContextualModeBits::encode(contextual_mode);
}
- static void GenerateMegamorphic(MacroAssembler* masm,
- int argc,
- Code::ExtraICState extra_ic_state);
-
- static void GenerateNormal(MacroAssembler* masm, int argc) {
- CallICBase::GenerateNormal(masm, argc);
- GenerateMiss(masm, argc, Code::kNoExtraICState);
+ static ContextualMode GetContextualMode(ExtraICState state) {
+ return ContextualModeBits::decode(state);
}
- bool TryUpdateExtraICState(LookupResult* lookup, Handle<Object> object);
-
- protected:
- virtual Code::ExtraICState extra_ic_state() { return extra_ic_state_; }
-
- private:
- Code::ExtraICState extra_ic_state_;
-};
-
-class KeyedCallIC: public CallICBase {
- public:
- explicit KeyedCallIC(Isolate* isolate)
- : CallICBase(Code::KEYED_CALL_IC, isolate) {
- ASSERT(target()->is_keyed_call_stub());
- }
-
- MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
- Handle<Object> key);
-
- // Code generator routines.
- static void GenerateInitialize(MacroAssembler* masm, int argc) {
- GenerateMiss(masm, argc);
+ ContextualMode contextual_mode() const {
+ return ContextualModeBits::decode(extra_ic_state());
}
- static void GenerateMiss(MacroAssembler* masm, int argc) {
- CallICBase::GenerateMiss(masm, argc, IC::kKeyedCallIC_Miss,
- Code::kNoExtraICState);
+ explicit LoadIC(FrameDepth depth, Isolate* isolate)
+ : IC(depth, isolate) {
+ ASSERT(IsLoadStub());
}
- static void GenerateMegamorphic(MacroAssembler* masm, int argc);
- static void GenerateNormal(MacroAssembler* masm, int argc);
- static void GenerateNonStrictArguments(MacroAssembler* masm, int argc);
-};
-
-
-class LoadIC: public IC {
- public:
- explicit LoadIC(FrameDepth depth, Isolate* isolate) : IC(depth, isolate) {
- ASSERT(target()->is_load_stub() || target()->is_keyed_load_stub());
+ // Returns if this IC is for contextual (no explicit receiver)
+ // access to properties.
+ bool IsUndeclaredGlobal(Handle<Object> receiver) {
+ if (receiver->IsGlobalObject()) {
+ return contextual_mode() == CONTEXTUAL;
+ } else {
+ ASSERT(contextual_mode() != CONTEXTUAL);
+ return false;
+ }
}
// Code generator routines.
@@ -401,19 +340,28 @@ class LoadIC: public IC {
static void GenerateNormal(MacroAssembler* masm);
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
+ static Handle<Code> initialize_stub(Isolate* isolate,
+ ExtraICState extra_state);
+
MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
Handle<String> name);
protected:
virtual Code::Kind kind() const { return Code::LOAD_IC; }
+ void set_target(Code* code) {
+ // The contextual mode must be preserved across IC patching.
+ ASSERT(GetContextualMode(code->extra_ic_state()) ==
+ GetContextualMode(target()->extra_ic_state()));
+
+ IC::set_target(code);
+ }
+
virtual Handle<Code> slow_stub() const {
return isolate()->builtins()->LoadIC_Slow();
}
- virtual Handle<Code> megamorphic_stub() {
- return isolate()->builtins()->LoadIC_Megamorphic();
- }
+ virtual Handle<Code> megamorphic_stub();
// Update the inline cache and the global stub cache based on the
// lookup result.
@@ -422,22 +370,18 @@ class LoadIC: public IC {
Handle<String> name);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> unused);
+ Handle<Object> unused,
+ InlineCacheHolderFlag cache_holder);
private:
// Stub accessors.
- static Handle<Code> initialize_stub(Isolate* isolate) {
- return isolate->builtins()->LoadIC_Initialize();
- }
-
- static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
- return isolate->builtins()->LoadIC_PreMonomorphic();
- }
+ static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
+ ExtraICState exstra_state);
virtual Handle<Code> pre_monomorphic_stub() {
- return pre_monomorphic_stub(isolate());
+ return pre_monomorphic_stub(isolate(), extra_ic_state());
}
Handle<Code> SimpleFieldLoad(int offset,
@@ -451,12 +395,6 @@ class LoadIC: public IC {
};
-enum ICMissMode {
- MISS_FORCE_GENERIC,
- MISS
-};
-
-
class KeyedLoadIC: public LoadIC {
public:
explicit KeyedLoadIC(FrameDepth depth, Isolate* isolate)
@@ -465,17 +403,14 @@ class KeyedLoadIC: public LoadIC {
}
MUST_USE_RESULT MaybeObject* Load(Handle<Object> object,
- Handle<Object> key,
- ICMissMode force_generic);
+ Handle<Object> key);
// Code generator routines.
- static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
+ static void GenerateMiss(MacroAssembler* masm);
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
- static void GenerateInitialize(MacroAssembler* masm) {
- GenerateMiss(masm, MISS);
- }
+ static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
static void GeneratePreMonomorphic(MacroAssembler* masm) {
- GenerateMiss(masm, MISS);
+ GenerateMiss(masm);
}
static void GenerateGeneric(MacroAssembler* masm);
static void GenerateString(MacroAssembler* masm);
@@ -504,13 +439,10 @@ class KeyedLoadIC: public LoadIC {
return isolate()->builtins()->KeyedLoadIC_Slow();
}
- virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
+ virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {}
private:
// Stub accessors.
- static Handle<Code> initialize_stub(Isolate* isolate) {
- return isolate->builtins()->KeyedLoadIC_Initialize();
- }
static Handle<Code> pre_monomorphic_stub(Isolate* isolate) {
return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
}
@@ -535,13 +467,28 @@ class KeyedLoadIC: public LoadIC {
class StoreIC: public IC {
public:
+ class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
+ static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
+ return StrictModeState::encode(flag);
+ }
+
+ static StrictModeFlag GetStrictMode(ExtraICState state) {
+ return StrictModeState::decode(state);
+ }
+
+ // For convenience, a statically declared encoding of strict mode extra
+ // IC state.
+ static const ExtraICState kStrictModeState =
+ 1 << StrictModeState::kShift;
+
StoreIC(FrameDepth depth, Isolate* isolate)
- : IC(depth, isolate),
- strict_mode_(Code::GetStrictMode(target()->extra_ic_state())) {
- ASSERT(target()->is_store_stub() || target()->is_keyed_store_stub());
+ : IC(depth, isolate) {
+ ASSERT(IsStoreStub());
}
- virtual StrictModeFlag strict_mode() const { return strict_mode_; }
+ StrictModeFlag strict_mode() const {
+ return StrictModeState::decode(extra_ic_state());
+ }
// Code generators for stub routines. Only called once at startup.
static void GenerateSlow(MacroAssembler* masm);
@@ -550,12 +497,14 @@ class StoreIC: public IC {
GenerateMiss(masm);
}
static void GenerateMiss(MacroAssembler* masm);
- static void GenerateMegamorphic(MacroAssembler* masm,
- StrictModeFlag strict_mode);
+ static void GenerateMegamorphic(MacroAssembler* masm);
static void GenerateNormal(MacroAssembler* masm);
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
StrictModeFlag strict_mode);
+ static Handle<Code> initialize_stub(Isolate* isolate,
+ StrictModeFlag strict_mode);
+
MUST_USE_RESULT MaybeObject* Store(
Handle<Object> object,
Handle<String> name,
@@ -565,28 +514,13 @@ class StoreIC: public IC {
protected:
virtual Code::Kind kind() const { return Code::STORE_IC; }
- virtual Handle<Code> megamorphic_stub() {
- if (strict_mode() == kStrictMode) {
- return isolate()->builtins()->StoreIC_Megamorphic_Strict();
- } else {
- return isolate()->builtins()->StoreIC_Megamorphic();
- }
- }
+ virtual Handle<Code> megamorphic_stub();
+
// Stub accessors.
- virtual Handle<Code> generic_stub() const {
- if (strict_mode() == kStrictMode) {
- return isolate()->builtins()->StoreIC_Generic_Strict();
- } else {
- return isolate()->builtins()->StoreIC_Generic();
- }
- }
+ virtual Handle<Code> generic_stub() const;
virtual Handle<Code> slow_stub() const {
- if (strict_mode() == kStrictMode) {
- return isolate()->builtins()->StoreIC_Slow_Strict();
- } else {
- return isolate()->builtins()->StoreIC_Slow();
- }
+ return isolate()->builtins()->StoreIC_Slow();
}
virtual Handle<Code> pre_monomorphic_stub() {
@@ -594,21 +528,7 @@ class StoreIC: public IC {
}
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
- if (strict_mode == kStrictMode) {
- return isolate->builtins()->StoreIC_PreMonomorphic_Strict();
- } else {
- return isolate->builtins()->StoreIC_PreMonomorphic();
- }
- }
-
- virtual Handle<Code> global_proxy_stub() {
- if (strict_mode() == kStrictMode) {
- return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
- } else {
- return isolate()->builtins()->StoreIC_GlobalProxy();
- }
- }
+ StrictModeFlag strict_mode);
// Update the inline cache and the global stub cache based on the
// lookup result.
@@ -617,31 +537,21 @@ class StoreIC: public IC {
Handle<String> name,
Handle<Object> value);
virtual Handle<Code> CompileHandler(LookupResult* lookup,
- Handle<JSObject> receiver,
+ Handle<Object> object,
Handle<String> name,
- Handle<Object> value);
+ Handle<Object> value,
+ InlineCacheHolderFlag cache_holder);
private:
void set_target(Code* code) {
// Strict mode must be preserved across IC patching.
- ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
- Code::GetStrictMode(target()->extra_ic_state()));
+ ASSERT(GetStrictMode(code->extra_ic_state()) ==
+ GetStrictMode(target()->extra_ic_state()));
IC::set_target(code);
}
- static Handle<Code> initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
- if (strict_mode == kStrictMode) {
- return isolate->builtins()->StoreIC_Initialize_Strict();
- } else {
- return isolate->builtins()->StoreIC_Initialize();
- }
- }
-
static void Clear(Isolate* isolate, Address address, Code* target);
- StrictModeFlag strict_mode_;
-
friend class IC;
};
@@ -660,6 +570,22 @@ enum KeyedStoreIncrementLength {
class KeyedStoreIC: public StoreIC {
public:
+ // ExtraICState bits (building on IC)
+ // ExtraICState bits
+ class ExtraICStateKeyedAccessStoreMode:
+ public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT
+
+ static ExtraICState ComputeExtraICState(StrictModeFlag flag,
+ KeyedAccessStoreMode mode) {
+ return StrictModeState::encode(flag) |
+ ExtraICStateKeyedAccessStoreMode::encode(mode);
+ }
+
+ static KeyedAccessStoreMode GetKeyedAccessStoreMode(
+ ExtraICState extra_state) {
+ return ExtraICStateKeyedAccessStoreMode::decode(extra_state);
+ }
+
KeyedStoreIC(FrameDepth depth, Isolate* isolate)
: StoreIC(depth, isolate) {
ASSERT(target()->is_keyed_store_stub());
@@ -667,17 +593,14 @@ class KeyedStoreIC: public StoreIC {
MUST_USE_RESULT MaybeObject* Store(Handle<Object> object,
Handle<Object> name,
- Handle<Object> value,
- ICMissMode force_generic);
+ Handle<Object> value);
// Code generators for stub routines. Only called once at startup.
- static void GenerateInitialize(MacroAssembler* masm) {
- GenerateMiss(masm, MISS);
- }
+ static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
static void GeneratePreMonomorphic(MacroAssembler* masm) {
- GenerateMiss(masm, MISS);
+ GenerateMiss(masm);
}
- static void GenerateMiss(MacroAssembler* masm, ICMissMode force_generic);
+ static void GenerateMiss(MacroAssembler* masm);
static void GenerateSlow(MacroAssembler* masm);
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
StrictModeFlag strict_mode);
@@ -687,7 +610,7 @@ class KeyedStoreIC: public StoreIC {
protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
- virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code) { }
+ virtual void UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {}
virtual Handle<Code> pre_monomorphic_stub() {
return pre_monomorphic_stub(isolate(), strict_mode());
@@ -701,11 +624,7 @@ class KeyedStoreIC: public StoreIC {
}
}
virtual Handle<Code> slow_stub() const {
- if (strict_mode() == kStrictMode) {
- return isolate()->builtins()->KeyedStoreIC_Slow_Strict();
- } else {
- return isolate()->builtins()->KeyedStoreIC_Slow();
- }
+ return isolate()->builtins()->KeyedStoreIC_Slow();
}
virtual Handle<Code> megamorphic_stub() {
if (strict_mode() == kStrictMode) {
@@ -721,20 +640,11 @@ class KeyedStoreIC: public StoreIC {
private:
void set_target(Code* code) {
// Strict mode must be preserved across IC patching.
- ASSERT(Code::GetStrictMode(code->extra_ic_state()) == strict_mode());
+ ASSERT(GetStrictMode(code->extra_ic_state()) == strict_mode());
IC::set_target(code);
}
// Stub accessors.
- static Handle<Code> initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
- if (strict_mode == kStrictMode) {
- return isolate->builtins()->KeyedStoreIC_Initialize_Strict();
- } else {
- return isolate->builtins()->KeyedStoreIC_Initialize();
- }
- }
-
virtual Handle<Code> generic_stub() const {
if (strict_mode() == kStrictMode) {
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
@@ -760,27 +670,134 @@ 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));
+ }
+
+ // Returns true if the IC _could_ create allocation mementos.
+ bool CouldCreateAllocationMementos() const {
+ if (left_kind_ == STRING || right_kind_ == STRING) {
+ ASSERT_EQ(Token::ADD, op_);
+ return true;
+ }
+ return false;
+ }
+
+ // Returns true if the IC _should_ create allocation mementos.
+ bool ShouldCreateAllocationMementos() const {
+ return FLAG_allocation_site_pretenuring &&
+ CouldCreateAllocationMementos();
+ }
+
+ bool HasSideEffects() const {
+ return Max(left_kind_, right_kind_) == GENERIC;
+ }
+
+ // Returns true if the IC should enable the inline smi code (i.e. if either
+ // parameter may be a smi).
+ 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_; }
+
+ Type* GetLeftType(Zone* zone) const {
+ return KindToType(left_kind_, zone);
+ }
+ Type* GetRightType(Zone* zone) const {
+ return KindToType(right_kind_, zone);
+ }
+ Type* GetResultType(Zone* zone) 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 Type* KindToType(Kind kind, Zone* zone);
+ 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);
+ MaybeObject* Transition(Handle<AllocationSite> allocation_site,
+ Handle<Object> left,
+ Handle<Object> right) V8_WARN_UNUSED_RESULT;
};
@@ -806,22 +823,22 @@ class CompareIC: public IC {
static State NewInputState(State old_state, Handle<Object> value);
- static Handle<Type> StateToType(Isolate* isolate,
- State state,
- Handle<Map> map = Handle<Map>());
+ static Type* StateToType(Zone* zone,
+ State state,
+ Handle<Map> map = Handle<Map>());
static void StubInfoToType(int stub_minor_key,
- Handle<Type>* left_type,
- Handle<Type>* right_type,
- Handle<Type>* overall_type,
+ Type** left_type,
+ Type** right_type,
+ Type** overall_type,
Handle<Map> map,
- Isolate* isolate);
+ Zone* zone);
CompareIC(Isolate* isolate, Token::Value op)
: IC(EXTRA_CALL_FRAME, isolate), op_(op) { }
// Update the inline cache for the given operands.
- void UpdateCaches(Handle<Object> x, Handle<Object> y);
+ Code* UpdateCaches(Handle<Object> x, Handle<Object> y);
// Factory method for getting an uninitialized compare stub.
@@ -874,7 +891,7 @@ class ToBooleanIC: public IC {
public:
explicit ToBooleanIC(Isolate* isolate) : IC(EXTRA_CALL_FRAME, isolate) { }
- MaybeObject* ToBoolean(Handle<Object> object, Code::ExtraICState state);
+ MaybeObject* ToBoolean(Handle<Object> object);
};
@@ -888,6 +905,7 @@ DECLARE_RUNTIME_FUNCTION(MaybeObject*, UnaryOpIC_Miss);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss);
+DECLARE_RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss);
DECLARE_RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss);