Index: src/stub-cache.cc |
diff --git a/src/stub-cache.cc b/src/stub-cache.cc |
index 1bc4b1314e79cbff3a4616181ed3f236c5095557..9dc89c2314b55fa552558514163221455f0d09a7 100644 |
--- a/src/stub-cache.cc |
+++ b/src/stub-cache.cc |
@@ -102,8 +102,10 @@ Code* StubCache::Set(Name* name, Map* map, Code* code) { |
Handle<Code> StubCache::FindIC(Handle<Name> name, |
Handle<Map> stub_holder_map, |
Code::Kind kind, |
- Code::ExtraICState extra_state) { |
- Code::Flags flags = Code::ComputeMonomorphicFlags(kind, extra_state); |
+ Code::ExtraICState extra_state, |
+ InlineCacheHolderFlag cache_holder) { |
+ Code::Flags flags = Code::ComputeMonomorphicFlags( |
+ kind, extra_state, cache_holder); |
Handle<Object> probe(stub_holder_map->FindInCodeCache(*name, flags), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
@@ -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<JSObject> receiver, |
+ Handle<HeapObject> stub_holder, |
Code::Kind kind, |
+ InlineCacheHolderFlag cache_holder, |
StrictModeFlag strict_mode) { |
Code::ExtraICState extra_ic_state = Code::kNoExtraICState; |
if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { |
@@ -129,28 +124,36 @@ Handle<Code> StubCache::FindHandler(Handle<Name> name, |
STANDARD_STORE, strict_mode); |
} |
Code::Flags flags = Code::ComputeMonomorphicFlags( |
- Code::HANDLER, extra_ic_state, Code::NORMAL, kind); |
- Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
+ Code::HANDLER, extra_ic_state, cache_holder, Code::NORMAL, kind); |
+ |
+ Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
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<Name> name, |
StrictModeFlag strict_mode) { |
Code::Kind kind = handler->handler_kind(); |
- Handle<Map> map(receiver->map()); |
- Handle<Code> ic = FindIC(name, map, kind, strict_mode); |
+ // Use the same cache holder for the IC as for the handler. |
+ 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; |
+ Handle<Map> map(object->map()); |
if (kind == Code::LOAD_IC) { |
- LoadStubCompiler ic_compiler(isolate()); |
+ LoadStubCompiler ic_compiler(isolate(), cache_holder); |
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); |
} else if (kind == Code::KEYED_LOAD_IC) { |
- KeyedLoadStubCompiler ic_compiler(isolate()); |
+ KeyedLoadStubCompiler ic_compiler(isolate(), cache_holder); |
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); |
} else if (kind == Code::STORE_IC) { |
StoreStubCompiler ic_compiler(isolate(), strict_mode); |
@@ -161,13 +164,16 @@ Handle<Code> StubCache::ComputeMonomorphicIC(Handle<HeapObject> receiver, |
ic = ic_compiler.CompileMonomorphicIC(map, handler, name); |
} |
- HeapObject::UpdateMapCodeCache(receiver, name, ic); |
+ HeapObject::UpdateMapCodeCache(stub_holder, name, ic); |
return ic; |
} |
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 |
// 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 |
@@ -176,7 +182,7 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
// specific to the name. |
Handle<Name> cache_name = factory()->empty_string(); |
Handle<JSObject> current; |
- Handle<Object> next = receiver; |
+ Handle<Object> next = stub_holder; |
Handle<JSGlobalObject> global; |
do { |
current = Handle<JSObject>::cast(next); |
@@ -191,13 +197,14 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, |
// Compile the stub that is either shared for all names or |
// 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; |
- LoadStubCompiler compiler(isolate_); |
+ LoadStubCompiler compiler(isolate_, cache_holder); |
handler = |
- compiler.CompileLoadNonexistent(receiver, current, cache_name, global); |
- HeapObject::UpdateMapCodeCache(receiver, cache_name, handler); |
+ compiler.CompileLoadNonexistent(object, current, cache_name, global); |
+ HeapObject::UpdateMapCodeCache(stub_holder, cache_name, handler); |
return handler; |
} |
@@ -257,9 +264,8 @@ Handle<Code> StubCache::ComputeCallConstant(int argc, |
Handle<JSObject> holder, |
Handle<JSFunction> function) { |
// Compute the check type and the map. |
- InlineCacheHolderFlag cache_holder = |
- IC::GetCodeCacheForObject(*object, *holder); |
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
isolate_, *object, cache_holder)); |
// Compute check type based on receiver/holder. |
@@ -283,7 +289,7 @@ Handle<Code> StubCache::ComputeCallConstant(int argc, |
} |
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), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
@@ -312,9 +318,8 @@ Handle<Code> StubCache::ComputeCallField(int argc, |
Handle<JSObject> holder, |
PropertyIndex index) { |
// Compute the check type and the map. |
- InlineCacheHolderFlag cache_holder = |
- IC::GetCodeCacheForObject(*object, *holder); |
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
isolate_, *object, cache_holder)); |
// TODO(1233596): We cannot do receiver map check for non-JS objects |
@@ -326,7 +331,7 @@ Handle<Code> StubCache::ComputeCallField(int argc, |
} |
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), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
@@ -351,9 +356,8 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
Handle<Object> object, |
Handle<JSObject> holder) { |
// Compute the check type and the map. |
- InlineCacheHolderFlag cache_holder = |
- IC::GetCodeCacheForObject(*object, *holder); |
- Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
+ InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); |
+ Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( |
isolate_, *object, cache_holder)); |
// TODO(1233596): We cannot do receiver map check for non-JS objects |
@@ -365,7 +369,7 @@ Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
} |
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), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
@@ -392,7 +396,7 @@ Handle<Code> StubCache::ComputeCallGlobal(int argc, |
Handle<PropertyCell> cell, |
Handle<JSFunction> function) { |
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), |
isolate_); |
if (probe->IsCode()) return Handle<Code>::cast(probe); |
@@ -1096,10 +1100,7 @@ Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
masm_.GetCode(&desc); |
Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
#ifdef ENABLE_DISASSEMBLER |
- if (FLAG_print_code_stubs) { |
- CodeTracer::Scope trace_scope(isolate()->GetCodeTracer()); |
- code->Disassemble(name, trace_scope.file()); |
- } |
+ if (FLAG_print_code_stubs) code->Disassemble(name); |
#endif |
return code; |
} |
@@ -1127,55 +1128,82 @@ void StubCompiler::LookupPostInterceptor(Handle<JSObject> holder, |
Register LoadStubCompiler::HandlerFrontendHeader( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Register object_reg, |
Handle<JSObject> holder, |
Handle<Name> name, |
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(), |
- name, miss, SKIP_RECEIVER); |
+ name, miss, check_type); |
} |
// HandlerFrontend for store uses the name register. It has to be restored |
// before a miss. |
Register StoreStubCompiler::HandlerFrontendHeader( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Register object_reg, |
Handle<JSObject> holder, |
Handle<Name> name, |
Label* miss) { |
- return CheckPrototypes(object, object_reg, holder, |
+ return CheckPrototypes(Handle<JSObject>::cast(object), object_reg, holder, |
this->name(), scratch1(), scratch2(), |
name, miss, SKIP_RECEIVER); |
} |
-Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<JSObject> object, |
+Register BaseLoadStoreStubCompiler::HandlerFrontend(Handle<Object> object, |
Register object_reg, |
Handle<JSObject> holder, |
- Handle<Name> name, |
- Label* success) { |
+ Handle<Name> name) { |
Label miss; |
Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
- HandlerFrontendFooter(name, success, &miss); |
+ HandlerFrontendFooter(name, &miss); |
+ |
return reg; |
} |
void LoadStubCompiler::NonexistentHandlerFrontend( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> last, |
Handle<Name> name, |
- Label* success, |
Handle<JSGlobalObject> global) { |
Label miss; |
- Register holder = |
- HandlerFrontendHeader(object, receiver(), last, name, &miss); |
+ Register holder = HandlerFrontendHeader( |
+ object, receiver(), last, name, &miss); |
if (!last->HasFastProperties() && |
!last->IsJSGlobalObject() && |
@@ -1196,12 +1224,12 @@ void LoadStubCompiler::NonexistentHandlerFrontend( |
GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss); |
} |
- HandlerFrontendFooter(name, success, &miss); |
+ HandlerFrontendFooter(name, &miss); |
} |
Handle<Code> LoadStubCompiler::CompileLoadField( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name, |
PropertyIndex field, |
@@ -1221,13 +1249,11 @@ Handle<Code> LoadStubCompiler::CompileLoadField( |
Handle<Code> LoadStubCompiler::CompileLoadConstant( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name, |
Handle<Object> value) { |
- Label success; |
- HandlerFrontend(object, receiver(), holder, name, &success); |
- __ bind(&success); |
+ HandlerFrontend(object, receiver(), holder, name); |
GenerateLoadConstant(value); |
// Return the generated code. |
@@ -1236,15 +1262,12 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant( |
Handle<Code> LoadStubCompiler::CompileLoadCallback( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name, |
Handle<ExecutableAccessorInfo> callback) { |
- Label success; |
- |
Register reg = CallbackHandlerFrontend( |
- object, receiver(), holder, name, &success, callback); |
- __ bind(&success); |
+ object, receiver(), holder, name, callback); |
GenerateLoadCallback(reg, callback); |
// Return the generated code. |
@@ -1253,17 +1276,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback( |
Handle<Code> LoadStubCompiler::CompileLoadCallback( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name, |
const CallOptimization& call_optimization) { |
ASSERT(call_optimization.is_simple_api_call()); |
- Label success; |
- |
Handle<JSFunction> callback = call_optimization.constant_function(); |
- CallbackHandlerFrontend( |
- object, receiver(), holder, name, &success, callback); |
- __ bind(&success); |
+ CallbackHandlerFrontend(object, receiver(), holder, name, callback); |
GenerateLoadCallback(call_optimization); |
// Return the generated code. |
@@ -1272,16 +1291,13 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback( |
Handle<Code> LoadStubCompiler::CompileLoadInterceptor( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name) { |
- Label success; |
- |
LookupResult lookup(isolate()); |
LookupPostInterceptor(holder, name, &lookup); |
- Register reg = HandlerFrontend(object, receiver(), holder, name, &success); |
- __ bind(&success); |
+ Register reg = HandlerFrontend(object, receiver(), holder, name); |
// TODO(368): Compile in the whole chain: all the interceptors in |
// prototypes and ultimate answer. |
GenerateLoadInterceptor(reg, object, holder, &lookup, name); |
@@ -1296,7 +1312,6 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( |
Handle<JSObject> interceptor_holder, |
Handle<Name> name, |
LookupResult* lookup) { |
- Label success; |
Handle<JSObject> holder(lookup->holder()); |
if (lookup->IsField()) { |
PropertyIndex field = lookup->GetFieldIndex(); |
@@ -1307,8 +1322,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( |
// We found FIELD property in prototype chain of interceptor's holder. |
// Retrieve a field from field's holder. |
Register reg = HandlerFrontend( |
- interceptor_holder, interceptor_reg, holder, name, &success); |
- __ bind(&success); |
+ interceptor_holder, interceptor_reg, holder, name); |
GenerateLoadField( |
reg, holder, field, lookup->representation()); |
} |
@@ -1321,8 +1335,7 @@ void LoadStubCompiler::GenerateLoadPostInterceptor( |
ASSERT(callback->getter() != NULL); |
Register reg = CallbackHandlerFrontend( |
- interceptor_holder, interceptor_reg, holder, name, &success, callback); |
- __ bind(&success); |
+ interceptor_holder, interceptor_reg, holder, name, callback); |
GenerateLoadCallback(reg, callback); |
} |
} |
@@ -1342,14 +1355,11 @@ Handle<Code> BaseLoadStoreStubCompiler::CompileMonomorphicIC( |
Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
- Handle<JSObject> object, |
+ Handle<Object> object, |
Handle<JSObject> holder, |
Handle<Name> name, |
Handle<JSFunction> getter) { |
- Label success; |
- HandlerFrontend(object, receiver(), holder, name, &success); |
- |
- __ bind(&success); |
+ HandlerFrontend(object, receiver(), holder, name); |
GenerateLoadViaGetter(masm(), receiver(), getter); |
// Return the generated code. |
@@ -1442,10 +1452,7 @@ Handle<Code> StoreStubCompiler::CompileStoreViaSetter( |
Handle<JSObject> holder, |
Handle<Name> name, |
Handle<JSFunction> setter) { |
- Label success; |
- HandlerFrontend(object, receiver(), holder, name, &success); |
- |
- __ bind(&success); |
+ HandlerFrontend(object, receiver(), holder, name); |
GenerateStoreViaSetter(masm(), setter); |
return GetCode(kind(), Code::CALLBACKS, name); |
@@ -1555,7 +1562,7 @@ Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind, |
Code::StubType type, |
Handle<Name> name) { |
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); |
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
JitEvent(name, code); |
@@ -1723,11 +1730,8 @@ Handle<Code> CallStubCompiler::CompileCustomCall( |
Handle<Code> CallStubCompiler::GetCode(Code::StubType type, |
Handle<Name> name) { |
int argc = arguments_.immediate(); |
- Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
- extra_state_, |
- type, |
- argc, |
- cache_holder_); |
+ Code::Flags flags = Code::ComputeMonomorphicFlags( |
+ kind_, extra_state_, cache_holder_, type, argc); |
return GetCodeWithFlags(flags, name); |
} |