Revision: 4374
Author: [email protected]
Date: Fri Apr  9 04:25:52 2010
Log: Call to C function support in macro assembler

Implement macro assembler operations PrepareCallCFunction and CallCFunction like on both Intel platforms. Used these for direct calls to C functions.
Review URL: http://codereview.chromium.org/1549031
http://code.google.com/p/v8/source/detail?r=4374

Modified:
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.h

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Thu Apr  8 15:30:30 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Apr  9 04:25:52 2010
@@ -3956,8 +3956,9 @@
   __ CallRuntime(Runtime::kNumberUnaryMinus, 1);

   __ bind(&heapnumber_allocated);
- __ Call(ExternalReference::fill_heap_number_with_random_function().address(),
-          RelocInfo::RUNTIME_ENTRY);
+  __ PrepareCallCFunction(1, r1);
+  __ CallCFunction(
+      ExternalReference::fill_heap_number_with_random_function(), 1);
   frame_->EmitPush(r0);
 }

@@ -5958,28 +5959,23 @@
       // r5: Address of heap number for result.

       __ push(lr);   // For later.
-      __ push(r5);   // Address of heap number that is answer.
-      __ AlignStack(0);
-      // Call C routine that may not cause GC or other trouble.
-      __ mov(r5, Operand(ExternalReference::double_fp_operation(op_)));
-      __ Call(r5);
-      __ pop(r4);  // Address of heap number.
-      __ cmp(r4, Operand(Smi::FromInt(0)));
-      __ pop(r4, eq);  // Conditional pop instruction
-                       // to get rid of alignment push.
+      __ PrepareCallCFunction(4, r4);  // Two doubles count as 4 arguments.
+ // Call C routine that may not cause GC or other trouble. r5 is callee
+      // save.
+      __ CallCFunction(ExternalReference::double_fp_operation(op_), 4);
       // Store answer in the overwritable heap number.
   #if !defined(USE_ARM_EABI)
// Double returned in fp coprocessor register 0 and 1, encoded as register
       // cr8.  Offsets must be divisible by 4 for coprocessor so we need to
-      // substract the tag from r4.
-      __ sub(r5, r4, Operand(kHeapObjectTag));
-      __ stc(p1, cr8, MemOperand(r5, HeapNumber::kValueOffset));
+      // substract the tag from r5.
+      __ sub(r4, r5, Operand(kHeapObjectTag));
+      __ stc(p1, cr8, MemOperand(r4, HeapNumber::kValueOffset));
   #else
       // Double returned in registers 0 and 1.
-      __ str(r0, FieldMemOperand(r4, HeapNumber::kValueOffset));
-      __ str(r1, FieldMemOperand(r4, HeapNumber::kValueOffset + 4));
+      __ str(r0, FieldMemOperand(r5, HeapNumber::kValueOffset));
+      __ str(r1, FieldMemOperand(r5, HeapNumber::kValueOffset + 4));
   #endif
-      __ mov(r0, Operand(r4));
+      __ mov(r0, Operand(r5));
       // And we are done.
       __ pop(pc);
     }
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Apr 8 15:30:30 2010 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Apr 9 04:25:52 2010
@@ -1555,6 +1555,45 @@
   cmp(scratch, Operand(kFlatAsciiStringTag));
   b(ne, failure);
 }
+
+
+void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
+  int frameAlignment = OS::ActivationFrameAlignment();
+  // Up to four simple arguments are passed in registers r0..r3.
+ int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
+  if (frameAlignment > kPointerSize) {
+ // Make stack end at alignment and make room for num_arguments - 4 words
+    // and the original value of sp.
+    mov(scratch, sp);
+    sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
+    ASSERT(IsPowerOf2(frameAlignment));
+    and_(sp, sp, Operand(-frameAlignment));
+    str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  } else {
+    sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::CallCFunction(ExternalReference function,
+                                   int num_arguments) {
+  mov(ip, Operand(function));
+  CallCFunction(ip, num_arguments);
+}
+
+
+void MacroAssembler::CallCFunction(Register function, int num_arguments) {
+  // Just call directly. The function called cannot cause a GC, or
+  // allow preemption, so the return address in the link register
+  // stays correct.
+  Call(function);
+ int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
+  if (OS::ActivationFrameAlignment() > kPointerSize) {
+    ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
+  } else {
+    add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
+  }
+}


 #ifdef ENABLE_DEBUGGER_SUPPORT
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Apr 8 15:30:30 2010 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Fri Apr 9 04:25:52 2010
@@ -373,6 +373,24 @@
                        int num_arguments,
                        int result_size);

+ // Before calling a C-function from generated code, align arguments on stack.
+  // After aligning the frame, non-register arguments must be stored in
+ // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
+  // are word sized.
+  // Some compilers/platforms require the stack to be aligned when calling
+  // C++ code.
+  // Needs a scratch register to do some arithmetic. This register will be
+  // trashed.
+  void PrepareCallCFunction(int num_arguments, Register scratch);
+
+  // Calls a C function and cleans up the space for arguments allocated
+ // by PrepareCallCFunction. The called function is not allowed to trigger a
+  // garbage collection, since that might move the code and invalidate the
+  // return address (unless this is somehow accounted for by the called
+  // function).
+  void CallCFunction(ExternalReference function, int num_arguments);
+  void CallCFunction(Register function, int num_arguments);
+
   // Jump to a runtime routine.
   void JumpToExternalReference(const ExternalReference& builtin);

=======================================
--- /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Tue Apr 6 03:36:38 2010 +++ /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.cc Fri Apr 9 04:25:52 2010
@@ -163,7 +163,7 @@
   CheckPreemption();
   // Pop Code* offset from backtrack stack, add Code* and jump to location.
   Pop(r0);
-  __ add(pc, r0, Operand(r5));
+  __ add(pc, r0, Operand(code_pointer()));
 }


@@ -338,7 +338,7 @@
   } else {
     ASSERT(mode_ == UC16);
     int argument_count = 3;
-    FrameAlign(argument_count, r2);
+    __ PrepareCallCFunction(argument_count, r2);

     // r0 - offset of start of capture
     // r1 - length of capture
@@ -360,7 +360,7 @@

     ExternalReference function =
         ExternalReference::re_case_insensitive_compare_uc16();
-    CallCFunction(function, argument_count);
+    __ CallCFunction(function, argument_count);

     // Check if function returned non-zero for success or zero for failure.
     __ cmp(r0, Operand(0));
@@ -770,12 +770,12 @@

     // Call GrowStack(backtrack_stackpointer())
     static const int num_arguments = 2;
-    FrameAlign(num_arguments, r0);
+    __ PrepareCallCFunction(num_arguments, r0);
     __ mov(r0, backtrack_stackpointer());
     __ add(r1, frame_pointer(), Operand(kStackHighEnd));
     ExternalReference grow_stack =
       ExternalReference::re_grow_stack();
-    CallCFunction(grow_stack, num_arguments);
+    __ CallCFunction(grow_stack, num_arguments);
     // If return NULL, we have failed to grow the stack, and
     // must exit with a stack-overflow exception.
     __ cmp(r0, Operand(0));
@@ -971,7 +971,7 @@

 void RegExpMacroAssemblerARM::CallCheckStackGuardState(Register scratch) {
   static const int num_arguments = 3;
-  FrameAlign(num_arguments, scratch);
+  __ PrepareCallCFunction(num_arguments, scratch);
   // RegExp code frame pointer.
   __ mov(r2, frame_pointer());
   // Code* of self.
@@ -1181,41 +1181,6 @@
   backtrack_constant_pool_capacity_--;
   return offset;
 }
-
-
-void RegExpMacroAssemblerARM::FrameAlign(int num_arguments, Register scratch) {
-  int frameAlignment = OS::ActivationFrameAlignment();
-  // Up to four simple arguments are passed in registers r0..r3.
- int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
-  if (frameAlignment != 0) {
- // Make stack end at alignment and make room for num_arguments - 4 words
-    // and the original value of sp.
-    __ mov(scratch, sp);
-    __ sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize));
-    ASSERT(IsPowerOf2(frameAlignment));
-    __ and_(sp, sp, Operand(-frameAlignment));
-    __ str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize));
-  } else {
-    __ sub(sp, sp, Operand(stack_passed_arguments * kPointerSize));
-  }
-}
-
-
-void RegExpMacroAssemblerARM::CallCFunction(ExternalReference function,
-                                            int num_arguments) {
-  __ mov(r5, Operand(function));
-  // Just call directly. The function called cannot cause a GC, or
-  // allow preemption, so the return address in the link register
-  // stays correct.
-  __ Call(r5);
- int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4;
-  if (OS::ActivationFrameAlignment() > kIntSize) {
-    __ ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize));
-  } else {
-    __ add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize)));
-  }
-  __ mov(code_pointer(), Operand(masm_->CodeObject()));
-}


 void RegExpMacroAssemblerARM::CallCFunctionUsingStub(
@@ -1223,7 +1188,7 @@
     int num_arguments) {
   // Must pass all arguments in registers. The stub pushes on the stack.
   ASSERT(num_arguments <= 4);
-  __ mov(r5, Operand(function));
+  __ mov(code_pointer(), Operand(function));
   RegExpCEntryStub stub;
   __ CallStub(&stub);
   if (OS::ActivationFrameAlignment() != 0) {
=======================================
--- /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.h Tue Jan 26 03:08:42 2010 +++ /branches/bleeding_edge/src/arm/regexp-macro-assembler-arm.h Fri Apr 9 04:25:52 2010
@@ -206,22 +206,6 @@
   // and increments it by a word size.
   inline void Pop(Register target);

- // Before calling a C-function from generated code, align arguments on stack.
-  // After aligning the frame, non-register arguments must be stored in
- // sp[0], sp[4], etc., not pushed. The argument count assumes all arguments
-  // are word sized.
-  // Some compilers/platforms require the stack to be aligned when calling
-  // C++ code.
-  // Needs a scratch register to do some arithmetic. This register will be
-  // trashed.
-  inline void FrameAlign(int num_arguments, Register scratch);
-
-  // Calls a C function and cleans up the space for arguments allocated
-  // by FrameAlign. The called function is not allowed to trigger a garbage
-  // collection.
-  inline void CallCFunction(ExternalReference function,
-                            int num_arguments);
-
   // Calls a C function and cleans up the frame alignment done by
   // by FrameAlign. The called function *is* allowed to trigger a garbage
   // collection, but may not take more than four arguments (no arguments

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

To unsubscribe, reply using "remove me" as the subject.

Reply via email to