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.h365
1 files changed, 233 insertions, 132 deletions
diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h
index fca7fc00b5..4b301c5baa 100644
--- a/deps/v8/src/ic.h
+++ b/deps/v8/src/ic.h
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -29,6 +29,7 @@
#define V8_IC_H_
#include "macro-assembler.h"
+#include "type-info.h"
namespace v8 {
namespace internal {
@@ -39,12 +40,15 @@ namespace internal {
#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(SharedStoreIC_ExtendStorage) \
ICU(KeyedStoreIC_Miss) \
+ ICU(KeyedStoreIC_MissForceGeneric) \
+ ICU(KeyedStoreIC_Slow) \
/* Utilities for IC stubs. */ \
ICU(LoadCallbackProperty) \
ICU(StoreCallbackProperty) \
@@ -53,8 +57,8 @@ namespace internal {
ICU(LoadPropertyWithInterceptorForCall) \
ICU(KeyedLoadPropertyWithInterceptor) \
ICU(StoreInterceptorProperty) \
+ ICU(UnaryOp_Patch) \
ICU(BinaryOp_Patch) \
- ICU(TypeRecordingBinaryOp_Patch) \
ICU(CompareIC_Miss)
//
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
@@ -62,7 +66,6 @@ namespace internal {
//
class IC {
public:
-
// The ids for utility called from the generated code.
enum UtilityId {
#define CONST_NAME(name) k##name,
@@ -86,7 +89,7 @@ class IC {
// Construct the IC structure with the given number of extra
// JavaScript frames on the stack.
- explicit IC(FrameDepth depth);
+ IC(FrameDepth depth, Isolate* isolate);
// Get the call-site target; used for determining the state.
Code* target() { return GetTargetAtAddress(address()); }
@@ -130,6 +133,7 @@ class IC {
protected:
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
+ Isolate* isolate() const { return isolate_; }
#ifdef ENABLE_DEBUGGER_SUPPORT
// Computes the address in the original code when the code running is
@@ -141,17 +145,17 @@ class IC {
void set_target(Code* code) { SetTargetAtAddress(address(), code); }
#ifdef DEBUG
- static void TraceIC(const char* type,
- Handle<Object> name,
- State old_state,
- Code* new_target,
- const char* extra_info = "");
+ void TraceIC(const char* type,
+ Handle<Object> name,
+ State old_state,
+ Code* new_target,
+ const char* extra_info = "");
#endif
- static Failure* TypeError(const char* type,
- Handle<Object> object,
- Handle<Object> key);
- static Failure* ReferenceError(const char* type, Handle<String> name);
+ Failure* TypeError(const char* type,
+ Handle<Object> object,
+ Handle<Object> key);
+ Failure* ReferenceError(const char* type, Handle<String> name);
// Access the target code for the given IC address.
static inline Code* GetTargetAtAddress(Address address);
@@ -167,6 +171,8 @@ class IC {
// invoke the garbage collector.
Address* pc_address_;
+ Isolate* isolate_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(IC);
};
@@ -188,8 +194,13 @@ class IC_Utility {
class CallICBase: public IC {
+ public:
+ class Contextual: public BitField<bool, 0, 1> {};
+ class StringStubState: public BitField<StringStubFeedback, 1, 1> {};
+
protected:
- explicit CallICBase(Code::Kind kind) : IC(EXTRA_CALL_FRAME), kind_(kind) {}
+ CallICBase(Code::Kind kind, Isolate* isolate)
+ : IC(EXTRA_CALL_FRAME, isolate), kind_(kind) {}
public:
MUST_USE_RESULT MaybeObject* LoadFunction(State state,
@@ -227,27 +238,37 @@ class CallICBase: public IC {
void ReceiverToObjectIfRequired(Handle<Object> callee, Handle<Object> object);
static void Clear(Address address, Code* target);
+
friend class IC;
};
class CallIC: public CallICBase {
public:
- CallIC() : CallICBase(Code::CALL_IC) { ASSERT(target()->is_call_stub()); }
+ explicit CallIC(Isolate* isolate) : CallICBase(Code::CALL_IC, isolate) {
+ ASSERT(target()->is_call_stub());
+ }
// Code generator routines.
- static void GenerateInitialize(MacroAssembler* masm, int argc) {
- GenerateMiss(masm, argc);
+ static void GenerateInitialize(MacroAssembler* masm,
+ int argc,
+ Code::ExtraICState extra_ic_state) {
+ GenerateMiss(masm, argc, extra_ic_state);
}
- static void GenerateMiss(MacroAssembler* masm, int argc);
- static void GenerateMegamorphic(MacroAssembler* masm, int argc);
+ static void GenerateMiss(MacroAssembler* masm,
+ int argc,
+ Code::ExtraICState extra_ic_state);
+ static void GenerateMegamorphic(MacroAssembler* masm,
+ int argc,
+ Code::ExtraICState extra_ic_state);
static void GenerateNormal(MacroAssembler* masm, int argc);
};
class KeyedCallIC: public CallICBase {
public:
- KeyedCallIC() : CallICBase(Code::KEYED_CALL_IC) {
+ explicit KeyedCallIC(Isolate* isolate)
+ : CallICBase(Code::KEYED_CALL_IC, isolate) {
ASSERT(target()->is_keyed_call_stub());
}
@@ -262,12 +283,15 @@ class KeyedCallIC: public CallICBase {
static void GenerateMiss(MacroAssembler* masm, int argc);
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:
- LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
+ explicit LoadIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+ ASSERT(target()->is_load_stub());
+ }
MUST_USE_RESULT MaybeObject* Load(State state,
Handle<Object> object,
@@ -288,14 +312,6 @@ class LoadIC: public IC {
bool support_wrappers);
static void GenerateFunctionPrototype(MacroAssembler* masm);
- // Clear the use of the inlined version.
- static void ClearInlinedVersion(Address address);
-
- // The offset from the inlined patch site to the start of the
- // inlined load instruction. It is architecture-dependent, and not
- // used on ARM.
- static const int kOffsetToLoadInstruction;
-
private:
// Update the inline cache and the global stub cache based on the
// lookup result.
@@ -305,51 +321,94 @@ class LoadIC: public IC {
Handle<String> name);
// Stub accessors.
- static Code* megamorphic_stub() {
- return Builtins::builtin(Builtins::LoadIC_Megamorphic);
+ Code* megamorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kLoadIC_Megamorphic);
}
static Code* initialize_stub() {
- return Builtins::builtin(Builtins::LoadIC_Initialize);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kLoadIC_Initialize);
}
- static Code* pre_monomorphic_stub() {
- return Builtins::builtin(Builtins::LoadIC_PreMonomorphic);
+ Code* pre_monomorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kLoadIC_PreMonomorphic);
}
static void Clear(Address address, Code* target);
- static bool PatchInlinedLoad(Address address, Object* map, int index);
+ friend class IC;
+};
- static bool PatchInlinedContextualLoad(Address address,
- Object* map,
- Object* cell,
- bool is_dont_delete);
- friend class IC;
+class KeyedIC: public IC {
+ public:
+ explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
+ virtual ~KeyedIC() {}
+
+ virtual MaybeObject* GetFastElementStubWithoutMapCheck(
+ bool is_js_array) = 0;
+
+ virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
+ JSObject::ElementsKind elements_kind) = 0;
+
+ protected:
+ virtual Code* string_stub() {
+ return NULL;
+ }
+
+ virtual Code::Kind kind() const = 0;
+
+ virtual String* GetStubNameForCache(IC::State ic_state) = 0;
+
+ MaybeObject* ComputeStub(JSObject* receiver,
+ bool is_store,
+ StrictModeFlag strict_mode,
+ Code* default_stub);
+
+ virtual MaybeObject* ConstructMegamorphicStub(
+ MapList* receiver_maps,
+ CodeList* targets,
+ StrictModeFlag strict_mode) = 0;
+
+ private:
+ void GetReceiverMapsForStub(Code* stub, MapList* result);
+
+ MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
+ Map* receiver_map,
+ StrictModeFlag strict_mode,
+ Code* generic_stub);
+
+ MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
+ bool is_store,
+ StrictModeFlag strict_mode,
+ Code* default_stub);
};
-class KeyedLoadIC: public IC {
+class KeyedLoadIC: public KeyedIC {
public:
- KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
+ explicit KeyedLoadIC(Isolate* isolate) : KeyedIC(isolate) {
+ ASSERT(target()->is_keyed_load_stub());
+ }
MUST_USE_RESULT MaybeObject* Load(State state,
Handle<Object> object,
- Handle<Object> key);
+ Handle<Object> key,
+ bool force_generic_stub);
// Code generator routines.
- static void GenerateMiss(MacroAssembler* masm);
+ static void GenerateMiss(MacroAssembler* masm, bool force_generic);
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
- static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
+ static void GenerateInitialize(MacroAssembler* masm) {
+ GenerateMiss(masm, false);
+ }
static void GeneratePreMonomorphic(MacroAssembler* masm) {
- GenerateMiss(masm);
+ GenerateMiss(masm, false);
}
static void GenerateGeneric(MacroAssembler* masm);
static void GenerateString(MacroAssembler* masm);
-
static void GenerateIndexedInterceptor(MacroAssembler* masm);
-
- // Clear the use of the inlined version.
- static void ClearInlinedVersion(Address address);
+ static void GenerateNonStrictArguments(MacroAssembler* masm);
// Bit mask to be tested against bit field for the cases when
// generic stub should go into slow case.
@@ -358,6 +417,27 @@ class KeyedLoadIC: public IC {
static const int kSlowCaseBitFieldMask =
(1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
+ virtual MaybeObject* GetFastElementStubWithoutMapCheck(
+ bool is_js_array);
+
+ virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
+ JSObject::ElementsKind elements_kind);
+
+ protected:
+ virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
+
+ virtual String* GetStubNameForCache(IC::State ic_state);
+
+ virtual MaybeObject* ConstructMegamorphicStub(
+ MapList* receiver_maps,
+ CodeList* targets,
+ StrictModeFlag strict_mode);
+
+ virtual Code* string_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_String);
+ }
+
private:
// Update the inline cache.
void UpdateCaches(LookupResult* lookup,
@@ -367,38 +447,41 @@ class KeyedLoadIC: public IC {
// Stub accessors.
static Code* initialize_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_Initialize);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_Initialize);
}
- static Code* megamorphic_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+ Code* megamorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_Generic);
}
- static Code* generic_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_Generic);
+ Code* generic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_Generic);
}
- static Code* pre_monomorphic_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_PreMonomorphic);
+ Code* pre_monomorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_PreMonomorphic);
}
- static Code* string_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_String);
+ Code* indexed_interceptor_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_IndexedInterceptor);
}
-
- static Code* indexed_interceptor_stub() {
- return Builtins::builtin(Builtins::KeyedLoadIC_IndexedInterceptor);
+ Code* non_strict_arguments_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedLoadIC_NonStrictArguments);
}
static void Clear(Address address, Code* target);
- // Support for patching the map that is checked in an inlined
- // version of keyed load.
- static bool PatchInlinedLoad(Address address, Object* map);
-
friend class IC;
};
class StoreIC: public IC {
public:
- StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
+ explicit StoreIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {
+ ASSERT(target()->is_store_stub());
+ }
MUST_USE_RESULT MaybeObject* Store(State state,
StrictModeFlag strict_mode,
@@ -416,13 +499,6 @@ class StoreIC: public IC {
static void GenerateGlobalProxy(MacroAssembler* masm,
StrictModeFlag strict_mode);
- // Clear the use of an inlined version.
- static void ClearInlinedVersion(Address address);
-
- // The offset from the inlined patch site to the start of the
- // inlined store instruction.
- static const int kOffsetToStoreInstruction;
-
private:
// Update the inline cache and the global stub cache based on the
// lookup result.
@@ -441,59 +517,78 @@ class StoreIC: public IC {
}
// Stub accessors.
- static Code* megamorphic_stub() {
- return Builtins::builtin(Builtins::StoreIC_Megamorphic);
+ Code* megamorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kStoreIC_Megamorphic);
}
- static Code* megamorphic_stub_strict() {
- return Builtins::builtin(Builtins::StoreIC_Megamorphic_Strict);
+ Code* megamorphic_stub_strict() {
+ return isolate()->builtins()->builtin(
+ Builtins::kStoreIC_Megamorphic_Strict);
}
static Code* initialize_stub() {
- return Builtins::builtin(Builtins::StoreIC_Initialize);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kStoreIC_Initialize);
}
static Code* initialize_stub_strict() {
- return Builtins::builtin(Builtins::StoreIC_Initialize_Strict);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kStoreIC_Initialize_Strict);
}
- static Code* global_proxy_stub() {
- return Builtins::builtin(Builtins::StoreIC_GlobalProxy);
+ Code* global_proxy_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kStoreIC_GlobalProxy);
}
- static Code* global_proxy_stub_strict() {
- return Builtins::builtin(Builtins::StoreIC_GlobalProxy_Strict);
+ Code* global_proxy_stub_strict() {
+ return isolate()->builtins()->builtin(
+ Builtins::kStoreIC_GlobalProxy_Strict);
}
static void Clear(Address address, Code* target);
- // Support for patching the index and the map that is checked in an
- // inlined version of the named store.
- static bool PatchInlinedStore(Address address, Object* map, int index);
-
friend class IC;
};
-class KeyedStoreIC: public IC {
+class KeyedStoreIC: public KeyedIC {
public:
- KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
+ explicit KeyedStoreIC(Isolate* isolate) : KeyedIC(isolate) {
+ ASSERT(target()->is_keyed_store_stub());
+ }
MUST_USE_RESULT MaybeObject* Store(State state,
- StrictModeFlag strict_mode,
+ StrictModeFlag strict_mode,
Handle<Object> object,
Handle<Object> name,
- Handle<Object> value);
+ Handle<Object> value,
+ bool force_generic);
// Code generators for stub routines. Only called once at startup.
- static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
- static void GenerateMiss(MacroAssembler* masm);
+ static void GenerateInitialize(MacroAssembler* masm) {
+ GenerateMiss(masm, false);
+ }
+ static void GenerateMiss(MacroAssembler* masm, bool force_generic);
+ static void GenerateSlow(MacroAssembler* masm);
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
StrictModeFlag strict_mode);
static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
+ static void GenerateNonStrictArguments(MacroAssembler* masm);
- // Clear the inlined version so the IC is always hit.
- static void ClearInlinedVersion(Address address);
+ virtual MaybeObject* GetFastElementStubWithoutMapCheck(
+ bool is_js_array);
- // Restore the inlined version so the fast case can get hit.
- static void RestoreInlinedVersion(Address address);
+ virtual MaybeObject* GetExternalArrayStubWithoutMapCheck(
+ JSObject::ElementsKind elements_kind);
- private:
+ protected:
+ virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
+
+ virtual String* GetStubNameForCache(IC::State ic_state);
+
+ virtual MaybeObject* ConstructMegamorphicStub(
+ MapList* receiver_maps,
+ CodeList* targets,
+ StrictModeFlag strict_mode);
+
+ private:
// Update the inline cache.
void UpdateCaches(LookupResult* lookup,
State state,
@@ -511,51 +606,52 @@ class KeyedStoreIC: public IC {
// Stub accessors.
static Code* initialize_stub() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Initialize);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Initialize);
+ }
+ Code* megamorphic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Generic);
}
static Code* initialize_stub_strict() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Initialize_Strict);
+ return Isolate::Current()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Initialize_Strict);
}
- static Code* megamorphic_stub() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
+ Code* megamorphic_stub_strict() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Generic_Strict);
}
- static Code* megamorphic_stub_strict() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+ Code* generic_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Generic);
}
- static Code* generic_stub() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Generic);
+ Code* generic_stub_strict() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_Generic_Strict);
}
- static Code* generic_stub_strict() {
- return Builtins::builtin(Builtins::KeyedStoreIC_Generic_Strict);
+ Code* non_strict_arguments_stub() {
+ return isolate()->builtins()->builtin(
+ Builtins::kKeyedStoreIC_NonStrictArguments);
}
static void Clear(Address address, Code* target);
- // Support for patching the map that is checked in an inlined
- // version of keyed store.
- // The address is the patch point for the IC call
- // (Assembler::kCallTargetAddressOffset before the end of
- // the call/return address).
- // The map is the new map that the inlined code should check against.
- static bool PatchInlinedStore(Address address, Object* map);
-
friend class IC;
};
-class BinaryOpIC: public IC {
+class UnaryOpIC: public IC {
public:
-
+ // sorted: increasingly more unspecific (ignoring UNINITIALIZED)
+ // TODO(svenpanne) Using enums+switch is an antipattern, use a class instead.
enum TypeInfo {
- UNINIT_OR_SMI,
- DEFAULT, // Initial state. When first executed, patches to one
- // of the following states depending on the operands types.
- HEAP_NUMBERS, // Both arguments are HeapNumbers.
- STRINGS, // At least one of the arguments is String.
- GENERIC // Non-specialized case (processes any type combination).
+ UNINITIALIZED,
+ SMI,
+ HEAP_NUMBER,
+ GENERIC
};
- BinaryOpIC() : IC(NO_EXTRA_FRAME) { }
+ explicit UnaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
void patch(Code* code);
@@ -563,25 +659,27 @@ class BinaryOpIC: public IC {
static State ToState(TypeInfo type_info);
- static TypeInfo GetTypeInfo(Object* left, Object* right);
+ static TypeInfo GetTypeInfo(Handle<Object> operand);
+
+ static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous);
};
// Type Recording BinaryOpIC, that records the types of the inputs and outputs.
-class TRBinaryOpIC: public IC {
+class BinaryOpIC: public IC {
public:
-
enum TypeInfo {
UNINITIALIZED,
SMI,
INT32,
HEAP_NUMBER,
ODDBALL,
+ BOTH_STRING, // Only used for addition operation.
STRING, // Only used for addition operation. At least one string operand.
GENERIC
};
- TRBinaryOpIC() : IC(NO_EXTRA_FRAME) { }
+ explicit BinaryOpIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) { }
void patch(Code* code);
@@ -601,11 +699,14 @@ class CompareIC: public IC {
UNINITIALIZED,
SMIS,
HEAP_NUMBERS,
+ SYMBOLS,
+ STRINGS,
OBJECTS,
GENERIC
};
- explicit CompareIC(Token::Value op) : IC(EXTRA_CALL_FRAME), op_(op) { }
+ 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);
@@ -632,7 +733,7 @@ class CompareIC: public IC {
Token::Value op_;
};
-// Helper for TRBinaryOpIC and CompareIC.
+// Helper for BinaryOpIC and CompareIC.
void PatchInlinedSmiCode(Address address);
} } // namespace v8::internal