From 866eac3057951ae453857ac1d1da3aa3ee01544e Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Mon, 1 Feb 2010 08:35:38 +0000 Subject: [PATCH] StoreIC interface changed on ia32 to take receiver in edx, not on stack. Review URL: http://codereview.chromium.org/555162 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3750 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/codegen-ia32.cc | 4 +--- src/ia32/full-codegen-ia32.cc | 21 +++++++++++------- src/ia32/ic-ia32.cc | 12 +++++----- src/ia32/stub-cache-ia32.cc | 38 ++++++++++++-------------------- src/ia32/virtual-frame-ia32.cc | 40 +++++++++++++++++++++++----------- 5 files changed, 60 insertions(+), 55 deletions(-) diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 326d609605..8691dd4eac 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -4472,8 +4472,6 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { Load(property->value()); frame_->Push(key); Result ignored = frame_->CallStoreIC(); - // Drop the duplicated receiver and ignore the result. - frame_->Drop(); break; } // Fall through @@ -6715,7 +6713,7 @@ void Reference::SetValue(InitState init_state) { cgen_->frame()->Push(GetName()); Result answer = cgen_->frame()->CallStoreIC(); cgen_->frame()->Push(&answer); - cgen_->UnloadReference(this); + set_unloaded(); break; } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 6b610609fb..5fd594cbe9 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -917,10 +917,10 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { if (key->handle()->IsSymbol()) { VisitForValue(value, kAccumulator); __ mov(ecx, Immediate(key->handle())); + __ mov(edx, Operand(esp, 0)); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); __ nop(); - // StoreIC leaves the receiver on the stack. break; } // Fall through. @@ -1046,12 +1046,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, // assignment. Right-hand-side value is passed in eax, variable name in // ecx, and the global object on the stack. __ mov(ecx, var->name()); - __ push(CodeGenerator::GlobalObject()); + __ mov(edx, CodeGenerator::GlobalObject()); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); __ nop(); - // Overwrite the receiver on the stack with the result if needed. - DropAndApply(1, context, eax); + Apply(context, eax); } else if (slot != NULL && slot->type() == Slot::LOOKUP) { __ push(result_register()); // Value. @@ -1111,6 +1110,11 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { // Record source code position before IC call. SetSourcePosition(expr->position()); __ mov(ecx, prop->key()->AsLiteral()->handle()); + if (expr->ends_initialization_block()) { + __ mov(edx, Operand(esp, 0)); + } else { + __ pop(edx); + } Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); __ nop(); @@ -1121,9 +1125,10 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { __ push(Operand(esp, kPointerSize)); // Receiver is under value. __ CallRuntime(Runtime::kToFastProperties, 1); __ pop(eax); + DropAndApply(1, context_, eax); + } else { + Apply(context_, eax); } - - DropAndApply(1, context_, eax); } @@ -1642,18 +1647,18 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { break; case NAMED_PROPERTY: { __ mov(ecx, prop->key()->AsLiteral()->handle()); + __ pop(edx); Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); __ call(ic, RelocInfo::CODE_TARGET); // This nop signals to the IC that there is no inlined code at the call // site for it to patch. __ nop(); if (expr->is_postfix()) { - __ Drop(1); // Result is on the stack under the receiver. if (context_ != Expression::kEffect) { ApplyTOS(context_); } } else { - DropAndApply(1, context_, eax); + Apply(context_, eax); } break; } diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc index 7f7e73140a..307a82bbbd 100644 --- a/src/ia32/ic-ia32.cc +++ b/src/ia32/ic-ia32.cc @@ -1379,12 +1379,10 @@ void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- - // Get the receiver from the stack and probe the stub cache. - __ mov(edx, Operand(esp, 4)); Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, NOT_IN_LOOP, MONOMORPHIC); @@ -1399,12 +1397,12 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : transition map + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- __ pop(ebx); - __ push(Operand(esp, 0)); // receiver + __ push(edx); // receiver __ push(ecx); // transition map __ push(eax); // value __ push(ebx); // return address @@ -1419,12 +1417,12 @@ void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- __ pop(ebx); - __ push(Operand(esp, 0)); + __ push(edx); __ push(ecx); __ push(eax); __ push(ebx); diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc index 38498305de..030c1569fa 100644 --- a/src/ia32/stub-cache-ia32.cc +++ b/src/ia32/stub-cache-ia32.cc @@ -1255,21 +1255,18 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object, // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- Label miss; - // Get the object from the stack. - __ mov(ebx, Operand(esp, 1 * kPointerSize)); - // Generate store field code. Trashes the name register. GenerateStoreField(masm(), Builtins::StoreIC_ExtendStorage, object, index, transition, - ebx, ecx, edx, + edx, ecx, ebx, &miss); // Handle store cache miss. @@ -1289,26 +1286,23 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- Label miss; - // Get the object from the stack. - __ mov(ebx, Operand(esp, 1 * kPointerSize)); - // Check that the object isn't a smi. - __ test(ebx, Immediate(kSmiTagMask)); + __ test(edx, Immediate(kSmiTagMask)); __ j(zero, &miss, not_taken); // Check that the map of the object hasn't changed. - __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), + __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Immediate(Handle(object->map()))); __ j(not_equal, &miss, not_taken); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { - __ CheckAccessGlobalProxy(ebx, edx, &miss); + __ CheckAccessGlobalProxy(edx, ebx, &miss); } // Stub never generated for non-global objects that require access @@ -1316,7 +1310,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); __ pop(ebx); // remove the return address - __ push(Operand(esp, 0)); // receiver + __ push(edx); // receiver __ push(Immediate(Handle(callback))); // callback info __ push(ecx); // name __ push(eax); // value @@ -1342,26 +1336,23 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- Label miss; - // Get the object from the stack. - __ mov(ebx, Operand(esp, 1 * kPointerSize)); - // Check that the object isn't a smi. - __ test(ebx, Immediate(kSmiTagMask)); + __ test(edx, Immediate(kSmiTagMask)); __ j(zero, &miss, not_taken); // Check that the map of the object hasn't changed. - __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), + __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Immediate(Handle(receiver->map()))); __ j(not_equal, &miss, not_taken); // Perform global security token check if needed. if (receiver->IsJSGlobalProxy()) { - __ CheckAccessGlobalProxy(ebx, edx, &miss); + __ CheckAccessGlobalProxy(edx, ebx, &miss); } // Stub never generated for non-global objects that require access @@ -1369,7 +1360,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); __ pop(ebx); // remove the return address - __ push(Operand(esp, 0)); // receiver + __ push(edx); // receiver __ push(ecx); // name __ push(eax); // value __ push(ebx); // restore return address @@ -1395,14 +1386,13 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, // ----------- S t a t e ------------- // -- eax : value // -- ecx : name + // -- edx : receiver // -- esp[0] : return address - // -- esp[4] : receiver // ----------------------------------- Label miss; // Check that the map of the global has not changed. - __ mov(ebx, Operand(esp, kPointerSize)); - __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), + __ cmp(FieldOperand(edx, HeapObject::kMapOffset), Immediate(Handle(object->map()))); __ j(not_equal, &miss, not_taken); diff --git a/src/ia32/virtual-frame-ia32.cc b/src/ia32/virtual-frame-ia32.cc index 104d187507..9267507c7e 100644 --- a/src/ia32/virtual-frame-ia32.cc +++ b/src/ia32/virtual-frame-ia32.cc @@ -899,31 +899,45 @@ Result VirtualFrame::CallKeyedLoadIC(RelocInfo::Mode mode) { Result VirtualFrame::CallStoreIC() { // Name, value, and receiver are on top of the frame. The IC - // expects name in ecx, value in eax, and receiver on the stack. It - // does not drop the receiver. + // expects name in ecx, value in eax, and receiver in edx. Handle ic(Builtins::builtin(Builtins::StoreIC_Initialize)); Result name = Pop(); Result value = Pop(); - PrepareForCall(1, 0); // One stack arg, not callee-dropped. + Result receiver = Pop(); + PrepareForCall(0, 0); - if (value.is_register() && value.reg().is(ecx)) { - if (name.is_register() && name.reg().is(eax)) { - // Wrong registers. - __ xchg(eax, ecx); - } else { - // Register eax is free for value, which frees ecx for name. - value.ToRegister(eax); + // Optimized for case in which name is a constant value. + if (name.is_register() && (name.reg().is(edx) || name.reg().is(eax))) { + if (!is_used(ecx)) { name.ToRegister(ecx); + } else if (!is_used(ebx)) { + name.ToRegister(ebx); + } else { + ASSERT(!is_used(edi)); // Only three results are live, so edi is free. + name.ToRegister(edi); + } + } + // Now name is not in edx or eax, so we can fix them, then move name to ecx. + if (value.is_register() && value.reg().is(edx)) { + if (receiver.is_register() && receiver.reg().is(eax)) { + // Wrong registers. + __ xchg(eax, edx); + } else { + // Register eax is free for value, which frees edx for receiver. + value.ToRegister(eax); + receiver.ToRegister(edx); } } else { - // Register ecx is free for name, which guarantees eax is free for + // Register edx is free for receiver, which guarantees eax is free for // value. - name.ToRegister(ecx); + receiver.ToRegister(edx); value.ToRegister(eax); } - + // Receiver and value are in the right place, so ecx is free for name. + name.ToRegister(ecx); name.Unuse(); value.Unuse(); + receiver.Unuse(); return RawCallCodeObject(ic, RelocInfo::CODE_TARGET); }