Implemented StoreIC for setters.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11771 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
svenpanne@chromium.org 2012-06-12 09:32:17 +00:00
parent 075cd7ac5a
commit e6f2eab7f6
7 changed files with 231 additions and 9 deletions

View File

@ -2668,6 +2668,51 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
}
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<JSObject> receiver,
Handle<JSFunction> setter,
Handle<String> name) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
// -- r2 : name
// -- lr : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(r1, r3, Handle<Map>(receiver->map()), &miss, DO_SMI_CHECK,
ALLOW_ELEMENT_TRANSITION_MAPS);
{
FrameScope scope(masm(), StackFrame::INTERNAL);
// Save value register, so we can restore it later.
__ push(r0);
// Call the JavaScript getter with the receiver and the value on the stack.
__ Push(r1, r0);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
// We have to return the passed value, not the return value of the setter.
__ pop(r0);
// Restore context register.
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
__ Ret();
__ bind(&miss);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<String> name) {

View File

@ -2587,6 +2587,52 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
}
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<JSObject> receiver,
Handle<JSFunction> setter,
Handle<String> name) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(edx, Handle<Map>(receiver->map()), &miss, DO_SMI_CHECK,
ALLOW_ELEMENT_TRANSITION_MAPS);
{
FrameScope scope(masm(), StackFrame::INTERNAL);
// Save value register, so we can restore it later.
__ push(eax);
// Call the JavaScript getter with the receiver and the value on the stack.
__ push(edx);
__ push(eax);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
// We have to return the passed value, not the return value of the setter.
__ pop(eax);
// Restore context register.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
__ ret(0);
__ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
__ jmp(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<String> name) {

View File

@ -1450,6 +1450,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
// Compute the code stub for this store; used for rewriting to
// monomorphic state and making sure that the code stub is in the
// stub cache.
Handle<JSObject> holder(lookup->holder());
Handle<Code> code;
switch (type) {
case FIELD:
@ -1477,19 +1478,30 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
code = isolate()->stub_cache()->ComputeStoreGlobal(
name, global, cell, strict_mode);
} else {
if (lookup->holder() != *receiver) return;
if (!holder.is_identical_to(receiver)) return;
code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
}
break;
case CALLBACKS: {
Handle<Object> callback_object(lookup->GetCallbackObject());
if (!callback_object->IsAccessorInfo()) return;
Handle<AccessorInfo> callback =
Handle<AccessorInfo>::cast(callback_object);
if (v8::ToCData<Address>(callback->setter()) == 0) return;
ASSERT(callback->IsCompatibleReceiver(*receiver));
code = isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, callback, strict_mode);
Handle<Object> callback(lookup->GetCallbackObject());
if (callback->IsAccessorInfo()) {
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->setter()) == 0) return;
ASSERT(info->IsCompatibleReceiver(*receiver));
code = isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, info, strict_mode);
} else if (callback->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
if (!setter->IsJSFunction()) return;
if (holder->IsGlobalObject()) return;
if (!receiver->HasFastProperties()) return;
code = isolate()->stub_cache()->ComputeStoreViaSetter(
name, receiver, Handle<JSFunction>::cast(setter), strict_mode);
} else {
ASSERT(callback->IsForeign());
// No IC support for old-style native accessors.
return;
}
break;
}
case INTERCEPTOR:

View File

@ -2672,6 +2672,52 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
}
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<JSObject> receiver,
Handle<JSFunction> setter,
Handle<String> name) {
// ----------- S t a t e -------------
// -- a0 : value
// -- a1 : receiver
// -- a2 : name
// -- ra : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss, DO_SMI_CHECK,
ALLOW_ELEMENT_TRANSITION_MAPS);
{
FrameScope scope(masm(), StackFrame::INTERNAL);
// Save value register, so we can restore it later.
__ push(a0);
// Call the JavaScript getter with the receiver and the value on the stack.
__ push(a1);
__ push(a0);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
// We have to return the passed value, not the return value of the setter.
__ pop(a0);
// Restore context register.
__ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
__ Ret();
__ bind(&miss);
Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss();
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<String> name) {

View File

@ -515,6 +515,24 @@ Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
}
Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSFunction> setter,
StrictModeFlag strict_mode) {
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::STORE_IC, CALLBACKS, strict_mode);
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreViaSetter(receiver, setter, name);
PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
JSObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name,
Handle<JSObject> receiver,
StrictModeFlag strict_mode) {

View File

@ -162,6 +162,11 @@ class StubCache {
Handle<AccessorInfo> callback,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreViaSetter(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSFunction> setter,
StrictModeFlag strict_mode);
Handle<Code> ComputeStoreInterceptor(Handle<String> name,
Handle<JSObject> receiver,
StrictModeFlag strict_mode);
@ -693,6 +698,10 @@ class StoreStubCompiler: public StubCompiler {
Handle<AccessorInfo> callback,
Handle<String> name);
Handle<Code> CompileStoreViaSetter(Handle<JSObject> receiver,
Handle<JSFunction> setter,
Handle<String> name);
Handle<Code> CompileStoreInterceptor(Handle<JSObject> object,
Handle<String> name);

View File

@ -2424,6 +2424,52 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
}
Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
Handle<JSObject> receiver,
Handle<JSFunction> setter,
Handle<String> name) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
__ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, DO_SMI_CHECK,
ALLOW_ELEMENT_TRANSITION_MAPS);
{
FrameScope scope(masm(), StackFrame::INTERNAL);
// Save value register, so we can restore it later.
__ push(rax);
// Call the JavaScript getter with the receiver and the value on the stack.
__ push(rdx);
__ push(rax);
ParameterCount actual(1);
__ InvokeFunction(setter, actual, CALL_FUNCTION, NullCallWrapper(),
CALL_AS_METHOD);
// We have to return the passed value, not the return value of the setter.
__ pop(rax);
// Restore context register.
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
__ ret(0);
__ bind(&miss);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
__ Jump(ic, RelocInfo::CODE_TARGET);
// Return the generated code.
return GetCode(CALLBACKS, name);
}
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
Handle<JSObject> receiver,
Handle<String> name) {