| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 164 | 164 |
| 165 void MacroAssembler::Ret(Condition cond) { | 165 void MacroAssembler::Ret(Condition cond) { |
| 166 #if USE_BX | 166 #if USE_BX |
| 167 bx(lr, cond); | 167 bx(lr, cond); |
| 168 #else | 168 #else |
| 169 mov(pc, Operand(lr), LeaveCC, cond); | 169 mov(pc, Operand(lr), LeaveCC, cond); |
| 170 #endif | 170 #endif |
| 171 } | 171 } |
| 172 | 172 |
| 173 | 173 |
| 174 void MacroAssembler::StackLimitCheck(Label* on_stack_overflow) { | |
| 175 LoadRoot(ip, Heap::kStackLimitRootIndex); | |
| 176 cmp(sp, Operand(ip)); | |
| 177 b(lo, on_stack_overflow); | |
| 178 } | |
| 179 | |
| 180 | |
| 181 void MacroAssembler::Drop(int count, Condition cond) { | 174 void MacroAssembler::Drop(int count, Condition cond) { |
| 182 if (count > 0) { | 175 if (count > 0) { |
| 183 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); | 176 add(sp, sp, Operand(count * kPointerSize), LeaveCC, cond); |
| 184 } | 177 } |
| 185 } | 178 } |
| 186 | 179 |
| 187 | 180 |
| 188 void MacroAssembler::Swap(Register reg1, | 181 void MacroAssembler::Swap(Register reg1, |
| 189 Register reg2, | 182 Register reg2, |
| 190 Register scratch, | 183 Register scratch, |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 // Clobber all input registers when running with the debug-code flag | 433 // Clobber all input registers when running with the debug-code flag |
| 441 // turned on to provoke errors. | 434 // turned on to provoke errors. |
| 442 if (FLAG_debug_code) { | 435 if (FLAG_debug_code) { |
| 443 mov(object, Operand(BitCast<int32_t>(kZapValue))); | 436 mov(object, Operand(BitCast<int32_t>(kZapValue))); |
| 444 mov(address, Operand(BitCast<int32_t>(kZapValue))); | 437 mov(address, Operand(BitCast<int32_t>(kZapValue))); |
| 445 mov(scratch, Operand(BitCast<int32_t>(kZapValue))); | 438 mov(scratch, Operand(BitCast<int32_t>(kZapValue))); |
| 446 } | 439 } |
| 447 } | 440 } |
| 448 | 441 |
| 449 | 442 |
| 443 // Push and pop all registers that can hold pointers. |
| 444 void MacroAssembler::PushSafepointRegisters() { |
| 445 // Safepoints expect a block of contiguous register values starting with r0: |
| 446 ASSERT(((1 << kNumSafepointSavedRegisters) - 1) == kSafepointSavedRegisters); |
| 447 // Safepoints expect a block of kNumSafepointRegisters values on the |
| 448 // stack, so adjust the stack for unsaved registers. |
| 449 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 450 ASSERT(num_unsaved >= 0); |
| 451 sub(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 452 stm(db_w, sp, kSafepointSavedRegisters); |
| 453 } |
| 454 |
| 455 |
| 456 void MacroAssembler::PopSafepointRegisters() { |
| 457 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 458 ldm(ia_w, sp, kSafepointSavedRegisters); |
| 459 add(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 460 } |
| 461 |
| 462 |
| 463 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { |
| 464 // The registers are pushed starting with the highest encoding, |
| 465 // which means that lowest encodings are closest to the stack pointer. |
| 466 ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); |
| 467 return reg_code; |
| 468 } |
| 469 |
| 470 |
| 450 void MacroAssembler::Ldrd(Register dst1, Register dst2, | 471 void MacroAssembler::Ldrd(Register dst1, Register dst2, |
| 451 const MemOperand& src, Condition cond) { | 472 const MemOperand& src, Condition cond) { |
| 452 ASSERT(src.rm().is(no_reg)); | 473 ASSERT(src.rm().is(no_reg)); |
| 453 ASSERT(!dst1.is(lr)); // r14. | 474 ASSERT(!dst1.is(lr)); // r14. |
| 454 ASSERT_EQ(0, dst1.code() % 2); | 475 ASSERT_EQ(0, dst1.code() % 2); |
| 455 ASSERT_EQ(dst1.code() + 1, dst2.code()); | 476 ASSERT_EQ(dst1.code() + 1, dst2.code()); |
| 456 | 477 |
| 457 // Generate two ldr instructions if ldrd is not available. | 478 // Generate two ldr instructions if ldrd is not available. |
| 458 if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) { | 479 if (Isolate::Current()->cpu_features()->IsSupported(ARMv7)) { |
| 459 CpuFeatures::Scope scope(ARMv7); | 480 CpuFeatures::Scope scope(ARMv7); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 // r1: preserved | 529 // r1: preserved |
| 509 // r2: preserved | 530 // r2: preserved |
| 510 | 531 |
| 511 // Drop the execution stack down to the frame pointer and restore | 532 // Drop the execution stack down to the frame pointer and restore |
| 512 // the caller frame pointer and return address. | 533 // the caller frame pointer and return address. |
| 513 mov(sp, fp); | 534 mov(sp, fp); |
| 514 ldm(ia_w, sp, fp.bit() | lr.bit()); | 535 ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 515 } | 536 } |
| 516 | 537 |
| 517 | 538 |
| 518 void MacroAssembler::EnterExitFrame() { | 539 void MacroAssembler::EnterExitFrame(bool save_doubles) { |
| 519 // Compute the argv pointer and keep it in a callee-saved register. | |
| 520 // r0 is argc. | 540 // r0 is argc. |
| 521 add(r6, sp, Operand(r0, LSL, kPointerSizeLog2)); | |
| 522 sub(r6, r6, Operand(kPointerSize)); | |
| 523 | |
| 524 // Compute callee's stack pointer before making changes and save it as | 541 // Compute callee's stack pointer before making changes and save it as |
| 525 // ip register so that it is restored as sp register on exit, thereby | 542 // ip register so that it is restored as sp register on exit, thereby |
| 526 // popping the args. | 543 // popping the args. |
| 527 | 544 |
| 528 // ip = sp + kPointerSize * #args; | 545 // ip = sp + kPointerSize * #args; |
| 529 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); | 546 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 530 | 547 |
| 548 // Compute the argv pointer and keep it in a callee-saved register. |
| 549 sub(r6, ip, Operand(kPointerSize)); |
| 550 |
| 531 // Prepare the stack to be aligned when calling into C. After this point there | 551 // Prepare the stack to be aligned when calling into C. After this point there |
| 532 // are 5 pushes before the call into C, so the stack needs to be aligned after | 552 // are 5 pushes before the call into C, so the stack needs to be aligned after |
| 533 // 5 pushes. | 553 // 5 pushes. |
| 534 int frame_alignment = ActivationFrameAlignment(); | 554 int frame_alignment = ActivationFrameAlignment(); |
| 535 int frame_alignment_mask = frame_alignment - 1; | 555 int frame_alignment_mask = frame_alignment - 1; |
| 536 if (frame_alignment != kPointerSize) { | 556 if (frame_alignment != kPointerSize) { |
| 537 // The following code needs to be more general if this assert does not hold. | 557 // The following code needs to be more general if this assert does not hold. |
| 538 ASSERT(frame_alignment == 2 * kPointerSize); | 558 ASSERT(frame_alignment == 2 * kPointerSize); |
| 539 // With 5 pushes left the frame must be unaligned at this point. | 559 // With 5 pushes left the frame must be unaligned at this point. |
| 540 mov(r7, Operand(Smi::FromInt(0))); | 560 mov(r7, Operand(Smi::FromInt(0))); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 551 | 571 |
| 552 // Save the frame pointer and the context in top. | 572 // Save the frame pointer and the context in top. |
| 553 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address))); | 573 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address))); |
| 554 str(fp, MemOperand(ip)); | 574 str(fp, MemOperand(ip)); |
| 555 mov(ip, Operand(ExternalReference(Isolate::k_context_address))); | 575 mov(ip, Operand(ExternalReference(Isolate::k_context_address))); |
| 556 str(cp, MemOperand(ip)); | 576 str(cp, MemOperand(ip)); |
| 557 | 577 |
| 558 // Setup argc and the builtin function in callee-saved registers. | 578 // Setup argc and the builtin function in callee-saved registers. |
| 559 mov(r4, Operand(r0)); | 579 mov(r4, Operand(r0)); |
| 560 mov(r5, Operand(r1)); | 580 mov(r5, Operand(r1)); |
| 581 |
| 582 // Optionally save all double registers. |
| 583 if (save_doubles) { |
| 584 // TODO(regis): Use vstrm instruction. |
| 585 // The stack alignment code above made sp unaligned, so add space for one |
| 586 // more double register and use aligned addresses. |
| 587 ASSERT(kDoubleSize == frame_alignment); |
| 588 // Mark the frame as containing doubles by pushing a non-valid return |
| 589 // address, i.e. 0. |
| 590 ASSERT(ExitFrameConstants::kMarkerOffset == -2 * kPointerSize); |
| 591 mov(ip, Operand(0)); // Marker and alignment word. |
| 592 push(ip); |
| 593 int space = DwVfpRegister::kNumRegisters * kDoubleSize + kPointerSize; |
| 594 sub(sp, sp, Operand(space)); |
| 595 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 596 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 597 vstr(reg, sp, i * kDoubleSize + kPointerSize); |
| 598 } |
| 599 // Note that d0 will be accessible at fp - 2*kPointerSize - |
| 600 // DwVfpRegister::kNumRegisters * kDoubleSize, since the code slot and the |
| 601 // alignment word were pushed after the fp. |
| 602 } |
| 561 } | 603 } |
| 562 | 604 |
| 563 | 605 |
| 564 void MacroAssembler::InitializeNewString(Register string, | 606 void MacroAssembler::InitializeNewString(Register string, |
| 565 Register length, | 607 Register length, |
| 566 Heap::RootListIndex map_index, | 608 Heap::RootListIndex map_index, |
| 567 Register scratch1, | 609 Register scratch1, |
| 568 Register scratch2) { | 610 Register scratch2) { |
| 569 mov(scratch1, Operand(length, LSL, kSmiTagSize)); | 611 mov(scratch1, Operand(length, LSL, kSmiTagSize)); |
| 570 LoadRoot(scratch2, map_index); | 612 LoadRoot(scratch2, map_index); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 585 #else // defined(V8_HOST_ARCH_ARM) | 627 #else // defined(V8_HOST_ARCH_ARM) |
| 586 // If we are using the simulator then we should always align to the expected | 628 // If we are using the simulator then we should always align to the expected |
| 587 // alignment. As the simulator is used to generate snapshots we do not know | 629 // alignment. As the simulator is used to generate snapshots we do not know |
| 588 // if the target platform will need alignment, so this is controlled from a | 630 // if the target platform will need alignment, so this is controlled from a |
| 589 // flag. | 631 // flag. |
| 590 return FLAG_sim_stack_alignment; | 632 return FLAG_sim_stack_alignment; |
| 591 #endif // defined(V8_HOST_ARCH_ARM) | 633 #endif // defined(V8_HOST_ARCH_ARM) |
| 592 } | 634 } |
| 593 | 635 |
| 594 | 636 |
| 595 void MacroAssembler::LeaveExitFrame() { | 637 void MacroAssembler::LeaveExitFrame(bool save_doubles) { |
| 638 // Optionally restore all double registers. |
| 639 if (save_doubles) { |
| 640 // TODO(regis): Use vldrm instruction. |
| 641 for (int i = 0; i < DwVfpRegister::kNumRegisters; i++) { |
| 642 DwVfpRegister reg = DwVfpRegister::from_code(i); |
| 643 // Register d15 is just below the marker. |
| 644 const int offset = ExitFrameConstants::kMarkerOffset; |
| 645 vldr(reg, fp, (i - DwVfpRegister::kNumRegisters) * kDoubleSize + offset); |
| 646 } |
| 647 } |
| 648 |
| 596 // Clear top frame. | 649 // Clear top frame. |
| 597 mov(r3, Operand(0, RelocInfo::NONE)); | 650 mov(r3, Operand(0, RelocInfo::NONE)); |
| 598 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address))); | 651 mov(ip, Operand(ExternalReference(Isolate::k_c_entry_fp_address))); |
| 599 str(r3, MemOperand(ip)); | 652 str(r3, MemOperand(ip)); |
| 600 | 653 |
| 601 // Restore current context from top and clear it in debug mode. | 654 // Restore current context from top and clear it in debug mode. |
| 602 mov(ip, Operand(ExternalReference(Isolate::k_context_address))); | 655 mov(ip, Operand(ExternalReference(Isolate::k_context_address))); |
| 603 ldr(cp, MemOperand(ip)); | 656 ldr(cp, MemOperand(ip)); |
| 604 #ifdef DEBUG | 657 #ifdef DEBUG |
| 605 str(r3, MemOperand(ip)); | 658 str(r3, MemOperand(ip)); |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 InvokeFlag flag) { | 803 InvokeFlag flag) { |
| 751 ASSERT(function->is_compiled()); | 804 ASSERT(function->is_compiled()); |
| 752 | 805 |
| 753 // Get the function and setup the context. | 806 // Get the function and setup the context. |
| 754 mov(r1, Operand(Handle<JSFunction>(function))); | 807 mov(r1, Operand(Handle<JSFunction>(function))); |
| 755 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 808 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 756 | 809 |
| 757 // Invoke the cached code. | 810 // Invoke the cached code. |
| 758 Handle<Code> code(function->code()); | 811 Handle<Code> code(function->code()); |
| 759 ParameterCount expected(function->shared()->formal_parameter_count()); | 812 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 760 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); | 813 if (V8::UseCrankshaft()) { |
| 814 // TODO(kasperl): For now, we always call indirectly through the |
| 815 // code field in the function to allow recompilation to take effect |
| 816 // without changing any of the call sites. |
| 817 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 818 InvokeCode(r3, expected, actual, flag); |
| 819 } else { |
| 820 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); |
| 821 } |
| 761 } | 822 } |
| 762 | 823 |
| 763 | 824 |
| 764 #ifdef ENABLE_DEBUGGER_SUPPORT | 825 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 765 void MacroAssembler::DebugBreak() { | 826 void MacroAssembler::DebugBreak() { |
| 766 ASSERT(allow_stub_calls()); | 827 ASSERT(allow_stub_calls()); |
| 767 mov(r0, Operand(0, RelocInfo::NONE)); | 828 mov(r0, Operand(0, RelocInfo::NONE)); |
| 768 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak))); | 829 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak))); |
| 769 CEntryStub ces(1); | 830 CEntryStub ces(1); |
| 770 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); | 831 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 CEntryStub stub(1); | 1570 CEntryStub stub(1); |
| 1510 CallStub(&stub); | 1571 CallStub(&stub); |
| 1511 } | 1572 } |
| 1512 | 1573 |
| 1513 | 1574 |
| 1514 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) { | 1575 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) { |
| 1515 CallRuntime(Runtime::FunctionForId(fid), num_arguments); | 1576 CallRuntime(Runtime::FunctionForId(fid), num_arguments); |
| 1516 } | 1577 } |
| 1517 | 1578 |
| 1518 | 1579 |
| 1580 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { |
| 1581 const Runtime::Function* function = Runtime::FunctionForId(id); |
| 1582 mov(r0, Operand(function->nargs)); |
| 1583 mov(r1, Operand(ExternalReference(function))); |
| 1584 CEntryStub stub(1); |
| 1585 stub.SaveDoubles(); |
| 1586 CallStub(&stub); |
| 1587 } |
| 1588 |
| 1589 |
| 1519 void MacroAssembler::CallExternalReference(const ExternalReference& ext, | 1590 void MacroAssembler::CallExternalReference(const ExternalReference& ext, |
| 1520 int num_arguments) { | 1591 int num_arguments) { |
| 1521 mov(r0, Operand(num_arguments)); | 1592 mov(r0, Operand(num_arguments)); |
| 1522 mov(r1, Operand(ext)); | 1593 mov(r1, Operand(ext)); |
| 1523 | 1594 |
| 1524 CEntryStub stub(1); | 1595 CEntryStub stub(1); |
| 1525 CallStub(&stub); | 1596 CallStub(&stub); |
| 1526 } | 1597 } |
| 1527 | 1598 |
| 1528 | 1599 |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2068 | 2139 |
| 2069 void CodePatcher::Emit(Address addr) { | 2140 void CodePatcher::Emit(Address addr) { |
| 2070 masm()->emit(reinterpret_cast<Instr>(addr)); | 2141 masm()->emit(reinterpret_cast<Instr>(addr)); |
| 2071 } | 2142 } |
| 2072 #endif // ENABLE_DEBUGGER_SUPPORT | 2143 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2073 | 2144 |
| 2074 | 2145 |
| 2075 } } // namespace v8::internal | 2146 } } // namespace v8::internal |
| 2076 | 2147 |
| 2077 #endif // V8_TARGET_ARCH_ARM | 2148 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |