Make IC patching resilient to flushing of the original target() ic.
Review URL: https://chromiumcodereview.appspot.com/12451003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13831 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
80195113ab
commit
34697f5b12
@ -662,7 +662,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Probe the stub cache.
|
// Probe the stub cache.
|
||||||
Code::Flags flags = Code::ComputeFlags(
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
|
Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
|
||||||
|
Code::NORMAL, Code::LOAD_IC);
|
||||||
Isolate::Current()->stub_cache()->GenerateProbe(
|
Isolate::Current()->stub_cache()->GenerateProbe(
|
||||||
masm, flags, r0, r2, r3, r4, r5, r6);
|
masm, flags, r0, r2, r3, r4, r5, r6);
|
||||||
|
|
||||||
|
@ -2878,7 +2878,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
|||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
|
return GetCode(kind(), Code::NONEXISTENT, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2974,7 +2974,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
|||||||
__ Ret();
|
__ Ret();
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
|
return GetICCode(kind(), Code::NORMAL, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3002,7 +3002,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
|||||||
__ Jump(ic, RelocInfo::CODE_TARGET);
|
__ Jump(ic, RelocInfo::CODE_TARGET);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
|
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3035,7 +3035,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
|||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
InlineCacheState state =
|
InlineCacheState state =
|
||||||
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
||||||
return GetCode(Code::IC_FRAGMENT, type, name, state);
|
return GetICCode(kind(), type, name, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ enum BuiltinExtraArguments {
|
|||||||
V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC, \
|
V(LoadIC_PreMonomorphic, LOAD_IC, PREMONOMORPHIC, \
|
||||||
Code::kNoExtraICState) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
|
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
|
||||||
Code::IC_FRAGMENT) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
||||||
Code::kNoExtraICState) \
|
Code::kNoExtraICState) \
|
||||||
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
|
V(LoadIC_Getter_ForDeopt, LOAD_IC, MONOMORPHIC, \
|
||||||
|
@ -101,7 +101,8 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
|
|||||||
static_cast<Code::Kind>(GetCodeKind()),
|
static_cast<Code::Kind>(GetCodeKind()),
|
||||||
GetICState(),
|
GetICState(),
|
||||||
GetExtraICState(),
|
GetExtraICState(),
|
||||||
GetStubType());
|
GetStubType(),
|
||||||
|
GetStubFlags());
|
||||||
Handle<Code> new_object = factory->NewCode(
|
Handle<Code> new_object = factory->NewCode(
|
||||||
desc, flags, masm.CodeObject(), NeedsImmovableCode());
|
desc, flags, masm.CodeObject(), NeedsImmovableCode());
|
||||||
return new_object;
|
return new_object;
|
||||||
|
@ -251,6 +251,7 @@ class PlatformCodeStub : public CodeStub {
|
|||||||
virtual Handle<Code> GenerateCode();
|
virtual Handle<Code> GenerateCode();
|
||||||
|
|
||||||
virtual int GetCodeKind() { return Code::STUB; }
|
virtual int GetCodeKind() { return Code::STUB; }
|
||||||
|
virtual int GetStubFlags() { return -1; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Generates the assembler code for the stub.
|
// Generates the assembler code for the stub.
|
||||||
@ -662,11 +663,8 @@ class StoreArrayLengthStub: public StoreICStub {
|
|||||||
class HandlerStub: public ICStub {
|
class HandlerStub: public ICStub {
|
||||||
public:
|
public:
|
||||||
explicit HandlerStub(Code::Kind kind) : ICStub(kind) { }
|
explicit HandlerStub(Code::Kind kind) : ICStub(kind) { }
|
||||||
|
virtual int GetCodeKind() { return Code::STUB; }
|
||||||
protected:
|
virtual int GetStubFlags() { return kind(); }
|
||||||
virtual Code::ExtraICState GetExtraICState() {
|
|
||||||
return Code::HANDLER_FRAGMENT;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1301,7 +1301,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Probe the stub cache.
|
// Probe the stub cache.
|
||||||
Code::Flags flags = Code::ComputeFlags(
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
|
Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
|
||||||
|
Code::NORMAL, Code::LOAD_IC);
|
||||||
Isolate::Current()->stub_cache()->GenerateProbe(
|
Isolate::Current()->stub_cache()->GenerateProbe(
|
||||||
masm, flags, edx, ecx, ebx, eax);
|
masm, flags, edx, ecx, ebx, eax);
|
||||||
|
|
||||||
|
@ -2946,7 +2946,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
|||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
|
return GetCode(kind(), Code::NONEXISTENT, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3046,7 +3046,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
|||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
|
return GetICCode(kind(), Code::NORMAL, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3074,7 +3074,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
|||||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
|
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3105,7 +3105,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
|||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
InlineCacheState state =
|
InlineCacheState state =
|
||||||
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
||||||
return GetCode(Code::IC_FRAGMENT, type, name, state);
|
return GetICCode(kind(), type, name, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
54
src/ic.cc
54
src/ic.cc
@ -959,13 +959,23 @@ bool IC::UpdatePolymorphicIC(State state,
|
|||||||
target()->type() == Code::NORMAL) {
|
target()->type() == Code::NORMAL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MapHandleList receiver_maps;
|
MapHandleList receiver_maps;
|
||||||
CodeHandleList handlers;
|
CodeHandleList handlers;
|
||||||
target()->FindAllMaps(&receiver_maps);
|
|
||||||
int number_of_maps = receiver_maps.length();
|
|
||||||
if (number_of_maps == 0 || number_of_maps >= 4) return false;
|
|
||||||
|
|
||||||
target()->FindAllCode(&handlers, receiver_maps.length());
|
{
|
||||||
|
AssertNoAllocation no_gc;
|
||||||
|
target()->FindAllMaps(&receiver_maps);
|
||||||
|
int number_of_maps = receiver_maps.length();
|
||||||
|
if (number_of_maps >= 4) return false;
|
||||||
|
|
||||||
|
// Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC.
|
||||||
|
// In that case, allow the IC to go back monomorphic.
|
||||||
|
if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
target()->FindAllCode(&handlers, receiver_maps.length());
|
||||||
|
}
|
||||||
|
|
||||||
if (!AddOneReceiverMapIfMissing(&receiver_maps,
|
if (!AddOneReceiverMapIfMissing(&receiver_maps,
|
||||||
Handle<Map>(receiver->map()))) {
|
Handle<Map>(receiver->map()))) {
|
||||||
@ -1000,6 +1010,8 @@ void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Since GC may have been invoked, by the time PatchCache is called, |state| is
|
||||||
|
// not necessarily equal to target()->state().
|
||||||
void IC::PatchCache(State state,
|
void IC::PatchCache(State state,
|
||||||
StrictModeFlag strict_mode,
|
StrictModeFlag strict_mode,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
@ -1019,11 +1031,28 @@ void IC::PatchCache(State state,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We are transitioning from monomorphic to megamorphic case. Place the
|
if (target()->type() != Code::NORMAL) {
|
||||||
// stub compiled for the receiver into stub cache.
|
// We are transitioning from monomorphic to megamorphic case. Place
|
||||||
Map* map = target()->FindFirstMap();
|
// the stub compiled for the receiver into stub cache.
|
||||||
if (map != NULL) {
|
Map* map;
|
||||||
UpdateMegamorphicCache(map, *name, target());
|
Code* handler;
|
||||||
|
{
|
||||||
|
AssertNoAllocation no_gc;
|
||||||
|
map = target()->FindFirstMap();
|
||||||
|
if (map != NULL) {
|
||||||
|
if (target()->is_load_stub()) {
|
||||||
|
handler = target()->FindFirstCode();
|
||||||
|
} else {
|
||||||
|
handler = target();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Avoid compiler warnings.
|
||||||
|
handler = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (handler != NULL) {
|
||||||
|
UpdateMegamorphicCache(map, *name, handler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UpdateMegamorphicCache(receiver->map(), *name, *code);
|
UpdateMegamorphicCache(receiver->map(), *name, *code);
|
||||||
set_target((strict_mode == kStrictMode)
|
set_target((strict_mode == kStrictMode)
|
||||||
@ -1042,8 +1071,11 @@ void IC::PatchCache(State state,
|
|||||||
}
|
}
|
||||||
MapHandleList receiver_maps;
|
MapHandleList receiver_maps;
|
||||||
CodeHandleList handlers;
|
CodeHandleList handlers;
|
||||||
target()->FindAllMaps(&receiver_maps);
|
{
|
||||||
target()->FindAllCode(&handlers, receiver_maps.length());
|
AssertNoAllocation no_gc;
|
||||||
|
target()->FindAllMaps(&receiver_maps);
|
||||||
|
target()->FindAllCode(&handlers, receiver_maps.length());
|
||||||
|
}
|
||||||
for (int i = 0; i < receiver_maps.length(); i++) {
|
for (int i = 0; i < receiver_maps.length(); i++) {
|
||||||
UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
|
UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
|
||||||
}
|
}
|
||||||
|
@ -4989,6 +4989,7 @@ int Code::stub_info() {
|
|||||||
void Code::set_stub_info(int value) {
|
void Code::set_stub_info(int value) {
|
||||||
ASSERT(kind() == COMPARE_IC ||
|
ASSERT(kind() == COMPARE_IC ||
|
||||||
kind() == BINARY_OP_IC ||
|
kind() == BINARY_OP_IC ||
|
||||||
|
kind() == STUB ||
|
||||||
kind() == LOAD_IC ||
|
kind() == LOAD_IC ||
|
||||||
kind() == KEYED_LOAD_IC ||
|
kind() == KEYED_LOAD_IC ||
|
||||||
kind() == STORE_IC ||
|
kind() == STORE_IC ||
|
||||||
|
@ -8804,7 +8804,7 @@ void Code::FindAllCode(CodeHandleList* code_list, int length) {
|
|||||||
if (i++ == length) return;
|
if (i++ == length) return;
|
||||||
RelocInfo* info = it.rinfo();
|
RelocInfo* info = it.rinfo();
|
||||||
Code* code = Code::GetCodeFromTargetAddress(info->target_address());
|
Code* code = Code::GetCodeFromTargetAddress(info->target_address());
|
||||||
ASSERT(code->is_load_stub());
|
ASSERT(code->kind() == Code::STUB);
|
||||||
code_list->Add(Handle<Code>(code));
|
code_list->Add(Handle<Code>(code));
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
|
@ -4280,11 +4280,6 @@ class Code: public HeapObject {
|
|||||||
NONEXISTENT
|
NONEXISTENT
|
||||||
};
|
};
|
||||||
|
|
||||||
enum IcFragment {
|
|
||||||
IC_FRAGMENT,
|
|
||||||
HANDLER_FRAGMENT
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
NUMBER_OF_KINDS = LAST_IC_KIND + 1
|
NUMBER_OF_KINDS = LAST_IC_KIND + 1
|
||||||
};
|
};
|
||||||
|
@ -109,12 +109,12 @@ Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::FindStub(Handle<Name> name,
|
Handle<Code> StubCache::FindIC(Handle<Name> name,
|
||||||
Handle<JSObject> stub_holder,
|
Handle<JSObject> stub_holder,
|
||||||
Code::Kind kind,
|
Code::Kind kind,
|
||||||
Code::StubType type,
|
Code::StubType type) {
|
||||||
Code::IcFragment fragment) {
|
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||||
Code::Flags flags = Code::ComputeMonomorphicFlags(kind, fragment, type);
|
kind, Code::kNoExtraICState, type);
|
||||||
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);
|
||||||
@ -122,19 +122,29 @@ Handle<Code> StubCache::FindStub(Handle<Name> name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> StubCache::FindHandler(Handle<Name> name,
|
Handle<Code> StubCache::FindStub(Handle<Name> name,
|
||||||
Handle<JSObject> handler_holder,
|
Handle<JSObject> stub_holder,
|
||||||
Code::Kind kind,
|
Code::Kind kind,
|
||||||
Code::StubType type) {
|
Code::StubType type) {
|
||||||
return FindStub(name, handler_holder, kind, type, Code::HANDLER_FRAGMENT);
|
ASSERT(type != Code::NORMAL);
|
||||||
|
int extra_flags = -1;
|
||||||
|
if (kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC) {
|
||||||
|
extra_flags = kind;
|
||||||
|
kind = Code::STUB;
|
||||||
|
}
|
||||||
|
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||||
|
kind, Code::kNoExtraICState, type, extra_flags);
|
||||||
|
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<JSObject> receiver,
|
Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver,
|
||||||
Handle<Code> handler,
|
Handle<Code> handler,
|
||||||
Handle<Name> name) {
|
Handle<Name> name) {
|
||||||
Handle<Code> ic = FindStub(name, receiver, Code::LOAD_IC,
|
Handle<Code> ic = FindIC(name, receiver, Code::LOAD_IC, handler->type());
|
||||||
handler->type(), Code::IC_FRAGMENT);
|
|
||||||
if (!ic.is_null()) return ic;
|
if (!ic.is_null()) return ic;
|
||||||
|
|
||||||
LoadStubCompiler ic_compiler(isolate());
|
LoadStubCompiler ic_compiler(isolate());
|
||||||
@ -149,8 +159,8 @@ Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver,
|
|||||||
Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
|
Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver,
|
||||||
Handle<Code> handler,
|
Handle<Code> handler,
|
||||||
Handle<Name> name) {
|
Handle<Name> name) {
|
||||||
Handle<Code> ic = FindStub(name, receiver, Code::KEYED_LOAD_IC,
|
Handle<Code> ic = FindIC(
|
||||||
handler->type(), Code::IC_FRAGMENT);
|
name, receiver, Code::KEYED_LOAD_IC, handler->type());
|
||||||
if (!ic.is_null()) return ic;
|
if (!ic.is_null()) return ic;
|
||||||
|
|
||||||
KeyedLoadStubCompiler ic_compiler(isolate());
|
KeyedLoadStubCompiler ic_compiler(isolate());
|
||||||
@ -187,7 +197,7 @@ 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(
|
Handle<Code> handler = FindStub(
|
||||||
cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
|
cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT);
|
||||||
if (!handler.is_null()) return handler;
|
if (!handler.is_null()) return handler;
|
||||||
|
|
||||||
@ -211,7 +221,7 @@ Handle<Code> StubCache::ComputeLoadField(Handle<Name> name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::LOAD_IC, Code::FIELD);
|
name, stub_holder, Code::LOAD_IC, Code::FIELD);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -230,7 +240,7 @@ Handle<Code> StubCache::ComputeLoadCallback(
|
|||||||
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 = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -247,7 +257,7 @@ Handle<Code> StubCache::ComputeLoadViaGetter(Handle<Name> name,
|
|||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<JSFunction> getter) {
|
Handle<JSFunction> getter) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
name, stub_holder, Code::LOAD_IC, Code::CALLBACKS);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -264,7 +274,7 @@ Handle<Code> StubCache::ComputeLoadConstant(Handle<Name> name,
|
|||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<JSFunction> value) {
|
Handle<JSFunction> value) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> handler = FindHandler(
|
Handle<Code> handler = FindStub(
|
||||||
name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
|
name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION);
|
||||||
if (!handler.is_null()) return handler;
|
if (!handler.is_null()) return handler;
|
||||||
|
|
||||||
@ -280,7 +290,7 @@ Handle<Code> StubCache::ComputeLoadInterceptor(Handle<Name> name,
|
|||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder) {
|
Handle<JSObject> holder) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
|
name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -304,8 +314,7 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
|
|||||||
Handle<JSGlobalPropertyCell> cell,
|
Handle<JSGlobalPropertyCell> cell,
|
||||||
bool is_dont_delete) {
|
bool is_dont_delete) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindStub(
|
Handle<Code> stub = FindIC(name, stub_holder, Code::LOAD_IC, Code::NORMAL);
|
||||||
name, stub_holder, Code::LOAD_IC, Code::NORMAL, Code::IC_FRAGMENT);
|
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
LoadStubCompiler compiler(isolate_);
|
LoadStubCompiler compiler(isolate_);
|
||||||
@ -328,7 +337,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<Name> name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
|
name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -345,7 +354,7 @@ Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<Name> name,
|
|||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<JSFunction> value) {
|
Handle<JSFunction> value) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> handler = FindHandler(
|
Handle<Code> handler = FindStub(
|
||||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
|
name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION);
|
||||||
if (!handler.is_null()) return handler;
|
if (!handler.is_null()) return handler;
|
||||||
|
|
||||||
@ -360,7 +369,7 @@ Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<Name> name,
|
|||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder) {
|
Handle<JSObject> holder) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
|
name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -378,7 +387,7 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
|
|||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<ExecutableAccessorInfo> callback) {
|
Handle<ExecutableAccessorInfo> callback) {
|
||||||
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
Handle<JSObject> stub_holder = StubHolder(receiver, holder);
|
||||||
Handle<Code> stub = FindHandler(
|
Handle<Code> stub = FindStub(
|
||||||
name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
||||||
if (!stub.is_null()) return stub;
|
if (!stub.is_null()) return stub;
|
||||||
|
|
||||||
@ -895,8 +904,10 @@ Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps,
|
|||||||
CodeHandleList* handlers,
|
CodeHandleList* handlers,
|
||||||
Handle<Name> name) {
|
Handle<Name> name) {
|
||||||
LoadStubCompiler ic_compiler(isolate_);
|
LoadStubCompiler ic_compiler(isolate_);
|
||||||
|
Code::StubType type = handlers->length() == 1 ? handlers->at(0)->type()
|
||||||
|
: Code::NORMAL;
|
||||||
Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
|
Handle<Code> ic = ic_compiler.CompilePolymorphicIC(
|
||||||
receiver_maps, handlers, name, Code::NORMAL, PROPERTY);
|
receiver_maps, handlers, name, type, PROPERTY);
|
||||||
return ic;
|
return ic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,7 +992,7 @@ void StubCache::CollectMatchingMaps(SmallMapList* types,
|
|||||||
Zone* zone) {
|
Zone* zone) {
|
||||||
for (int i = 0; i < kPrimaryTableSize; i++) {
|
for (int i = 0; i < kPrimaryTableSize; i++) {
|
||||||
if (primary_[i].key == name) {
|
if (primary_[i].key == name) {
|
||||||
Map* map = primary_[i].value->FindFirstMap();
|
Map* map = primary_[i].map;
|
||||||
// Map can be NULL, if the stub is constant function call
|
// Map can be NULL, if the stub is constant function call
|
||||||
// with a primitive receiver.
|
// with a primitive receiver.
|
||||||
if (map == NULL) continue;
|
if (map == NULL) continue;
|
||||||
@ -996,7 +1007,7 @@ void StubCache::CollectMatchingMaps(SmallMapList* types,
|
|||||||
|
|
||||||
for (int i = 0; i < kSecondaryTableSize; i++) {
|
for (int i = 0; i < kSecondaryTableSize; i++) {
|
||||||
if (secondary_[i].key == name) {
|
if (secondary_[i].key == name) {
|
||||||
Map* map = secondary_[i].value->FindFirstMap();
|
Map* map = secondary_[i].map;
|
||||||
// Map can be NULL, if the stub is constant function call
|
// Map can be NULL, if the stub is constant function call
|
||||||
// with a primitive receiver.
|
// with a primitive receiver.
|
||||||
if (map == NULL) continue;
|
if (map == NULL) continue;
|
||||||
@ -1005,7 +1016,7 @@ void StubCache::CollectMatchingMaps(SmallMapList* types,
|
|||||||
int primary_offset = PrimaryOffset(name, flags, map);
|
int primary_offset = PrimaryOffset(name, flags, map);
|
||||||
Entry* primary_entry = entry(primary_, primary_offset);
|
Entry* primary_entry = entry(primary_, primary_offset);
|
||||||
if (primary_entry->key == name) {
|
if (primary_entry->key == name) {
|
||||||
Map* primary_map = primary_entry->value->FindFirstMap();
|
Map* primary_map = primary_entry->map;
|
||||||
if (map == primary_map) continue;
|
if (map == primary_map) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1448,7 +1459,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object,
|
|||||||
GenerateLoadMiss(masm(), kind());
|
GenerateLoadMiss(masm(), kind());
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::FIELD, name);
|
return GetCode(kind(), Code::FIELD, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1463,7 +1474,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadConstant(
|
|||||||
GenerateLoadConstant(value);
|
GenerateLoadConstant(value);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::CONSTANT_FUNCTION, name);
|
return GetCode(kind(), Code::CONSTANT_FUNCTION, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1480,7 +1491,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadCallback(
|
|||||||
GenerateLoadCallback(reg, callback);
|
GenerateLoadCallback(reg, callback);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name);
|
return GetCode(kind(), Code::CALLBACKS, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1500,7 +1511,7 @@ Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor(
|
|||||||
GenerateLoadInterceptor(reg, object, holder, &lookup, name);
|
GenerateLoadInterceptor(reg, object, holder, &lookup, name);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::INTERCEPTOR, name);
|
return GetCode(kind(), Code::INTERCEPTOR, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1567,7 +1578,7 @@ Handle<Code> LoadStubCompiler::CompileLoadViaGetter(
|
|||||||
GenerateLoadViaGetter(masm(), getter);
|
GenerateLoadViaGetter(masm(), getter);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name);
|
return GetCode(kind(), Code::CALLBACKS, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1584,11 +1595,25 @@ void KeyedLoadStubCompiler::JitEvent(Handle<Name> name, Handle<Code> code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> BaseLoadStubCompiler::GetCode(Code::IcFragment fragment,
|
Handle<Code> BaseLoadStubCompiler::GetICCode(Code::Kind kind,
|
||||||
|
Code::StubType type,
|
||||||
|
Handle<Name> name,
|
||||||
|
InlineCacheState state) {
|
||||||
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
|
kind, state, Code::kNoExtraICState, type);
|
||||||
|
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||||
|
PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
|
||||||
|
JitEvent(name, code);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> BaseLoadStubCompiler::GetCode(Code::Kind kind,
|
||||||
Code::StubType type,
|
Code::StubType type,
|
||||||
Handle<Name> name,
|
Handle<Name> name) {
|
||||||
InlineCacheState state) {
|
ASSERT(type != Code::NORMAL);
|
||||||
Code::Flags flags = Code::ComputeFlags(kind(), state, fragment, type);
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
|
Code::STUB, MONOMORPHIC, Code::kNoExtraICState, type, kind);
|
||||||
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);
|
||||||
|
@ -77,16 +77,15 @@ class StubCache {
|
|||||||
Handle<JSObject> StubHolder(Handle<JSObject> receiver,
|
Handle<JSObject> StubHolder(Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder);
|
Handle<JSObject> holder);
|
||||||
|
|
||||||
|
Handle<Code> FindIC(Handle<Name> name,
|
||||||
|
Handle<JSObject> stub_holder,
|
||||||
|
Code::Kind kind,
|
||||||
|
Code::StubType type);
|
||||||
|
|
||||||
Handle<Code> FindStub(Handle<Name> name,
|
Handle<Code> FindStub(Handle<Name> name,
|
||||||
Handle<JSObject> stub_holder,
|
Handle<JSObject> stub_holder,
|
||||||
Code::Kind kind,
|
Code::Kind kind,
|
||||||
Code::StubType type,
|
Code::StubType type);
|
||||||
Code::IcFragment fragment);
|
|
||||||
|
|
||||||
Handle<Code> FindHandler(Handle<Name> name,
|
|
||||||
Handle<JSObject> stub_holder,
|
|
||||||
Code::Kind kind,
|
|
||||||
Code::StubType type);
|
|
||||||
|
|
||||||
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
|
Handle<Code> ComputeMonomorphicIC(Handle<JSObject> receiver,
|
||||||
Handle<Code> handler,
|
Handle<Code> handler,
|
||||||
@ -666,10 +665,14 @@ class BaseLoadStubCompiler: public StubCompiler {
|
|||||||
Handle<Name> name,
|
Handle<Name> name,
|
||||||
LookupResult* lookup);
|
LookupResult* lookup);
|
||||||
|
|
||||||
Handle<Code> GetCode(Code::IcFragment fragment,
|
Handle<Code> GetICCode(Code::Kind kind,
|
||||||
|
Code::StubType type,
|
||||||
|
Handle<Name> name,
|
||||||
|
InlineCacheState state = MONOMORPHIC);
|
||||||
|
|
||||||
|
Handle<Code> GetCode(Code::Kind kind,
|
||||||
Code::StubType type,
|
Code::StubType type,
|
||||||
Handle<Name> name,
|
Handle<Name> name);
|
||||||
InlineCacheState state = MONOMORPHIC);
|
|
||||||
|
|
||||||
Register receiver() { return registers_[0]; }
|
Register receiver() { return registers_[0]; }
|
||||||
Register name() { return registers_[1]; }
|
Register name() { return registers_[1]; }
|
||||||
@ -719,6 +722,7 @@ class LoadStubCompiler: public BaseLoadStubCompiler {
|
|||||||
static Register* registers();
|
static Register* registers();
|
||||||
virtual Code::Kind kind() { return Code::LOAD_IC; }
|
virtual Code::Kind kind() { return Code::LOAD_IC; }
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
||||||
|
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
||||||
return code->ic_state() == MONOMORPHIC
|
return code->ic_state() == MONOMORPHIC
|
||||||
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
|
? Logger::LOAD_IC_TAG : Logger::LOAD_POLYMORPHIC_IC_TAG;
|
||||||
}
|
}
|
||||||
@ -746,6 +750,7 @@ class KeyedLoadStubCompiler: public BaseLoadStubCompiler {
|
|||||||
static Register* registers();
|
static Register* registers();
|
||||||
virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
|
virtual Code::Kind kind() { return Code::KEYED_LOAD_IC; }
|
||||||
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
virtual Logger::LogEventsAndTags log_kind(Handle<Code> code) {
|
||||||
|
if (!code->is_inline_cache_stub()) return Logger::STUB_TAG;
|
||||||
return code->ic_state() == MONOMORPHIC
|
return code->ic_state() == MONOMORPHIC
|
||||||
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
|
? Logger::KEYED_LOAD_IC_TAG : Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG;
|
||||||
}
|
}
|
||||||
|
@ -1328,7 +1328,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
|
|||||||
|
|
||||||
// Probe the stub cache.
|
// Probe the stub cache.
|
||||||
Code::Flags flags = Code::ComputeFlags(
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT);
|
Code::STUB, MONOMORPHIC, Code::kNoExtraICState,
|
||||||
|
Code::NORMAL, Code::LOAD_IC);
|
||||||
Isolate::Current()->stub_cache()->GenerateProbe(
|
Isolate::Current()->stub_cache()->GenerateProbe(
|
||||||
masm, flags, rax, rcx, rbx, rdx);
|
masm, flags, rax, rcx, rbx, rdx);
|
||||||
|
|
||||||
|
@ -2771,7 +2771,7 @@ Handle<Code> LoadStubCompiler::CompileLoadNonexistent(
|
|||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name);
|
return GetCode(kind(), Code::NONEXISTENT, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2871,7 +2871,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
|||||||
__ ret(0);
|
__ ret(0);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name);
|
return GetICCode(kind(), Code::NORMAL, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2898,7 +2898,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
|||||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||||
|
|
||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string());
|
return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2930,7 +2930,7 @@ Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
|
|||||||
// Return the generated code.
|
// Return the generated code.
|
||||||
InlineCacheState state =
|
InlineCacheState state =
|
||||||
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC;
|
||||||
return GetCode(Code::IC_FRAGMENT, type, name, state);
|
return GetICCode(kind(), type, name, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user