Reviewers: Søren Gjesse,

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

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

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

Affected files:
  M src/arm/lithium-codegen-arm.cc
  M src/arm/macro-assembler-arm.h
  M src/arm/macro-assembler-arm.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 dd740c2c60c565aa99dc29e570c81dd6a33bf4b9..27c32eb6006821e1d0a37e62763cd95d9535776d 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1705,7 +1705,62 @@ 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(receiver);
+  __ mov(receiver, length);
+  __ add(elements, elements, Operand(4));
+
+  // 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);
+
+  // Invoke the function.
+  __ bind(&invoke);
+  v8::internal::ParameterCount actual(receiver);
+
+  SafepointGenerator safepoint_generator(this,
+                                         instr->pointer_map(),
+ Safepoint::kNoDeoptimizationIndex);
+  __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
 }


Index: src/arm/macro-assembler-arm.cc
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 6bb08198ae8f64a5335592b9a254cf8f07ceb4d3..d1b6f3696fcb9f64503093b68d8a439eecaddef1 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -675,7 +675,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;

@@ -731,6 +732,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);
@@ -743,12 +745,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);
@@ -782,7 +787,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));

@@ -799,7 +805,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);
 }


Index: src/arm/macro-assembler-arm.h
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index 36b0cee2951c17e9f1689e8f19d395c9e9a01c93..7b95d69154c0046d0c5aa64fdd7f8b00335ca629 100644
--- a/src/arm/macro-assembler-arm.h
+++ b/src/arm/macro-assembler-arm.h
@@ -33,6 +33,9 @@
 namespace v8 {
 namespace internal {

+// Forward declaration.
+class PostCallGenerator;
+
// ----------------------------------------------------------------------------
 // Static helper functions

@@ -281,7 +284,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,
@@ -293,7 +297,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,
@@ -742,7 +747,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);


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to