Commit 93f2ed48 authored by verwaest@chromium.org's avatar verwaest@chromium.org

Handle all object types (minus smi) in load/store ICs

R=ulan@chromium.org

Review URL: https://chromiumcodereview.appspot.com/62953007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17755 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 883a5c80
...@@ -1298,34 +1298,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, ...@@ -1298,34 +1298,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
} }
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ b(success); Label success;
__ b(&success);
__ bind(miss); __ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ b(success); Label success;
__ b(&success);
GenerateRestoreName(masm(), miss, name); GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
Register LoadStubCompiler::CallbackHandlerFrontend( Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object, Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
...@@ -1362,7 +1361,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( ...@@ -1362,7 +1361,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ b(ne, &miss); __ b(ne, &miss);
} }
HandlerFrontendFooter(name, success, &miss); HandlerFrontendFooter(name, &miss);
return reg; return reg;
} }
...@@ -1468,7 +1467,7 @@ void LoadStubCompiler::GenerateLoadCallback( ...@@ -1468,7 +1467,7 @@ void LoadStubCompiler::GenerateLoadCallback(
void LoadStubCompiler::GenerateLoadInterceptor( void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg, Register holder_reg,
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> interceptor_holder, Handle<JSObject> interceptor_holder,
LookupResult* lookup, LookupResult* lookup,
Handle<Name> name) { Handle<Name> name) {
...@@ -2539,11 +2538,23 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2539,11 +2538,23 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
} }
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(object, ip);
__ b(eq, &success);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(object, ip);
__ b(ne, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
CheckType check, CheckType check) {
Label* success) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
...@@ -2619,15 +2630,8 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2619,15 +2630,8 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break; break;
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
Label fast; GenerateBooleanCheck(r1, &miss);
// Check that the object is a boolean.
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r1, ip);
__ b(eq, &fast);
__ LoadRoot(ip, Heap::kFalseValueRootIndex);
__ cmp(r1, ip);
__ b(ne, &miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype( GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss); masm(), Context::BOOLEAN_FUNCTION_INDEX, r0, &miss);
...@@ -2638,11 +2642,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2638,11 +2642,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
} }
} }
__ b(success); Label success;
__ b(&success);
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
GenerateMissBranch(); GenerateMissBranch();
__ bind(&success);
} }
...@@ -2671,10 +2678,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant( ...@@ -2671,10 +2678,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code; if (!code.is_null()) return code;
} }
Label success; CompileHandlerFrontend(object, holder, name, check);
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerBackend(function); CompileHandlerBackend(function);
// Return the generated code. // Return the generated code.
...@@ -2785,9 +2789,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2785,9 +2789,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
// Stub never generated for non-global objects that require access checks. // Stub never generated for non-global objects that require access checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
...@@ -2813,9 +2815,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2813,9 +2815,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
const CallOptimization& call_optimization) { const CallOptimization& call_optimization) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
Register values[] = { value() }; Register values[] = { value() };
GenerateFastApiCall( GenerateFastApiCall(
...@@ -2910,15 +2910,12 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor( ...@@ -2910,15 +2910,12 @@ Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent( Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Handle<JSGlobalObject> global) { Handle<JSGlobalObject> global) {
Label success; NonexistentHandlerFrontend(object, last, name, global);
NonexistentHandlerFrontend(object, last, name, &success, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex); __ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
...@@ -3013,12 +3010,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, ...@@ -3013,12 +3010,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal( Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object, Handle<Object> object,
Handle<GlobalObject> global, Handle<GlobalObject> global,
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<Name> name, Handle<Name> name,
bool is_dont_delete) { bool is_dont_delete) {
Label success, miss; Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss); HandlerFrontendHeader(object, receiver(), global, name, &miss);
...@@ -3033,8 +3030,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -3033,8 +3030,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ b(eq, &miss); __ b(eq, &miss);
} }
HandlerFrontendFooter(name, &success, &miss); HandlerFrontendFooter(name, &miss);
__ bind(&success);
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3); __ IncrementCounter(counters->named_load_global_stub(), 1, r1, r3);
......
...@@ -1267,34 +1267,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, ...@@ -1267,34 +1267,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
} }
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); Label success;
__ jmp(&success);
__ bind(miss); __ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); Label success;
__ jmp(&success);
GenerateRestoreName(masm(), miss, name); GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
Register LoadStubCompiler::CallbackHandlerFrontend( Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object, Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
...@@ -1344,7 +1343,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( ...@@ -1344,7 +1343,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ j(not_equal, &miss); __ j(not_equal, &miss);
} }
HandlerFrontendFooter(name, success, &miss); HandlerFrontendFooter(name, &miss);
return reg; return reg;
} }
...@@ -1450,7 +1449,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { ...@@ -1450,7 +1449,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadInterceptor( void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg, Register holder_reg,
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> interceptor_holder, Handle<JSObject> interceptor_holder,
LookupResult* lookup, LookupResult* lookup,
Handle<Name> name) { Handle<Name> name) {
...@@ -2613,11 +2612,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2613,11 +2612,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
} }
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ cmp(object, factory()->true_value());
__ j(equal, &success);
__ cmp(object, factory()->false_value());
__ j(not_equal, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
CheckType check, CheckType check) {
Label* success) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
...@@ -2696,13 +2705,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2696,13 +2705,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break; break;
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
Label fast; GenerateBooleanCheck(edx, &miss);
// Check that the object is a boolean.
__ cmp(edx, factory()->true_value());
__ j(equal, &fast);
__ cmp(edx, factory()->false_value());
__ j(not_equal, &miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype( GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss); masm(), Context::BOOLEAN_FUNCTION_INDEX, eax, &miss);
...@@ -2713,11 +2716,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2713,11 +2716,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
} }
} }
__ jmp(success); Label success;
__ jmp(&success);
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
GenerateMissBranch(); GenerateMissBranch();
__ bind(&success);
} }
...@@ -2747,10 +2753,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant( ...@@ -2747,10 +2753,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code; if (!code.is_null()) return code;
} }
Label success; CompileHandlerFrontend(object, holder, name, check);
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerBackend(function); CompileHandlerBackend(function);
// Return the generated code. // Return the generated code.
...@@ -2885,9 +2888,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2885,9 +2888,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
__ pop(scratch1()); // remove the return address __ pop(scratch1()); // remove the return address
__ push(receiver()); __ push(receiver());
...@@ -2911,9 +2912,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2911,9 +2912,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
const CallOptimization& call_optimization) { const CallOptimization& call_optimization) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
Register values[] = { value() }; Register values[] = { value() };
GenerateFastApiCall( GenerateFastApiCall(
...@@ -3020,15 +3019,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( ...@@ -3020,15 +3019,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent( Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Handle<JSGlobalObject> global) { Handle<JSGlobalObject> global) {
Label success; NonexistentHandlerFrontend(object, last, name, global);
NonexistentHandlerFrontend(object, last, name, &success, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
__ mov(eax, isolate()->factory()->undefined_value()); __ mov(eax, isolate()->factory()->undefined_value());
...@@ -3118,12 +3114,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, ...@@ -3118,12 +3114,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal( Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object, Handle<Object> object,
Handle<GlobalObject> global, Handle<GlobalObject> global,
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<Name> name, Handle<Name> name,
bool is_dont_delete) { bool is_dont_delete) {
Label success, miss; Label miss;
HandlerFrontendHeader(object, receiver(), global, name, &miss); HandlerFrontendHeader(object, receiver(), global, name, &miss);
// Get the value from the cell. // Get the value from the cell.
...@@ -3143,8 +3139,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -3143,8 +3139,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole); __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
} }
HandlerFrontendFooter(name, &success, &miss); HandlerFrontendFooter(name, &miss);
__ bind(&success);
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1); __ IncrementCounter(counters->named_load_global_stub(), 1);
......
...@@ -100,8 +100,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) { ...@@ -100,8 +100,7 @@ void IC::SetTargetAtAddress(Address address, Code* target) {
} }
InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object, InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object) {
JSObject* holder) {
if (object->IsJSObject()) return OWN_MAP; if (object->IsJSObject()) return OWN_MAP;
// If the object is a value, we use the prototype map for the cache. // If the object is a value, we use the prototype map for the cache.
...@@ -111,13 +110,12 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object, ...@@ -111,13 +110,12 @@ InlineCacheHolderFlag IC::GetCodeCacheForObject(Object* object,
} }
JSObject* IC::GetCodeCacheHolder(Isolate* isolate, HeapObject* IC::GetCodeCacheHolder(Isolate* isolate,
Object* object, Object* object,
InlineCacheHolderFlag holder) { InlineCacheHolderFlag holder) {
Object* map_owner = Object* map_owner =
holder == OWN_MAP ? object : object->GetPrototype(isolate); holder == OWN_MAP ? object : object->GetPrototype(isolate);
ASSERT(map_owner->IsJSObject()); return HeapObject::cast(map_owner);
return JSObject::cast(map_owner);
} }
......
This diff is collapsed.
...@@ -132,11 +132,13 @@ class IC { ...@@ -132,11 +132,13 @@ class IC {
// Determines which map must be used for keeping the code stub. // Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null. // These methods should not be called with undefined or null.
static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object, static inline InlineCacheHolderFlag GetCodeCacheForObject(Object* object);
JSObject* holder); // TODO(verwaest): This currently returns a HeapObject rather than JSObject*
static inline JSObject* GetCodeCacheHolder(Isolate* isolate, // since loading the IC for loading the length from strings are stored on
Object* object, // the string map directly, rather than on the JSObject-typed prototype.
InlineCacheHolderFlag holder); static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
Object* object,
InlineCacheHolderFlag holder);
static bool IsCleared(Code* code) { static bool IsCleared(Code* code) {
InlineCacheState state = code->ic_state(); InlineCacheState state = code->ic_state();
...@@ -180,13 +182,14 @@ class IC { ...@@ -180,13 +182,14 @@ class IC {
// Compute the handler either by compiling or by retrieving a cached version. // Compute the handler either by compiling or by retrieving a cached version.
Handle<Code> ComputeHandler(LookupResult* lookup, Handle<Code> ComputeHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value = Handle<Code>::null()); Handle<Object> value = Handle<Code>::null());
virtual Handle<Code> CompileHandler(LookupResult* lookup, virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value,
InlineCacheHolderFlag cache_holder) {
UNREACHABLE(); UNREACHABLE();
return Handle<Code>::null(); return Handle<Code>::null();
} }
...@@ -200,7 +203,7 @@ class IC { ...@@ -200,7 +203,7 @@ class IC {
void CopyICToMegamorphicCache(Handle<String> name); void CopyICToMegamorphicCache(Handle<String> name);
bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map); bool IsTransitionedMapOfMonomorphicTarget(Map* receiver_map);
void PatchCache(Handle<HeapObject> receiver, void PatchCache(Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Code> code); Handle<Code> code);
virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code); virtual void UpdateMegamorphicCache(Map* map, Name* name, Code* code);
...@@ -422,9 +425,10 @@ class LoadIC: public IC { ...@@ -422,9 +425,10 @@ class LoadIC: public IC {
Handle<String> name); Handle<String> name);
virtual Handle<Code> CompileHandler(LookupResult* lookup, virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> unused); Handle<Object> unused,
InlineCacheHolderFlag cache_holder);
private: private:
// Stub accessors. // Stub accessors.
...@@ -617,9 +621,10 @@ class StoreIC: public IC { ...@@ -617,9 +621,10 @@ class StoreIC: public IC {
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value);
virtual Handle<Code> CompileHandler(LookupResult* lookup, virtual Handle<Code> CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value,
InlineCacheHolderFlag cache_holder);
private: private:
void set_target(Code* code) { void set_target(Code* code) {
......
...@@ -4185,9 +4185,9 @@ Code::Flags Code::ComputeFlags(Kind kind, ...@@ -4185,9 +4185,9 @@ Code::Flags Code::ComputeFlags(Kind kind,
Code::Flags Code::ComputeMonomorphicFlags(Kind kind, Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
ExtraICState extra_ic_state, ExtraICState extra_ic_state,
InlineCacheHolderFlag holder,
StubType type, StubType type,
int argc, int argc) {
InlineCacheHolderFlag holder) {
return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder); return ComputeFlags(kind, MONOMORPHIC, extra_ic_state, type, argc, holder);
} }
......
...@@ -5253,9 +5253,9 @@ class Code: public HeapObject { ...@@ -5253,9 +5253,9 @@ class Code: public HeapObject {
static inline Flags ComputeMonomorphicFlags( static inline Flags ComputeMonomorphicFlags(
Kind kind, Kind kind,
ExtraICState extra_ic_state = kNoExtraICState, ExtraICState extra_ic_state = kNoExtraICState,
InlineCacheHolderFlag holder = OWN_MAP,
StubType type = NORMAL, StubType type = NORMAL,
int argc = -1, int argc = -1);
InlineCacheHolderFlag holder = OWN_MAP);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags); static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline StubType ExtractTypeFromFlags(Flags flags); static inline StubType ExtractTypeFromFlags(Flags flags);
......
This diff is collapsed.
This diff is collapsed.
...@@ -298,11 +298,8 @@ void TypeFeedbackOracle::CallReceiverTypes(Call* expr, ...@@ -298,11 +298,8 @@ void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
Code::ExtraICState extra_ic_state = Code::ExtraICState extra_ic_state =
CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION); CallIC::Contextual::encode(call_kind == CALL_AS_FUNCTION);
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC, Code::Flags flags = Code::ComputeMonomorphicFlags(
extra_ic_state, Code::CALL_IC, extra_ic_state, OWN_MAP, Code::NORMAL, arity);
Code::NORMAL,
arity,
OWN_MAP);
CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types); CollectReceiverTypes(expr->CallFeedbackId(), name, flags, types);
} }
......
...@@ -1200,34 +1200,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object, ...@@ -1200,34 +1200,33 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
} }
void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); Label success;
__ jmp(&success);
__ bind(miss); __ bind(miss);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) {
Label* success,
Label* miss) {
if (!miss->is_unused()) { if (!miss->is_unused()) {
__ jmp(success); Label success;
__ jmp(&success);
GenerateRestoreName(masm(), miss, name); GenerateRestoreName(masm(), miss, name);
TailCallBuiltin(masm(), MissBuiltin(kind())); TailCallBuiltin(masm(), MissBuiltin(kind()));
__ bind(&success);
} }
} }
Register LoadStubCompiler::CallbackHandlerFrontend( Register LoadStubCompiler::CallbackHandlerFrontend(
Handle<JSObject> object, Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* success,
Handle<Object> callback) { Handle<Object> callback) {
Label miss; Label miss;
...@@ -1268,7 +1267,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend( ...@@ -1268,7 +1267,7 @@ Register LoadStubCompiler::CallbackHandlerFrontend(
__ j(not_equal, &miss); __ j(not_equal, &miss);
} }
HandlerFrontendFooter(name, success, &miss); HandlerFrontendFooter(name, &miss);
return reg; return reg;
} }
...@@ -1389,7 +1388,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { ...@@ -1389,7 +1388,7 @@ void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) {
void LoadStubCompiler::GenerateLoadInterceptor( void LoadStubCompiler::GenerateLoadInterceptor(
Register holder_reg, Register holder_reg,
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> interceptor_holder, Handle<JSObject> interceptor_holder,
LookupResult* lookup, LookupResult* lookup,
Handle<Name> name) { Handle<Name> name) {
...@@ -2507,11 +2506,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall( ...@@ -2507,11 +2506,21 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
} }
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
__ CompareRoot(object, Heap::kTrueValueRootIndex);
__ j(equal, &success);
__ CompareRoot(object, Heap::kFalseValueRootIndex);
__ j(not_equal, miss);
__ bind(&success);
}
void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
CheckType check, CheckType check) {
Label* success) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rcx : function name // rcx : function name
// rsp[0] : return address // rsp[0] : return address
...@@ -2593,13 +2602,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2593,13 +2602,7 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
break; break;
} }
case BOOLEAN_CHECK: { case BOOLEAN_CHECK: {
Label fast; GenerateBooleanCheck(rdx, &miss);
// Check that the object is a boolean.
__ CompareRoot(rdx, Heap::kTrueValueRootIndex);
__ j(equal, &fast);
__ CompareRoot(rdx, Heap::kFalseValueRootIndex);
__ j(not_equal, &miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed. // Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype( GenerateDirectLoadGlobalFunctionPrototype(
masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss);
...@@ -2610,11 +2613,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object, ...@@ -2610,11 +2613,14 @@ void CallStubCompiler::CompileHandlerFrontend(Handle<Object> object,
} }
} }
__ jmp(success); Label success;
__ jmp(&success);
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
GenerateMissBranch(); GenerateMissBranch();
__ bind(&success);
} }
...@@ -2643,10 +2649,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant( ...@@ -2643,10 +2649,7 @@ Handle<Code> CallStubCompiler::CompileCallConstant(
if (!code.is_null()) return code; if (!code.is_null()) return code;
} }
Label success; CompileHandlerFrontend(object, holder, name, check);
CompileHandlerFrontend(object, holder, name, check, &success);
__ bind(&success);
CompileHandlerBackend(function); CompileHandlerBackend(function);
// Return the generated code. // Return the generated code.
...@@ -2782,9 +2785,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2782,9 +2785,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
__ PopReturnAddressTo(scratch1()); __ PopReturnAddressTo(scratch1());
__ push(receiver()); __ push(receiver());
...@@ -2808,9 +2809,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2808,9 +2809,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
const CallOptimization& call_optimization) { const CallOptimization& call_optimization) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
Register values[] = { value() }; Register values[] = { value() };
GenerateFastApiCall( GenerateFastApiCall(
...@@ -2924,15 +2923,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( ...@@ -2924,15 +2923,12 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
Handle<Code> LoadStubCompiler::CompileLoadNonexistent( Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Handle<JSGlobalObject> global) { Handle<JSGlobalObject> global) {
Label success; NonexistentHandlerFrontend(object, last, name, global);
NonexistentHandlerFrontend(object, last, name, &success, global);
__ bind(&success);
// Return undefined if maps of the full prototype chain are still the // Return undefined if maps of the full prototype chain are still the
// same and no global property with this name contains a value. // same and no global property with this name contains a value.
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex); __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
...@@ -3027,12 +3023,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, ...@@ -3027,12 +3023,12 @@ void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
Handle<Code> LoadStubCompiler::CompileLoadGlobal( Handle<Code> LoadStubCompiler::CompileLoadGlobal(
Handle<JSObject> object, Handle<Object> object,
Handle<GlobalObject> global, Handle<GlobalObject> global,
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<Name> name, Handle<Name> name,
bool is_dont_delete) { bool is_dont_delete) {
Label success, miss; Label miss;
// TODO(verwaest): Directly store to rax. Currently we cannot do this, since // TODO(verwaest): Directly store to rax. Currently we cannot do this, since
// rax is used as receiver(), which we would otherwise clobber before a // rax is used as receiver(), which we would otherwise clobber before a
// potential miss. // potential miss.
...@@ -3051,8 +3047,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal( ...@@ -3051,8 +3047,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole); __ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
} }
HandlerFrontendFooter(name, &success, &miss); HandlerFrontendFooter(name, &miss);
__ bind(&success);
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1); __ IncrementCounter(counters->named_load_global_stub(), 1);
......
// Copyright 2013 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:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Object.defineProperty(Boolean.prototype, "v",
{get:function() { return this; }});
function f(b) {
return b.v;
}
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
assertEquals("object", typeof f(true));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment