OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); | 348 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); |
349 sub(r6, r6, Operand(kPointerSize)); | 349 sub(r6, r6, Operand(kPointerSize)); |
350 | 350 |
351 // Compute callee's stack pointer before making changes and save it as | 351 // Compute callee's stack pointer before making changes and save it as |
352 // ip register so that it is restored as sp register on exit, thereby | 352 // ip register so that it is restored as sp register on exit, thereby |
353 // popping the args. | 353 // popping the args. |
354 | 354 |
355 // ip = sp + kPointerSize * #args; | 355 // ip = sp + kPointerSize * #args; |
356 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); | 356 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); |
357 | 357 |
358 // Align the stack at this point. After this point we have 5 pushes, | 358 // Prepare the stack to be aligned when calling into C. After this point there |
359 // so in fact we have to unalign here! See also the assert on the | 359 // are 5 pushes before the call into C, so the stack needs to be aligned after |
360 // alignment in AlignStack. | 360 // 5 pushes. |
361 AlignStack(1); | 361 int frame_alignment = ActivationFrameAlignment(); |
| 362 int frame_alignment_mask = frame_alignment - 1; |
| 363 if (frame_alignment != kPointerSize) { |
| 364 // The following code needs to be more general if this assert does not hold. |
| 365 ASSERT(frame_alignment == 2 * kPointerSize); |
| 366 // With 5 pushes left the frame must be unaligned at this point. |
| 367 mov(r7, Operand(Smi::FromInt(0))); |
| 368 tst(sp, Operand((frame_alignment - kPointerSize) & frame_alignment_mask)); |
| 369 push(r7, eq); // Push if aligned to make it unaligned. |
| 370 } |
362 | 371 |
363 // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. | 372 // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. |
364 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); | 373 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); |
365 mov(fp, Operand(sp)); // Setup new frame pointer. | 374 mov(fp, Operand(sp)); // Setup new frame pointer. |
366 | 375 |
367 mov(ip, Operand(CodeObject())); | 376 mov(ip, Operand(CodeObject())); |
368 push(ip); // Accessed from ExitFrame::code_slot. | 377 push(ip); // Accessed from ExitFrame::code_slot. |
369 | 378 |
370 // Save the frame pointer and the context in top. | 379 // Save the frame pointer and the context in top. |
371 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 380 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
(...skipping 10 matching lines...) Expand all Loading... |
382 // Save the state of all registers to the stack from the memory | 391 // Save the state of all registers to the stack from the memory |
383 // location. This is needed to allow nested break points. | 392 // location. This is needed to allow nested break points. |
384 if (mode == ExitFrame::MODE_DEBUG) { | 393 if (mode == ExitFrame::MODE_DEBUG) { |
385 // Use sp as base to push. | 394 // Use sp as base to push. |
386 CopyRegistersFromMemoryToStack(sp, kJSCallerSaved); | 395 CopyRegistersFromMemoryToStack(sp, kJSCallerSaved); |
387 } | 396 } |
388 #endif | 397 #endif |
389 } | 398 } |
390 | 399 |
391 | 400 |
392 void MacroAssembler::AlignStack(int offset) { | 401 int MacroAssembler::ActivationFrameAlignment() { |
393 #if defined(V8_HOST_ARCH_ARM) | 402 #if defined(V8_HOST_ARCH_ARM) |
394 // Running on the real platform. Use the alignment as mandated by the local | 403 // Running on the real platform. Use the alignment as mandated by the local |
395 // environment. | 404 // environment. |
396 // Note: This will break if we ever start generating snapshots on one ARM | 405 // Note: This will break if we ever start generating snapshots on one ARM |
397 // platform for another ARM platform with a different alignment. | 406 // platform for another ARM platform with a different alignment. |
398 int activation_frame_alignment = OS::ActivationFrameAlignment(); | 407 return OS::ActivationFrameAlignment(); |
399 #else // defined(V8_HOST_ARCH_ARM) | 408 #else // defined(V8_HOST_ARCH_ARM) |
400 // If we are using the simulator then we should always align to the expected | 409 // If we are using the simulator then we should always align to the expected |
401 // alignment. As the simulator is used to generate snapshots we do not know | 410 // alignment. As the simulator is used to generate snapshots we do not know |
402 // if the target platform will need alignment, so we will always align at | 411 // if the target platform will need alignment, so this is controlled from a |
403 // this point here. | 412 // flag. |
404 int activation_frame_alignment = 2 * kPointerSize; | 413 return FLAG_sim_stack_alignment; |
405 #endif // defined(V8_HOST_ARCH_ARM) | 414 #endif // defined(V8_HOST_ARCH_ARM) |
406 if (activation_frame_alignment != kPointerSize) { | |
407 // This code needs to be made more general if this assert doesn't hold. | |
408 ASSERT(activation_frame_alignment == 2 * kPointerSize); | |
409 mov(r7, Operand(Smi::FromInt(0))); | |
410 tst(sp, Operand(activation_frame_alignment - offset)); | |
411 push(r7, eq); // Conditional push instruction. | |
412 } | |
413 } | 415 } |
414 | 416 |
415 | 417 |
416 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) { | 418 void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) { |
417 #ifdef ENABLE_DEBUGGER_SUPPORT | 419 #ifdef ENABLE_DEBUGGER_SUPPORT |
418 // Restore the memory copy of the registers by digging them out from | 420 // Restore the memory copy of the registers by digging them out from |
419 // the stack. This is needed to allow nested break points. | 421 // the stack. This is needed to allow nested break points. |
420 if (mode == ExitFrame::MODE_DEBUG) { | 422 if (mode == ExitFrame::MODE_DEBUG) { |
421 // This code intentionally clobbers r2 and r3. | 423 // This code intentionally clobbers r2 and r3. |
422 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; | 424 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; |
(...skipping 1142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1565 int kFlatAsciiStringMask = | 1567 int kFlatAsciiStringMask = |
1566 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; | 1568 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask; |
1567 int kFlatAsciiStringTag = ASCII_STRING_TYPE; | 1569 int kFlatAsciiStringTag = ASCII_STRING_TYPE; |
1568 and_(scratch, type, Operand(kFlatAsciiStringMask)); | 1570 and_(scratch, type, Operand(kFlatAsciiStringMask)); |
1569 cmp(scratch, Operand(kFlatAsciiStringTag)); | 1571 cmp(scratch, Operand(kFlatAsciiStringTag)); |
1570 b(ne, failure); | 1572 b(ne, failure); |
1571 } | 1573 } |
1572 | 1574 |
1573 | 1575 |
1574 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { | 1576 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { |
1575 int frameAlignment = OS::ActivationFrameAlignment(); | 1577 int frame_alignment = ActivationFrameAlignment(); |
1576 // Up to four simple arguments are passed in registers r0..r3. | 1578 // Up to four simple arguments are passed in registers r0..r3. |
1577 int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4; | 1579 int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4; |
1578 if (frameAlignment > kPointerSize) { | 1580 if (frame_alignment > kPointerSize) { |
1579 // Make stack end at alignment and make room for num_arguments - 4 words | 1581 // Make stack end at alignment and make room for num_arguments - 4 words |
1580 // and the original value of sp. | 1582 // and the original value of sp. |
1581 mov(scratch, sp); | 1583 mov(scratch, sp); |
1582 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); | 1584 sub(sp, sp, Operand((stack_passed_arguments + 1) * kPointerSize)); |
1583 ASSERT(IsPowerOf2(frameAlignment)); | 1585 ASSERT(IsPowerOf2(frame_alignment)); |
1584 and_(sp, sp, Operand(-frameAlignment)); | 1586 and_(sp, sp, Operand(-frame_alignment)); |
1585 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 1587 str(scratch, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
1586 } else { | 1588 } else { |
1587 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); | 1589 sub(sp, sp, Operand(stack_passed_arguments * kPointerSize)); |
1588 } | 1590 } |
1589 } | 1591 } |
1590 | 1592 |
1591 | 1593 |
1592 void MacroAssembler::CallCFunction(ExternalReference function, | 1594 void MacroAssembler::CallCFunction(ExternalReference function, |
1593 int num_arguments) { | 1595 int num_arguments) { |
1594 mov(ip, Operand(function)); | 1596 mov(ip, Operand(function)); |
1595 CallCFunction(ip, num_arguments); | 1597 CallCFunction(ip, num_arguments); |
1596 } | 1598 } |
1597 | 1599 |
1598 | 1600 |
1599 void MacroAssembler::CallCFunction(Register function, int num_arguments) { | 1601 void MacroAssembler::CallCFunction(Register function, int num_arguments) { |
| 1602 // Make sure that the stack is aligned before calling a C function unless |
| 1603 // running in the simulator. The simulator has its own alignment check which |
| 1604 // provides more information. |
| 1605 #if defined(V8_HOST_ARCH_ARM) |
| 1606 if (FLAG_debug_code) { |
| 1607 int frame_alignment = OS::ActivationFrameAlignment(); |
| 1608 int frame_alignment_mask = frame_alignment - 1; |
| 1609 if (frame_alignment > kPointerSize) { |
| 1610 ASSERT(IsPowerOf2(frame_alignment)); |
| 1611 Label alignment_as_expected; |
| 1612 tst(sp, Operand(frame_alignment_mask)); |
| 1613 b(eq, &alignment_as_expected); |
| 1614 // Don't use Check here, as it will call Runtime_Abort possibly |
| 1615 // re-entering here. |
| 1616 stop("Unexpected alignment"); |
| 1617 bind(&alignment_as_expected); |
| 1618 } |
| 1619 } |
| 1620 #endif |
| 1621 |
1600 // Just call directly. The function called cannot cause a GC, or | 1622 // Just call directly. The function called cannot cause a GC, or |
1601 // allow preemption, so the return address in the link register | 1623 // allow preemption, so the return address in the link register |
1602 // stays correct. | 1624 // stays correct. |
1603 Call(function); | 1625 Call(function); |
1604 int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4; | 1626 int stack_passed_arguments = (num_arguments <= 4) ? 0 : num_arguments - 4; |
1605 if (OS::ActivationFrameAlignment() > kPointerSize) { | 1627 if (OS::ActivationFrameAlignment() > kPointerSize) { |
1606 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); | 1628 ldr(sp, MemOperand(sp, stack_passed_arguments * kPointerSize)); |
1607 } else { | 1629 } else { |
1608 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); | 1630 add(sp, sp, Operand(stack_passed_arguments * sizeof(kPointerSize))); |
1609 } | 1631 } |
(...skipping 28 matching lines...) Expand all Loading... |
1638 } | 1660 } |
1639 | 1661 |
1640 | 1662 |
1641 void CodePatcher::Emit(Address addr) { | 1663 void CodePatcher::Emit(Address addr) { |
1642 masm()->emit(reinterpret_cast<Instr>(addr)); | 1664 masm()->emit(reinterpret_cast<Instr>(addr)); |
1643 } | 1665 } |
1644 #endif // ENABLE_DEBUGGER_SUPPORT | 1666 #endif // ENABLE_DEBUGGER_SUPPORT |
1645 | 1667 |
1646 | 1668 |
1647 } } // namespace v8::internal | 1669 } } // namespace v8::internal |
OLD | NEW |