Unify computation of load stubs in stub cache.
R=verwaest@chromium.org Review URL: https://codereview.chromium.org/23647011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16660 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
8bf91ffe71
commit
45a65d870d
33
src/ic.cc
33
src/ic.cc
@ -1318,7 +1318,7 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
switch (lookup->type()) {
|
switch (lookup->type()) {
|
||||||
case FIELD:
|
case FIELD:
|
||||||
return isolate()->stub_cache()->ComputeLoadField(
|
return isolate()->stub_cache()->ComputeLoadField(
|
||||||
name, receiver, holder,
|
name, receiver, holder, Code::LOAD_IC,
|
||||||
lookup->GetFieldIndex(), lookup->representation());
|
lookup->GetFieldIndex(), lookup->representation());
|
||||||
case CONSTANT: {
|
case CONSTANT: {
|
||||||
Handle<Object> constant(lookup->GetConstant(), isolate());
|
Handle<Object> constant(lookup->GetConstant(), isolate());
|
||||||
@ -1326,7 +1326,7 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
// be embedded into code.
|
// be embedded into code.
|
||||||
if (constant->IsConsString()) return Handle<Code>::null();
|
if (constant->IsConsString()) return Handle<Code>::null();
|
||||||
return isolate()->stub_cache()->ComputeLoadConstant(
|
return isolate()->stub_cache()->ComputeLoadConstant(
|
||||||
name, receiver, holder, constant);
|
name, receiver, holder, Code::LOAD_IC, constant);
|
||||||
}
|
}
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
if (holder->IsGlobalObject()) {
|
if (holder->IsGlobalObject()) {
|
||||||
@ -1350,7 +1350,7 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
if (v8::ToCData<Address>(info->getter()) == 0) break;
|
if (v8::ToCData<Address>(info->getter()) == 0) break;
|
||||||
if (!info->IsCompatibleReceiver(*receiver)) break;
|
if (!info->IsCompatibleReceiver(*receiver)) break;
|
||||||
return isolate()->stub_cache()->ComputeLoadCallback(
|
return isolate()->stub_cache()->ComputeLoadCallback(
|
||||||
name, receiver, holder, info);
|
name, receiver, holder, Code::LOAD_IC, 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());
|
||||||
@ -1363,7 +1363,7 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
call_optimization.IsCompatibleReceiver(*receiver) &&
|
call_optimization.IsCompatibleReceiver(*receiver) &&
|
||||||
FLAG_js_accessor_ics) {
|
FLAG_js_accessor_ics) {
|
||||||
return isolate()->stub_cache()->ComputeLoadCallback(
|
return isolate()->stub_cache()->ComputeLoadCallback(
|
||||||
name, receiver, holder, call_optimization);
|
name, receiver, holder, Code::LOAD_IC, call_optimization);
|
||||||
}
|
}
|
||||||
return isolate()->stub_cache()->ComputeLoadViaGetter(
|
return isolate()->stub_cache()->ComputeLoadViaGetter(
|
||||||
name, receiver, holder, function);
|
name, receiver, holder, function);
|
||||||
@ -1372,7 +1372,8 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
PropertyIndex lengthIndex =
|
PropertyIndex lengthIndex =
|
||||||
PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
|
PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
|
||||||
return isolate()->stub_cache()->ComputeLoadField(
|
return isolate()->stub_cache()->ComputeLoadField(
|
||||||
name, receiver, holder, lengthIndex, Representation::Tagged());
|
name, receiver, holder, Code::LOAD_IC,
|
||||||
|
lengthIndex, Representation::Tagged());
|
||||||
}
|
}
|
||||||
// TODO(dcarney): Handle correctly.
|
// TODO(dcarney): Handle correctly.
|
||||||
if (callback->IsDeclaredAccessorInfo()) break;
|
if (callback->IsDeclaredAccessorInfo()) break;
|
||||||
@ -1383,7 +1384,7 @@ Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
case INTERCEPTOR:
|
case INTERCEPTOR:
|
||||||
ASSERT(HasInterceptorGetter(*holder));
|
ASSERT(HasInterceptorGetter(*holder));
|
||||||
return isolate()->stub_cache()->ComputeLoadInterceptor(
|
return isolate()->stub_cache()->ComputeLoadInterceptor(
|
||||||
name, receiver, holder);
|
name, receiver, holder, Code::LOAD_IC);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1538,16 +1539,16 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
Handle<JSObject> holder(lookup->holder(), isolate());
|
Handle<JSObject> holder(lookup->holder(), isolate());
|
||||||
switch (lookup->type()) {
|
switch (lookup->type()) {
|
||||||
case FIELD:
|
case FIELD:
|
||||||
return isolate()->stub_cache()->ComputeKeyedLoadField(
|
return isolate()->stub_cache()->ComputeLoadField(
|
||||||
name, receiver, holder,
|
name, receiver, holder, Code::KEYED_LOAD_IC,
|
||||||
lookup->GetFieldIndex(), lookup->representation());
|
lookup->GetFieldIndex(), 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()) return Handle<Code>::null();
|
if (constant->IsConsString()) return Handle<Code>::null();
|
||||||
return isolate()->stub_cache()->ComputeKeyedLoadConstant(
|
return isolate()->stub_cache()->ComputeLoadConstant(
|
||||||
name, receiver, holder, constant);
|
name, receiver, holder, Code::KEYED_LOAD_IC, constant);
|
||||||
}
|
}
|
||||||
case CALLBACKS: {
|
case CALLBACKS: {
|
||||||
Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
|
Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
|
||||||
@ -1557,8 +1558,8 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
Handle<ExecutableAccessorInfo>::cast(callback_object);
|
Handle<ExecutableAccessorInfo>::cast(callback_object);
|
||||||
if (v8::ToCData<Address>(callback->getter()) == 0) break;
|
if (v8::ToCData<Address>(callback->getter()) == 0) break;
|
||||||
if (!callback->IsCompatibleReceiver(*receiver)) break;
|
if (!callback->IsCompatibleReceiver(*receiver)) break;
|
||||||
return isolate()->stub_cache()->ComputeKeyedLoadCallback(
|
return isolate()->stub_cache()->ComputeLoadCallback(
|
||||||
name, receiver, holder, callback);
|
name, receiver, holder, Code::KEYED_LOAD_IC, callback);
|
||||||
} else if (callback_object->IsAccessorPair()) {
|
} else if (callback_object->IsAccessorPair()) {
|
||||||
Handle<Object> getter(
|
Handle<Object> getter(
|
||||||
Handle<AccessorPair>::cast(callback_object)->getter(),
|
Handle<AccessorPair>::cast(callback_object)->getter(),
|
||||||
@ -1571,16 +1572,16 @@ Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
|
|||||||
if (call_optimization.is_simple_api_call() &&
|
if (call_optimization.is_simple_api_call() &&
|
||||||
call_optimization.IsCompatibleReceiver(*receiver) &&
|
call_optimization.IsCompatibleReceiver(*receiver) &&
|
||||||
FLAG_js_accessor_ics) {
|
FLAG_js_accessor_ics) {
|
||||||
return isolate()->stub_cache()->ComputeKeyedLoadCallback(
|
return isolate()->stub_cache()->ComputeLoadCallback(
|
||||||
name, receiver, holder, call_optimization);
|
name, receiver, holder, Code::KEYED_LOAD_IC, call_optimization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INTERCEPTOR:
|
case INTERCEPTOR:
|
||||||
ASSERT(HasInterceptorGetter(lookup->holder()));
|
ASSERT(HasInterceptorGetter(lookup->holder()));
|
||||||
return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
|
return isolate()->stub_cache()->ComputeLoadInterceptor(
|
||||||
name, receiver, holder);
|
name, receiver, holder, Code::KEYED_LOAD_IC);
|
||||||
default:
|
default:
|
||||||
// Always rewrite to the generic case so that we do not
|
// Always rewrite to the generic case so that we do not
|
||||||
// repeatedly try to rewrite.
|
// repeatedly try to rewrite.
|
||||||
|
@ -272,21 +272,29 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
|
|||||||
Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
|
Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
PropertyIndex field,
|
PropertyIndex field,
|
||||||
Representation representation) {
|
Representation representation) {
|
||||||
if (receiver.is_identical_to(holder)) {
|
if (receiver.is_identical_to(holder)) {
|
||||||
LoadFieldStub stub(field.is_inobject(holder),
|
if (kind == Code::LOAD_IC) {
|
||||||
field.translate(holder),
|
LoadFieldStub stub(field.is_inobject(holder),
|
||||||
representation);
|
field.translate(holder),
|
||||||
return stub.GetCode(isolate());
|
representation);
|
||||||
|
return stub.GetCode(isolate());
|
||||||
|
} else {
|
||||||
|
KeyedLoadFieldStub stub(field.is_inobject(holder),
|
||||||
|
field.translate(holder),
|
||||||
|
representation);
|
||||||
|
return stub.GetCode(isolate());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindLoadHandler(
|
Handle<Code> stub = FindLoadHandler(
|
||||||
name, receiver, stub_holder, Code::LOAD_IC, Code::FIELD);
|
name, receiver, stub_holder, kind, Code::FIELD);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
BaseLoadStubCompiler compiler(isolate_, kind);
|
||||||
Handle<Code> handler =
|
Handle<Code> handler =
|
||||||
compiler.CompileLoadField(receiver, holder, name, field, representation);
|
compiler.CompileLoadField(receiver, holder, name, field, representation);
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
||||||
@ -298,14 +306,15 @@ Handle<Code> StubCache::ComputeLoadCallback(
|
|||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
Handle<ExecutableAccessorInfo> callback) {
|
Handle<ExecutableAccessorInfo> callback) {
|
||||||
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
ASSERT(v8::ToCData<Address>(callback->getter()) != 0);
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindLoadHandler(
|
Handle<Code> stub = FindLoadHandler(
|
||||||
name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
name, receiver, stub_holder, kind, Code::CALLBACKS);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
BaseLoadStubCompiler compiler(isolate_, kind);
|
||||||
Handle<Code> handler =
|
Handle<Code> handler =
|
||||||
compiler.CompileLoadCallback(receiver, holder, name, callback);
|
compiler.CompileLoadCallback(receiver, holder, name, callback);
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
||||||
@ -317,13 +326,14 @@ Handle<Code> StubCache::ComputeLoadCallback(
|
|||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
const CallOptimization& call_optimization) {
|
const CallOptimization& call_optimization) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindLoadHandler(
|
Handle<Code> stub = FindLoadHandler(
|
||||||
name, receiver, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
name, receiver, stub_holder, kind, Code::CALLBACKS);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
BaseLoadStubCompiler compiler(isolate_, kind);
|
||||||
Handle<Code> handler =
|
Handle<Code> handler =
|
||||||
compiler.CompileLoadCallback(receiver, holder, name, call_optimization);
|
compiler.CompileLoadCallback(receiver, holder, name, call_optimization);
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
||||||
@ -351,29 +361,30 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
|
|||||||
Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
|
Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
Handle<Object> value) {
|
Handle<Object> value) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> handler = FindLoadHandler(
|
Handle<Code> handler = FindLoadHandler(
|
||||||
name, receiver, stub_holder, Code::LOAD_IC, Code::CONSTANT);
|
name, receiver, stub_holder, kind, Code::CONSTANT);
|
||||||
if (!handler.is_null()) return handler;
|
if (!handler.is_null()) return handler;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
BaseLoadStubCompiler compiler(isolate_, kind);
|
||||||
handler = compiler.CompileLoadConstant(receiver, holder, name, value);
|
handler = compiler.CompileLoadConstant(receiver, holder, name, value);
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
||||||
|
|
||||||
return handler;
|
return handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
|
Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder) {
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindLoadHandler(
|
Handle<Code> stub = FindLoadHandler(
|
||||||
name, receiver, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
|
name, receiver, stub_holder, kind, Code::INTERCEPTOR);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
BaseLoadStubCompiler compiler(isolate_, kind);
|
||||||
Handle<Code> handler =
|
Handle<Code> handler =
|
||||||
compiler.CompileLoadInterceptor(receiver, holder, name);
|
compiler.CompileLoadInterceptor(receiver, holder, name);
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
||||||
@ -404,101 +415,6 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
|
|
||||||
Handle<JSObject> receiver,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
PropertyIndex field,
|
|
||||||
Representation representation) {
|
|
||||||
if (receiver.is_identical_to(holder)) {
|
|
||||||
// TODO(titzer): this should use an HObjectAccess
|
|
||||||
KeyedLoadFieldStub stub(field.is_inobject(holder),
|
|
||||||
field.translate(holder),
|
|
||||||
representation);
|
|
||||||
return stub.GetCode(isolate());
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
|
||||||
Handle<Code> stub = FindLoadHandler(
|
|
||||||
name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
|
|
||||||
if (!stub.is_null()) return stub;
|
|
||||||
|
|
||||||
KeyedLoadStubCompiler compiler(isolate_);
|
|
||||||
Handle<Code> handler =
|
|
||||||
compiler.CompileLoadField(receiver, holder, name, field, representation);
|
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
|
|
||||||
Handle<JSObject> receiver,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
Handle<Object> value) {
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
|
||||||
Handle<Code> handler = FindLoadHandler(
|
|
||||||
name, receiver, stub_holder, Code::KEYED_LOAD_IC,
|
|
||||||
Code::CONSTANT);
|
|
||||||
if (!handler.is_null()) return handler;
|
|
||||||
|
|
||||||
KeyedLoadStubCompiler compiler(isolate_);
|
|
||||||
handler = compiler.CompileLoadConstant(receiver, holder, name, value);
|
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
|
|
||||||
Handle<JSObject> receiver,
|
|
||||||
Handle<JSObject> holder) {
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
|
||||||
Handle<Code> stub = FindLoadHandler(
|
|
||||||
name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
|
|
||||||
if (!stub.is_null()) return stub;
|
|
||||||
|
|
||||||
KeyedLoadStubCompiler compiler(isolate_);
|
|
||||||
Handle<Code> handler =
|
|
||||||
compiler.CompileLoadInterceptor(receiver, holder, name);
|
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
|
||||||
Handle<Name> name,
|
|
||||||
Handle<JSObject> receiver,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
Handle<ExecutableAccessorInfo> callback) {
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
|
||||||
Handle<Code> stub = FindLoadHandler(
|
|
||||||
name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
|
||||||
if (!stub.is_null()) return stub;
|
|
||||||
|
|
||||||
KeyedLoadStubCompiler compiler(isolate_);
|
|
||||||
Handle<Code> handler =
|
|
||||||
compiler.CompileLoadCallback(receiver, holder, name, callback);
|
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
|
||||||
Handle<Name> name,
|
|
||||||
Handle<JSObject> receiver,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
const CallOptimization& call_optimization) {
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
|
||||||
Handle<Code> stub = FindLoadHandler(
|
|
||||||
name, receiver, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
|
||||||
if (!stub.is_null()) return stub;
|
|
||||||
|
|
||||||
KeyedLoadStubCompiler compiler(isolate_);
|
|
||||||
Handle<Code> handler =
|
|
||||||
compiler.CompileLoadCallback(receiver, holder, name, call_optimization);
|
|
||||||
JSObject::UpdateMapCodeCache(stub_holder, name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
|
Handle<Code> StubCache::ComputeStoreField(Handle<Name> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
LookupResult* lookup,
|
LookupResult* lookup,
|
||||||
@ -1957,23 +1873,15 @@ void StubCompiler::TailCallBuiltin(MacroAssembler* masm, Builtins::Name name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
Register* BaseLoadStoreStubCompiler::GetRegisters(Code::Kind kind) {
|
||||||
GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code));
|
switch (kind) {
|
||||||
}
|
case Code::LOAD_IC: return LoadStubCompiler::registers();
|
||||||
|
case Code::STORE_IC: return StoreStubCompiler::registers();
|
||||||
|
case Code::KEYED_LOAD_IC: return KeyedLoadStubCompiler::registers();
|
||||||
void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
case Code::KEYED_STORE_IC: return KeyedStoreStubCompiler::registers();
|
||||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
|
|
||||||
void StoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
|
||||||
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void KeyedStoreStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
|
||||||
GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
137
src/stub-cache.h
137
src/stub-cache.h
@ -130,17 +130,20 @@ class StubCache {
|
|||||||
Handle<Code> ComputeLoadField(Handle<Name> name,
|
Handle<Code> ComputeLoadField(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
PropertyIndex field_index,
|
PropertyIndex field_index,
|
||||||
Representation representation);
|
Representation representation);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadCallback(Handle<Name> name,
|
Handle<Code> ComputeLoadCallback(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
Handle<ExecutableAccessorInfo> callback);
|
Handle<ExecutableAccessorInfo> callback);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadCallback(Handle<Name> name,
|
Handle<Code> ComputeLoadCallback(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
const CallOptimization& call_optimization);
|
const CallOptimization& call_optimization);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
|
Handle<Code> ComputeLoadViaGetter(Handle<Name> name,
|
||||||
@ -151,11 +154,13 @@ class StubCache {
|
|||||||
Handle<Code> ComputeLoadConstant(Handle<Name> name,
|
Handle<Code> ComputeLoadConstant(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind,
|
||||||
Handle<Object> value);
|
Handle<Object> value);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
|
Handle<Code> ComputeLoadInterceptor(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder);
|
Handle<JSObject> holder,
|
||||||
|
Code::Kind kind);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadNormal(Handle<Name> name,
|
Handle<Code> ComputeLoadNormal(Handle<Name> name,
|
||||||
Handle<JSObject> object);
|
Handle<JSObject> object);
|
||||||
@ -168,35 +173,6 @@ class StubCache {
|
|||||||
|
|
||||||
// ---
|
// ---
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadField(Handle<Name> name,
|
|
||||||
Handle<JSObject> object,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
PropertyIndex field_index,
|
|
||||||
Representation representation);
|
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadCallback(
|
|
||||||
Handle<Name> name,
|
|
||||||
Handle<JSObject> object,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
Handle<ExecutableAccessorInfo> callback);
|
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadCallback(
|
|
||||||
Handle<Name> name,
|
|
||||||
Handle<JSObject> object,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
const CallOptimization& call_optimization);
|
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadConstant(Handle<Name> name,
|
|
||||||
Handle<JSObject> object,
|
|
||||||
Handle<JSObject> holder,
|
|
||||||
Handle<Object> value);
|
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadInterceptor(Handle<Name> name,
|
|
||||||
Handle<JSObject> object,
|
|
||||||
Handle<JSObject> holder);
|
|
||||||
|
|
||||||
// ---
|
|
||||||
|
|
||||||
Handle<Code> ComputeStoreField(Handle<Name> name,
|
Handle<Code> ComputeStoreField(Handle<Name> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
LookupResult* lookup,
|
LookupResult* lookup,
|
||||||
@ -642,8 +618,10 @@ enum FrontendCheckType { PERFORM_INITIAL_CHECKS, SKIP_INITIAL_CHECKS };
|
|||||||
|
|
||||||
class BaseLoadStoreStubCompiler: public StubCompiler {
|
class BaseLoadStoreStubCompiler: public StubCompiler {
|
||||||
public:
|
public:
|
||||||
BaseLoadStoreStubCompiler(Isolate* isolate, Register* registers)
|
BaseLoadStoreStubCompiler(Isolate* isolate,
|
||||||
: StubCompiler(isolate), registers_(registers) { }
|
Code::Kind kind,
|
||||||
|
Register* registers)
|
||||||
|
: StubCompiler(isolate), kind_(kind), registers_(registers) { }
|
||||||
virtual ~BaseLoadStoreStubCompiler() { }
|
virtual ~BaseLoadStoreStubCompiler() { }
|
||||||
|
|
||||||
Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
|
Handle<Code> CompileMonomorphicIC(Handle<Map> receiver_map,
|
||||||
@ -671,6 +649,17 @@ class BaseLoadStoreStubCompiler: public StubCompiler {
|
|||||||
return Builtins::kLoadIC_Miss;
|
return Builtins::kLoadIC_Miss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GDBJITInterface::CodeTag GetGDBJITCodeTag(Code::Kind kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case Code::LOAD_IC: return GDBJITInterface::LOAD_IC;
|
||||||
|
case Code::STORE_IC: return GDBJITInterface::STORE_IC;
|
||||||
|
case Code::KEYED_LOAD_IC: return GDBJITInterface::KEYED_LOAD_IC;
|
||||||
|
case Code::KEYED_STORE_IC: return GDBJITInterface::KEYED_STORE_IC;
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
return static_cast<GDBJITInterface::CodeTag>(0);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Register HandlerFrontendHeader(Handle<JSObject> object,
|
virtual Register HandlerFrontendHeader(Handle<JSObject> object,
|
||||||
Register object_reg,
|
Register object_reg,
|
||||||
@ -693,24 +682,48 @@ class BaseLoadStoreStubCompiler: public StubCompiler {
|
|||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
InlineCacheState state = MONOMORPHIC);
|
InlineCacheState state = MONOMORPHIC);
|
||||||
|
|
||||||
|
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
||||||
|
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
||||||
|
switch (kind()) {
|
||||||
|
case Code::LOAD_IC: return code->ic_state() == MONOMORPHIC
|
||||||
|
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
|
||||||
|
case Code::STORE_IC: return code->ic_state() == MONOMORPHIC
|
||||||
|
? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
|
||||||
|
case Code::KEYED_LOAD_IC: return code->ic_state() == MONOMORPHIC
|
||||||
|
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
|
||||||
|
case Code::KEYED_STORE_IC: return code->ic_state() == MONOMORPHIC
|
||||||
|
? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
|
||||||
|
default: UNREACHABLE();
|
||||||
|
}
|
||||||
|
return static_cast<Logger::LogEventsAndTags>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JitEvent(Handle<Name> name, Handle<Code> code) {
|
||||||
|
GDBJIT(AddCode(GetGDBJITCodeTag(kind()), *name, *code));
|
||||||
|
}
|
||||||
|
|
||||||
|
Code::Kind kind() const { return kind_; }
|
||||||
|
|
||||||
virtual Code::ExtraICState extra_state() { return Code::kNoExtraICState; }
|
virtual Code::ExtraICState extra_state() { return Code::kNoExtraICState; }
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) = 0;
|
|
||||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code) = 0;
|
|
||||||
virtual Code::Kind kind() = 0;
|
|
||||||
virtual Register receiver() = 0;
|
virtual Register receiver() = 0;
|
||||||
virtual Register name() = 0;
|
virtual Register name() = 0;
|
||||||
virtual Register scratch1() = 0;
|
virtual Register scratch1() = 0;
|
||||||
virtual Register scratch2() = 0;
|
virtual Register scratch2() = 0;
|
||||||
virtual Register scratch3() = 0;
|
virtual Register scratch3() = 0;
|
||||||
|
|
||||||
|
static Register* GetRegisters(Code::Kind kind);
|
||||||
|
|
||||||
|
Code::Kind kind_;
|
||||||
Register* registers_;
|
Register* registers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
|
class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
|
||||||
public:
|
public:
|
||||||
BaseLoadStubCompiler(Isolate* isolate, Register* registers)
|
BaseLoadStubCompiler(Isolate* isolate, Code::Kind kind)
|
||||||
: BaseLoadStoreStubCompiler(isolate, registers) { }
|
: BaseLoadStoreStubCompiler(isolate, kind, GetRegisters(kind)) { }
|
||||||
|
BaseLoadStubCompiler(Isolate* isolate, Code::Kind kind, Register* registers)
|
||||||
|
: BaseLoadStoreStubCompiler(isolate, kind, registers) { }
|
||||||
virtual ~BaseLoadStubCompiler() { }
|
virtual ~BaseLoadStubCompiler() { }
|
||||||
|
|
||||||
Handle<Code> CompileLoadField(Handle<JSObject> object,
|
Handle<Code> CompileLoadField(Handle<JSObject> object,
|
||||||
@ -795,7 +808,7 @@ class BaseLoadStubCompiler: public BaseLoadStoreStubCompiler {
|
|||||||
class LoadStubCompiler: public BaseLoadStubCompiler {
|
class LoadStubCompiler: public BaseLoadStubCompiler {
|
||||||
public:
|
public:
|
||||||
explicit LoadStubCompiler(Isolate* isolate)
|
explicit LoadStubCompiler(Isolate* isolate)
|
||||||
: BaseLoadStubCompiler(isolate, registers()) { }
|
: BaseLoadStubCompiler(isolate, Code::LOAD_IC, registers()) { }
|
||||||
|
|
||||||
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
|
Handle<Code> CompileLoadNonexistent(Handle<JSObject> object,
|
||||||
Handle<JSObject> last,
|
Handle<JSObject> last,
|
||||||
@ -816,22 +829,14 @@ class LoadStubCompiler: public BaseLoadStubCompiler {
|
|||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
bool is_dont_delete);
|
bool is_dont_delete);
|
||||||
|
|
||||||
private:
|
|
||||||
static Register* registers();
|
static Register* registers();
|
||||||
virtual Code::Kind kind() { return Code::LOAD_IC; }
|
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
|
||||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
|
||||||
return code->ic_state() == MONOMORPHIC
|
|
||||||
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
|
|
||||||
}
|
|
||||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
||||||
public:
|
public:
|
||||||
explicit KeyedLoadStubCompiler(Isolate* isolate)
|
explicit KeyedLoadStubCompiler(Isolate* isolate)
|
||||||
: BaseLoadStubCompiler(isolate, registers()) { }
|
: BaseLoadStubCompiler(isolate, Code::KEYED_LOAD_IC, registers()) { }
|
||||||
|
|
||||||
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
||||||
|
|
||||||
@ -840,15 +845,9 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
|||||||
|
|
||||||
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
|
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
|
||||||
|
|
||||||
private:
|
|
||||||
static Register* registers();
|
static Register* registers();
|
||||||
virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
|
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
private:
|
||||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
|
||||||
return code->ic_state() == MONOMORPHIC
|
|
||||||
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
|
|
||||||
}
|
|
||||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
|
||||||
virtual void GenerateNameCheck(Handle<Name> name,
|
virtual void GenerateNameCheck(Handle<Name> name,
|
||||||
Register name_reg,
|
Register name_reg,
|
||||||
Label* miss);
|
Label* miss);
|
||||||
@ -858,9 +857,9 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
|||||||
class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
|
class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
|
||||||
public:
|
public:
|
||||||
BaseStoreStubCompiler(Isolate* isolate,
|
BaseStoreStubCompiler(Isolate* isolate,
|
||||||
StrictModeFlag strict_mode,
|
Code::Kind kind,
|
||||||
Register* registers)
|
StrictModeFlag strict_mode)
|
||||||
: BaseLoadStoreStubCompiler(isolate, registers),
|
: BaseLoadStoreStubCompiler(isolate, kind, GetRegisters(kind)),
|
||||||
strict_mode_(strict_mode) { }
|
strict_mode_(strict_mode) { }
|
||||||
|
|
||||||
virtual ~BaseStoreStubCompiler() { }
|
virtual ~BaseStoreStubCompiler() { }
|
||||||
@ -958,7 +957,7 @@ class BaseStoreStubCompiler: public BaseLoadStoreStubCompiler {
|
|||||||
class StoreStubCompiler: public BaseStoreStubCompiler {
|
class StoreStubCompiler: public BaseStoreStubCompiler {
|
||||||
public:
|
public:
|
||||||
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
StoreStubCompiler(Isolate* isolate, StrictModeFlag strict_mode)
|
||||||
: BaseStoreStubCompiler(isolate, strict_mode, registers()) { }
|
: BaseStoreStubCompiler(isolate, Code::STORE_IC, strict_mode) { }
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
|
Handle<Code> CompileStoreCallback(Handle<JSObject> object,
|
||||||
@ -982,15 +981,7 @@ class StoreStubCompiler: public BaseStoreStubCompiler {
|
|||||||
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
|
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
|
||||||
Handle<Name> name);
|
Handle<Name> name);
|
||||||
|
|
||||||
private:
|
|
||||||
static Register* registers();
|
static Register* registers();
|
||||||
virtual Code::Kind kind() { return Code::STORE_IC; }
|
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
|
||||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
|
||||||
return code->ic_state() == MONOMORPHIC
|
|
||||||
? Logger::STORE_IC_TAG : Logger::STORE_POLYMORPHIC_IC_TAG;
|
|
||||||
}
|
|
||||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -999,7 +990,7 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
|
|||||||
KeyedStoreStubCompiler(Isolate* isolate,
|
KeyedStoreStubCompiler(Isolate* isolate,
|
||||||
StrictModeFlag strict_mode,
|
StrictModeFlag strict_mode,
|
||||||
KeyedAccessStoreMode store_mode)
|
KeyedAccessStoreMode store_mode)
|
||||||
: BaseStoreStubCompiler(isolate, strict_mode, registers()),
|
: BaseStoreStubCompiler(isolate, Code::KEYED_STORE_IC, strict_mode),
|
||||||
store_mode_(store_mode) { }
|
store_mode_(store_mode) { }
|
||||||
|
|
||||||
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
|
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
|
||||||
@ -1012,6 +1003,8 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
|
|||||||
|
|
||||||
static void GenerateStoreDictionaryElement(MacroAssembler* masm);
|
static void GenerateStoreDictionaryElement(MacroAssembler* masm);
|
||||||
|
|
||||||
|
static Register* registers();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual Code::ExtraICState extra_state() {
|
virtual Code::ExtraICState extra_state() {
|
||||||
return Code::ComputeExtraICState(store_mode_, strict_mode());
|
return Code::ComputeExtraICState(store_mode_, strict_mode());
|
||||||
@ -1022,14 +1015,6 @@ class KeyedStoreStubCompiler: public BaseStoreStubCompiler {
|
|||||||
return registers()[3];
|
return registers()[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Register* registers();
|
|
||||||
virtual Code::Kind kind() { return Code::KEYED_STORE_IC; }
|
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
|
||||||
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
|
||||||
return code->ic_state() == MONOMORPHIC
|
|
||||||
? Logger::KEYED_STORE_IC_TAG : Logger::KEYED_STORE_POLYMORPHIC_IC_TAG;
|
|
||||||
}
|
|
||||||
virtual void JitEvent(Handle<Name> name, Handle<Code> code);
|
|
||||||
virtual void GenerateNameCheck(Handle<Name> name,
|
virtual void GenerateNameCheck(Handle<Name> name,
|
||||||
Register name_reg,
|
Register name_reg,
|
||||||
Label* miss);
|
Label* miss);
|
||||||
|
Loading…
Reference in New Issue
Block a user