Port bug fixes to optimized Function.prototype.apply to ARM.

There were a couple of bug fixes to this code on IA32 which have not yet
been ported to ARM.  They are: failure to correctly handle non-JSObject
receivers and failure to restore the context register after calling JS code.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6744 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e3fd635f
...@@ -2488,29 +2488,33 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { ...@@ -2488,29 +2488,33 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
void LCodeGen::DoApplyArguments(LApplyArguments* instr) { void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
Register receiver = ToRegister(instr->receiver()); Register receiver = ToRegister(instr->receiver());
Register function = ToRegister(instr->function()); Register function = ToRegister(instr->function());
Register length = ToRegister(instr->length());
Register elements = ToRegister(instr->elements());
Register scratch = scratch0(); Register scratch = scratch0();
ASSERT(receiver.is(r0)); // Used for parameter count.
ASSERT(receiver.is(r0)); ASSERT(function.is(r1)); // Required by InvokeFunction.
ASSERT(function.is(r1));
ASSERT(ToRegister(instr->result()).is(r0)); ASSERT(ToRegister(instr->result()).is(r0));
// If the receiver is null or undefined, we have to pass the // If the receiver is null or undefined, we have to pass the global object
// global object as a receiver. // as a receiver.
Label global_receiver, receiver_ok; Label global_object, receiver_ok;
__ LoadRoot(scratch, Heap::kNullValueRootIndex); __ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ cmp(receiver, scratch); __ cmp(receiver, scratch);
__ b(eq, &global_receiver); __ b(eq, &global_object);
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ cmp(receiver, scratch); __ cmp(receiver, scratch);
__ b(ne, &receiver_ok); __ b(eq, &global_object);
__ bind(&global_receiver);
__ ldr(receiver, GlobalObjectOperand());
__ bind(&receiver_ok);
Register length = ToRegister(instr->length()); // Deoptimize if the receiver is not a JS object.
Register elements = ToRegister(instr->elements()); __ tst(receiver, Operand(kSmiTagMask));
DeoptimizeIf(eq, instr->environment());
__ CompareObjectType(receiver, scratch, scratch, FIRST_JS_OBJECT_TYPE);
DeoptimizeIf(lo, instr->environment());
__ jmp(&receiver_ok);
Label invoke; __ bind(&global_object);
__ ldr(receiver, GlobalObjectOperand());
__ bind(&receiver_ok);
// Copy the arguments to this function possibly from the // Copy the arguments to this function possibly from the
// adaptor frame below it. // adaptor frame below it.
...@@ -2527,7 +2531,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { ...@@ -2527,7 +2531,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// Loop through the arguments pushing them onto the execution // Loop through the arguments pushing them onto the execution
// stack. // stack.
Label loop; Label invoke, loop;
// length is a small non-negative integer, due to the test above. // length is a small non-negative integer, due to the test above.
__ tst(length, Operand(length)); __ tst(length, Operand(length));
__ b(eq, &invoke); __ b(eq, &invoke);
...@@ -2550,6 +2554,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { ...@@ -2550,6 +2554,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// by InvokeFunction. // by InvokeFunction.
v8::internal::ParameterCount actual(receiver); v8::internal::ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator); __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
} }
......
...@@ -2161,28 +2161,30 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { ...@@ -2161,28 +2161,30 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
void LCodeGen::DoApplyArguments(LApplyArguments* instr) { void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
Register receiver = ToRegister(instr->receiver()); Register receiver = ToRegister(instr->receiver());
Register function = ToRegister(instr->function());
Register length = ToRegister(instr->length()); Register length = ToRegister(instr->length());
Register elements = ToRegister(instr->elements()); Register elements = ToRegister(instr->elements());
Register temp = ToRegister(instr->TempAt(0)); Register scratch = ToRegister(instr->TempAt(0));
ASSERT(ToRegister(instr->function()).is(edi)); ASSERT(receiver.is(eax)); // Used for parameter count.
ASSERT(function.is(edi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(eax)); ASSERT(ToRegister(instr->result()).is(eax));
// If the receiver is null or undefined, we have to pass the // If the receiver is null or undefined, we have to pass the global object
// global object as a receiver. // as a receiver.
NearLabel global_receiver, receiver_ok; NearLabel global_object, receiver_ok;
__ cmp(receiver, Factory::null_value()); __ cmp(receiver, Factory::null_value());
__ j(equal, &global_receiver); __ j(equal, &global_object);
__ cmp(receiver, Factory::undefined_value()); __ cmp(receiver, Factory::undefined_value());
__ j(equal, &global_receiver); __ j(equal, &global_object);
// The receiver should be a JS object. // The receiver should be a JS object.
__ test(receiver, Immediate(kSmiTagMask)); __ test(receiver, Immediate(kSmiTagMask));
DeoptimizeIf(equal, instr->environment()); DeoptimizeIf(equal, instr->environment());
__ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, temp); __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch);
DeoptimizeIf(below, instr->environment()); DeoptimizeIf(below, instr->environment());
__ jmp(&receiver_ok); __ jmp(&receiver_ok);
__ bind(&global_receiver); __ bind(&global_object);
// TODO(kmillikin): We have a hydrogen value for the global object. See // TODO(kmillikin): We have a hydrogen value for the global object. See
// if it's better to use it than to explicitly fetch it from the context // if it's better to use it than to explicitly fetch it from the context
// here. // here.
...@@ -2190,8 +2192,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { ...@@ -2190,8 +2192,6 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX)); __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
__ bind(&receiver_ok); __ bind(&receiver_ok);
Label invoke;
// Copy the arguments to this function possibly from the // Copy the arguments to this function possibly from the
// adaptor frame below it. // adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB; const uint32_t kArgumentsLimit = 1 * KB;
...@@ -2203,7 +2203,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { ...@@ -2203,7 +2203,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// Loop through the arguments pushing them onto the execution // Loop through the arguments pushing them onto the execution
// stack. // stack.
Label loop; NearLabel invoke, loop;
// length is a small non-negative integer, due to the test above. // length is a small non-negative integer, due to the test above.
__ test(length, Operand(length)); __ test(length, Operand(length));
__ j(zero, &invoke); __ j(zero, &invoke);
...@@ -2222,9 +2222,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) { ...@@ -2222,9 +2222,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
SafepointGenerator safepoint_generator(this, SafepointGenerator safepoint_generator(this,
pointers, pointers,
env->deoptimization_index()); env->deoptimization_index());
ASSERT(receiver.is(eax));
v8::internal::ParameterCount actual(eax); v8::internal::ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
} }
......
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