Commit b79a927e authored by verwaest@chromium.org's avatar verwaest@chromium.org

Migrate FunctionPrototype (Keyed|Named)LoadIC to CodeStub

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13459 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f80379f3
...@@ -4532,6 +4532,35 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) { ...@@ -4532,6 +4532,35 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
} }
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver;
if (kind() == Code::KEYED_LOAD_IC) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
__ cmp(r0, Operand(masm->isolate()->factory()->prototype_symbol()));
__ b(ne, &miss);
receiver = r1;
} else {
ASSERT(kind() == Code::LOAD_IC);
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -- r0 : receiver
// -- sp[0] : receiver
// -----------------------------------
receiver = r0;
}
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r3, r4, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind());
}
void StringLengthStub::Generate(MacroAssembler* masm) { void StringLengthStub::Generate(MacroAssembler* masm) {
Label miss; Label miss;
Register receiver; Register receiver;
......
...@@ -213,21 +213,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm, ...@@ -213,21 +213,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
} }
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
// -- r0 : receiver
// -- sp[0] : receiver
// -----------------------------------
Label miss;
StubCompiler::GenerateLoadFunctionPrototype(masm, r0, r1, r3, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
// Checks the receiver for special cases (value type, slow case bits). // Checks the receiver for special cases (value type, slow case bits).
// Falls through for regular JS object. // Falls through for regular JS object.
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
......
...@@ -3207,31 +3207,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( ...@@ -3207,31 +3207,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
} }
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
Handle<String> name) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
Label miss;
Counters* counters = masm()->isolate()->counters();
__ IncrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
// Check the name hasn't changed.
__ cmp(r0, Operand(name));
__ b(ne, &miss);
GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
__ bind(&miss);
__ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
return GetCode(Code::CALLBACKS, name);
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) { Handle<Map> receiver_map) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
......
...@@ -414,13 +414,13 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle, ...@@ -414,13 +414,13 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
receiver_types_.Clear(); receiver_types_.Clear();
if (key()->IsPropertyName()) { if (key()->IsPropertyName()) {
ArrayLengthStub array_stub(Code::LOAD_IC); ArrayLengthStub array_stub(Code::LOAD_IC);
FunctionPrototypeStub proto_stub(Code::LOAD_IC);
StringLengthStub string_stub(Code::LOAD_IC, false); StringLengthStub string_stub(Code::LOAD_IC, false);
if (oracle->LoadIsStub(this, &array_stub)) { if (oracle->LoadIsStub(this, &array_stub)) {
is_array_length_ = true; is_array_length_ = true;
} else if (oracle->LoadIsStub(this, &string_stub)) { } else if (oracle->LoadIsStub(this, &string_stub)) {
is_string_length_ = true; is_string_length_ = true;
} else if (oracle->LoadIsBuiltin(this, } else if (oracle->LoadIsStub(this, &proto_stub)) {
Builtins::kLoadIC_FunctionPrototype)) {
is_function_prototype_ = true; is_function_prototype_ = true;
} else { } else {
Literal* lit_key = key()->AsLiteral(); Literal* lit_key = key()->AsLiteral();
......
...@@ -1453,11 +1453,6 @@ BUILTIN(HandleApiCallAsConstructor) { ...@@ -1453,11 +1453,6 @@ BUILTIN(HandleApiCallAsConstructor) {
} }
static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
LoadIC::GenerateFunctionPrototype(masm);
}
static void Generate_LoadIC_Initialize(MacroAssembler* masm) { static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
LoadIC::GenerateInitialize(masm); LoadIC::GenerateInitialize(masm);
} }
......
...@@ -134,8 +134,6 @@ enum BuiltinExtraArguments { ...@@ -134,8 +134,6 @@ enum BuiltinExtraArguments {
Code::kNoExtraICState) \ Code::kNoExtraICState) \
V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \ V(LoadIC_Normal, LOAD_IC, MONOMORPHIC, \
Code::kNoExtraICState) \ Code::kNoExtraICState) \
V(LoadIC_FunctionPrototype, LOAD_IC, MONOMORPHIC, \
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, \
......
...@@ -49,6 +49,7 @@ namespace internal { ...@@ -49,6 +49,7 @@ namespace internal {
V(MathPow) \ V(MathPow) \
V(ArrayLength) \ V(ArrayLength) \
V(StringLength) \ V(StringLength) \
V(FunctionPrototype) \
V(RecordWrite) \ V(RecordWrite) \
V(StoreBufferOverflow) \ V(StoreBufferOverflow) \
V(RegExpExec) \ V(RegExpExec) \
...@@ -577,6 +578,16 @@ class ArrayLengthStub: public ICStub { ...@@ -577,6 +578,16 @@ class ArrayLengthStub: public ICStub {
}; };
class FunctionPrototypeStub: public ICStub {
public:
explicit FunctionPrototypeStub(Code::Kind kind) : ICStub(kind) { }
virtual void Generate(MacroAssembler* masm);
private:
virtual CodeStub::Major MajorKey() { return FunctionPrototype; }
};
class StringLengthStub: public ICStub { class StringLengthStub: public ICStub {
public: public:
StringLengthStub(Code::Kind kind, bool support_wrapper) StringLengthStub(Code::Kind kind, bool support_wrapper)
......
...@@ -3278,6 +3278,25 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) { ...@@ -3278,6 +3278,25 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
} }
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
if (kind() == Code::KEYED_LOAD_IC) {
__ cmp(ecx, Immediate(masm->isolate()->factory()->prototype_symbol()));
__ j(not_equal, &miss);
}
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind());
}
void StringLengthStub::Generate(MacroAssembler* masm) { void StringLengthStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
......
...@@ -216,20 +216,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm, ...@@ -216,20 +216,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
} }
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
StubCompiler::GenerateLoadFunctionPrototype(masm, edx, eax, ebx, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
// Checks the receiver for special cases (value type, slow case bits). // Checks the receiver for special cases (value type, slow case bits).
// Falls through for regular JS object. // Falls through for regular JS object.
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
......
...@@ -3315,32 +3315,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( ...@@ -3315,32 +3315,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
} }
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
Handle<String> name) {
// ----------- S t a t e -------------
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->keyed_load_function_prototype(), 1);
// Check that the name has not changed.
__ cmp(ecx, Immediate(name));
__ j(not_equal, &miss);
GenerateLoadFunctionPrototype(masm(), edx, eax, ebx, &miss);
__ bind(&miss);
__ DecrementCounter(counters->keyed_load_function_prototype(), 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
return GetCode(Code::CALLBACKS, name);
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) { Handle<Map> receiver_map) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
......
...@@ -836,6 +836,7 @@ bool IC::HandleLoad(State state, ...@@ -836,6 +836,7 @@ bool IC::HandleLoad(State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name, Handle<String> name,
MaybeObject** result) { MaybeObject** result) {
if (FLAG_use_ic) {
// Use specialized code for getting the length of strings and // Use specialized code for getting the length of strings and
// string wrapper objects. The length property of string wrapper // string wrapper objects. The length property of string wrapper
// objects is read-only and therefore always returns the length of // objects is read-only and therefore always returns the length of
...@@ -870,7 +871,8 @@ bool IC::HandleLoad(State state, ...@@ -870,7 +871,8 @@ bool IC::HandleLoad(State state,
} }
// Use specialized code for getting the length of arrays. // Use specialized code for getting the length of arrays.
if (object->IsJSArray() && name->Equals(isolate()->heap()->length_symbol())) { if (object->IsJSArray() &&
name->Equals(isolate()->heap()->length_symbol())) {
Handle<Code> stub; Handle<Code> stub;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
stub = pre_monomorphic_stub(); stub = pre_monomorphic_stub();
...@@ -891,25 +893,6 @@ bool IC::HandleLoad(State state, ...@@ -891,25 +893,6 @@ bool IC::HandleLoad(State state,
return true; return true;
} }
return false;
}
MaybeObject* LoadIC::Load(State state,
Handle<Object> object,
Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) {
return TypeError("non_object_property_load", object, name);
}
if (FLAG_use_ic) {
MaybeObject* result;
if (HandleLoad(state, object, name, &result)) {
return result;
}
// Use specialized code for getting prototype of functions. // Use specialized code for getting prototype of functions.
if (object->IsJSFunction() && if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_symbol()) && name->Equals(isolate()->heap()->prototype_symbol()) &&
...@@ -918,7 +901,8 @@ MaybeObject* LoadIC::Load(State state, ...@@ -918,7 +901,8 @@ MaybeObject* LoadIC::Load(State state,
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
stub = pre_monomorphic_stub(); stub = pre_monomorphic_stub();
} else if (state == PREMONOMORPHIC) { } else if (state == PREMONOMORPHIC) {
stub = isolate()->builtins()->LoadIC_FunctionPrototype(); FunctionPrototypeStub function_prototype_stub(kind());
stub = function_prototype_stub.GetCode();
} else if (state != MEGAMORPHIC) { } else if (state != MEGAMORPHIC) {
ASSERT(state != GENERIC); ASSERT(state != GENERIC);
stub = megamorphic_stub(); stub = megamorphic_stub();
...@@ -929,10 +913,29 @@ MaybeObject* LoadIC::Load(State state, ...@@ -929,10 +913,29 @@ MaybeObject* LoadIC::Load(State state,
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
#endif #endif
} }
return Accessors::FunctionGetPrototype(*object, 0); *result = Accessors::FunctionGetPrototype(*object, 0);
return true;
} }
} }
return false;
}
MaybeObject* LoadIC::Load(State state,
Handle<Object> object,
Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) {
return TypeError("non_object_property_load", object, name);
}
MaybeObject* result;
if (HandleLoad(state, object, name, &result)) {
return result;
}
// Check if the name is trivially convertible to an index and get // Check if the name is trivially convertible to an index and get
// the element if so. // the element if so.
uint32_t index; uint32_t index;
...@@ -1170,28 +1173,11 @@ MaybeObject* KeyedLoadIC::Load(State state, ...@@ -1170,28 +1173,11 @@ MaybeObject* KeyedLoadIC::Load(State state,
return TypeError("non_object_property_load", object, name); return TypeError("non_object_property_load", object, name);
} }
if (FLAG_use_ic) {
MaybeObject* result; MaybeObject* result;
if (HandleLoad(state, object, name, &result)) { if (HandleLoad(state, object, name, &result)) {
return result; return result;
} }
// TODO(1073): don't ignore the current stub state.
// Use specialized code for getting prototype of functions.
if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_symbol()) &&
Handle<JSFunction>::cast(object)->should_have_prototype()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
Handle<Code> code =
isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
name, function);
ASSERT(!code.is_null());
set_target(*code);
TRACE_IC("KeyedLoadIC", name, state, target());
return Accessors::FunctionGetPrototype(*object, 0);
}
}
// Check if the name is trivially convertible to an index and get // Check if the name is trivially convertible to an index and get
// the element or char if so. // the element or char if so.
uint32_t index = 0; uint32_t index = 0;
......
...@@ -348,24 +348,6 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback( ...@@ -348,24 +348,6 @@ Handle<Code> StubCache::ComputeKeyedLoadCallback(
} }
Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
Handle<String> name,
Handle<JSFunction> receiver) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags),
isolate_);
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
Handle<Code> StubCache::ComputeStoreField(Handle<String> name, Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
int field_index, int field_index,
......
...@@ -133,9 +133,6 @@ class StubCache { ...@@ -133,9 +133,6 @@ class StubCache {
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder); Handle<JSObject> holder);
Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
Handle<JSFunction> receiver);
// --- // ---
Handle<Code> ComputeStoreField(Handle<String> name, Handle<Code> ComputeStoreField(Handle<String> name,
...@@ -664,8 +661,6 @@ class KeyedLoadStubCompiler: public StubCompiler { ...@@ -664,8 +661,6 @@ class KeyedLoadStubCompiler: public StubCompiler {
Handle<JSObject> holder, Handle<JSObject> holder,
Handle<String> name); Handle<String> name);
Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
Handle<Code> CompileLoadElement(Handle<Map> receiver_map); Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps, Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
......
...@@ -2387,6 +2387,33 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) { ...@@ -2387,6 +2387,33 @@ void ArrayLengthStub::Generate(MacroAssembler* masm) {
} }
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver;
if (kind() == Code::KEYED_LOAD_IC) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
__ Cmp(rax, masm->isolate()->factory()->prototype_symbol());
receiver = rdx;
} else {
ASSERT(kind() == Code::LOAD_IC);
// ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
receiver = rax;
}
StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, r8, r9, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, kind());
}
void StringLengthStub::Generate(MacroAssembler* masm) { void StringLengthStub::Generate(MacroAssembler* masm) {
Label miss; Label miss;
Register receiver; Register receiver;
......
...@@ -224,20 +224,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm, ...@@ -224,20 +224,6 @@ static void GenerateDictionaryStore(MacroAssembler* masm,
} }
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : receiver
// -- rcx : name
// -- rsp[0] : return address
// -----------------------------------
Label miss;
StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
__ bind(&miss);
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
// Checks the receiver for special cases (value type, slow case bits). // Checks the receiver for special cases (value type, slow case bits).
// Falls through for regular JS object. // Falls through for regular JS object.
static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
......
...@@ -3128,32 +3128,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( ...@@ -3128,32 +3128,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
} }
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
Handle<String> name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->keyed_load_function_prototype(), 1);
// Check that the name has not changed.
__ Cmp(rax, name);
__ j(not_equal, &miss);
GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
__ bind(&miss);
__ DecrementCounter(counters->keyed_load_function_prototype(), 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
// Return the generated code.
return GetCode(Code::CALLBACKS, name);
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadElement( Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
Handle<Map> receiver_map) { Handle<Map> receiver_map) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
......
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