Chromium Code Reviews| 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 |