diff options
Diffstat (limited to 'deps/v8/src/arm/macro-assembler-arm.cc')
-rw-r--r-- | deps/v8/src/arm/macro-assembler-arm.cc | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 1131760db3..376c4fbe81 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -355,10 +355,19 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { // ip = sp + kPointerSize * #args; add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); - // Align the stack at this point. After this point we have 5 pushes, - // so in fact we have to unalign here! See also the assert on the - // alignment in AlignStack. - AlignStack(1); + // Prepare the stack to be aligned when calling into C. After this point there + // are 5 pushes before the call into C, so the stack needs to be aligned after + // 5 pushes. + int frame_alignment = ActivationFrameAlignment(); + int frame_alignment_mask = frame_alignment - 1; + if (frame_alignment != kPointerSize) { + // The following code needs to be more general if this assert does not hold. + ASSERT(frame_alignment == 2 * kPointerSize); + // With 5 pushes left the frame must be unaligned at this point. + mov(r7, Operand(Smi::FromInt(0))); + tst(sp, Operand((frame_alignment - kPointerSize) & frame_alignment_mask)); + push(r7, eq); // Push if aligned to make it unaligned. + } // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); @@ -389,27 +398,20 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) { } -void MacroAssembler::AlignStack(int offset) { +int MacroAssembler::ActivationFrameAlignment() { #if defined(V8_HOST_ARCH_ARM) // Running on the real platform. Use the alignment as mandated by the local // environment. // Note: This will break if we ever start generating snapshots on one ARM // platform for another ARM platform with a different alignment. - int activation_frame_alignment = OS::ActivationFrameAlignment(); + return OS::ActivationFrameAlignment(); #else // defined(V8_HOST_ARCH_ARM) // If we are using the simulator then we should always align to the expected // alignment. As the simulator is used to generate snapshots we do not know - // if the target platform will need alignment, so we will always align at - // this point here. - int activation_frame_alignment = 2 * kPointerSize; + // if the target platform will need alignment, so this is controlled from a + // flag. + return FLAG_sim_stack_alignment; #endif // defined(V8_HOST_ARCH_ARM) - if (activation_frame_alignment != kPointerSize) { - // This code needs to be made more general if this assert doesn't hold. - ASSERT(activation_frame_alignment == 2 * kPointerSize); - mov(r7, Operand(Smi::FromInt(0))); - tst(sp, Operand(activation_frame_alignment - offset)); - push(r7, eq); // Conditional push instruction. - } } @@ -1309,15 +1311,29 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { + ASSERT(!target.is(r1)); + + // Load the builtins object into target register. + ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); + ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset)); + // Load the JavaScript builtin function from the builtins object. - ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); - ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); - int builtins_offset = - JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); - ldr(r1, FieldMemOperand(r1, builtins_offset)); - // Load the code entry point from the function into the target register. - ldr(target, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); - ldr(target, FieldMemOperand(target, SharedFunctionInfo::kCodeOffset)); + ldr(r1, FieldMemOperand(target, + JSBuiltinsObject::OffsetOfFunctionWithId(id))); + + // Load the code entry point from the builtins object. + ldr(target, FieldMemOperand(target, + JSBuiltinsObject::OffsetOfCodeWithId(id))); + if (FLAG_debug_code) { + // Make sure the code objects in the builtins object and in the + // builtin function are the same. + push(r1); + ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); + ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset)); + cmp(r1, target); + Assert(eq, "Builtin code object changed"); + pop(r1); + } add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); } @@ -1558,16 +1574,16 @@ void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(Register type, void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { - int frameAlignment = OS::ActivationFrameAlignment(); + int frame_alignment = 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) { + if (frame_alignment > 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)); + ASSERT(IsPowerOf2(frame_alignment)); + and_(sp, sp, Operand(-frame_alignment)); str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); } else { sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); @@ -1583,6 +1599,26 @@ void MacroAssembler::CallCFunction(ExternalReference function, void MacroAssembler::CallCFunction(Register function, int num_arguments) { + // Make sure that the stack is aligned before calling a C function unless + // running in the simulator. The simulator has its own alignment check which + // provides more information. +#if defined(V8_HOST_ARCH_ARM) + if (FLAG_debug_code) { + int frame_alignment = OS::ActivationFrameAlignment(); + int frame_alignment_mask = frame_alignment - 1; + if (frame_alignment > kPointerSize) { + ASSERT(IsPowerOf2(frame_alignment)); + Label alignment_as_expected; + tst(sp, Operand(frame_alignment_mask)); + b(eq, &alignment_as_expected); + // Don't use Check here, as it will call Runtime_Abort possibly + // re-entering here. + stop("Unexpected alignment"); + bind(&alignment_as_expected); + } + } +#endif + // Just call directly. The function called cannot cause a GC, or // allow preemption, so the return address in the link register // stays correct. |