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:
parent
075cd7ac5a
commit
e6f2eab7f6
@ -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) {
|
||||
|
@ -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) {
|
||||
|
30
src/ic.cc
30
src/ic.cc
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user