diff options
Diffstat (limited to 'deps/v8/src/ic.h')
-rw-r--r-- | deps/v8/src/ic.h | 365 |
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 |