Revision: 11771
Author: [email protected]
Date: Tue Jun 12 02:32:17 2012
Log: Implemented StoreIC for setters.
Review URL: https://chromiumcodereview.appspot.com/10534091
http://code.google.com/p/v8/source/detail?r=11771
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/mips/stub-cache-mips.cc
/branches/bleeding_edge/src/stub-cache.cc
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Jun 8 05:53:20
2012
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Jun 12 02:32:17
2012
@@ -2666,6 +2666,51 @@
// Return the generated code.
return GetCode(CALLBACKS, name);
}
+
+
+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(
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Jun 8 02:15:32
2012
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Jun 12 02:32:17
2012
@@ -2585,6 +2585,52 @@
// Return the generated code.
return GetCode(CALLBACKS, name);
}
+
+
+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(
=======================================
--- /branches/bleeding_edge/src/ic.cc Sun Jun 10 23:59:56 2012
+++ /branches/bleeding_edge/src/ic.cc Tue Jun 12 02:32:17 2012
@@ -1450,6 +1450,7 @@
// 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 @@
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:
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Fri Jun 8 05:53:20
2012
+++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Tue Jun 12 02:32:17
2012
@@ -2670,6 +2670,52 @@
// Return the generated code.
return GetCode(CALLBACKS, name);
}
+
+
+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(
=======================================
--- /branches/bleeding_edge/src/stub-cache.cc Mon Jun 11 05:42:31 2012
+++ /branches/bleeding_edge/src/stub-cache.cc Tue Jun 12 02:32:17 2012
@@ -513,6 +513,24 @@
JSObject::UpdateMapCodeCache(receiver, name, code);
return code;
}
+
+
+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,
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Mon Jun 11 05:42:31 2012
+++ /branches/bleeding_edge/src/stub-cache.h Tue Jun 12 02:32:17 2012
@@ -162,6 +162,11 @@
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 @@
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);
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Jun 8 05:53:20
2012
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Jun 12 02:32:17
2012
@@ -2422,6 +2422,52 @@
// Return the generated code.
return GetCode(CALLBACKS, name);
}
+
+
+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(
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev