__ 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);
}
// 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);
}
}
+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
CodePatcher::CodePatcher(byte* address, int instructions)
: address_(address),
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);
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()));
}
} 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
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));
// 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));
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.
}
-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(
ExternalReference function,
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) {
// 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