Implement DoApplyArguments.

ARM: Implement DoApplyArguments in the lithium code generator.

This patch also introduces an optional SafepointGenerator argument to InvokeFunction, InvokeCode and InvokeProloque.

BUG=
TEST=

Review URL: http://codereview.chromium.org/6164003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6272 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
karlklose@chromium.org 2011-01-11 14:11:03 +00:00
parent 59c158e43f
commit 43b0399505
3 changed files with 76 additions and 10 deletions

View File

@ -1804,7 +1804,65 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
Abort("DoApplyArguments unimplemented.");
Register receiver = ToRegister(instr->receiver());
Register function = ToRegister(instr->function());
Register scratch = scratch0();
ASSERT(receiver.is(r0));
ASSERT(function.is(r1));
ASSERT(ToRegister(instr->result()).is(r0));
// If the receiver is null or undefined, we have to pass the
// global object as a receiver.
Label global_receiver, receiver_ok;
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ cmp(receiver, scratch);
__ b(eq, &global_receiver);
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ cmp(receiver, scratch);
__ b(ne, &receiver_ok);
__ bind(&global_receiver);
__ ldr(receiver, GlobalObjectOperand());
__ bind(&receiver_ok);
Register length = ToRegister(instr->length());
Register elements = ToRegister(instr->elements());
Label invoke;
// Copy the arguments to this function possibly from the
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
__ cmp(length, Operand(kArgumentsLimit));
DeoptimizeIf(hi, instr->environment());
// Push the receiver and use the register to keep the original
// number of arguments.
__ push(receiver);
__ mov(receiver, length);
// The arguments are at a one pointer size offset from elements.
__ add(elements, elements, Operand(1 * kPointerSize));
// Loop through the arguments pushing them onto the execution
// stack.
Label loop;
// length is a small non-negative integer, due to the test above.
__ tst(length, Operand(length));
__ b(eq, &invoke);
__ bind(&loop);
__ ldr(scratch, MemOperand(elements, length, LSL, 2));
__ push(scratch);
__ sub(length, length, Operand(1), SetCC);
__ b(ne, &loop);
__ bind(&invoke);
// Invoke the function. The number of arguments is stored in receiver
// which is r0, as expected by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
SafepointGenerator safepoint_generator(this,
instr->pointer_map(),
Safepoint::kNoDeoptimizationIndex);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}

View File

@ -726,7 +726,8 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code> code_constant,
Register code_reg,
Label* done,
InvokeFlag flag) {
InvokeFlag flag,
PostCallGenerator* post_call_generator) {
bool definitely_matches = false;
Label regular_invoke;
@ -782,6 +783,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
if (flag == CALL_FUNCTION) {
Call(adaptor, RelocInfo::CODE_TARGET);
if (post_call_generator != NULL) post_call_generator->Generate();
b(done);
} else {
Jump(adaptor, RelocInfo::CODE_TARGET);
@ -794,12 +796,15 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
void MacroAssembler::InvokeCode(Register code,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag) {
InvokeFlag flag,
PostCallGenerator* post_call_generator) {
Label done;
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag,
post_call_generator);
if (flag == CALL_FUNCTION) {
Call(code);
if (post_call_generator != NULL) post_call_generator->Generate();
} else {
ASSERT(flag == JUMP_FUNCTION);
Jump(code);
@ -833,7 +838,8 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
void MacroAssembler::InvokeFunction(Register fun,
const ParameterCount& actual,
InvokeFlag flag) {
InvokeFlag flag,
PostCallGenerator* post_call_generator) {
// Contract with called JS functions requires that function is passed in r1.
ASSERT(fun.is(r1));
@ -850,7 +856,7 @@ void MacroAssembler::InvokeFunction(Register fun,
FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
ParameterCount expected(expected_reg);
InvokeCode(code_reg, expected, actual, flag);
InvokeCode(code_reg, expected, actual, flag, post_call_generator);
}

View File

@ -36,7 +36,6 @@ namespace internal {
// Forward declaration.
class PostCallGenerator;
// ----------------------------------------------------------------------------
// Static helper functions
@ -309,7 +308,8 @@ class MacroAssembler: public Assembler {
void InvokeCode(Register code,
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag);
InvokeFlag flag,
PostCallGenerator* post_call_generator = NULL);
void InvokeCode(Handle<Code> code,
const ParameterCount& expected,
@ -321,7 +321,8 @@ class MacroAssembler: public Assembler {
// current context to the context in the function before invoking.
void InvokeFunction(Register function,
const ParameterCount& actual,
InvokeFlag flag);
InvokeFlag flag,
PostCallGenerator* post_call_generator = NULL);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
@ -772,7 +773,8 @@ class MacroAssembler: public Assembler {
Handle<Code> code_constant,
Register code_reg,
Label* done,
InvokeFlag flag);
InvokeFlag flag,
PostCallGenerator* post_call_generator = NULL);
// Activation support.
void EnterFrame(StackFrame::Type type);