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 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1067 } | 1112 } |
1068 | 1113 |
1069 | 1114 |
1070 void MacroAssembler::LoadConstantPoolPointerRegister() { | 1115 void MacroAssembler::LoadConstantPoolPointerRegister() { |
1071 DCHECK(FLAG_enable_embedded_constant_pool); | 1116 DCHECK(FLAG_enable_embedded_constant_pool); |
1072 int entry_offset = pc_offset() + Instruction::kPCReadOffset; | 1117 int entry_offset = pc_offset() + Instruction::kPCReadOffset; |
1073 sub(ip, pc, Operand(entry_offset)); | 1118 sub(ip, pc, Operand(entry_offset)); |
1074 LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip); | 1119 LoadConstantPoolPointerRegisterFromCodeTargetAddress(ip); |
1075 } | 1120 } |
1076 | 1121 |
1077 | 1122 void MacroAssembler::StubPrologue(StackFrame::Type type) { |
1078 void MacroAssembler::StubPrologue() { | 1123 mov(ip, Operand(Smi::FromInt(type))); |
1079 PushFixedFrame(); | 1124 PushCommonFrame(ip); |
1080 Push(Smi::FromInt(StackFrame::STUB)); | |
1081 // Adjust FP to point to saved FP. | |
1082 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1083 if (FLAG_enable_embedded_constant_pool) { | 1125 if (FLAG_enable_embedded_constant_pool) { |
1084 LoadConstantPoolPointerRegister(); | 1126 LoadConstantPoolPointerRegister(); |
1085 set_constant_pool_available(true); | 1127 set_constant_pool_available(true); |
1086 } | 1128 } |
1087 } | 1129 } |
1088 | 1130 |
1089 | |
1090 void MacroAssembler::Prologue(bool code_pre_aging) { | 1131 void MacroAssembler::Prologue(bool code_pre_aging) { |
1091 { PredictableCodeSizeScope predictible_code_size_scope( | 1132 { PredictableCodeSizeScope predictible_code_size_scope( |
1092 this, kNoCodeAgeSequenceLength); | 1133 this, kNoCodeAgeSequenceLength); |
1093 // The following three instructions must remain together and unmodified | 1134 // The following three instructions must remain together and unmodified |
1094 // for code aging to work properly. | 1135 // for code aging to work properly. |
1095 if (code_pre_aging) { | 1136 if (code_pre_aging) { |
1096 // Pre-age the code. | 1137 // Pre-age the code. |
1097 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 1138 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
1098 add(r0, pc, Operand(-8)); | 1139 add(r0, pc, Operand(-8)); |
1099 ldr(pc, MemOperand(pc, -4)); | 1140 ldr(pc, MemOperand(pc, -4)); |
1100 emit_code_stub_address(stub); | 1141 emit_code_stub_address(stub); |
1101 } else { | 1142 } else { |
1102 PushFixedFrame(r1); | 1143 PushStandardFrame(r1); |
1103 nop(ip.code()); | 1144 nop(ip.code()); |
1104 // Adjust FP to point to saved FP. | |
1105 add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp)); | |
1106 } | 1145 } |
1107 } | 1146 } |
1108 if (FLAG_enable_embedded_constant_pool) { | 1147 if (FLAG_enable_embedded_constant_pool) { |
1109 LoadConstantPoolPointerRegister(); | 1148 LoadConstantPoolPointerRegister(); |
1110 set_constant_pool_available(true); | 1149 set_constant_pool_available(true); |
1111 } | 1150 } |
1112 } | 1151 } |
1113 | 1152 |
1114 | 1153 |
1115 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { | 1154 void MacroAssembler::EmitLoadTypeFeedbackVector(Register vector) { |
1116 ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1155 ldr(vector, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1117 ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); | 1156 ldr(vector, FieldMemOperand(vector, JSFunction::kSharedFunctionInfoOffset)); |
1118 ldr(vector, | 1157 ldr(vector, |
1119 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); | 1158 FieldMemOperand(vector, SharedFunctionInfo::kFeedbackVectorOffset)); |
1120 } | 1159 } |
1121 | 1160 |
1122 | 1161 |
1123 void MacroAssembler::EnterFrame(StackFrame::Type type, | 1162 void MacroAssembler::EnterFrame(StackFrame::Type type, |
1124 bool load_constant_pool_pointer_reg) { | 1163 bool load_constant_pool_pointer_reg) { |
1125 // r0-r3: preserved | 1164 // r0-r3: preserved |
1126 PushFixedFrame(); | 1165 mov(ip, Operand(Smi::FromInt(type))); |
1166 PushCommonFrame(ip); | |
1127 if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) { | 1167 if (FLAG_enable_embedded_constant_pool && load_constant_pool_pointer_reg) { |
1128 LoadConstantPoolPointerRegister(); | 1168 LoadConstantPoolPointerRegister(); |
1129 } | 1169 } |
1130 mov(ip, Operand(Smi::FromInt(type))); | 1170 if (type == StackFrame::INTERNAL) { |
1131 push(ip); | 1171 mov(ip, Operand(CodeObject())); |
1132 mov(ip, Operand(CodeObject())); | 1172 push(ip); |
1133 push(ip); | 1173 } |
1134 // Adjust FP to point to saved FP. | |
1135 add(fp, sp, | |
1136 Operand(StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); | |
1137 } | 1174 } |
1138 | 1175 |
1139 | 1176 |
1140 int MacroAssembler::LeaveFrame(StackFrame::Type type) { | 1177 int MacroAssembler::LeaveFrame(StackFrame::Type type) { |
1141 // r0: preserved | 1178 // r0: preserved |
1142 // r1: preserved | 1179 // r1: preserved |
1143 // r2: preserved | 1180 // r2: preserved |
1144 | 1181 |
1145 // Drop the execution stack down to the frame pointer and restore | 1182 // Drop the execution stack down to the frame pointer and restore |
1146 // the caller frame pointer, return address and constant pool pointer | 1183 // the caller frame pointer, return address and constant pool pointer |
(...skipping 10 matching lines...) Expand all Loading... | |
1157 } | 1194 } |
1158 return frame_ends; | 1195 return frame_ends; |
1159 } | 1196 } |
1160 | 1197 |
1161 | 1198 |
1162 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { | 1199 void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
1163 // Set up the frame structure on the stack. | 1200 // Set up the frame structure on the stack. |
1164 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); | 1201 DCHECK_EQ(2 * kPointerSize, ExitFrameConstants::kCallerSPDisplacement); |
1165 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); | 1202 DCHECK_EQ(1 * kPointerSize, ExitFrameConstants::kCallerPCOffset); |
1166 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); | 1203 DCHECK_EQ(0 * kPointerSize, ExitFrameConstants::kCallerFPOffset); |
1167 Push(lr, fp); | 1204 mov(ip, Operand(Smi::FromInt(StackFrame::EXIT))); |
1168 mov(fp, Operand(sp)); // Set up new frame pointer. | 1205 PushCommonFrame(ip); |
1169 // Reserve room for saved entry sp and code object. | 1206 // Reserve room for saved entry sp and code object. |
1170 sub(sp, sp, Operand(ExitFrameConstants::kFrameSize)); | 1207 sub(sp, fp, Operand(ExitFrameConstants::kFixedFrameSizeFromFp)); |
1171 if (emit_debug_code()) { | 1208 if (emit_debug_code()) { |
1172 mov(ip, Operand::Zero()); | 1209 mov(ip, Operand::Zero()); |
1173 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); | 1210 str(ip, MemOperand(fp, ExitFrameConstants::kSPOffset)); |
1174 } | 1211 } |
1175 if (FLAG_enable_embedded_constant_pool) { | 1212 if (FLAG_enable_embedded_constant_pool) { |
1176 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); | 1213 str(pp, MemOperand(fp, ExitFrameConstants::kConstantPoolOffset)); |
1177 } | 1214 } |
1178 mov(ip, Operand(CodeObject())); | 1215 mov(ip, Operand(CodeObject())); |
1179 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); | 1216 str(ip, MemOperand(fp, ExitFrameConstants::kCodeOffset)); |
1180 | 1217 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1242 | 1279 |
1243 | 1280 |
1244 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, | 1281 void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
1245 bool restore_context, | 1282 bool restore_context, |
1246 bool argument_count_is_length) { | 1283 bool argument_count_is_length) { |
1247 ConstantPoolUnavailableScope constant_pool_unavailable(this); | 1284 ConstantPoolUnavailableScope constant_pool_unavailable(this); |
1248 | 1285 |
1249 // Optionally restore all double registers. | 1286 // Optionally restore all double registers. |
1250 if (save_doubles) { | 1287 if (save_doubles) { |
1251 // Calculate the stack location of the saved doubles and restore them. | 1288 // Calculate the stack location of the saved doubles and restore them. |
1252 const int offset = ExitFrameConstants::kFrameSize; | 1289 const int offset = ExitFrameConstants::kFixedFrameSizeFromFp; |
1253 sub(r3, fp, | 1290 sub(r3, fp, |
1254 Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize)); | 1291 Operand(offset + DwVfpRegister::kMaxNumRegisters * kDoubleSize)); |
1255 RestoreFPRegs(r3, ip); | 1292 RestoreFPRegs(r3, ip); |
1256 } | 1293 } |
1257 | 1294 |
1258 // Clear top frame. | 1295 // Clear top frame. |
1259 mov(r3, Operand::Zero()); | 1296 mov(r3, Operand::Zero()); |
1260 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); | 1297 mov(ip, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate()))); |
1261 str(r3, MemOperand(ip)); | 1298 str(r3, MemOperand(ip)); |
1262 | 1299 |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1571 | 1608 |
1572 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 1609 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
1573 Register scratch, | 1610 Register scratch, |
1574 Label* miss) { | 1611 Label* miss) { |
1575 Label same_contexts; | 1612 Label same_contexts; |
1576 | 1613 |
1577 DCHECK(!holder_reg.is(scratch)); | 1614 DCHECK(!holder_reg.is(scratch)); |
1578 DCHECK(!holder_reg.is(ip)); | 1615 DCHECK(!holder_reg.is(ip)); |
1579 DCHECK(!scratch.is(ip)); | 1616 DCHECK(!scratch.is(ip)); |
1580 | 1617 |
1581 // Load current lexical context from the stack frame. | 1618 // Load current lexical context from the active StandardFrame, which |
1582 ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 1619 // my require crawling past STUB frames. |
titzer
2016/03/07 10:48:43
s/my/may
danno
2016/03/08 07:04:44
Done.
| |
1620 Label load_context; | |
1621 Label has_context; | |
1622 DCHECK(!ip.is(scratch)); | |
1623 mov(ip, fp); | |
1624 bind(&load_context); | |
1625 ldr(scratch, MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
1626 JumpIfNotSmi(scratch, &has_context); | |
1627 ldr(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset)); | |
1628 b(&load_context); | |
1629 bind(&has_context); | |
1630 | |
1583 // In debug mode, make sure the lexical context is set. | 1631 // In debug mode, make sure the lexical context is set. |
1584 #ifdef DEBUG | 1632 #ifdef DEBUG |
1585 cmp(scratch, Operand::Zero()); | 1633 cmp(scratch, Operand::Zero()); |
1586 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext); | 1634 Check(ne, kWeShouldNotHaveAnEmptyLexicalContext); |
1587 #endif | 1635 #endif |
1588 | 1636 |
1589 // Load the native context of the current context. | 1637 // Load the native context of the current context. |
1590 ldr(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); | 1638 ldr(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX)); |
1591 | 1639 |
1592 // Check the context is a native context. | 1640 // Check the context is a native context. |
(...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3688 } | 3736 } |
3689 } | 3737 } |
3690 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); | 3738 if (mag.shift > 0) mov(result, Operand(result, ASR, mag.shift)); |
3691 add(result, result, Operand(dividend, LSR, 31)); | 3739 add(result, result, Operand(dividend, LSR, 31)); |
3692 } | 3740 } |
3693 | 3741 |
3694 } // namespace internal | 3742 } // namespace internal |
3695 } // namespace v8 | 3743 } // namespace v8 |
3696 | 3744 |
3697 #endif // V8_TARGET_ARCH_ARM | 3745 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |