Added IC support for native setters on the prototype chain.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12402 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f9d48562
...@@ -2673,9 +2673,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, ...@@ -2673,9 +2673,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<String> name,
Handle<AccessorInfo> callback, Handle<JSObject> receiver,
Handle<String> name) { Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : receiver // -- r1 : receiver
...@@ -2683,19 +2684,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2683,19 +2684,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// -- lr : return address // -- lr : return address
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(r1, &miss);
CheckPrototypes(receiver, r1, holder, r3, r4, r5, name, &miss);
// Check that the map of the object hasn't changed. // Stub never generated for non-global objects that require access checks.
__ CheckMap(r1, r3, Handle<Map>(object->map()), &miss, ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(r1, r3, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ push(r1); // receiver __ push(r1); // receiver
__ mov(ip, Operand(callback)); // callback info __ mov(ip, Operand(callback)); // callback info
......
...@@ -2601,9 +2601,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, ...@@ -2601,9 +2601,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<String> name,
Handle<AccessorInfo> callback, Handle<JSObject> receiver,
Handle<String> name) { Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
...@@ -2611,19 +2612,14 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2611,19 +2612,14 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// -- esp[0] : return address // -- esp[0] : return address
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed, preserving the value register.
__ push(eax);
__ JumpIfSmi(edx, &miss);
CheckPrototypes(receiver, edx, holder, ebx, eax, edi, name, &miss);
__ pop(eax); // restore value
// Check that the map of the object hasn't changed. // Stub never generated for non-global objects that require access checks.
__ CheckMap(edx, Handle<Map>(object->map()), ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
&miss, DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(edx, ebx, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(ebx); // remove the return address __ pop(ebx); // remove the return address
__ push(edx); // receiver __ push(edx); // receiver
...@@ -2639,6 +2635,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2639,6 +2635,7 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
__ pop(eax);
Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
__ jmp(ic, RelocInfo::CODE_TARGET); __ jmp(ic, RelocInfo::CODE_TARGET);
......
...@@ -1331,7 +1331,7 @@ static bool LookupForWrite(Handle<JSObject> receiver, ...@@ -1331,7 +1331,7 @@ static bool LookupForWrite(Handle<JSObject> receiver,
return false; return false;
} }
Handle<Object> callback(lookup->GetCallbackObject()); Handle<Object> callback(lookup->GetCallbackObject());
return callback->IsAccessorPair() && StoreICableLookup(lookup); return StoreICableLookup(lookup);
} }
if (lookup->IsInterceptor() && if (lookup->IsInterceptor() &&
...@@ -1491,13 +1491,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ...@@ -1491,13 +1491,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
case CALLBACKS: { case CALLBACKS: {
Handle<Object> callback(lookup->GetCallbackObject()); Handle<Object> callback(lookup->GetCallbackObject());
if (callback->IsAccessorInfo()) { if (callback->IsAccessorInfo()) {
ASSERT(*holder == *receiver); // LookupForWrite checks this.
Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback); Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
if (v8::ToCData<Address>(info->setter()) == 0) return; if (v8::ToCData<Address>(info->setter()) == 0) return;
if (!holder->HasFastProperties()) return; if (!holder->HasFastProperties()) return;
ASSERT(info->IsCompatibleReceiver(*receiver)); if (!info->IsCompatibleReceiver(*receiver)) return;
code = isolate()->stub_cache()->ComputeStoreCallback( code = isolate()->stub_cache()->ComputeStoreCallback(
name, receiver, info, strict_mode); name, receiver, holder, info, strict_mode);
} else if (callback->IsAccessorPair()) { } else if (callback->IsAccessorPair()) {
Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
if (!setter->IsJSFunction()) return; if (!setter->IsJSFunction()) return;
......
...@@ -2676,9 +2676,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, ...@@ -2676,9 +2676,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<String> name,
Handle<AccessorInfo> callback, Handle<JSObject> receiver,
Handle<String> name) { Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : value // -- a0 : value
// -- a1 : receiver // -- a1 : receiver
...@@ -2686,19 +2687,13 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2686,19 +2687,13 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// -- ra : return address // -- ra : return address
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed.
// Check that the map of the object hasn't changed. __ JumpIfSmi(a1, &miss, a3);
__ CheckMap(a1, a3, Handle<Map>(object->map()), &miss, CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss);
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(a1, a3, &miss);
}
// Stub never generated for non-global objects that require access // Stub never generated for non-global objects that require access
// checks. // checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
__ push(a1); // Receiver. __ push(a1); // Receiver.
__ li(a3, Operand(callback)); // Callback info. __ li(a3, Operand(callback)); // Callback info.
......
...@@ -504,6 +504,7 @@ Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, ...@@ -504,6 +504,7 @@ Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name,
Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name, Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<AccessorInfo> callback, Handle<AccessorInfo> callback,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
ASSERT(v8::ToCData<Address>(callback->setter()) != 0); ASSERT(v8::ToCData<Address>(callback->setter()) != 0);
...@@ -513,7 +514,8 @@ Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name, ...@@ -513,7 +514,8 @@ Handle<Code> StubCache::ComputeStoreCallback(Handle<String> name,
if (probe->IsCode()) return Handle<Code>::cast(probe); if (probe->IsCode()) return Handle<Code>::cast(probe);
StoreStubCompiler compiler(isolate_, strict_mode); StoreStubCompiler compiler(isolate_, strict_mode);
Handle<Code> code = compiler.CompileStoreCallback(receiver, callback, name); Handle<Code> code =
compiler.CompileStoreCallback(name, receiver, holder, callback);
PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code));
JSObject::UpdateMapCodeCache(receiver, name, code); JSObject::UpdateMapCodeCache(receiver, name, code);
......
...@@ -159,6 +159,7 @@ class StubCache { ...@@ -159,6 +159,7 @@ class StubCache {
Handle<Code> ComputeStoreCallback(Handle<String> name, Handle<Code> ComputeStoreCallback(Handle<String> name,
Handle<JSObject> receiver, Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<AccessorInfo> callback, Handle<AccessorInfo> callback,
StrictModeFlag strict_mode); StrictModeFlag strict_mode);
...@@ -704,9 +705,10 @@ class StoreStubCompiler: public StubCompiler { ...@@ -704,9 +705,10 @@ class StoreStubCompiler: public StubCompiler {
Handle<Map> transition, Handle<Map> transition,
Handle<String> name); Handle<String> name);
Handle<Code> CompileStoreCallback(Handle<JSObject> object, Handle<Code> CompileStoreCallback(Handle<String> name,
Handle<AccessorInfo> callback, Handle<JSObject> receiver,
Handle<String> name); Handle<JSObject> holder,
Handle<AccessorInfo> callback);
static void GenerateStoreViaSetter(MacroAssembler* masm, static void GenerateStoreViaSetter(MacroAssembler* masm,
Handle<JSFunction> setter); Handle<JSFunction> setter);
......
...@@ -2429,9 +2429,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, ...@@ -2429,9 +2429,10 @@ Handle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object,
Handle<Code> StoreStubCompiler::CompileStoreCallback( Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> object, Handle<String> name,
Handle<AccessorInfo> callback, Handle<JSObject> receiver,
Handle<String> name) { Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
...@@ -2439,19 +2440,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback( ...@@ -2439,19 +2440,12 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
// -- rsp[0] : return address // -- rsp[0] : return address
// ----------------------------------- // -----------------------------------
Label miss; Label miss;
// Check that the maps haven't changed.
__ JumpIfSmi(rdx, &miss);
CheckPrototypes(receiver, rdx, holder, rbx, r8, rdi, name, &miss);
// Check that the map of the object hasn't changed. // Stub never generated for non-global objects that require access checks.
__ CheckMap(rdx, Handle<Map>(object->map()), &miss, ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
if (object->IsJSGlobalProxy()) {
__ CheckAccessGlobalProxy(rdx, rbx, &miss);
}
// Stub never generated for non-global objects that require access
// checks.
ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
__ pop(rbx); // remove the return address __ pop(rbx); // remove the return address
__ push(rdx); // receiver __ push(rdx); // receiver
......
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