OLD | NEW |
1 | 1 |
2 // Copyright 2012 the V8 project authors. All rights reserved. | 2 // Copyright 2012 the V8 project authors. All rights reserved. |
3 // Use of this source code is governed by a BSD-style license that can be | 3 // Use of this source code is governed by a BSD-style license that can be |
4 // found in the LICENSE file. | 4 // found in the LICENSE file. |
5 | 5 |
6 #include <limits.h> // For LONG_MIN, LONG_MAX. | 6 #include <limits.h> // For LONG_MIN, LONG_MAX. |
7 | 7 |
8 #if V8_TARGET_ARCH_MIPS | 8 #if V8_TARGET_ARCH_MIPS |
9 | 9 |
10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 93 |
94 void MacroAssembler::StoreRoot(Register source, | 94 void MacroAssembler::StoreRoot(Register source, |
95 Heap::RootListIndex index, | 95 Heap::RootListIndex index, |
96 Condition cond, | 96 Condition cond, |
97 Register src1, const Operand& src2) { | 97 Register src1, const Operand& src2) { |
98 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); | 98 DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); |
99 Branch(2, NegateCondition(cond), src1, src2); | 99 Branch(2, NegateCondition(cond), src1, src2); |
100 sw(source, MemOperand(s6, index << kPointerSizeLog2)); | 100 sw(source, MemOperand(s6, index << kPointerSizeLog2)); |
101 } | 101 } |
102 | 102 |
| 103 void MacroAssembler::PushCommonFrame(Register marker_reg) { |
| 104 if (marker_reg.is_valid()) { |
| 105 Push(ra, fp, marker_reg); |
| 106 Addu(fp, sp, Operand(kPointerSize)); |
| 107 } else { |
| 108 Push(ra, fp); |
| 109 mov(fp, sp); |
| 110 } |
| 111 } |
| 112 |
| 113 void MacroAssembler::PopCommonFrame(Register marker_reg) { |
| 114 if (marker_reg.is_valid()) { |
| 115 Pop(ra, fp, marker_reg); |
| 116 } else { |
| 117 Pop(ra, fp); |
| 118 } |
| 119 } |
| 120 |
| 121 void MacroAssembler::PushStandardFrame(Register function_reg) { |
| 122 int offset = -StandardFrameConstants::kContextOffset; |
| 123 if (function_reg.is_valid()) { |
| 124 Push(ra, fp, cp, function_reg); |
| 125 offset += kPointerSize; |
| 126 } else { |
| 127 Push(ra, fp, cp); |
| 128 } |
| 129 Addu(fp, sp, Operand(offset)); |
| 130 } |
103 | 131 |
104 // Push and pop all registers that can hold pointers. | 132 // Push and pop all registers that can hold pointers. |
105 void MacroAssembler::PushSafepointRegisters() { | 133 void MacroAssembler::PushSafepointRegisters() { |
106 // Safepoints expect a block of kNumSafepointRegisters values on the | 134 // Safepoints expect a block of kNumSafepointRegisters values on the |
107 // stack, so adjust the stack for unsaved registers. | 135 // stack, so adjust the stack for unsaved registers. |
108 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; | 136 const int num_unsaved = kNumSafepointRegisters - kNumSafepointSavedRegisters; |
109 DCHECK(num_unsaved >= 0); | 137 DCHECK(num_unsaved >= 0); |
110 if (num_unsaved > 0) { | 138 if (num_unsaved > 0) { |
111 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); | 139 Subu(sp, sp, Operand(num_unsaved * kPointerSize)); |
112 } | 140 } |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 | 507 |
480 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 508 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
481 Register scratch, | 509 Register scratch, |
482 Label* miss) { | 510 Label* miss) { |
483 Label same_contexts; | 511 Label same_contexts; |
484 | 512 |
485 DCHECK(!holder_reg.is(scratch)); | 513 DCHECK(!holder_reg.is(scratch)); |
486 DCHECK(!holder_reg.is(at)); | 514 DCHECK(!holder_reg.is(at)); |
487 DCHECK(!scratch.is(at)); | 515 DCHECK(!scratch.is(at)); |
488 | 516 |
489 // Load current lexical context from the stack frame. | 517 // Load current lexical context from the active StandardFrame, which |
490 lw(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 518 // my require crawling past STUB frames. |
| 519 Label load_context; |
| 520 Label has_context; |
| 521 mov(at, fp); |
| 522 bind(&load_context); |
| 523 lw(scratch, MemOperand(at, CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 524 JumpIfNotSmi(scratch, &has_context); |
| 525 lw(at, MemOperand(at, CommonFrameConstants::kCallerFPOffset)); |
| 526 b(&load_context); |
| 527 bind(&has_context); |
| 528 |
491 // In debug mode, make sure the lexical context is set. | 529 // In debug mode, make sure the lexical context is set. |
492 #ifdef DEBUG | 530 #ifdef DEBUG |
493 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, | 531 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext, |
494 scratch, Operand(zero_reg)); | 532 scratch, Operand(zero_reg)); |
495 #endif | 533 #endif |
496 | 534 |
497 // Load the native context of the current context. | 535 // Load the native context of the current context. |
498 lw(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 536 lw(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
499 | 537 |
500 // Check the context is a native context. | 538 // Check the context is a native context. |
(...skipping 4371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4872 if (emit_debug_code()) { | 4910 if (emit_debug_code()) { |
4873 Label ok, fail; | 4911 Label ok, fail; |
4874 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 4912 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
4875 Branch(&ok); | 4913 Branch(&ok); |
4876 bind(&fail); | 4914 bind(&fail); |
4877 Abort(kGlobalFunctionsMustHaveInitialMap); | 4915 Abort(kGlobalFunctionsMustHaveInitialMap); |
4878 bind(&ok); | 4916 bind(&ok); |
4879 } | 4917 } |
4880 } | 4918 } |
4881 | 4919 |
4882 | 4920 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
4883 void MacroAssembler::StubPrologue() { | 4921 li(at, Operand(Smi::FromInt(type))); |
4884 Push(ra, fp, cp); | 4922 PushCommonFrame(at); |
4885 Push(Smi::FromInt(StackFrame::STUB)); | |
4886 // Adjust FP to point to saved FP. | |
4887 Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
4888 } | 4923 } |
4889 | 4924 |
4890 | 4925 |
4891 void MacroAssembler::Prologue(bool code_pre_aging) { | 4926 void MacroAssembler::Prologue(bool code_pre_aging) { |
4892 PredictableCodeSizeScope predictible_code_size_scope( | 4927 PredictableCodeSizeScope predictible_code_size_scope( |
4893 this, kNoCodeAgeSequenceLength); | 4928 this, kNoCodeAgeSequenceLength); |
4894 // The following three instructions must remain together and unmodified | 4929 // The following three instructions must remain together and unmodified |
4895 // for code aging to work properly. | 4930 // for code aging to work properly. |
4896 if (code_pre_aging) { | 4931 if (code_pre_aging) { |
4897 // Pre-age the code. | 4932 // Pre-age the code. |
4898 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 4933 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
4899 nop(Assembler::CODE_AGE_MARKER_NOP); | 4934 nop(Assembler::CODE_AGE_MARKER_NOP); |
4900 // Load the stub address to t9 and call it, | 4935 // Load the stub address to t9 and call it, |
4901 // GetCodeAgeAndParity() extracts the stub address from this instruction. | 4936 // GetCodeAgeAndParity() extracts the stub address from this instruction. |
4902 li(t9, | 4937 li(t9, |
4903 Operand(reinterpret_cast<uint32_t>(stub->instruction_start())), | 4938 Operand(reinterpret_cast<uint32_t>(stub->instruction_start())), |
4904 CONSTANT_SIZE); | 4939 CONSTANT_SIZE); |
4905 nop(); // Prevent jalr to jal optimization. | 4940 nop(); // Prevent jalr to jal optimization. |
4906 jalr(t9, a0); | 4941 jalr(t9, a0); |
4907 nop(); // Branch delay slot nop. | 4942 nop(); // Branch delay slot nop. |
4908 nop(); // Pad the empty space. | 4943 nop(); // Pad the empty space. |
4909 } else { | 4944 } else { |
4910 Push(ra, fp, cp, a1); | 4945 PushStandardFrame(a1); |
4911 nop(Assembler::CODE_AGE_SEQUENCE_NOP); | 4946 nop(Assembler::CODE_AGE_SEQUENCE_NOP); |
4912 // Adjust fp to point to caller's fp. | |
4913 Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
4914 } | 4947 } |
4915 } | 4948 } |
4916 | 4949 |
4917 | 4950 |
4918 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { | 4951 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { |
4919 lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 4952 lw(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
4920 lw(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 4953 lw(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
4921 lw(vector, | 4954 lw(vector, |
4922 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 4955 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
4923 } | 4956 } |
4924 | 4957 |
4925 | 4958 |
4926 void MacroAssembler::EnterFrame(StackFrame::Type type, | 4959 void MacroAssembler::EnterFrame(StackFrame::Type type, |
4927 bool load_constant_pool_pointer_reg) { | 4960 bool load_constant_pool_pointer_reg) { |
4928 // Out-of-line constant pool not implemented on mips. | 4961 // Out-of-line constant pool not implemented on mips. |
4929 UNREACHABLE(); | 4962 UNREACHABLE(); |
4930 } | 4963 } |
4931 | 4964 |
4932 | 4965 |
4933 void MacroAssembler::EnterFrame(StackFrame::Type type) { | 4966 void MacroAssembler::EnterFrame(StackFrame::Type type) { |
4934 addiu(sp, sp, -5 * kPointerSize); | 4967 int stack_offset, fp_offset; |
4935 li(t8, Operand(Smi::FromInt(type))); | 4968 if (type == StackFrame::INTERNAL) { |
4936 li(t9, Operand(CodeObject()), CONSTANT_SIZE); | 4969 stack_offset = -4 * kPointerSize; |
4937 sw(ra, MemOperand(sp, 4 * kPointerSize)); | 4970 fp_offset = 2 * kPointerSize; |
4938 sw(fp, MemOperand(sp, 3 * kPointerSize)); | 4971 } else { |
4939 sw(cp, MemOperand(sp, 2 * kPointerSize)); | 4972 stack_offset = -3 * kPointerSize; |
4940 sw(t8, MemOperand(sp, 1 * kPointerSize)); | 4973 fp_offset = 1 * kPointerSize; |
4941 sw(t9, MemOperand(sp, 0 * kPointerSize)); | 4974 } |
| 4975 addiu(sp, sp, stack_offset); |
| 4976 stack_offset = -stack_offset - kPointerSize; |
| 4977 sw(ra, MemOperand(sp, stack_offset)); |
| 4978 stack_offset -= kPointerSize; |
| 4979 sw(fp, MemOperand(sp, stack_offset)); |
| 4980 stack_offset -= kPointerSize; |
| 4981 li(t9, Operand(Smi::FromInt(type))); |
| 4982 sw(t9, MemOperand(sp, stack_offset)); |
| 4983 if (type == StackFrame::INTERNAL) { |
| 4984 DCHECK_EQ(stack_offset, kPointerSize); |
| 4985 li(t9, Operand(CodeObject())); |
| 4986 sw(t9, MemOperand(sp, 0)); |
| 4987 } else { |
| 4988 DCHECK_EQ(stack_offset, 0); |
| 4989 } |
4942 // Adjust FP to point to saved FP. | 4990 // Adjust FP to point to saved FP. |
4943 Addu(fp, sp, | 4991 Addu(fp, sp, Operand(fp_offset)); |
4944 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | |
4945 } | 4992 } |
4946 | 4993 |
4947 | 4994 |
4948 void MacroAssembler::LeaveFrame(StackFrame::Type type) { | 4995 void MacroAssembler::LeaveFrame(StackFrame::Type type) { |
4949 mov(sp, fp); | 4996 addiu(sp, fp, 2 * kPointerSize); |
4950 lw(fp, MemOperand(sp, 0 * kPointerSize)); | 4997 lw(ra, MemOperand(fp, 1 * kPointerSize)); |
4951 lw(ra, MemOperand(sp, 1 * kPointerSize)); | 4998 lw(fp, MemOperand(fp, 0 * kPointerSize)); |
4952 addiu(sp, sp, 2 * kPointerSize); | |
4953 } | 4999 } |
4954 | 5000 |
4955 | 5001 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
4956 void MacroAssembler::EnterExitFrame(bool save_doubles, | |
4957 int stack_space) { | |
4958 // Set up the frame structure on the stack. | 5002 // Set up the frame structure on the stack. |
4959 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); | 5003 STATIC_ASSERT(2 * kPointerSize == ExitFrameConstants::kCallerSPDisplacement); |
4960 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); | 5004 STATIC_ASSERT(1 * kPointerSize == ExitFrameConstants::kCallerPCOffset); |
4961 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); | 5005 STATIC_ASSERT(0 * kPointerSize == ExitFrameConstants::kCallerFPOffset); |
4962 | 5006 |
4963 // This is how the stack will look: | 5007 // This is how the stack will look: |
4964 // fp + 2 (==kCallerSPDisplacement) - old stack's end | 5008 // fp + 2 (==kCallerSPDisplacement) - old stack's end |
4965 // [fp + 1 (==kCallerPCOffset)] - saved old ra | 5009 // [fp + 1 (==kCallerPCOffset)] - saved old ra |
4966 // [fp + 0 (==kCallerFPOffset)] - saved old fp | 5010 // [fp + 0 (==kCallerFPOffset)] - saved old fp |
4967 // [fp - 1 (==kSPOffset)] - sp of the called function | 5011 // [fp - 1 StackFrame::EXIT Smi |
4968 // [fp - 2 (==kCodeOffset)] - CodeObject | 5012 // [fp - 2 (==kSPOffset)] - sp of the called function |
| 5013 // [fp - 3 (==kCodeOffset)] - CodeObject |
4969 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the | 5014 // fp - (2 + stack_space + alignment) == sp == [fp - kSPOffset] - top of the |
4970 // new stack (will contain saved ra) | 5015 // new stack (will contain saved ra) |
4971 | 5016 |
4972 // Save registers. | 5017 // Save registers and reserve room for saved entry sp and code object. |
4973 addiu(sp, sp, -4 * kPointerSize); | 5018 addiu(sp, sp, -2 * kPointerSize - ExitFrameConstants::kFixedFrameSizeFromFp); |
4974 sw(ra, MemOperand(sp, 3 * kPointerSize)); | 5019 sw(ra, MemOperand(sp, 4 * kPointerSize)); |
4975 sw(fp, MemOperand(sp, 2 * kPointerSize)); | 5020 sw(fp, MemOperand(sp, 3 * kPointerSize)); |
4976 addiu(fp, sp, 2 * kPointerSize); // Set up new frame pointer. | 5021 li(at, Operand(Smi::FromInt(StackFrame::EXIT))); |
| 5022 sw(at, MemOperand(sp, 2 * kPointerSize)); |
| 5023 // Set up new frame pointer. |
| 5024 addiu(fp, sp, ExitFrameConstants::kFixedFrameSizeFromFp); |
4977 | 5025 |
4978 if (emit_debug_code()) { | 5026 if (emit_debug_code()) { |
4979 sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 5027 sw(zero_reg, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
4980 } | 5028 } |
4981 | 5029 |
4982 // Accessed from ExitFrame::code_slot. | 5030 // Accessed from ExitFrame::code_slot. |
4983 li(t8, Operand(CodeObject()), CONSTANT_SIZE); | 5031 li(t8, Operand(CodeObject()), CONSTANT_SIZE); |
4984 sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 5032 sw(t8, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
4985 | 5033 |
4986 // Save the frame pointer and the context in top. | 5034 // Save the frame pointer and the context in top. |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5913 if (mag.shift > 0) sra(result, result, mag.shift); | 5961 if (mag.shift > 0) sra(result, result, mag.shift); |
5914 srl(at, dividend, 31); | 5962 srl(at, dividend, 31); |
5915 Addu(result, result, Operand(at)); | 5963 Addu(result, result, Operand(at)); |
5916 } | 5964 } |
5917 | 5965 |
5918 | 5966 |
5919 } // namespace internal | 5967 } // namespace internal |
5920 } // namespace v8 | 5968 } // namespace v8 |
5921 | 5969 |
5922 #endif // V8_TARGET_ARCH_MIPS | 5970 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |