| 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 #if V8_TARGET_ARCH_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 | 952 |
| 953 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 953 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
| 954 Generate_JSEntryTrampolineHelper(masm, false); | 954 Generate_JSEntryTrampolineHelper(masm, false); |
| 955 } | 955 } |
| 956 | 956 |
| 957 | 957 |
| 958 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 958 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
| 959 Generate_JSEntryTrampolineHelper(masm, true); | 959 Generate_JSEntryTrampolineHelper(masm, true); |
| 960 } | 960 } |
| 961 | 961 |
| 962 |
| 962 // Generate code for entering a JS function with the interpreter. | 963 // Generate code for entering a JS function with the interpreter. |
| 963 // On entry to the function the receiver and arguments have been pushed on the | 964 // On entry to the function the receiver and arguments have been pushed on the |
| 964 // stack left to right. The actual argument count matches the formal parameter | 965 // stack left to right. The actual argument count matches the formal parameter |
| 965 // count expected by the function. | 966 // count expected by the function. |
| 966 // | 967 // |
| 967 // The live registers are: | 968 // The live registers are: |
| 968 // o r1: the JS function object being called. | 969 // o r1: the JS function object being called. |
| 969 // o r3: the new target | 970 // o r3: the new target |
| 970 // o cp: our context | 971 // o cp: our context |
| 971 // o pp: the caller's constant pool pointer (if enabled) | 972 // o pp: the caller's constant pool pointer (if enabled) |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 __ mov(kInterpreterDispatchTableRegister, | 1053 __ mov(kInterpreterDispatchTableRegister, |
| 1053 Operand(ExternalReference::interpreter_dispatch_table_address( | 1054 Operand(ExternalReference::interpreter_dispatch_table_address( |
| 1054 masm->isolate()))); | 1055 masm->isolate()))); |
| 1055 | 1056 |
| 1056 // Dispatch to the first bytecode handler for the function. | 1057 // Dispatch to the first bytecode handler for the function. |
| 1057 __ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister, | 1058 __ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister, |
| 1058 kInterpreterBytecodeOffsetRegister)); | 1059 kInterpreterBytecodeOffsetRegister)); |
| 1059 __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL, | 1060 __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL, |
| 1060 kPointerSizeLog2)); | 1061 kPointerSizeLog2)); |
| 1061 __ Call(ip); | 1062 __ Call(ip); |
| 1062 masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); | |
| 1063 | 1063 |
| 1064 // The return value is in r0. | 1064 // Even though the first bytecode handler was called, we will never return. |
| 1065 | 1065 __ Abort(kUnexpectedReturnFromBytecodeHandler); |
| 1066 // Get the arguments + reciever count. | |
| 1067 __ ldr(r2, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | |
| 1068 __ ldr(r2, FieldMemOperand(r2, BytecodeArray::kParameterSizeOffset)); | |
| 1069 | |
| 1070 // Leave the frame (also dropping the register file). | |
| 1071 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | |
| 1072 | |
| 1073 __ add(sp, sp, r2, LeaveCC); | |
| 1074 __ Jump(lr); | |
| 1075 | 1066 |
| 1076 // If the bytecode array is no longer present, then the underlying function | 1067 // If the bytecode array is no longer present, then the underlying function |
| 1077 // has been switched to a different kind of code and we heal the closure by | 1068 // has been switched to a different kind of code and we heal the closure by |
| 1078 // switching the code entry field over to the new code object as well. | 1069 // switching the code entry field over to the new code object as well. |
| 1079 __ bind(&bytecode_array_not_present); | 1070 __ bind(&bytecode_array_not_present); |
| 1080 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 1071 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 1081 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1072 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1082 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kCodeOffset)); | 1073 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kCodeOffset)); |
| 1083 __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1074 __ add(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1084 __ str(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1075 __ str(r4, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1085 __ RecordWriteCodeEntryField(r1, r4, r5); | 1076 __ RecordWriteCodeEntryField(r1, r4, r5); |
| 1086 __ Jump(r4); | 1077 __ Jump(r4); |
| 1087 } | 1078 } |
| 1088 | 1079 |
| 1080 |
| 1081 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { |
| 1082 // The return value is in accumulator, which is already in r0. |
| 1083 |
| 1084 // Leave the frame (also dropping the register file). |
| 1085 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 1086 |
| 1087 // Drop receiver + arguments and return. |
| 1088 __ ldr(ip, FieldMemOperand(kInterpreterBytecodeArrayRegister, |
| 1089 BytecodeArray::kParameterSizeOffset)); |
| 1090 __ add(sp, sp, ip, LeaveCC); |
| 1091 __ Jump(lr); |
| 1092 } |
| 1093 |
| 1094 |
| 1089 static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index, | 1095 static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index, |
| 1090 Register limit, Register scratch) { | 1096 Register limit, Register scratch) { |
| 1091 Label loop_header, loop_check; | 1097 Label loop_header, loop_check; |
| 1092 __ b(al, &loop_check); | 1098 __ b(al, &loop_check); |
| 1093 __ bind(&loop_header); | 1099 __ bind(&loop_header); |
| 1094 __ ldr(scratch, MemOperand(index, -kPointerSize, PostIndex)); | 1100 __ ldr(scratch, MemOperand(index, -kPointerSize, PostIndex)); |
| 1095 __ push(scratch); | 1101 __ push(scratch); |
| 1096 __ bind(&loop_check); | 1102 __ bind(&loop_check); |
| 1097 __ cmp(index, limit); | 1103 __ cmp(index, limit); |
| 1098 __ b(gt, &loop_header); | 1104 __ b(gt, &loop_header); |
| 1099 } | 1105 } |
| 1100 | 1106 |
| 1107 |
| 1101 // static | 1108 // static |
| 1102 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 1109 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 1103 MacroAssembler* masm, TailCallMode tail_call_mode) { | 1110 MacroAssembler* masm, TailCallMode tail_call_mode) { |
| 1104 // ----------- S t a t e ------------- | 1111 // ----------- S t a t e ------------- |
| 1105 // -- r0 : the number of arguments (not including the receiver) | 1112 // -- r0 : the number of arguments (not including the receiver) |
| 1106 // -- r2 : the address of the first argument to be pushed. Subsequent | 1113 // -- r2 : the address of the first argument to be pushed. Subsequent |
| 1107 // arguments should be consecutive above this, in the same order as | 1114 // arguments should be consecutive above this, in the same order as |
| 1108 // they are to be pushed onto the stack. | 1115 // they are to be pushed onto the stack. |
| 1109 // -- r1 : the target to call (can be any Object). | 1116 // -- r1 : the target to call (can be any Object). |
| 1110 // ----------------------------------- | 1117 // ----------------------------------- |
| 1111 | 1118 |
| 1112 // Find the address of the last argument. | 1119 // Find the address of the last argument. |
| 1113 __ add(r3, r0, Operand(1)); // Add one for receiver. | 1120 __ add(r3, r0, Operand(1)); // Add one for receiver. |
| 1114 __ mov(r3, Operand(r3, LSL, kPointerSizeLog2)); | 1121 __ mov(r3, Operand(r3, LSL, kPointerSizeLog2)); |
| 1115 __ sub(r3, r2, r3); | 1122 __ sub(r3, r2, r3); |
| 1116 | 1123 |
| 1117 // Push the arguments. | 1124 // Push the arguments. |
| 1118 Generate_InterpreterPushArgs(masm, r2, r3, r4); | 1125 Generate_InterpreterPushArgs(masm, r2, r3, r4); |
| 1119 | 1126 |
| 1120 // Call the target. | 1127 // Call the target. |
| 1121 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 1128 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 1122 tail_call_mode), | 1129 tail_call_mode), |
| 1123 RelocInfo::CODE_TARGET); | 1130 RelocInfo::CODE_TARGET); |
| 1124 } | 1131 } |
| 1125 | 1132 |
| 1133 |
| 1126 // static | 1134 // static |
| 1127 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 1135 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { |
| 1128 // ----------- S t a t e ------------- | 1136 // ----------- S t a t e ------------- |
| 1129 // -- r0 : argument count (not including receiver) | 1137 // -- r0 : argument count (not including receiver) |
| 1130 // -- r3 : new target | 1138 // -- r3 : new target |
| 1131 // -- r1 : constructor to call | 1139 // -- r1 : constructor to call |
| 1132 // -- r2 : address of the first argument | 1140 // -- r2 : address of the first argument |
| 1133 // ----------------------------------- | 1141 // ----------------------------------- |
| 1134 | 1142 |
| 1135 // Find the address of the last argument. | 1143 // Find the address of the last argument. |
| 1136 __ mov(r4, Operand(r0, LSL, kPointerSizeLog2)); | 1144 __ mov(r4, Operand(r0, LSL, kPointerSizeLog2)); |
| 1137 __ sub(r4, r2, r4); | 1145 __ sub(r4, r2, r4); |
| 1138 | 1146 |
| 1139 // Push a slot for the receiver to be constructed. | 1147 // Push a slot for the receiver to be constructed. |
| 1140 __ mov(ip, Operand::Zero()); | 1148 __ mov(ip, Operand::Zero()); |
| 1141 __ push(ip); | 1149 __ push(ip); |
| 1142 | 1150 |
| 1143 // Push the arguments. | 1151 // Push the arguments. |
| 1144 Generate_InterpreterPushArgs(masm, r2, r4, r5); | 1152 Generate_InterpreterPushArgs(masm, r2, r4, r5); |
| 1145 | 1153 |
| 1146 // Call the constructor with r0, r1, and r3 unmodified. | 1154 // Call the constructor with r0, r1, and r3 unmodified. |
| 1147 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1155 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1148 } | 1156 } |
| 1149 | 1157 |
| 1150 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | |
| 1151 // Set the return address to the correct point in the interpreter entry | |
| 1152 // trampoline. | |
| 1153 Smi* interpreter_entry_return_pc_offset( | |
| 1154 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); | |
| 1155 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); | |
| 1156 __ Move(r2, masm->isolate()->builtins()->InterpreterEntryTrampoline()); | |
| 1157 __ add(lr, r2, Operand(interpreter_entry_return_pc_offset->value() + | |
| 1158 Code::kHeaderSize - kHeapObjectTag)); | |
| 1159 | 1158 |
| 1159 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { |
| 1160 // Initialize the dispatch table register. | 1160 // Initialize the dispatch table register. |
| 1161 __ mov(kInterpreterDispatchTableRegister, | 1161 __ mov(kInterpreterDispatchTableRegister, |
| 1162 Operand(ExternalReference::interpreter_dispatch_table_address( | 1162 Operand(ExternalReference::interpreter_dispatch_table_address( |
| 1163 masm->isolate()))); | 1163 masm->isolate()))); |
| 1164 | 1164 |
| 1165 // Get the bytecode array pointer from the frame. | 1165 // Get the bytecode array pointer from the frame. |
| 1166 __ ldr(kInterpreterBytecodeArrayRegister, | 1166 __ ldr(kInterpreterBytecodeArrayRegister, |
| 1167 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 1167 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 1168 | 1168 |
| 1169 if (FLAG_debug_code) { | 1169 if (FLAG_debug_code) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1181 __ SmiUntag(kInterpreterBytecodeOffsetRegister); | 1181 __ SmiUntag(kInterpreterBytecodeOffsetRegister); |
| 1182 | 1182 |
| 1183 // Dispatch to the target bytecode. | 1183 // Dispatch to the target bytecode. |
| 1184 __ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister, | 1184 __ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister, |
| 1185 kInterpreterBytecodeOffsetRegister)); | 1185 kInterpreterBytecodeOffsetRegister)); |
| 1186 __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL, | 1186 __ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL, |
| 1187 kPointerSizeLog2)); | 1187 kPointerSizeLog2)); |
| 1188 __ mov(pc, ip); | 1188 __ mov(pc, ip); |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 |
| 1192 static void Generate_InterpreterNotifyDeoptimizedHelper( |
| 1193 MacroAssembler* masm, Deoptimizer::BailoutType type) { |
| 1194 // Enter an internal frame. |
| 1195 { |
| 1196 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1197 |
| 1198 // Pass the deoptimization type to the runtime system. |
| 1199 __ mov(r1, Operand(Smi::FromInt(static_cast<int>(type)))); |
| 1200 __ push(r1); |
| 1201 __ CallRuntime(Runtime::kNotifyDeoptimized); |
| 1202 // Tear down internal frame. |
| 1203 } |
| 1204 |
| 1205 // Drop state (we don't use these for interpreter deopts) and and pop the |
| 1206 // accumulator value into the accumulator register. |
| 1207 __ Drop(1); |
| 1208 __ Pop(kInterpreterAccumulatorRegister); |
| 1209 |
| 1210 // Enter the bytecode dispatch. |
| 1211 Generate_EnterBytecodeDispatch(masm); |
| 1212 } |
| 1213 |
| 1214 |
| 1215 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) { |
| 1216 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| 1217 } |
| 1218 |
| 1219 |
| 1220 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) { |
| 1221 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); |
| 1222 } |
| 1223 |
| 1224 |
| 1225 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) { |
| 1226 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
| 1227 } |
| 1228 |
| 1229 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
| 1230 // Set the address of the interpreter entry trampoline as a return address. |
| 1231 // This simulates the initial call to bytecode handlers in interpreter entry |
| 1232 // trampoline. The return will never actually be taken, but our stack walker |
| 1233 // uses this address to determine whether a frame is interpreted. |
| 1234 __ Move(lr, masm->isolate()->builtins()->InterpreterEntryTrampoline()); |
| 1235 |
| 1236 Generate_EnterBytecodeDispatch(masm); |
| 1237 } |
| 1238 |
| 1239 |
| 1191 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 1240 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
| 1192 // ----------- S t a t e ------------- | 1241 // ----------- S t a t e ------------- |
| 1193 // -- r0 : argument count (preserved for callee) | 1242 // -- r0 : argument count (preserved for callee) |
| 1194 // -- r3 : new target (preserved for callee) | 1243 // -- r3 : new target (preserved for callee) |
| 1195 // -- r1 : target function (preserved for callee) | 1244 // -- r1 : target function (preserved for callee) |
| 1196 // ----------------------------------- | 1245 // ----------------------------------- |
| 1197 // First lookup code, maybe we don't need to compile! | 1246 // First lookup code, maybe we don't need to compile! |
| 1198 Label gotta_call_runtime, gotta_call_runtime_no_stack; | 1247 Label gotta_call_runtime, gotta_call_runtime_no_stack; |
| 1199 Label maybe_call_runtime; | 1248 Label maybe_call_runtime; |
| 1200 Label try_shared; | 1249 Label try_shared; |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1470 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); | 1519 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); |
| 1471 __ push(r0); | 1520 __ push(r0); |
| 1472 __ CallRuntime(Runtime::kNotifyDeoptimized); | 1521 __ CallRuntime(Runtime::kNotifyDeoptimized); |
| 1473 } | 1522 } |
| 1474 | 1523 |
| 1475 // Get the full codegen state from the stack and untag it -> r6. | 1524 // Get the full codegen state from the stack and untag it -> r6. |
| 1476 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); | 1525 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); |
| 1477 __ SmiUntag(r6); | 1526 __ SmiUntag(r6); |
| 1478 // Switch on the state. | 1527 // Switch on the state. |
| 1479 Label with_tos_register, unknown_state; | 1528 Label with_tos_register, unknown_state; |
| 1480 __ cmp(r6, | 1529 __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); |
| 1481 Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS))); | |
| 1482 __ b(ne, &with_tos_register); | 1530 __ b(ne, &with_tos_register); |
| 1483 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. | 1531 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. |
| 1484 __ Ret(); | 1532 __ Ret(); |
| 1485 | 1533 |
| 1486 __ bind(&with_tos_register); | 1534 __ bind(&with_tos_register); |
| 1487 DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r0.code()); | |
| 1488 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); | 1535 __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); |
| 1489 __ cmp(r6, | 1536 __ cmp(r6, Operand(FullCodeGenerator::TOS_REG)); |
| 1490 Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER))); | |
| 1491 __ b(ne, &unknown_state); | 1537 __ b(ne, &unknown_state); |
| 1492 __ add(sp, sp, Operand(2 * kPointerSize)); // Remove state. | 1538 __ add(sp, sp, Operand(2 * kPointerSize)); // Remove state. |
| 1493 __ Ret(); | 1539 __ Ret(); |
| 1494 | 1540 |
| 1495 __ bind(&unknown_state); | 1541 __ bind(&unknown_state); |
| 1496 __ stop("no cases left"); | 1542 __ stop("no cases left"); |
| 1497 } | 1543 } |
| 1498 | 1544 |
| 1499 | 1545 |
| 1500 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { | 1546 void Builtins::Generate_NotifyDeoptimized(MacroAssembler* masm) { |
| (...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2764 } | 2810 } |
| 2765 } | 2811 } |
| 2766 | 2812 |
| 2767 | 2813 |
| 2768 #undef __ | 2814 #undef __ |
| 2769 | 2815 |
| 2770 } // namespace internal | 2816 } // namespace internal |
| 2771 } // namespace v8 | 2817 } // namespace v8 |
| 2772 | 2818 |
| 2773 #endif // V8_TARGET_ARCH_ARM | 2819 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |