Reviewers: fschneider,

Description:
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.

Please review this at http://codereview.chromium.org/6479019/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/arm/lithium-codegen-arm.cc
  M src/ia32/lithium-codegen-ia32.cc


Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index a027629e5e2552207302a7ef0a811d14762b1aff..ca11d644cc5c59eb72b53d5e22ca8c795d91f9c2 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -2488,29 +2488,33 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
 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);
-  __ ldr(receiver, GlobalObjectOperand());
-  __ bind(&receiver_ok);
+  __ b(eq, &global_object);

-  Register length = ToRegister(instr->length());
-  Register elements = ToRegister(instr->elements());
+  // 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);

-  Label invoke;
+  __ bind(&global_object);
+  __ ldr(receiver, GlobalObjectOperand());
+  __ bind(&receiver_ok);

   // Copy the arguments to this function possibly from the
   // adaptor frame below it.
@@ -2527,7 +2531,7 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {

   // 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 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   // by InvokeFunction.
   v8::internal::ParameterCount actual(receiver);
   __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
+  __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
 }


Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index b21eec83d2bafd378a56d667d47355957d32e46d..46f60cd7f7f4d750e0ba8a740c5f3447ffd725a1 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2161,28 +2161,30 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {

 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 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   __ 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 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {

   // 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.
   __ test(length, Operand(length));
   __ j(zero, &invoke);
@@ -2222,9 +2222,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
   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

Reply via email to