From b8af68b03fce70a0dabfbc44d765653ef0637f5d Mon Sep 17 00:00:00 2001 From: "kmillikin@chromium.org" Date: Fri, 27 Mar 2009 10:29:37 +0000 Subject: [PATCH] Make VirtualFrame::CallStub on IA32 responsible for moving arguments into the appropriate registers for the stub call. Since stubs that take arguments in registers do not (currently) take any arguments on the stack, the unused generality has been removed (it's easy to put back in later). Review URL: http://codereview.chromium.org/55003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1629 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/codegen-arm.cc | 6 ++-- src/codegen-ia32.cc | 60 +++++++++++---------------------------- src/virtual-frame-arm.cc | 15 ++++++++++ src/virtual-frame-arm.h | 28 +++++++++++------- src/virtual-frame-ia32.cc | 33 +++++++++++++++++++++ src/virtual-frame-ia32.h | 25 ++++++++++------ src/virtual-frame.cc | 18 ------------ 7 files changed, 102 insertions(+), 83 deletions(-) diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc index a9a0af0e6b..0823f77865 100644 --- a/src/codegen-arm.cc +++ b/src/codegen-arm.cc @@ -868,11 +868,11 @@ void DeferredInlineSmiOperation::Generate() { } GenericBinaryOpStub igostub(op_); - Result arg0 = generator()->allocator()->Allocate(r0); + Result arg0 = generator()->allocator()->Allocate(r1); ASSERT(arg0.is_valid()); - Result arg1 = generator()->allocator()->Allocate(r1); + Result arg1 = generator()->allocator()->Allocate(r0); ASSERT(arg1.is_valid()); - generator()->frame()->CallStub(&igostub, &arg0, &arg1, 0); + generator()->frame()->CallStub(&igostub, &arg0, &arg1); exit_.Jump(); } diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc index 5ef264f647..e1cfb40702 100644 --- a/src/codegen-ia32.cc +++ b/src/codegen-ia32.cc @@ -1508,12 +1508,10 @@ void CodeGenerator::Comparison(Condition cc, __ test(left_side.reg(), Immediate(kSmiTagMask)); is_smi.Branch(zero, &left_side, &right_side, taken); - // Setup and call the compare stub, which expects arguments in edx - // and eax. + // Setup and call the compare stub, which expects its arguments + // in registers. CompareStub stub(cc, strict); - left_side.ToRegister(edx); // Only left_side currently uses a register. - right_side.ToRegister(eax); // left_side is not in eax. eax is free. - Result result = frame_->CallStub(&stub, &left_side, &right_side, 0); + Result result = frame_->CallStub(&stub, &left_side, &right_side); result.ToRegister(); __ cmp(result.reg(), 0); result.Unuse(); @@ -1588,23 +1586,10 @@ void CodeGenerator::Comparison(Condition cc, temp.Unuse(); is_smi.Branch(zero, &left_side, &right_side, taken); } - // When non-smi, call out to the compare stub. "parameters" setup by - // calling code in edx and eax and "result" is returned in the flags. - if (!left_side.reg().is(eax)) { - right_side.ToRegister(eax); - left_side.ToRegister(edx); - } else if (!right_side.reg().is(edx)) { - left_side.ToRegister(edx); - right_side.ToRegister(eax); - } else { - frame_->Spill(eax); // Can be multiply referenced, even now. - frame_->Spill(edx); - __ xchg(eax, edx); - // If left_side and right_side become real (non-dummy) arguments - // to CallStub, they need to be swapped in this case. - } + // When non-smi, call out to the compare stub, which expects its + // arguments in registers. CompareStub stub(cc, strict); - Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0); + Result answer = frame_->CallStub(&stub, &left_side, &right_side); if (cc == equal) { __ test(answer.reg(), Operand(answer.reg())); } else { @@ -4392,15 +4377,12 @@ void CodeGenerator::GenerateIsArray(ZoneList* args) { void CodeGenerator::GenerateArgumentsLength(ZoneList* args) { ASSERT(args->length() == 0); - Result initial_value = allocator()->Allocate(eax); - ASSERT(initial_value.is_valid()); - __ Set(initial_value.reg(), - Immediate(Smi::FromInt(scope_->num_parameters()))); // ArgumentsAccessStub takes the parameter count as an input argument - // in register eax. + // in register eax. Create a constant result for it. + Result count(Handle(Smi::FromInt(scope_->num_parameters())), this); // Call the shared stub to get to the arguments.length. ArgumentsAccessStub stub(ArgumentsAccessStub::READ_LENGTH); - Result result = frame_->CallStub(&stub, &initial_value, 0); + Result result = frame_->CallStub(&stub, &count); frame_->Push(&result); } @@ -4475,20 +4457,15 @@ void CodeGenerator::GenerateSetValueOf(ZoneList* args) { void CodeGenerator::GenerateArgumentsAccess(ZoneList* args) { ASSERT(args->length() == 1); - // Load the key into edx and set eax to the formal parameters count - // for the currently executing function. + // ArgumentsAccessStub expects the key in edx and the formal + // parameter count in eax. Load(args->at(0)); Result key = frame_->Pop(); - key.ToRegister(edx); - - Result parameters_count = allocator()->Allocate(eax); - ASSERT(parameters_count.is_valid()); - __ Set(parameters_count.reg(), - Immediate(Smi::FromInt(scope_->num_parameters()))); - + // Explicitly create a constant result. + Result count(Handle(Smi::FromInt(scope_->num_parameters())), this); // Call the shared stub to get to arguments[key]. ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); - Result result = frame_->CallStub(&stub, ¶meters_count, &key, 0); + Result result = frame_->CallStub(&stub, &key, &count); frame_->Push(&result); } @@ -4647,8 +4624,7 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { UnarySubStub stub; // TODO(1222589): remove dependency of TOS being cached inside stub Result operand = frame_->Pop(); - operand.ToRegister(eax); - Result answer = frame_->CallStub(&stub, &operand, 0); + Result answer = frame_->CallStub(&stub, &operand); frame_->Push(&answer); break; } @@ -4781,15 +4757,13 @@ void DeferredCountOperation::Generate() { Result value(cgen); enter()->Bind(&value); - value.ToRegister(eax); // The stubs below expect their argument in eax. - if (is_postfix_) { RevertToNumberStub to_number_stub(is_increment_); - value = generator()->frame()->CallStub(&to_number_stub, &value, 0); + value = generator()->frame()->CallStub(&to_number_stub, &value); } CounterOpStub stub(result_offset_, is_postfix_, is_increment_); - value = generator()->frame()->CallStub(&stub, &value, 0); + value = generator()->frame()->CallStub(&stub, &value); exit_.Jump(&value); } diff --git a/src/virtual-frame-arm.cc b/src/virtual-frame-arm.cc index eed1463888..0ba8beddf9 100644 --- a/src/virtual-frame-arm.cc +++ b/src/virtual-frame-arm.cc @@ -241,6 +241,21 @@ Result VirtualFrame::RawCallStub(CodeStub* stub) { } +Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) { + PrepareForCall(0, 0); + arg->Unuse(); + return RawCallStub(stub); +} + + +Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) { + PrepareForCall(0, 0); + arg0->Unuse(); + arg1->Unuse(); + return RawCallStub(stub); +} + + Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { PrepareForCall(arg_count, arg_count); ASSERT(cgen_->HasValidEntryRegisters()); diff --git a/src/virtual-frame-arm.h b/src/virtual-frame-arm.h index 3891dfc29d..965373e38e 100644 --- a/src/virtual-frame-arm.h +++ b/src/virtual-frame-arm.h @@ -248,27 +248,33 @@ class VirtualFrame : public Malloced { // Push a try-catch or try-finally handler on top of the virtual frame. void PushTryHandler(HandlerType type); - // Call a code stub, given the number of arguments it expects on (and - // removes from) the top of the physical frame. + // Call stub given the number of arguments it expects on (and + // removes from) the stack. Result CallStub(CodeStub* stub, int arg_count); - Result CallStub(CodeStub* stub, Result* arg, int arg_count); - Result CallStub(CodeStub* stub, Result* arg0, Result* arg1, int arg_count); - // Call the runtime, given the number of arguments expected on (and - // removed from) the top of the physical frame. + // Call stub that expects its argument in r0. The argument is given + // as a result which must be the register r0. + Result CallStub(CodeStub* stub, Result* arg); + + // Call stub that expects its arguments in r1 and r0. The arguments + // are given as results which must be the appropriate registers. + Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); + + // Call runtime given the number of arguments expected on (and + // removed from) the stack. Result CallRuntime(Runtime::Function* f, int arg_count); Result CallRuntime(Runtime::FunctionId id, int arg_count); - // Invoke a builtin, given the number of arguments it expects on (and - // removes from) the top of the physical frame. + // Invoke builtin given the number of arguments it expects on (and + // removes from) the stack. Result InvokeBuiltin(Builtins::JavaScript id, InvokeJSFlags flag, Result* arg_count_register, int arg_count); - // Call into a JS code object, given the number of arguments it - // removes from the top of the physical frame. - // Register arguments are passed as results and consumed by the call. + // Call into an IC stub given the number of arguments it removes + // from the stack. Register arguments are passed as results and + // consumed by the call. Result CallCodeObject(Handle ic, RelocInfo::Mode rmode, int dropped_args); diff --git a/src/virtual-frame-ia32.cc b/src/virtual-frame-ia32.cc index 0fadfb9fff..5bae6194f9 100644 --- a/src/virtual-frame-ia32.cc +++ b/src/virtual-frame-ia32.cc @@ -734,6 +734,39 @@ Result VirtualFrame::RawCallStub(CodeStub* stub) { } +Result VirtualFrame::CallStub(CodeStub* stub, Result* arg) { + PrepareForCall(0, 0); + arg->ToRegister(eax); + arg->Unuse(); + return RawCallStub(stub); +} + + +Result VirtualFrame::CallStub(CodeStub* stub, Result* arg0, Result* arg1) { + PrepareForCall(0, 0); + + if (arg0->is_register() && arg0->reg().is(eax)) { + if (arg1->is_register() && arg1->reg().is(edx)) { + // Wrong registers. + __ xchg(eax, edx); + } else { + // Register edx is free for arg0, which frees eax for arg1. + arg0->ToRegister(edx); + arg1->ToRegister(eax); + } + } else { + // Register eax is free for arg1, which guarantees edx is free for + // arg0. + arg1->ToRegister(eax); + arg0->ToRegister(edx); + } + + arg0->Unuse(); + arg1->Unuse(); + return RawCallStub(stub); +} + + Result VirtualFrame::CallRuntime(Runtime::Function* f, int arg_count) { PrepareForCall(arg_count, arg_count); ASSERT(cgen_->HasValidEntryRegisters()); diff --git a/src/virtual-frame-ia32.h b/src/virtual-frame-ia32.h index 8727c546f2..c44ff75e19 100644 --- a/src/virtual-frame-ia32.h +++ b/src/virtual-frame-ia32.h @@ -241,19 +241,28 @@ class VirtualFrame : public Malloced { // Push a try-catch or try-finally handler on top of the virtual frame. void PushTryHandler(HandlerType type); - // Call a code stub, given the number of arguments it expects on (and - // removes from) the top of the physical frame. + // Call stub given the number of arguments it expects on (and + // removes from) the stack. Result CallStub(CodeStub* stub, int arg_count); - Result CallStub(CodeStub* stub, Result* arg, int arg_count); - Result CallStub(CodeStub* stub, Result* arg0, Result* arg1, int arg_count); - // Call the runtime, given the number of arguments expected on (and - // removed from) the top of the physical frame. + // Call stub that takes a single argument passed in eax. The + // argument is given as a result which does not have to be eax or + // even a register. The argument is consumed by the call. + Result CallStub(CodeStub* stub, Result* arg); + + // Call stub that takes a pair of arguments passed in edx (arg0) and + // eax (arg1). The arguments are given as results which do not have + // to be in the proper registers or even in registers. The + // arguments are consumed by the call. + Result CallStub(CodeStub* stub, Result* arg0, Result* arg1); + + // Call runtime given the number of arguments expected on (and + // removed from) the stack. Result CallRuntime(Runtime::Function* f, int arg_count); Result CallRuntime(Runtime::FunctionId id, int arg_count); - // Invoke a builtin, given the number of arguments it expects on (and - // removes from) the top of the physical frame. + // Invoke builtin given the number of arguments it expects on (and + // removes from) the stack. Result InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag, int arg_count); diff --git a/src/virtual-frame.cc b/src/virtual-frame.cc index 67380f1507..b2b6c417b3 100644 --- a/src/virtual-frame.cc +++ b/src/virtual-frame.cc @@ -437,24 +437,6 @@ Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) { } -Result VirtualFrame::CallStub(CodeStub* stub, Result* arg, int arg_count) { - PrepareForCall(arg_count, arg_count); - arg->Unuse(); - return RawCallStub(stub); -} - - -Result VirtualFrame::CallStub(CodeStub* stub, - Result* arg0, - Result* arg1, - int arg_count) { - PrepareForCall(arg_count, arg_count); - arg0->Unuse(); - arg1->Unuse(); - return RawCallStub(stub); -} - - void VirtualFrame::Push(Register reg) { if (is_used(reg)) { elements_.Add(CopyElementAt(register_index(reg)));