Revision: 6744
Author: [email protected]
Date: Fri Feb 11 03:24:38 2011
Log: 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
http://code.google.com/p/v8/source/detail?r=6744
Modified:
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Thu Feb 10
04:02:36 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Fri Feb 11
03:24:38 2011
@@ -2488,30 +2488,34 @@
void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
Register receiver = ToRegister(instr->receiver());
Register function = ToRegister(instr->function());
+ Register length = ToRegister(instr->length());
+ Register elements = ToRegister(instr->elements());
Register scratch = scratch0();
-
- ASSERT(receiver.is(r0));
- ASSERT(function.is(r1));
+ ASSERT(receiver.is(r0)); // Used for parameter count.
+ ASSERT(function.is(r1)); // Required by InvokeFunction.
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;
+ // If the receiver is null or undefined, we have to pass the global
object
+ // as a receiver.
+ Label global_object, receiver_ok;
__ LoadRoot(scratch, Heap::kNullValueRootIndex);
__ cmp(receiver, scratch);
- __ b(eq, &global_receiver);
+ __ b(eq, &global_object);
__ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
__ cmp(receiver, scratch);
- __ b(ne, &receiver_ok);
- __ bind(&global_receiver);
+ __ b(eq, &global_object);
+
+ // Deoptimize if the receiver is not a JS object.
+ __ tst(receiver, Operand(kSmiTagMask));
+ DeoptimizeIf(eq, instr->environment());
+ __ CompareObjectType(receiver, scratch, scratch, FIRST_JS_OBJECT_TYPE);
+ DeoptimizeIf(lo, instr->environment());
+ __ jmp(&receiver_ok);
+
+ __ bind(&global_object);
__ 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;
@@ -2527,7 +2531,7 @@
// Loop through the arguments pushing them onto the execution
// stack.
- Label loop;
+ Label invoke, loop;
// length is a small non-negative integer, due to the test above.
__ tst(length, Operand(length));
__ b(eq, &invoke);
@@ -2550,6 +2554,7 @@
// by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
+ __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Thu Feb 10
04:02:36 2011
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Fri Feb 11
03:24:38 2011
@@ -2161,28 +2161,30 @@
void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
Register receiver = ToRegister(instr->receiver());
+ Register function = ToRegister(instr->function());
Register length = ToRegister(instr->length());
Register elements = ToRegister(instr->elements());
- Register temp = ToRegister(instr->TempAt(0));
- ASSERT(ToRegister(instr->function()).is(edi));
+ Register scratch = ToRegister(instr->TempAt(0));
+ ASSERT(receiver.is(eax)); // Used for parameter count.
+ ASSERT(function.is(edi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(eax));
- // If the receiver is null or undefined, we have to pass the
- // global object as a receiver.
- NearLabel global_receiver, receiver_ok;
+ // If the receiver is null or undefined, we have to pass the global
object
+ // as a receiver.
+ NearLabel global_object, receiver_ok;
__ cmp(receiver, Factory::null_value());
- __ j(equal, &global_receiver);
+ __ j(equal, &global_object);
__ cmp(receiver, Factory::undefined_value());
- __ j(equal, &global_receiver);
+ __ j(equal, &global_object);
// The receiver should be a JS object.
__ test(receiver, Immediate(kSmiTagMask));
DeoptimizeIf(equal, instr->environment());
- __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, temp);
+ __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch);
DeoptimizeIf(below, instr->environment());
__ jmp(&receiver_ok);
- __ bind(&global_receiver);
+ __ bind(&global_object);
// 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
// here.
@@ -2190,8 +2192,6 @@
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
__ bind(&receiver_ok);
- Label invoke;
-
// Copy the arguments to this function possibly from the
// adaptor frame below it.
const uint32_t kArgumentsLimit = 1 * KB;
@@ -2203,7 +2203,7 @@
// Loop through the arguments pushing them onto the execution
// stack.
- Label loop;
+ NearLabel invoke, loop;
// length is a small non-negative integer, due to the test above.
__ test(length, Operand(length));
__ j(zero, &invoke);
@@ -2222,9 +2222,8 @@
SafepointGenerator safepoint_generator(this,
pointers,
env->deoptimization_index());
- ASSERT(receiver.is(eax));
v8::internal::ParameterCount actual(eax);
- __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator);
+ __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev