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);
} }
......
...@@ -1005,7 +1005,7 @@ void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, ...@@ -1005,7 +1005,7 @@ void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
Handle<String> name) { Handle<String> name) {
if (!handler->is_handler()) return set_target(*handler); if (!handler->is_handler()) return set_target(*handler);
Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
receiver, handler, name, strict_mode()); name, receiver, handler, strict_mode());
set_target(*ic); set_target(*ic);
} }
...@@ -1035,9 +1035,13 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) { ...@@ -1035,9 +1035,13 @@ bool IC::IsTransitionedMapOfMonomorphicTarget(Map* receiver_map) {
} }
void IC::PatchCache(Handle<HeapObject> receiver, void IC::PatchCache(Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Code> code) { Handle<Code> code) {
// TODO(verwaest): Handle smi here as well.
if (!object->IsHeapObject()) return;
Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
switch (state()) { switch (state()) {
case UNINITIALIZED: case UNINITIALIZED:
case PREMONOMORPHIC: case PREMONOMORPHIC:
...@@ -1097,13 +1101,6 @@ Handle<Code> LoadIC::SimpleFieldLoad(int offset, ...@@ -1097,13 +1101,6 @@ Handle<Code> LoadIC::SimpleFieldLoad(int offset,
void LoadIC::UpdateCaches(LookupResult* lookup, void LoadIC::UpdateCaches(LookupResult* lookup,
Handle<Object> object, Handle<Object> object,
Handle<String> name) { Handle<String> name) {
// TODO(verwaest): It would be nice to support loading fields from smis as
// well. For now just fail to update the cache.
if (!object->IsHeapObject()) return;
Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
Handle<Code> code;
if (state() == UNINITIALIZED) { if (state() == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
...@@ -1111,27 +1108,23 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -1111,27 +1108,23 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
set_target(*pre_monomorphic_stub()); set_target(*pre_monomorphic_stub());
TRACE_IC("LoadIC", name); TRACE_IC("LoadIC", name);
return; return;
} else if (!lookup->IsCacheable()) { }
Handle<Code> code;
if (!lookup->IsCacheable()) {
// Bail out if the result is not cacheable. // Bail out if the result is not cacheable.
code = slow_stub(); code = slow_stub();
} else if (object->IsString() &&
name->Equals(isolate()->heap()->length_string())) {
int length_index = String::kLengthOffset / kPointerSize;
code = SimpleFieldLoad(length_index);
} else if (!object->IsJSObject()) {
// TODO(jkummerow): It would be nice to support non-JSObjects in
// ComputeLoadHandler, then we wouldn't need to go generic here.
code = slow_stub();
} else if (!lookup->IsProperty()) { } else if (!lookup->IsProperty()) {
code = kind() == Code::LOAD_IC if (kind() == Code::LOAD_IC) {
? isolate()->stub_cache()->ComputeLoadNonexistent( code = isolate()->stub_cache()->ComputeLoadNonexistent(name, object);
name, Handle<JSObject>::cast(receiver))
: slow_stub();
} else { } else {
code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name); code = slow_stub();
}
} else {
code = ComputeHandler(lookup, object, name);
} }
PatchCache(receiver, name, code); PatchCache(object, name, code);
TRACE_IC("LoadIC", name); TRACE_IC("LoadIC", name);
} }
...@@ -1144,18 +1137,22 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { ...@@ -1144,18 +1137,22 @@ void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) {
Handle<Code> IC::ComputeHandler(LookupResult* lookup, Handle<Code> IC::ComputeHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value) {
InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
Handle<HeapObject> stub_holder(GetCodeCacheHolder(
isolate(), *object, cache_holder));
Handle<Code> code = isolate()->stub_cache()->FindHandler( Handle<Code> code = isolate()->stub_cache()->FindHandler(
name, receiver, kind()); name, stub_holder, kind(), cache_holder, strict_mode());
if (!code.is_null()) return code; if (!code.is_null()) return code;
code = CompileHandler(lookup, receiver, name, value); code = CompileHandler(lookup, object, name, value, cache_holder);
ASSERT(code->is_handler()); ASSERT(code->is_handler());
if (code->type() != Code::NORMAL) { if (code->type() != Code::NORMAL) {
HeapObject::UpdateMapCodeCache(receiver, name, code); HeapObject::UpdateMapCodeCache(stub_holder, name, code);
} }
return code; return code;
...@@ -1163,29 +1160,35 @@ Handle<Code> IC::ComputeHandler(LookupResult* lookup, ...@@ -1163,29 +1160,35 @@ Handle<Code> IC::ComputeHandler(LookupResult* lookup,
Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> unused) { Handle<Object> unused,
InlineCacheHolderFlag cache_holder) {
if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
int length_index = String::kLengthOffset / kPointerSize;
return SimpleFieldLoad(length_index);
}
Handle<JSObject> holder(lookup->holder()); Handle<JSObject> holder(lookup->holder());
LoadStubCompiler compiler(isolate(), kind()); LoadStubCompiler compiler(isolate(), cache_holder, kind());
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
PropertyIndex field = lookup->GetFieldIndex(); PropertyIndex field = lookup->GetFieldIndex();
if (receiver.is_identical_to(holder)) { if (object.is_identical_to(holder)) {
return SimpleFieldLoad(field.translate(holder), return SimpleFieldLoad(field.translate(holder),
field.is_inobject(holder), field.is_inobject(holder),
lookup->representation()); lookup->representation());
} }
return compiler.CompileLoadField( return compiler.CompileLoadField(
receiver, holder, name, field, lookup->representation()); object, holder, name, field, lookup->representation());
} }
case CONSTANT: { case CONSTANT: {
Handle<Object> constant(lookup->GetConstant(), isolate()); Handle<Object> constant(lookup->GetConstant(), isolate());
// TODO(2803): Don't compute a stub for cons strings because they cannot // TODO(2803): Don't compute a stub for cons strings because they cannot
// be embedded into code. // be embedded into code.
if (constant->IsConsString()) break; if (constant->IsConsString()) break;
return compiler.CompileLoadConstant(receiver, holder, name, constant); return compiler.CompileLoadConstant(object, holder, name, constant);
} }
case NORMAL: case NORMAL:
if (kind() != Code::LOAD_IC) break; if (kind() != Code::LOAD_IC) break;
...@@ -1194,20 +1197,24 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, ...@@ -1194,20 +1197,24 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
Handle<PropertyCell> cell( Handle<PropertyCell> cell(
global->GetPropertyCell(lookup), isolate()); global->GetPropertyCell(lookup), isolate());
Handle<Code> code = compiler.CompileLoadGlobal( Handle<Code> code = compiler.CompileLoadGlobal(
receiver, global, cell, name, lookup->IsDontDelete()); object, global, cell, name, lookup->IsDontDelete());
// TODO(verwaest): Move caching of these NORMAL stubs outside as well. // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
HeapObject::UpdateMapCodeCache(receiver, name, code); Handle<HeapObject> stub_holder(GetCodeCacheHolder(
isolate(), *object, cache_holder));
HeapObject::UpdateMapCodeCache(stub_holder, name, code);
return code; return code;
} }
// There is only one shared stub for loading normalized // There is only one shared stub for loading normalized
// properties. It does not traverse the prototype chain, so the // properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be // property must be found in the object for the stub to be
// applicable. // applicable.
if (!holder.is_identical_to(receiver)) break; if (!object.is_identical_to(holder)) break;
return isolate()->builtins()->LoadIC_Normal(); return isolate()->builtins()->LoadIC_Normal();
case CALLBACKS: { case CALLBACKS: {
// Use simple field loads for some well-known callback properties. // Use simple field loads for some well-known callback properties.
int object_offset; int object_offset;
if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<Map> map(receiver->map()); Handle<Map> map(receiver->map());
if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) { if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
PropertyIndex index = PropertyIndex index =
...@@ -1215,14 +1222,15 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, ...@@ -1215,14 +1222,15 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
return compiler.CompileLoadField( return compiler.CompileLoadField(
receiver, receiver, name, index, Representation::Tagged()); receiver, receiver, name, index, Representation::Tagged());
} }
}
Handle<Object> callback(lookup->GetCallbackObject(), isolate()); Handle<Object> callback(lookup->GetCallbackObject(), isolate());
if (callback->IsExecutableAccessorInfo()) { if (callback->IsExecutableAccessorInfo()) {
Handle<ExecutableAccessorInfo> info = Handle<ExecutableAccessorInfo> info =
Handle<ExecutableAccessorInfo>::cast(callback); Handle<ExecutableAccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->getter()) == 0) break; if (v8::ToCData<Address>(info->getter()) == 0) break;
if (!info->IsCompatibleReceiver(*receiver)) break; if (!info->IsCompatibleReceiver(*object)) break;
return compiler.CompileLoadCallback(receiver, holder, name, info); return compiler.CompileLoadCallback(object, holder, name, info);
} else if (callback->IsAccessorPair()) { } else if (callback->IsAccessorPair()) {
Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
isolate()); isolate());
...@@ -1230,13 +1238,20 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, ...@@ -1230,13 +1238,20 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
if (holder->IsGlobalObject()) break; if (holder->IsGlobalObject()) break;
if (!holder->HasFastProperties()) break; if (!holder->HasFastProperties()) break;
Handle<JSFunction> function = Handle<JSFunction>::cast(getter); Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
if (!object->IsJSObject() &&
!function->IsBuiltin() &&
function->shared()->is_classic_mode()) {
// Calling non-strict non-builtins with a value as the receiver
// requires boxing.
break;
}
CallOptimization call_optimization(function); CallOptimization call_optimization(function);
if (call_optimization.is_simple_api_call() && if (call_optimization.is_simple_api_call() &&
call_optimization.IsCompatibleReceiver(*receiver)) { call_optimization.IsCompatibleReceiver(*object)) {
return compiler.CompileLoadCallback( return compiler.CompileLoadCallback(
receiver, holder, name, call_optimization); object, holder, name, call_optimization);
} }
return compiler.CompileLoadViaGetter(receiver, holder, name, function); return compiler.CompileLoadViaGetter(object, holder, name, function);
} }
// TODO(dcarney): Handle correctly. // TODO(dcarney): Handle correctly.
if (callback->IsDeclaredAccessorInfo()) break; if (callback->IsDeclaredAccessorInfo()) break;
...@@ -1246,7 +1261,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup, ...@@ -1246,7 +1261,7 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
} }
case INTERCEPTOR: case INTERCEPTOR:
ASSERT(HasInterceptorGetter(*holder)); ASSERT(HasInterceptorGetter(*holder));
return compiler.CompileLoadInterceptor(receiver, holder, name); return compiler.CompileLoadInterceptor(object, holder, name);
default: default:
break; break;
} }
...@@ -1582,9 +1597,14 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ...@@ -1582,9 +1597,14 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
Handle<Code> StoreIC::CompileHandler(LookupResult* lookup, Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
Handle<JSObject> receiver, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value,
InlineCacheHolderFlag cache_holder) {
ASSERT(cache_holder == OWN_MAP);
// This is currently guaranteed by checks in StoreIC::Store.
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
Handle<JSObject> holder(lookup->holder()); Handle<JSObject> holder(lookup->holder());
StoreStubCompiler compiler(isolate(), strict_mode(), kind()); StoreStubCompiler compiler(isolate(), strict_mode(), kind());
switch (lookup->type()) { switch (lookup->type()) {
......
...@@ -132,9 +132,11 @@ class IC { ...@@ -132,9 +132,11 @@ 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
// the string map directly, rather than on the JSObject-typed prototype.
static inline HeapObject* GetCodeCacheHolder(Isolate* isolate,
Object* object, Object* object,
InlineCacheHolderFlag holder); InlineCacheHolderFlag holder);
...@@ -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);
......
...@@ -102,8 +102,10 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) { ...@@ -102,8 +102,10 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) {
Handle<Code> StubCache::FindIC(Handle<Name> name, Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<Map> stub_holder_map, Handle<Map> stub_holder_map,
Code::Kind kind, Code::Kind kind,
Code::ExtraICState extra_state) { Code::ExtraICState extra_state,
Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state); InlineCacheHolderFlag cache_holder) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, cache_holder);
Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags), Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
...@@ -111,17 +113,10 @@ Handle<Code> StubCache::FindIC(Handle<Name> name, ...@@ -111,17 +113,10 @@ Handle<Code> StubCache::FindIC(Handle<Name> name,
} }
Handle<Code> StubCache::FindIC(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
Code::ExtraICState extra_ic_state) {
return FindIC(name, Handle<Map>(stub_holder->map()), kind, extra_ic_state);
}
Handle<Code> StubCache::FindHandler(Handle<Name> name, Handle<Code> StubCache::FindHandler(Handle<Name> name,
Handle<JSObject> receiver, Handle<HeapObject> stub_holder,
Code::Kind kind, Code::Kind kind,
InlineCacheHolderFlag cache_holder,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::ExtraICState extra_ic_state = Code::kNoExtraICState; Code::ExtraICState extra_ic_state = Code::kNoExtraICState;
if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) {
...@@ -129,28 +124,36 @@ Handle<Code> StubCache::FindHandler(Handle<Name> name, ...@@ -129,28 +124,36 @@ Handle<Code> StubCache::FindHandler(Handle<Name> name,
STANDARD_STORE, strict_mode); STANDARD_STORE, strict_mode);
} }
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::HANDLER, extra_ic_state, Code::NORMAL, kind); Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
return Handle<Code>::null(); return Handle<Code>::null();
} }
Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver, Handle<Code> StubCache::ComputeMonomorphicIC(Handle<Name> name,
Handle<HeapObject> object,
Handle<Code> handler, Handle<Code> handler,
Handle<Name> name,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::Kind kind = handler->handler_kind(); Code::Kind kind = handler->handler_kind();
Handle<Map> map(receiver->map()); // Use the same cache holder for the IC as for the handler.
Handle<Code> ic = FindIC(name, map, kind, strict_mode); InlineCacheHolderFlag cache_holder =
Code::ExtractCacheHolderFromFlags(handler->flags());
Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
isolate(), *object, cache_holder));
Handle<Map> stub_holder_map(stub_holder->map());
Handle<Code> ic = FindIC(
name, stub_holder_map, kind, strict_mode, cache_holder);
if (!ic.is_null()) return ic; if (!ic.is_null()) return ic;
Handle<Map> map(object->map());
if (kind == Code::LOAD_IC) { if (kind == Code::LOAD_IC) {
LoadStubCompiler ic_compiler(isolate()); LoadStubCompiler ic_compiler(isolate(), cache_holder);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
} else if (kind == Code::KEYED_LOAD_IC) { } else if (kind == Code::KEYED_LOAD_IC) {
KeyedLoadStubCompiler ic_compiler(isolate()); KeyedLoadStubCompiler ic_compiler(isolate(), cache_holder);
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
} else if (kind == Code::STORE_IC) { } else if (kind == Code::STORE_IC) {
StoreStubCompiler ic_compiler(isolate(), strict_mode); StoreStubCompiler ic_compiler(isolate(), strict_mode);
...@@ -161,13 +164,16 @@ Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver, ...@@ -161,13 +164,16 @@ Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver,
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); ic = ic_compiler.CompileMonomorphicIC(map, handler, name);
} }
HeapObject::UpdateMapCodeCache(receiver, name, ic); HeapObject::UpdateMapCodeCache(stub_holder, name, ic);
return ic; return ic;
} }
Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
Handle<JSObject> receiver) { Handle<Object> object) {
InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
isolate(), *object, cache_holder));
// If no global objects are present in the prototype chain, the load // If no global objects are present in the prototype chain, the load
// nonexistent IC stub can be shared for all names for a given map // nonexistent IC stub can be shared for all names for a given map
// and we use the empty string for the map cache in that case. If // and we use the empty string for the map cache in that case. If
...@@ -176,7 +182,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, ...@@ -176,7 +182,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
// specific to the name. // specific to the name.
Handle<Name> cache_name = factory()->empty_string(); Handle<Name> cache_name = factory()->empty_string();
Handle<JSObject> current; Handle<JSObject> current;
Handle<Object> next = receiver; Handle<Object> next = stub_holder;
Handle<JSGlobalObject> global; Handle<JSGlobalObject> global;
do { do {
current = Handle<JSObject>::cast(next); current = Handle<JSObject>::cast(next);
...@@ -191,13 +197,14 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, ...@@ -191,13 +197,14 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
// Compile the stub that is either shared for all names or // Compile the stub that is either shared for all names or
// name specific if there are global objects involved. // name specific if there are global objects involved.
Handle<Code> handler = FindHandler(cache_name, receiver, Code::LOAD_IC); Handle<Code> handler = FindHandler(
cache_name, stub_holder, Code::LOAD_IC, cache_holder);
if (!handler.is_null()) return handler; if (!handler.is_null()) return handler;
LoadStubCompiler compiler(isolate_); LoadStubCompiler compiler(isolate_, cache_holder);
handler = handler =
compiler.CompileLoadNonexistent(receiver, current, cache_name, global); compiler.CompileLoadNonexistent(object, current, cache_name, global);
HeapObject::UpdateMapCodeCache(receiver, cache_name, handler); HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler);
return handler; return handler;
} }
...@@ -257,9 +264,8 @@ Handle<Code> StubCache::ComputeCallConstant(int argc, ...@@ -257,9 +264,8 @@ Handle<Code> StubCache::ComputeCallConstant(int argc,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<JSFunction> function) { Handle<JSFunction> function) {
// Compute the check type and the map. // Compute the check type and the map.
InlineCacheHolderFlag cache_holder = InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
IC::GetCodeCacheForObject(*object, *holder); Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder)); isolate_, *object, cache_holder));
// Compute check type based on receiver/holder. // Compute check type based on receiver/holder.
...@@ -283,7 +289,7 @@ Handle<Code> StubCache::ComputeCallConstant(int argc, ...@@ -283,7 +289,7 @@ Handle<Code> StubCache::ComputeCallConstant(int argc,
} }
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, Code::CONSTANT, argc, cache_holder); kind, extra_state, cache_holder, Code::CONSTANT, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
...@@ -312,9 +318,8 @@ Handle<Code> StubCache::ComputeCallField(int argc, ...@@ -312,9 +318,8 @@ Handle<Code> StubCache::ComputeCallField(int argc,
Handle<JSObject> holder, Handle<JSObject> holder,
PropertyIndex index) { PropertyIndex index) {
// Compute the check type and the map. // Compute the check type and the map.
InlineCacheHolderFlag cache_holder = InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
IC::GetCodeCacheForObject(*object, *holder); Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder)); isolate_, *object, cache_holder));
// TODO(1233596): We cannot do receiver map check for non-JS objects // TODO(1233596): We cannot do receiver map check for non-JS objects
...@@ -326,7 +331,7 @@ Handle<Code> StubCache::ComputeCallField(int argc, ...@@ -326,7 +331,7 @@ Handle<Code> StubCache::ComputeCallField(int argc,
} }
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, Code::FIELD, argc, cache_holder); kind, extra_state, cache_holder, Code::FIELD, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
...@@ -351,9 +356,8 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc, ...@@ -351,9 +356,8 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc,
Handle<Object> object, Handle<Object> object,
Handle<JSObject> holder) { Handle<JSObject> holder) {
// Compute the check type and the map. // Compute the check type and the map.
InlineCacheHolderFlag cache_holder = InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object);
IC::GetCodeCacheForObject(*object, *holder); Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder(
Handle<JSObject> stub_holder(IC::GetCodeCacheHolder(
isolate_, *object, cache_holder)); isolate_, *object, cache_holder));
// TODO(1233596): We cannot do receiver map check for non-JS objects // TODO(1233596): We cannot do receiver map check for non-JS objects
...@@ -365,7 +369,7 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc, ...@@ -365,7 +369,7 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc,
} }
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, Code::INTERCEPTOR, argc, cache_holder); kind, extra_state, cache_holder, Code::INTERCEPTOR, argc);
Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
...@@ -392,7 +396,7 @@ Handle<Code> StubCache::ComputeCallGlobal(int argc, ...@@ -392,7 +396,7 @@ Handle<Code> StubCache::ComputeCallGlobal(int argc,
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<JSFunction> function) { Handle<JSFunction> function) {
Code::Flags flags = Code::ComputeMonomorphicFlags( Code::Flags flags = Code::ComputeMonomorphicFlags(
kind, extra_state, Code::NORMAL, argc); kind, extra_state, OWN_MAP, Code::NORMAL, argc);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
isolate_); isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
...@@ -1096,10 +1100,7 @@ Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, ...@@ -1096,10 +1100,7 @@ Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags,
masm_.GetCode(&desc); masm_.GetCode(&desc);
Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject());
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
if (FLAG_print_code_stubs) { if (FLAG_print_code_stubs) code->Disassemble(name);
CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
code->Disassemble(name, trace_scope.file());
}
#endif #endif
return code; return code;
} }
...@@ -1127,55 +1128,82 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, ...@@ -1127,55 +1128,82 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder,
Register LoadStubCompiler::HandlerFrontendHeader( Register LoadStubCompiler::HandlerFrontendHeader(
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* miss) { Label* miss) {
return CheckPrototypes(object, object_reg, holder, Handle<JSObject> receiver;
PrototypeCheckType check_type = CHECK_ALL_MAPS;
int function_index = -1;
if (object->IsJSObject()) {
receiver = Handle<JSObject>::cast(object);
check_type = SKIP_RECEIVER;
} else {
if (object->IsString()) {
function_index = Context::STRING_FUNCTION_INDEX;
} else if (object->IsSymbol()) {
function_index = Context::SYMBOL_FUNCTION_INDEX;
} else if (object->IsNumber()) {
function_index = Context::NUMBER_FUNCTION_INDEX;
} else {
ASSERT(object->IsBoolean());
// Booleans use the generic oddball map, so an additional check is
// needed to ensure the receiver is really a boolean.
GenerateBooleanCheck(object_reg, miss);
function_index = Context::BOOLEAN_FUNCTION_INDEX;
}
GenerateDirectLoadGlobalFunctionPrototype(
masm(), function_index, scratch1(), miss);
receiver = handle(JSObject::cast(object->GetPrototype(isolate())));
object_reg = scratch1();
}
// Check that the maps starting from the prototype haven't changed.
return CheckPrototypes(receiver, object_reg, holder,
scratch1(), scratch2(), scratch3(), scratch1(), scratch2(), scratch3(),
name, miss, SKIP_RECEIVER); name, miss, check_type);
} }
// HandlerFrontend for store uses the name register. It has to be restored // HandlerFrontend for store uses the name register. It has to be restored
// before a miss. // before a miss.
Register StoreStubCompiler::HandlerFrontendHeader( Register StoreStubCompiler::HandlerFrontendHeader(
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* miss) { Label* miss) {
return CheckPrototypes(object, object_reg, holder, return CheckPrototypes(Handle<JSObject>::cast(object), object_reg, holder,
this->name(), scratch1(), scratch2(), this->name(), scratch1(), scratch2(),
name, miss, SKIP_RECEIVER); name, miss, SKIP_RECEIVER);
} }
Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object, Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name) {
Label* success) {
Label miss; Label miss;
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss);
HandlerFrontendFooter(name, success, &miss); HandlerFrontendFooter(name, &miss);
return reg; return reg;
} }
void LoadStubCompiler::NonexistentHandlerFrontend( void LoadStubCompiler::NonexistentHandlerFrontend(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Label* success,
Handle<JSGlobalObject> global) { Handle<JSGlobalObject> global) {
Label miss; Label miss;
Register holder = Register holder = HandlerFrontendHeader(
HandlerFrontendHeader(object, receiver(), last, name, &miss); object, receiver(), last, name, &miss);
if (!last->HasFastProperties() && if (!last->HasFastProperties() &&
!last->IsJSGlobalObject() && !last->IsJSGlobalObject() &&
...@@ -1196,12 +1224,12 @@ void LoadStubCompiler::NonexistentHandlerFrontend( ...@@ -1196,12 +1224,12 @@ void LoadStubCompiler::NonexistentHandlerFrontend(
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
} }
HandlerFrontendFooter(name, success, &miss); HandlerFrontendFooter(name, &miss);
} }
Handle<Code> LoadStubCompiler::CompileLoadField( Handle<Code> LoadStubCompiler::CompileLoadField(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
PropertyIndex field, PropertyIndex field,
...@@ -1221,13 +1249,11 @@ Handle<Code> LoadStubCompiler::CompileLoadField( ...@@ -1221,13 +1249,11 @@ Handle<Code> LoadStubCompiler::CompileLoadField(
Handle<Code> LoadStubCompiler::CompileLoadConstant( Handle<Code> LoadStubCompiler::CompileLoadConstant(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> value) { Handle<Object> value) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
GenerateLoadConstant(value); GenerateLoadConstant(value);
// Return the generated code. // Return the generated code.
...@@ -1236,15 +1262,12 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant( ...@@ -1236,15 +1262,12 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant(
Handle<Code> LoadStubCompiler::CompileLoadCallback( Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback) { Handle<ExecutableAccessorInfo> callback) {
Label success;
Register reg = CallbackHandlerFrontend( Register reg = CallbackHandlerFrontend(
object, receiver(), holder, name, &success, callback); object, receiver(), holder, name, callback);
__ bind(&success);
GenerateLoadCallback(reg, callback); GenerateLoadCallback(reg, callback);
// Return the generated code. // Return the generated code.
...@@ -1253,17 +1276,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback( ...@@ -1253,17 +1276,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<Code> LoadStubCompiler::CompileLoadCallback( Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
const CallOptimization& call_optimization) { const CallOptimization& call_optimization) {
ASSERT(call_optimization.is_simple_api_call()); ASSERT(call_optimization.is_simple_api_call());
Label success;
Handle<JSFunction> callback = call_optimization.constant_function(); Handle<JSFunction> callback = call_optimization.constant_function();
CallbackHandlerFrontend( CallbackHandlerFrontend(object, receiver(), holder, name, callback);
object, receiver(), holder, name, &success, callback);
__ bind(&success);
GenerateLoadCallback(call_optimization); GenerateLoadCallback(call_optimization);
// Return the generated code. // Return the generated code.
...@@ -1272,16 +1291,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback( ...@@ -1272,16 +1291,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
Handle<Code> LoadStubCompiler::CompileLoadInterceptor( Handle<Code> LoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name) { Handle<Name> name) {
Label success;
LookupResult lookup(isolate()); LookupResult lookup(isolate());
LookupPostInterceptor(holder, name, &lookup); LookupPostInterceptor(holder, name, &lookup);
Register reg = HandlerFrontend(object, receiver(), holder, name, &success); Register reg = HandlerFrontend(object, receiver(), holder, name);
__ bind(&success);
// TODO(368): Compile in the whole chain: all the interceptors in // TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer. // prototypes and ultimate answer.
GenerateLoadInterceptor(reg, object, holder, &lookup, name); GenerateLoadInterceptor(reg, object, holder, &lookup, name);
...@@ -1296,7 +1312,6 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( ...@@ -1296,7 +1312,6 @@ void LoadStubCompiler::GenerateLoadPostInterceptor(
Handle<JSObject> interceptor_holder, Handle<JSObject> interceptor_holder,
Handle<Name> name, Handle<Name> name,
LookupResult* lookup) { LookupResult* lookup) {
Label success;
Handle<JSObject> holder(lookup->holder()); Handle<JSObject> holder(lookup->holder());
if (lookup->IsField()) { if (lookup->IsField()) {
PropertyIndex field = lookup->GetFieldIndex(); PropertyIndex field = lookup->GetFieldIndex();
...@@ -1307,8 +1322,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( ...@@ -1307,8 +1322,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor(
// We found FIELD property in prototype chain of interceptor's holder. // We found FIELD property in prototype chain of interceptor's holder.
// Retrieve a field from field's holder. // Retrieve a field from field's holder.
Register reg = HandlerFrontend( Register reg = HandlerFrontend(
interceptor_holder, interceptor_reg, holder, name, &success); interceptor_holder, interceptor_reg, holder, name);
__ bind(&success);
GenerateLoadField( GenerateLoadField(
reg, holder, field, lookup->representation()); reg, holder, field, lookup->representation());
} }
...@@ -1321,8 +1335,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( ...@@ -1321,8 +1335,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor(
ASSERT(callback->getter() != NULL); ASSERT(callback->getter() != NULL);
Register reg = CallbackHandlerFrontend( Register reg = CallbackHandlerFrontend(
interceptor_holder, interceptor_reg, holder, name, &success, callback); interceptor_holder, interceptor_reg, holder, name, callback);
__ bind(&success);
GenerateLoadCallback(reg, callback); GenerateLoadCallback(reg, callback);
} }
} }
...@@ -1342,14 +1355,11 @@ Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( ...@@ -1342,14 +1355,11 @@ Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC(
Handle<Code> LoadStubCompiler::CompileLoadViaGetter( Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<JSFunction> getter) { Handle<JSFunction> getter) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
GenerateLoadViaGetter(masm(), receiver(), getter); GenerateLoadViaGetter(masm(), receiver(), getter);
// Return the generated code. // Return the generated code.
...@@ -1442,10 +1452,7 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter( ...@@ -1442,10 +1452,7 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<JSFunction> setter) { Handle<JSFunction> setter) {
Label success; HandlerFrontend(object, receiver(), holder, name);
HandlerFrontend(object, receiver(), holder, name, &success);
__ bind(&success);
GenerateStoreViaSetter(masm(), setter); GenerateStoreViaSetter(masm(), setter);
return GetCode(kind(), Code::CALLBACKS, name); return GetCode(kind(), Code::CALLBACKS, name);
...@@ -1555,7 +1562,7 @@ Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, ...@@ -1555,7 +1562,7 @@ Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind,
Code::StubType type, Code::StubType type,
Handle<Name> name) { Handle<Name> name) {
Code::Flags flags = Code::ComputeFlags( Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, extra_state(), type, kind); Code::HANDLER, MONOMORPHIC, extra_state(), type, kind, cache_holder_);
Handle<Code> code = GetCodeWithFlags(flags, name); Handle<Code> code = GetCodeWithFlags(flags, name);
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
JitEvent(name, code); JitEvent(name, code);
...@@ -1723,11 +1730,8 @@ Handle<Code> CallStubCompiler::CompileCustomCall( ...@@ -1723,11 +1730,8 @@ Handle<Code> CallStubCompiler::CompileCustomCall(
Handle<Code> CallStubCompiler::GetCode(Code::StubType type, Handle<Code> CallStubCompiler::GetCode(Code::StubType type,
Handle<Name> name) { Handle<Name> name) {
int argc = arguments_.immediate(); int argc = arguments_.immediate();
Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, Code::Flags flags = Code::ComputeMonomorphicFlags(
extra_state_, kind_, extra_state_, cache_holder_, type, argc);
type,
argc,
cache_holder_);
return GetCodeWithFlags(flags, name); return GetCodeWithFlags(flags, name);
} }
......
...@@ -83,29 +83,21 @@ class StubCache { ...@@ -83,29 +83,21 @@ class StubCache {
Handle<Code> FindIC(Handle<Name> name, Handle<Code> FindIC(Handle<Name> name,
Handle<Map> stub_holder_map, Handle<Map> stub_holder_map,
Code::Kind kind, Code::Kind kind,
Code::ExtraICState extra_state = Code::kNoExtraICState); Code::ExtraICState extra_state = Code::kNoExtraICState,
InlineCacheHolderFlag cache_holder = OWN_MAP);
Handle<Code> FindIC(Handle<Name> name,
Handle<JSObject> stub_holder,
Code::Kind kind,
Code::ExtraICState extra_state = Code::kNoExtraICState);
Handle<Code> FindHandler(Handle<Name> name, Handle<Code> FindHandler(Handle<Name> name,
Handle<JSObject> receiver, Handle<HeapObject> stub_holder,
Code::Kind kind, Code::Kind kind,
InlineCacheHolderFlag cache_holder = OWN_MAP,
StrictModeFlag strict_mode = kNonStrictMode); StrictModeFlag strict_mode = kNonStrictMode);
Handle<Code> ComputeMonomorphicIC(Handle<HeapObject> receiver, Handle<Code> ComputeMonomorphicIC(Handle<Name> name,
Handle<HeapObject> receiver,
Handle<Code> handler, Handle<Code> handler,
Handle<Name> name,
StrictModeFlag strict_mode); StrictModeFlag strict_mode);
// Computes the right stub matching. Inserts the result in the Handle<Code> ComputeLoadNonexistent(Handle<Name> name, Handle<Object> object);
// cache before returning. This might compile a stub if needed.
Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
Handle<JSObject> object);
// ---
Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map); Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
...@@ -501,6 +493,7 @@ class StubCompiler BASE_EMBEDDED { ...@@ -501,6 +493,7 @@ class StubCompiler BASE_EMBEDDED {
Label* miss, Label* miss,
PrototypeCheckType check = CHECK_ALL_MAPS); PrototypeCheckType check = CHECK_ALL_MAPS);
void GenerateBooleanCheck(Register object, Label* miss);
protected: protected:
Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name); Handle<Code> GetCodeWithFlags(Code::Flags flags, const char* name);
...@@ -531,8 +524,10 @@ enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS }; ...@@ -531,8 +524,10 @@ enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
class BaseLoadStoreStubCompiler: public StubCompiler { class BaseLoadStoreStubCompiler: public StubCompiler {
public: public:
BaseLoadStoreStubCompiler(Isolate* isolate, Code::Kind kind) BaseLoadStoreStubCompiler(Isolate* isolate,
: StubCompiler(isolate), kind_(kind) { Code::Kind kind,
InlineCacheHolderFlag cache_holder = OWN_MAP)
: StubCompiler(isolate), kind_(kind), cache_holder_(cache_holder) {
InitializeRegisters(); InitializeRegisters();
} }
virtual ~BaseLoadStoreStubCompiler() { } virtual ~BaseLoadStoreStubCompiler() { }
...@@ -563,21 +558,18 @@ class BaseLoadStoreStubCompiler: public StubCompiler { ...@@ -563,21 +558,18 @@ class BaseLoadStoreStubCompiler: public StubCompiler {
} }
protected: protected:
virtual Register HandlerFrontendHeader(Handle<JSObject> object, virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* miss) = 0; Label* miss) = 0;
virtual void HandlerFrontendFooter(Handle<Name> name, virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss) = 0;
Label* success,
Label* miss) = 0;
Register HandlerFrontend(Handle<JSObject> object, Register HandlerFrontend(Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name);
Label* success);
Handle<Code> GetCode(Code::Kind kind, Handle<Code> GetCode(Code::Kind kind,
Code::StubType type, Code::StubType type,
...@@ -617,42 +609,45 @@ class BaseLoadStoreStubCompiler: public StubCompiler { ...@@ -617,42 +609,45 @@ class BaseLoadStoreStubCompiler: public StubCompiler {
void InitializeRegisters(); void InitializeRegisters();
Code::Kind kind_; Code::Kind kind_;
InlineCacheHolderFlag cache_holder_;
Register* registers_; Register* registers_;
}; };
class LoadStubCompiler: public BaseLoadStoreStubCompiler { class LoadStubCompiler: public BaseLoadStoreStubCompiler {
public: public:
LoadStubCompiler(Isolate* isolate, Code::Kind kind = Code::LOAD_IC) LoadStubCompiler(Isolate* isolate,
: BaseLoadStoreStubCompiler(isolate, kind) { } InlineCacheHolderFlag cache_holder = OWN_MAP,
Code::Kind kind = Code::LOAD_IC)
: BaseLoadStoreStubCompiler(isolate, kind, cache_holder) { }
virtual ~LoadStubCompiler() { } virtual ~LoadStubCompiler() { }
Handle<Code> CompileLoadField(Handle<JSObject> object, Handle<Code> CompileLoadField(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
PropertyIndex index, PropertyIndex index,
Representation representation); Representation representation);
Handle<Code> CompileLoadCallback(Handle<JSObject> object, Handle<Code> CompileLoadCallback(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<ExecutableAccessorInfo> callback); Handle<ExecutableAccessorInfo> callback);
Handle<Code> CompileLoadCallback(Handle<JSObject> object, Handle<Code> CompileLoadCallback(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
const CallOptimization& call_optimization); const CallOptimization& call_optimization);
Handle<Code> CompileLoadConstant(Handle<JSObject> object, Handle<Code> CompileLoadConstant(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<Object> value); Handle<Object> value);
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object, Handle<Code> CompileLoadInterceptor(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name); Handle<Name> name);
Handle<Code> CompileLoadViaGetter(Handle<JSObject> object, Handle<Code> CompileLoadViaGetter(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Handle<JSFunction> getter); Handle<JSFunction> getter);
...@@ -661,12 +656,12 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -661,12 +656,12 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
Register receiver, Register receiver,
Handle<JSFunction> getter); Handle<JSFunction> getter);
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object, Handle<Code> CompileLoadNonexistent(Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Handle<JSGlobalObject> global); Handle<JSGlobalObject> global);
Handle<Code> CompileLoadGlobal(Handle<JSObject> object, Handle<Code> CompileLoadGlobal(Handle<Object> object,
Handle<GlobalObject> holder, Handle<GlobalObject> holder,
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<Name> name, Handle<Name> name,
...@@ -675,26 +670,22 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -675,26 +670,22 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
static Register* registers(); static Register* registers();
protected: protected:
virtual Register HandlerFrontendHeader(Handle<JSObject> object, virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* miss); Label* miss);
virtual void HandlerFrontendFooter(Handle<Name> name, virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
Label* success,
Label* miss);
Register CallbackHandlerFrontend(Handle<JSObject> object, Register CallbackHandlerFrontend(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);
void NonexistentHandlerFrontend(Handle<JSObject> object, void NonexistentHandlerFrontend(Handle<Object> object,
Handle<JSObject> last, Handle<JSObject> last,
Handle<Name> name, Handle<Name> name,
Label* success,
Handle<JSGlobalObject> global); Handle<JSGlobalObject> global);
void GenerateLoadField(Register reg, void GenerateLoadField(Register reg,
...@@ -706,7 +697,7 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -706,7 +697,7 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
Handle<ExecutableAccessorInfo> callback); Handle<ExecutableAccessorInfo> callback);
void GenerateLoadCallback(const CallOptimization& call_optimization); void GenerateLoadCallback(const CallOptimization& call_optimization);
void GenerateLoadInterceptor(Register holder_reg, void GenerateLoadInterceptor(Register holder_reg,
Handle<JSObject> object, Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
LookupResult* lookup, LookupResult* lookup,
Handle<Name> name); Handle<Name> name);
...@@ -726,8 +717,9 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -726,8 +717,9 @@ class LoadStubCompiler: public BaseLoadStoreStubCompiler {
class KeyedLoadStubCompiler: public LoadStubCompiler { class KeyedLoadStubCompiler: public LoadStubCompiler {
public: public:
explicit KeyedLoadStubCompiler(Isolate* isolate) KeyedLoadStubCompiler(Isolate* isolate,
: LoadStubCompiler(isolate, Code::KEYED_LOAD_IC) { } InlineCacheHolderFlag cache_holder = OWN_MAP)
: LoadStubCompiler(isolate, cache_holder, Code::KEYED_LOAD_IC) { }
Handle<Code> CompileLoadElement(Handle<Map> receiver_map); Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
...@@ -827,15 +819,13 @@ class StoreStubCompiler: public BaseLoadStoreStubCompiler { ...@@ -827,15 +819,13 @@ class StoreStubCompiler: public BaseLoadStoreStubCompiler {
} }
protected: protected:
virtual Register HandlerFrontendHeader(Handle<JSObject> object, virtual Register HandlerFrontendHeader(Handle<Object> object,
Register object_reg, Register object_reg,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
Label* miss); Label* miss);
virtual void HandlerFrontendFooter(Handle<Name> name, virtual void HandlerFrontendFooter(Handle<Name> name, Label* miss);
Label* success,
Label* miss);
void GenerateRestoreName(MacroAssembler* masm, void GenerateRestoreName(MacroAssembler* masm,
Label* label, Label* label,
Handle<Name> name); Handle<Name> name);
...@@ -928,8 +918,7 @@ class CallStubCompiler: public StubCompiler { ...@@ -928,8 +918,7 @@ class CallStubCompiler: public StubCompiler {
void CompileHandlerFrontend(Handle<Object> object, void CompileHandlerFrontend(Handle<Object> object,
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<Name> name, Handle<Name> name,
CheckType check, CheckType check);
Label* success);
void CompileHandlerBackend(Handle<JSFunction> function); void CompileHandlerBackend(Handle<JSFunction> function);
......
...@@ -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