| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits.h> // For LONG_MIN, LONG_MAX. | 5 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_MIPS64 | 7 #if V8_TARGET_ARCH_MIPS64 |
| 8 | 8 |
| 9 #include "src/base/division-by-constant.h" | 9 #include "src/base/division-by-constant.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 | 95 |
| 96 void MacroAssembler::StoreRoot(Register source, | 96 void MacroAssembler::StoreRoot(Register source, |
| 97 Heap::RootListIndex index, | 97 Heap::RootListIndex index, |
| 98 Condition cond, | 98 Condition cond, |
| 99 Register src1, const Operand& src2) { | 99 Register src1, const Operand& src2) { |
| 100 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); | 100 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); |
| 101 Branch(2, NegateCondition(cond), src1, src2); | 101 Branch(2, NegateCondition(cond), src1, src2); |
| 102 sd(source, MemOperand(s6, index << kPointerSizeLog2)); | 102 sd(source, MemOperand(s6, index << kPointerSizeLog2)); |
| 103 } | 103 } |
| 104 | 104 |
| 105 void MacroAssembler::PushCommonFrame(Register marker_reg) { |
| 106 if (marker_reg.is_valid()) { |
| 107 Push(ra, fp, marker_reg); |
| 108 Daddu(fp, sp, Operand(kPointerSize)); |
| 109 } else { |
| 110 Push(ra, fp); |
| 111 mov(fp, sp); |
| 112 } |
| 113 } |
| 114 |
| 115 void MacroAssembler::PopCommonFrame(Register marker_reg) { |
| 116 if (marker_reg.is_valid()) { |
| 117 Pop(ra, fp, marker_reg); |
| 118 } else { |
| 119 Pop(ra, fp); |
| 120 } |
| 121 } |
| 122 |
| 123 void MacroAssembler::PushStandardFrame(Register function_reg) { |
| 124 int offset = -StandardFrameConstants::kContextOffset; |
| 125 if (function_reg.is_valid()) { |
| 126 Push(ra, fp, cp, function_reg); |
| 127 offset += kPointerSize; |
| 128 } else { |
| 129 Push(ra, fp, cp); |
| 130 } |
| 131 Daddu(fp, sp, Operand(offset)); |
| 132 } |
| 105 | 133 |
| 106 // Push and pop all registers that can hold pointers. | 134 // Push and pop all registers that can hold pointers. |
| 107 void MacroAssembler::PushSafepointRegisters() { | 135 void MacroAssembler::PushSafepointRegisters() { |
| 108 // Safepoints expect a block of kNumSafepointRegisters values on the | 136 // Safepoints expect a block of kNumSafepointRegisters values on the |
| 109 // stack, so adjust the stack for unsaved registers. | 137 // stack, so adjust the stack for unsaved registers. |
| 110 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 138 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
| 111 DCHECK(num_unsaved >= 0); | 139 DCHECK(num_unsaved >= 0); |
| 112 if (num_unsaved > 0) { | 140 if (num_unsaved > 0) { |
| 113 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); | 141 Dsubu(sp, sp, Operand(num_unsaved * kPointerSize)); |
| 114 } | 142 } |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 | 510 |
| 483 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 511 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
| 484 Register scratch, | 512 Register scratch, |
| 485 Label* miss) { | 513 Label* miss) { |
| 486 Label same_contexts; | 514 Label same_contexts; |
| 487 | 515 |
| 488 DCHECK(!holder_reg.is(scratch)); | 516 DCHECK(!holder_reg.is(scratch)); |
| 489 DCHECK(!holder_reg.is(at)); | 517 DCHECK(!holder_reg.is(at)); |
| 490 DCHECK(!scratch.is(at)); | 518 DCHECK(!scratch.is(at)); |
| 491 | 519 |
| 492 // Load current lexical context from the stack frame. | 520 // Load current lexical context from the active StandardFrame, which |
| 493 ld(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 521 // my require crawling past STUB frames. |
| 522 Label load_context; |
| 523 Label has_context; |
| 524 mov(at, fp); |
| 525 bind(&load_context); |
| 526 ld(scratch, MemOperand(at, CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 527 JumpIfNotSmi(scratch, &has_context); |
| 528 ld(at, MemOperand(at, CommonFrameConstants::kCallerFPOffset)); |
| 529 b(&load_context); |
| 530 bind(&has_context); |
| 531 |
| 494 // In debug mode, make sure the lexical context is set. | 532 // In debug mode, make sure the lexical context is set. |
| 495 #ifdef DEBUG | 533 #ifdef DEBUG |
| 496 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, | 534 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, |
| 497 scratch, Operand(zero_reg)); | 535 scratch, Operand(zero_reg)); |
| 498 #endif | 536 #endif |
| 499 | 537 |
| 500 // Load the native context of the current context. | 538 // Load the native context of the current context. |
| 501 ld(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 539 ld(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
| 502 | 540 |
| 503 // Check the context is a native context. | 541 // Check the context is a native context. |
| (...skipping 5055 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5559 if (emit_debug_code()) { | 5597 if (emit_debug_code()) { |
| 5560 Label ok, fail; | 5598 Label ok, fail; |
| 5561 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 5599 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
| 5562 Branch(&ok); | 5600 Branch(&ok); |
| 5563 bind(&fail); | 5601 bind(&fail); |
| 5564 Abort(kGlobalFunctionsMustHaveInitialMap); | 5602 Abort(kGlobalFunctionsMustHaveInitialMap); |
| 5565 bind(&ok); | 5603 bind(&ok); |
| 5566 } | 5604 } |
| 5567 } | 5605 } |
| 5568 | 5606 |
| 5569 | 5607 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
| 5570 void MacroAssembler::StubPrologue() { | 5608 li(at, Operand(Smi::FromInt(type))); |
| 5571 Push(ra, fp, cp); | 5609 PushCommonFrame(at); |
| 5572 Push(Smi::FromInt(StackFrame::STUB)); | |
| 5573 // Adjust FP to point to saved FP. | |
| 5574 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
| 5575 } | 5610 } |
| 5576 | 5611 |
| 5577 | 5612 |
| 5578 void MacroAssembler::Prologue(bool code_pre_aging) { | 5613 void MacroAssembler::Prologue(bool code_pre_aging) { |
| 5579 PredictableCodeSizeScope predictible_code_size_scope( | 5614 PredictableCodeSizeScope predictible_code_size_scope( |
| 5580 this, kNoCodeAgeSequenceLength); | 5615 this, kNoCodeAgeSequenceLength); |
| 5581 // The following three instructions must remain together and unmodified | 5616 // The following three instructions must remain together and unmodified |
| 5582 // for code aging to work properly. | 5617 // for code aging to work properly. |
| 5583 if (code_pre_aging) { | 5618 if (code_pre_aging) { |
| 5584 // Pre-age the code. | 5619 // Pre-age the code. |
| 5585 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 5620 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 5586 nop(Assembler::CODE_AGE_MARKER_NOP); | 5621 nop(Assembler::CODE_AGE_MARKER_NOP); |
| 5587 // Load the stub address to t9 and call it, | 5622 // Load the stub address to t9 and call it, |
| 5588 // GetCodeAgeAndParity() extracts the stub address from this instruction. | 5623 // GetCodeAgeAndParity() extracts the stub address from this instruction. |
| 5589 li(t9, | 5624 li(t9, |
| 5590 Operand(reinterpret_cast<uint64_t>(stub->instruction_start())), | 5625 Operand(reinterpret_cast<uint64_t>(stub->instruction_start())), |
| 5591 ADDRESS_LOAD); | 5626 ADDRESS_LOAD); |
| 5592 nop(); // Prevent jalr to jal optimization. | 5627 nop(); // Prevent jalr to jal optimization. |
| 5593 jalr(t9, a0); | 5628 jalr(t9, a0); |
| 5594 nop(); // Branch delay slot nop. | 5629 nop(); // Branch delay slot nop. |
| 5595 nop(); // Pad the empty space. | 5630 nop(); // Pad the empty space. |
| 5596 } else { | 5631 } else { |
| 5597 Push(ra, fp, cp, a1); | 5632 PushStandardFrame(a1); |
| 5598 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5633 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5599 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5634 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5600 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 5635 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
| 5601 // Adjust fp to point to caller's fp. | |
| 5602 Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
| 5603 } | 5636 } |
| 5604 } | 5637 } |
| 5605 | 5638 |
| 5606 | |
| 5607 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { | 5639 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { |
| 5608 ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 5640 ld(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 5609 ld(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 5641 ld(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
| 5610 ld(vector, | 5642 ld(vector, |
| 5611 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 5643 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
| 5612 } | 5644 } |
| 5613 | 5645 |
| 5614 | 5646 |
| 5615 void MacroAssembler::EnterFrame(StackFrame::Type type, | 5647 void MacroAssembler::EnterFrame(StackFrame::Type type, |
| 5616 bool load_constant_pool_pointer_reg) { | 5648 bool load_constant_pool_pointer_reg) { |
| 5617 // Out-of-line constant pool not implemented on mips64. | 5649 // Out-of-line constant pool not implemented on mips64. |
| 5618 UNREACHABLE(); | 5650 UNREACHABLE(); |
| 5619 } | 5651 } |
| 5620 | 5652 |
| 5621 | 5653 |
| 5622 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 5654 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
| 5623 daddiu(sp, sp, -5 * kPointerSize); | 5655 int stack_offset, fp_offset; |
| 5624 li(t8, Operand(Smi::FromInt(type))); | 5656 if (type == StackFrame::INTERNAL) { |
| 5625 li(t9, Operand(CodeObject()), CONSTANT_SIZE); | 5657 stack_offset = -4 * kPointerSize; |
| 5626 sd(ra, MemOperand(sp, 4 * kPointerSize)); | 5658 fp_offset = 2 * kPointerSize; |
| 5627 sd(fp, MemOperand(sp, 3 * kPointerSize)); | 5659 } else { |
| 5628 sd(cp, MemOperand(sp, 2 * kPointerSize)); | 5660 stack_offset = -3 * kPointerSize; |
| 5629 sd(t8, MemOperand(sp, 1 * kPointerSize)); | 5661 fp_offset = 1 * kPointerSize; |
| 5630 sd(t9, MemOperand(sp, 0 * kPointerSize)); | 5662 } |
| 5663 daddiu(sp, sp, stack_offset); |
| 5664 stack_offset = -stack_offset - kPointerSize; |
| 5665 sd(ra, MemOperand(sp, stack_offset)); |
| 5666 stack_offset -= kPointerSize; |
| 5667 sd(fp, MemOperand(sp, stack_offset)); |
| 5668 stack_offset -= kPointerSize; |
| 5669 li(t9, Operand(Smi::FromInt(type))); |
| 5670 sd(t9, MemOperand(sp, stack_offset)); |
| 5671 if (type == StackFrame::INTERNAL) { |
| 5672 DCHECK_EQ(stack_offset, kPointerSize); |
| 5673 li(t9, Operand(CodeObject())); |
| 5674 sd(t9, MemOperand(sp, 0)); |
| 5675 } else { |
| 5676 DCHECK_EQ(stack_offset, 0); |
| 5677 } |
| 5631 // Adjust FP to point to saved FP. | 5678 // Adjust FP to point to saved FP. |
| 5632 Daddu(fp, sp, | 5679 Daddu(fp, sp, Operand(fp_offset)); |
| 5633 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | |
| 5634 } | 5680 } |
| 5635 | 5681 |
| 5636 | 5682 |
| 5637 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 5683 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
| 5638 mov(sp, fp); | 5684 daddiu(sp, fp, 2 * kPointerSize); |
| 5639 ld(fp, MemOperand(sp, 0 * kPointerSize)); | 5685 ld(ra, MemOperand(fp, 1 * kPointerSize)); |
| 5640 ld(ra, MemOperand(sp, 1 * kPointerSize)); | 5686 ld(fp, MemOperand(fp, 0 * kPointerSize)); |
| 5641 daddiu(sp, sp, 2 * kPointerSize); | |
| 5642 } | 5687 } |
| 5643 | 5688 |
| 5644 | 5689 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
| 5645 void MacroAssembler::EnterExitFrame(bool save_doubles, | |
| 5646 int stack_space) { | |
| 5647 // Set up the frame structure on the stack. | 5690 // Set up the frame structure on the stack. |
| 5648 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); | 5691 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); |
| 5649 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); | 5692 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); |
| 5650 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); | 5693 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); |
| 5651 | 5694 |
| 5652 // This is how the stack will look: | 5695 // This is how the stack will look: |
| 5653 // fp + 2 (==kCallerSPDisplacement) - old stack's end | 5696 // fp + 2 (==kCallerSPDisplacement) - old stack's end |
| 5654 // [fp + 1 (==kCallerPCOffset)] - saved old ra | 5697 // [fp + 1 (==kCallerPCOffset)] - saved old ra |
| 5655 // [fp + 0 (==kCallerFPOffset)] - saved old fp | 5698 // [fp + 0 (==kCallerFPOffset)] - saved old fp |
| 5656 // [fp - 1 (==kSPOffset)] - sp of the called function | 5699 // [fp - 1 StackFrame::EXIT Smi |
| 5657 // [fp - 2 (==kCodeOffset)] - CodeObject | 5700 // [fp - 2 (==kSPOffset)] - sp of the called function |
| 5701 // [fp - 3 (==kCodeOffset)] - CodeObject |
| 5658 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the | 5702 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the |
| 5659 // new stack (will contain saved ra) | 5703 // new stack (will contain saved ra) |
| 5660 | 5704 |
| 5661 // Save registers. | 5705 // Save registers and reserve room for saved entry sp and code object. |
| 5662 daddiu(sp, sp, -4 * kPointerSize); | 5706 daddiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp); |
| 5663 sd(ra, MemOperand(sp, 3 * kPointerSize)); | 5707 sd(ra, MemOperand(sp, 4 * kPointerSize)); |
| 5664 sd(fp, MemOperand(sp, 2 * kPointerSize)); | 5708 sd(fp, MemOperand(sp, 3 * kPointerSize)); |
| 5665 daddiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. | 5709 li(at, Operand(Smi::FromInt(StackFrame::EXIT))); |
| 5710 sd(at, MemOperand(sp, 2 * kPointerSize)); |
| 5711 // Set up new frame pointer. |
| 5712 daddiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp); |
| 5666 | 5713 |
| 5667 if (emit_debug_code()) { | 5714 if (emit_debug_code()) { |
| 5668 sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 5715 sd(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
| 5669 } | 5716 } |
| 5670 | 5717 |
| 5671 // Accessed from ExitFrame::code_slot. | 5718 // Accessed from ExitFrame::code_slot. |
| 5672 li(t8, Operand(CodeObject()), CONSTANT_SIZE); | 5719 li(t8, Operand(CodeObject()), CONSTANT_SIZE); |
| 5673 sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 5720 sd(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
| 5674 | 5721 |
| 5675 // Save the frame pointer and the context in top. | 5722 // Save the frame pointer and the context in top. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5708 } | 5755 } |
| 5709 | 5756 |
| 5710 | 5757 |
| 5711 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, | 5758 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
| 5712 bool restore_context, bool do_return, | 5759 bool restore_context, bool do_return, |
| 5713 bool argument_count_is_length) { | 5760 bool argument_count_is_length) { |
| 5714 // Optionally restore all double registers. | 5761 // Optionally restore all double registers. |
| 5715 if (save_doubles) { | 5762 if (save_doubles) { |
| 5716 // Remember: we only need to restore every 2nd double FPU value. | 5763 // Remember: we only need to restore every 2nd double FPU value. |
| 5717 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; | 5764 int kNumOfSavedRegisters = FPURegister::kMaxNumRegisters / 2; |
| 5718 Dsubu(t8, fp, Operand(ExitFrameConstants::kFrameSize + | 5765 Dsubu(t8, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp + |
| 5719 kNumOfSavedRegisters * kDoubleSize)); | 5766 kNumOfSavedRegisters * kDoubleSize)); |
| 5720 for (int i = 0; i < kNumOfSavedRegisters; i++) { | 5767 for (int i = 0; i < kNumOfSavedRegisters; i++) { |
| 5721 FPURegister reg = FPURegister::from_code(2 * i); | 5768 FPURegister reg = FPURegister::from_code(2 * i); |
| 5722 ldc1(reg, MemOperand(t8, i * kDoubleSize)); | 5769 ldc1(reg, MemOperand(t8, i * kDoubleSize)); |
| 5723 } | 5770 } |
| 5724 } | 5771 } |
| 5725 | 5772 |
| 5726 // Clear top frame. | 5773 // Clear top frame. |
| 5727 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 5774 li(t8, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
| 5728 sd(zero_reg, MemOperand(t8)); | 5775 sd(zero_reg, MemOperand(t8)); |
| 5729 | 5776 |
| (...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6665 if (mag.shift > 0) sra(result, result, mag.shift); | 6712 if (mag.shift > 0) sra(result, result, mag.shift); |
| 6666 srl(at, dividend, 31); | 6713 srl(at, dividend, 31); |
| 6667 Addu(result, result, Operand(at)); | 6714 Addu(result, result, Operand(at)); |
| 6668 } | 6715 } |
| 6669 | 6716 |
| 6670 | 6717 |
| 6671 } // namespace internal | 6718 } // namespace internal |
| 6672 } // namespace v8 | 6719 } // namespace v8 |
| 6673 | 6720 |
| 6674 #endif // V8_TARGET_ARCH_MIPS64 | 6721 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |