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_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/division-by-constant.h" | 10 #include "src/base/division-by-constant.h" |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 push(lr); | 748 push(lr); |
749 StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode); | 749 StoreBufferOverflowStub store_buffer_overflow(isolate(), fp_mode); |
750 CallStub(&store_buffer_overflow); | 750 CallStub(&store_buffer_overflow); |
751 pop(lr); | 751 pop(lr); |
752 bind(&done); | 752 bind(&done); |
753 if (and_then == kReturnAtEnd) { | 753 if (and_then == kReturnAtEnd) { |
754 Ret(); | 754 Ret(); |
755 } | 755 } |
756 } | 756 } |
757 | 757 |
| 758 void MacroAssembler::PushCommonFrame(Register marker_reg) { |
| 759 if (marker_reg.is_valid()) { |
| 760 if (FLAG_enable_embedded_constant_pool) { |
| 761 if (marker_reg.code() > pp.code()) { |
| 762 stm(db_w, sp, pp.bit() | fp.bit() | lr.bit()); |
| 763 add(fp, sp, Operand(kPointerSize)); |
| 764 Push(marker_reg); |
| 765 } else { |
| 766 stm(db_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit()); |
| 767 add(fp, sp, Operand(2 * kPointerSize)); |
| 768 } |
| 769 } else { |
| 770 if (marker_reg.code() > fp.code()) { |
| 771 stm(db_w, sp, fp.bit() | lr.bit()); |
| 772 mov(fp, Operand(sp)); |
| 773 Push(marker_reg); |
| 774 } else { |
| 775 stm(db_w, sp, marker_reg.bit() | fp.bit() | lr.bit()); |
| 776 add(fp, sp, Operand(kPointerSize)); |
| 777 } |
| 778 } |
| 779 } else { |
| 780 stm(db_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | |
| 781 fp.bit() | lr.bit()); |
| 782 add(fp, sp, Operand(FLAG_enable_embedded_constant_pool ? kPointerSize : 0)); |
| 783 } |
| 784 } |
758 | 785 |
759 void MacroAssembler::PushFixedFrame(Register marker_reg) { | 786 void MacroAssembler::PopCommonFrame(Register marker_reg) { |
760 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); | 787 if (marker_reg.is_valid()) { |
761 stm(db_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | cp.bit() | | 788 if (FLAG_enable_embedded_constant_pool) { |
| 789 if (marker_reg.code() > pp.code()) { |
| 790 pop(marker_reg); |
| 791 ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit()); |
| 792 } else { |
| 793 ldm(ia_w, sp, marker_reg.bit() | pp.bit() | fp.bit() | lr.bit()); |
| 794 } |
| 795 } else { |
| 796 if (marker_reg.code() > fp.code()) { |
| 797 pop(marker_reg); |
| 798 ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 799 } else { |
| 800 ldm(ia_w, sp, marker_reg.bit() | fp.bit() | lr.bit()); |
| 801 } |
| 802 } |
| 803 } else { |
| 804 ldm(ia_w, sp, (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | |
| 805 fp.bit() | lr.bit()); |
| 806 } |
| 807 } |
| 808 |
| 809 void MacroAssembler::PushStandardFrame(Register function_reg) { |
| 810 DCHECK(!function_reg.is_valid() || function_reg.code() < cp.code()); |
| 811 stm(db_w, sp, (function_reg.is_valid() ? function_reg.bit() : 0) | cp.bit() | |
762 (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | | 812 (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | |
763 fp.bit() | lr.bit()); | 813 fp.bit() | lr.bit()); |
| 814 int offset = -StandardFrameConstants::kContextOffset; |
| 815 offset += function_reg.is_valid() ? kPointerSize : 0; |
| 816 add(fp, sp, Operand(offset)); |
764 } | 817 } |
765 | 818 |
766 | 819 |
767 void MacroAssembler::PopFixedFrame(Register marker_reg) { | |
768 DCHECK(!marker_reg.is_valid() || marker_reg.code() < cp.code()); | |
769 ldm(ia_w, sp, (marker_reg.is_valid() ? marker_reg.bit() : 0) | cp.bit() | | |
770 (FLAG_enable_embedded_constant_pool ? pp.bit() : 0) | | |
771 fp.bit() | lr.bit()); | |
772 } | |
773 | |
774 | |
775 // Push and pop all registers that can hold pointers. | 820 // Push and pop all registers that can hold pointers. |
776 void MacroAssembler::PushSafepointRegisters() { | 821 void MacroAssembler::PushSafepointRegisters() { |
777 // Safepoints expect a block of contiguous register values starting with r0. | 822 // Safepoints expect a block of contiguous register values starting with r0. |
778 // except when FLAG_enable_embedded_constant_pool, which omits pp. | 823 // except when FLAG_enable_embedded_constant_pool, which omits pp. |
779 DCHECK(kSafepointSavedRegisters == | 824 DCHECK(kSafepointSavedRegisters == |
780 (FLAG_enable_embedded_constant_pool | 825 (FLAG_enable_embedded_constant_pool |
781 ? ((1 << (kNumSafepointSavedRegisters + 1)) - 1) & ~pp.bit() | 826 ? ((1 << (kNumSafepointSavedRegisters + 1)) - 1) & ~pp.bit() |
782 : (1 << kNumSafepointSavedRegisters) - 1)); | 827 : (1 << kNumSafepointSavedRegisters) - 1)); |
783 // Safepoints expect a block of kNumSafepointRegisters values on the | 828 // Safepoints expect a block of kNumSafepointRegisters values on the |
784 // stack, so adjust the stack for unsaved registers. | 829 // stack, so adjust the stack for unsaved registers. |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1109 } | 1154 } |
1110 | 1155 |
1111 | 1156 |
1112 void MacroAssembler::LoadConstantPoolPointerRegister() { | 1157 void MacroAssembler::LoadConstantPoolPointerRegister() { |
1113 DCHECK(FLAG_enable_embedded_constant_pool); | 1158 DCHECK(FLAG_enable_embedded_constant_pool); |
1114 int entry_offset = pc_offset() + Instruction::kPCReadOffset; | 1159 int entry_offset = pc_offset() + Instruction::kPCReadOffset; |
1115 sub(ip, pc, Operand(entry_offset)); | 1160 sub(ip, pc, Operand(entry_offset)); |
1116 LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip); | 1161 LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip); |
1117 } | 1162 } |
1118 | 1163 |
1119 | 1164 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
1120 void MacroAssembler::StubPrologue() { | 1165 mov(ip, Operand(Smi::FromInt(type))); |
1121 PushFixedFrame(); | 1166 PushCommonFrame(ip); |
1122 Push(Smi::FromInt(StackFrame::STUB)); | |
1123 // Adjust FP to point to saved FP. | |
1124 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1125 if (FLAG_enable_embedded_constant_pool) { | 1167 if (FLAG_enable_embedded_constant_pool) { |
1126 LoadConstantPoolPointerRegister(); | 1168 LoadConstantPoolPointerRegister(); |
1127 set_constant_pool_available(true); | 1169 set_constant_pool_available(true); |
1128 } | 1170 } |
1129 } | 1171 } |
1130 | 1172 |
1131 | |
1132 void MacroAssembler::Prologue(bool code_pre_aging) { | 1173 void MacroAssembler::Prologue(bool code_pre_aging) { |
1133 { PredictableCodeSizeScope predictible_code_size_scope( | 1174 { PredictableCodeSizeScope predictible_code_size_scope( |
1134 this, kNoCodeAgeSequenceLength); | 1175 this, kNoCodeAgeSequenceLength); |
1135 // The following three instructions must remain together and unmodified | 1176 // The following three instructions must remain together and unmodified |
1136 // for code aging to work properly. | 1177 // for code aging to work properly. |
1137 if (code_pre_aging) { | 1178 if (code_pre_aging) { |
1138 // Pre-age the code. | 1179 // Pre-age the code. |
1139 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 1180 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
1140 add(r0, pc, Operand(-8)); | 1181 add(r0, pc, Operand(-8)); |
1141 ldr(pc, MemOperand(pc, -4)); | 1182 ldr(pc, MemOperand(pc, -4)); |
1142 emit_code_stub_address(stub); | 1183 emit_code_stub_address(stub); |
1143 } else { | 1184 } else { |
1144 PushFixedFrame(r1); | 1185 PushStandardFrame(r1); |
1145 nop(ip.code()); | 1186 nop(ip.code()); |
1146 // Adjust FP to point to saved FP. | |
1147 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1148 } | 1187 } |
1149 } | 1188 } |
1150 if (FLAG_enable_embedded_constant_pool) { | 1189 if (FLAG_enable_embedded_constant_pool) { |
1151 LoadConstantPoolPointerRegister(); | 1190 LoadConstantPoolPointerRegister(); |
1152 set_constant_pool_available(true); | 1191 set_constant_pool_available(true); |
1153 } | 1192 } |
1154 } | 1193 } |
1155 | 1194 |
1156 | 1195 |
1157 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { | 1196 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { |
1158 ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1197 ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1159 ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 1198 ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
1160 ldr(vector, | 1199 ldr(vector, |
1161 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 1200 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
1162 } | 1201 } |
1163 | 1202 |
1164 | 1203 |
1165 void MacroAssembler::EnterFrame(StackFrame::Type type, | 1204 void MacroAssembler::EnterFrame(StackFrame::Type type, |
1166 bool load_constant_pool_pointer_reg) { | 1205 bool load_constant_pool_pointer_reg) { |
1167 // r0-r3: preserved | 1206 // r0-r3: preserved |
1168 PushFixedFrame(); | 1207 mov(ip, Operand(Smi::FromInt(type))); |
| 1208 PushCommonFrame(ip); |
1169 if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) { | 1209 if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) { |
1170 LoadConstantPoolPointerRegister(); | 1210 LoadConstantPoolPointerRegister(); |
1171 } | 1211 } |
1172 mov(ip, Operand(Smi::FromInt(type))); | 1212 if (type == StackFrame::INTERNAL) { |
1173 push(ip); | 1213 mov(ip, Operand(CodeObject())); |
1174 mov(ip, Operand(CodeObject())); | 1214 push(ip); |
1175 push(ip); | 1215 } |
1176 // Adjust FP to point to saved FP. | |
1177 add(fp, sp, | |
1178 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | |
1179 } | 1216 } |
1180 | 1217 |
1181 | 1218 |
1182 int MacroAssembler::LeaveFrame(StackFrame::Type type) { | 1219 int MacroAssembler::LeaveFrame(StackFrame::Type type) { |
1183 // r0: preserved | 1220 // r0: preserved |
1184 // r1: preserved | 1221 // r1: preserved |
1185 // r2: preserved | 1222 // r2: preserved |
1186 | 1223 |
1187 // Drop the execution stack down to the frame pointer and restore | 1224 // Drop the execution stack down to the frame pointer and restore |
1188 // the caller frame pointer, return address and constant pool pointer | 1225 // the caller frame pointer, return address and constant pool pointer |
(...skipping 10 matching lines...) Expand all Loading... |
1199 } | 1236 } |
1200 return frame_ends; | 1237 return frame_ends; |
1201 } | 1238 } |
1202 | 1239 |
1203 | 1240 |
1204 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { | 1241 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
1205 // Set up the frame structure on the stack. | 1242 // Set up the frame structure on the stack. |
1206 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 1243 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
1207 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 1244 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
1208 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 1245 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
1209 Push(lr, fp); | 1246 mov(ip, Operand(Smi::FromInt(StackFrame::EXIT))); |
1210 mov(fp, Operand(sp)); // Set up new frame pointer. | 1247 PushCommonFrame(ip); |
1211 // Reserve room for saved entry sp and code object. | 1248 // Reserve room for saved entry sp and code object. |
1212 sub(sp, sp, Operand(ExitFrameConstants::kFrameSize)); | 1249 sub(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp)); |
1213 if (emit_debug_code()) { | 1250 if (emit_debug_code()) { |
1214 mov(ip, Operand::Zero()); | 1251 mov(ip, Operand::Zero()); |
1215 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 1252 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
1216 } | 1253 } |
1217 if (FLAG_enable_embedded_constant_pool) { | 1254 if (FLAG_enable_embedded_constant_pool) { |
1218 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); | 1255 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); |
1219 } | 1256 } |
1220 mov(ip, Operand(CodeObject())); | 1257 mov(ip, Operand(CodeObject())); |
1221 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 1258 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
1222 | 1259 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 | 1321 |
1285 | 1322 |
1286 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, | 1323 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
1287 bool restore_context, | 1324 bool restore_context, |
1288 bool argument_count_is_length) { | 1325 bool argument_count_is_length) { |
1289 ConstantPoolUnavailableScope constant_pool_unavailable(this); | 1326 ConstantPoolUnavailableScope constant_pool_unavailable(this); |
1290 | 1327 |
1291 // Optionally restore all double registers. | 1328 // Optionally restore all double registers. |
1292 if (save_doubles) { | 1329 if (save_doubles) { |
1293 // Calculate the stack location of the saved doubles and restore them. | 1330 // Calculate the stack location of the saved doubles and restore them. |
1294 const int offset = ExitFrameConstants::kFrameSize; | 1331 const int offset = ExitFrameConstants::kFixedFrameSizeFromFp; |
1295 sub(r3, fp, | 1332 sub(r3, fp, |
1296 Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize)); | 1333 Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize)); |
1297 RestoreFPRegs(r3, ip); | 1334 RestoreFPRegs(r3, ip); |
1298 } | 1335 } |
1299 | 1336 |
1300 // Clear top frame. | 1337 // Clear top frame. |
1301 mov(r3, Operand::Zero()); | 1338 mov(r3, Operand::Zero()); |
1302 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 1339 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
1303 str(r3, MemOperand(ip)); | 1340 str(r3, MemOperand(ip)); |
1304 | 1341 |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1671 | 1708 |
1672 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1709 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
1673 Register scratch, | 1710 Register scratch, |
1674 Label* miss) { | 1711 Label* miss) { |
1675 Label same_contexts; | 1712 Label same_contexts; |
1676 | 1713 |
1677 DCHECK(!holder_reg.is(scratch)); | 1714 DCHECK(!holder_reg.is(scratch)); |
1678 DCHECK(!holder_reg.is(ip)); | 1715 DCHECK(!holder_reg.is(ip)); |
1679 DCHECK(!scratch.is(ip)); | 1716 DCHECK(!scratch.is(ip)); |
1680 | 1717 |
1681 // Load current lexical context from the stack frame. | 1718 // Load current lexical context from the active StandardFrame, which |
1682 ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1719 // may require crawling past STUB frames. |
| 1720 Label load_context; |
| 1721 Label has_context; |
| 1722 DCHECK(!ip.is(scratch)); |
| 1723 mov(ip, fp); |
| 1724 bind(&load_context); |
| 1725 ldr(scratch, MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset)); |
| 1726 JumpIfNotSmi(scratch, &has_context); |
| 1727 ldr(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset)); |
| 1728 b(&load_context); |
| 1729 bind(&has_context); |
| 1730 |
1683 // In debug mode, make sure the lexical context is set. | 1731 // In debug mode, make sure the lexical context is set. |
1684 #ifdef DEBUG | 1732 #ifdef DEBUG |
1685 cmp(scratch, Operand::Zero()); | 1733 cmp(scratch, Operand::Zero()); |
1686 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext); | 1734 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext); |
1687 #endif | 1735 #endif |
1688 | 1736 |
1689 // Load the native context of the current context. | 1737 // Load the native context of the current context. |
1690 ldr(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 1738 ldr(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
1691 | 1739 |
1692 // Check the context is a native context. | 1740 // Check the context is a native context. |
(...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3788 } | 3836 } |
3789 } | 3837 } |
3790 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3838 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3791 add(result, result, Operand(dividend, LSR, 31)); | 3839 add(result, result, Operand(dividend, LSR, 31)); |
3792 } | 3840 } |
3793 | 3841 |
3794 } // namespace internal | 3842 } // namespace internal |
3795 } // namespace v8 | 3843 } // namespace v8 |
3796 | 3844 |
3797 #endif // V8_TARGET_ARCH_ARM | 3845 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |