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
This commit is contained in:
kmillikin@chromium.org 2009-03-27 10:29:37 +00:00
parent 6feb0d9a8f
commit b8af68b03f
7 changed files with 102 additions and 83 deletions

View File

@ -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();
}

View File

@ -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<Expression*>* args) {
void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* 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>(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<Expression*>* args) {
void CodeGenerator::GenerateArgumentsAccess(ZoneList<Expression*>* 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>(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, &parameters_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);
}

View File

@ -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());

View File

@ -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<Code> ic,
RelocInfo::Mode rmode,
int dropped_args);

View File

@ -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());

View File

@ -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);

View File

@ -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)));