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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
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 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 Operand(ExternalReference::interpreter_dispatch_table_address( | 1044 Operand(ExternalReference::interpreter_dispatch_table_address( |
1045 masm->isolate()))); | 1045 masm->isolate()))); |
1046 | 1046 |
1047 // Dispatch to the first bytecode handler for the function. | 1047 // Dispatch to the first bytecode handler for the function. |
1048 __ Addu(a0, kInterpreterBytecodeArrayRegister, | 1048 __ Addu(a0, kInterpreterBytecodeArrayRegister, |
1049 kInterpreterBytecodeOffsetRegister); | 1049 kInterpreterBytecodeOffsetRegister); |
1050 __ lbu(a0, MemOperand(a0)); | 1050 __ lbu(a0, MemOperand(a0)); |
1051 __ Lsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2); | 1051 __ Lsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2); |
1052 __ lw(at, MemOperand(at)); | 1052 __ lw(at, MemOperand(at)); |
1053 __ Call(at); | 1053 __ Call(at); |
1054 masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); | |
1055 | 1054 |
1056 // The return value is in v0. | 1055 // Even though the first bytecode handler was called, we will never return. |
1057 | 1056 __ Abort(kUnexpectedReturnFromBytecodeHandler); |
1058 // Get the arguments + reciever count. | |
1059 __ lw(t0, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | |
1060 __ lw(t0, FieldMemOperand(t0, BytecodeArray::kParameterSizeOffset)); | |
1061 | |
1062 // Leave the frame (also dropping the register file). | |
1063 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | |
1064 | |
1065 // Drop receiver + arguments and return. | |
1066 __ Addu(sp, sp, t0); | |
1067 __ Jump(ra); | |
1068 | 1057 |
1069 // Load debug copy of the bytecode array. | 1058 // Load debug copy of the bytecode array. |
1070 __ bind(&load_debug_bytecode_array); | 1059 __ bind(&load_debug_bytecode_array); |
1071 __ lw(kInterpreterBytecodeArrayRegister, | 1060 __ lw(kInterpreterBytecodeArrayRegister, |
1072 FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex)); | 1061 FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex)); |
1073 __ Branch(&bytecode_array_loaded); | 1062 __ Branch(&bytecode_array_loaded); |
1074 | 1063 |
1075 // If the bytecode array is no longer present, then the underlying function | 1064 // If the bytecode array is no longer present, then the underlying function |
1076 // has been switched to a different kind of code and we heal the closure by | 1065 // has been switched to a different kind of code and we heal the closure by |
1077 // switching the code entry field over to the new code object as well. | 1066 // switching the code entry field over to the new code object as well. |
1078 __ bind(&bytecode_array_not_present); | 1067 __ bind(&bytecode_array_not_present); |
1079 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 1068 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
1080 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1069 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
1081 __ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kCodeOffset)); | 1070 __ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kCodeOffset)); |
1082 __ Addu(t0, t0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1071 __ Addu(t0, t0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1083 __ sw(t0, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 1072 __ sw(t0, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
1084 __ RecordWriteCodeEntryField(a1, t0, t1); | 1073 __ RecordWriteCodeEntryField(a1, t0, t1); |
1085 __ Jump(t0); | 1074 __ Jump(t0); |
1086 } | 1075 } |
1087 | 1076 |
| 1077 |
| 1078 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { |
| 1079 // The return value is in accumulator, which is already in v0. |
| 1080 |
| 1081 // Leave the frame (also dropping the register file). |
| 1082 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 1083 |
| 1084 // Drop receiver + arguments and return. |
| 1085 __ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister, |
| 1086 BytecodeArray::kParameterSizeOffset)); |
| 1087 __ Addu(sp, sp, at); |
| 1088 __ Jump(ra); |
| 1089 } |
| 1090 |
| 1091 |
1088 // static | 1092 // static |
1089 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 1093 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
1090 MacroAssembler* masm, TailCallMode tail_call_mode) { | 1094 MacroAssembler* masm, TailCallMode tail_call_mode) { |
1091 // ----------- S t a t e ------------- | 1095 // ----------- S t a t e ------------- |
1092 // -- a0 : the number of arguments (not including the receiver) | 1096 // -- a0 : the number of arguments (not including the receiver) |
1093 // -- a2 : the address of the first argument to be pushed. Subsequent | 1097 // -- a2 : the address of the first argument to be pushed. Subsequent |
1094 // arguments should be consecutive above this, in the same order as | 1098 // arguments should be consecutive above this, in the same order as |
1095 // they are to be pushed onto the stack. | 1099 // they are to be pushed onto the stack. |
1096 // -- a1 : the target to call (can be any Object). | 1100 // -- a1 : the target to call (can be any Object). |
1097 // ----------------------------------- | 1101 // ----------------------------------- |
(...skipping 12 matching lines...) Expand all Loading... |
1110 __ push(t0); | 1114 __ push(t0); |
1111 __ bind(&loop_check); | 1115 __ bind(&loop_check); |
1112 __ Branch(&loop_header, gt, a2, Operand(a3)); | 1116 __ Branch(&loop_header, gt, a2, Operand(a3)); |
1113 | 1117 |
1114 // Call the target. | 1118 // Call the target. |
1115 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 1119 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
1116 tail_call_mode), | 1120 tail_call_mode), |
1117 RelocInfo::CODE_TARGET); | 1121 RelocInfo::CODE_TARGET); |
1118 } | 1122 } |
1119 | 1123 |
| 1124 |
1120 // static | 1125 // static |
1121 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 1126 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { |
1122 // ----------- S t a t e ------------- | 1127 // ----------- S t a t e ------------- |
1123 // -- a0 : argument count (not including receiver) | 1128 // -- a0 : argument count (not including receiver) |
1124 // -- a3 : new target | 1129 // -- a3 : new target |
1125 // -- a1 : constructor to call | 1130 // -- a1 : constructor to call |
1126 // -- a2 : address of the first argument | 1131 // -- a2 : address of the first argument |
1127 // ----------------------------------- | 1132 // ----------------------------------- |
1128 | 1133 |
1129 // Find the address of the last argument. | 1134 // Find the address of the last argument. |
(...skipping 10 matching lines...) Expand all Loading... |
1140 __ lw(t1, MemOperand(a2)); | 1145 __ lw(t1, MemOperand(a2)); |
1141 __ Addu(a2, a2, Operand(-kPointerSize)); | 1146 __ Addu(a2, a2, Operand(-kPointerSize)); |
1142 __ push(t1); | 1147 __ push(t1); |
1143 __ bind(&loop_check); | 1148 __ bind(&loop_check); |
1144 __ Branch(&loop_header, gt, a2, Operand(t0)); | 1149 __ Branch(&loop_header, gt, a2, Operand(t0)); |
1145 | 1150 |
1146 // Call the constructor with a0, a1, and a3 unmodified. | 1151 // Call the constructor with a0, a1, and a3 unmodified. |
1147 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1152 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
1148 } | 1153 } |
1149 | 1154 |
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 __ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline())); | |
1157 __ Addu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() + | |
1158 Code::kHeaderSize - kHeapObjectTag)); | |
1159 | 1155 |
| 1156 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { |
1160 // Initialize the dispatch table register. | 1157 // Initialize the dispatch table register. |
1161 __ li(kInterpreterDispatchTableRegister, | 1158 __ li(kInterpreterDispatchTableRegister, |
1162 Operand(ExternalReference::interpreter_dispatch_table_address( | 1159 Operand(ExternalReference::interpreter_dispatch_table_address( |
1163 masm->isolate()))); | 1160 masm->isolate()))); |
1164 | 1161 |
1165 // Get the bytecode array pointer from the frame. | 1162 // Get the bytecode array pointer from the frame. |
1166 __ lw(kInterpreterBytecodeArrayRegister, | 1163 __ lw(kInterpreterBytecodeArrayRegister, |
1167 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 1164 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
1168 | 1165 |
1169 if (FLAG_debug_code) { | 1166 if (FLAG_debug_code) { |
(...skipping 13 matching lines...) Expand all Loading... |
1183 | 1180 |
1184 // Dispatch to the target bytecode. | 1181 // Dispatch to the target bytecode. |
1185 __ Addu(a1, kInterpreterBytecodeArrayRegister, | 1182 __ Addu(a1, kInterpreterBytecodeArrayRegister, |
1186 kInterpreterBytecodeOffsetRegister); | 1183 kInterpreterBytecodeOffsetRegister); |
1187 __ lbu(a1, MemOperand(a1)); | 1184 __ lbu(a1, MemOperand(a1)); |
1188 __ Lsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2); | 1185 __ Lsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2); |
1189 __ lw(a1, MemOperand(a1)); | 1186 __ lw(a1, MemOperand(a1)); |
1190 __ Jump(a1); | 1187 __ Jump(a1); |
1191 } | 1188 } |
1192 | 1189 |
| 1190 |
| 1191 static void Generate_InterpreterNotifyDeoptimizedHelper( |
| 1192 MacroAssembler* masm, Deoptimizer::BailoutType type) { |
| 1193 // Enter an internal frame. |
| 1194 { |
| 1195 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1196 |
| 1197 // Pass the deoptimization type to the runtime system. |
| 1198 __ li(a1, Operand(Smi::FromInt(static_cast<int>(type)))); |
| 1199 __ push(a1); |
| 1200 __ CallRuntime(Runtime::kNotifyDeoptimized); |
| 1201 // Tear down internal frame. |
| 1202 } |
| 1203 |
| 1204 // Drop state (we don't use these for interpreter deopts) and and pop the |
| 1205 // accumulator value into the accumulator register. |
| 1206 __ Drop(1); |
| 1207 __ Pop(kInterpreterAccumulatorRegister); |
| 1208 |
| 1209 // Enter the bytecode dispatch. |
| 1210 Generate_EnterBytecodeDispatch(masm); |
| 1211 } |
| 1212 |
| 1213 |
| 1214 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) { |
| 1215 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); |
| 1216 } |
| 1217 |
| 1218 |
| 1219 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) { |
| 1220 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); |
| 1221 } |
| 1222 |
| 1223 |
| 1224 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) { |
| 1225 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
| 1226 } |
| 1227 |
| 1228 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
| 1229 // Set the address of the interpreter entry trampoline as a return address. |
| 1230 // This simulates the initial call to bytecode handlers in interpreter entry |
| 1231 // trampoline. The return will never actually be taken, but our stack walker |
| 1232 // uses this address to determine whether a frame is interpreted. |
| 1233 __ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline())); |
| 1234 |
| 1235 Generate_EnterBytecodeDispatch(masm); |
| 1236 } |
| 1237 |
| 1238 |
1193 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 1239 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
1194 // ----------- S t a t e ------------- | 1240 // ----------- S t a t e ------------- |
1195 // -- a0 : argument count (preserved for callee) | 1241 // -- a0 : argument count (preserved for callee) |
1196 // -- a3 : new target (preserved for callee) | 1242 // -- a3 : new target (preserved for callee) |
1197 // -- a1 : target function (preserved for callee) | 1243 // -- a1 : target function (preserved for callee) |
1198 // ----------------------------------- | 1244 // ----------------------------------- |
1199 // First lookup code, maybe we don't need to compile! | 1245 // First lookup code, maybe we don't need to compile! |
1200 Label gotta_call_runtime, gotta_call_runtime_no_stack; | 1246 Label gotta_call_runtime, gotta_call_runtime_no_stack; |
1201 Label maybe_call_runtime; | 1247 Label maybe_call_runtime; |
1202 Label try_shared; | 1248 Label try_shared; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1480 __ li(a0, Operand(Smi::FromInt(static_cast<int>(type)))); | 1526 __ li(a0, Operand(Smi::FromInt(static_cast<int>(type)))); |
1481 __ push(a0); | 1527 __ push(a0); |
1482 __ CallRuntime(Runtime::kNotifyDeoptimized); | 1528 __ CallRuntime(Runtime::kNotifyDeoptimized); |
1483 } | 1529 } |
1484 | 1530 |
1485 // Get the full codegen state from the stack and untag it -> t2. | 1531 // Get the full codegen state from the stack and untag it -> t2. |
1486 __ lw(t2, MemOperand(sp, 0 * kPointerSize)); | 1532 __ lw(t2, MemOperand(sp, 0 * kPointerSize)); |
1487 __ SmiUntag(t2); | 1533 __ SmiUntag(t2); |
1488 // Switch on the state. | 1534 // Switch on the state. |
1489 Label with_tos_register, unknown_state; | 1535 Label with_tos_register, unknown_state; |
1490 __ Branch(&with_tos_register, ne, t2, | 1536 __ Branch(&with_tos_register, |
1491 Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS))); | 1537 ne, t2, Operand(FullCodeGenerator::NO_REGISTERS)); |
1492 __ Ret(USE_DELAY_SLOT); | 1538 __ Ret(USE_DELAY_SLOT); |
1493 // Safe to fill delay slot Addu will emit one instruction. | 1539 // Safe to fill delay slot Addu will emit one instruction. |
1494 __ Addu(sp, sp, Operand(1 * kPointerSize)); // Remove state. | 1540 __ Addu(sp, sp, Operand(1 * kPointerSize)); // Remove state. |
1495 | 1541 |
1496 __ bind(&with_tos_register); | 1542 __ bind(&with_tos_register); |
1497 DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code()); | |
1498 __ lw(v0, MemOperand(sp, 1 * kPointerSize)); | 1543 __ lw(v0, MemOperand(sp, 1 * kPointerSize)); |
1499 __ Branch(&unknown_state, ne, t2, | 1544 __ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG)); |
1500 Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER))); | |
1501 | 1545 |
1502 __ Ret(USE_DELAY_SLOT); | 1546 __ Ret(USE_DELAY_SLOT); |
1503 // Safe to fill delay slot Addu will emit one instruction. | 1547 // Safe to fill delay slot Addu will emit one instruction. |
1504 __ Addu(sp, sp, Operand(2 * kPointerSize)); // Remove state. | 1548 __ Addu(sp, sp, Operand(2 * kPointerSize)); // Remove state. |
1505 | 1549 |
1506 __ bind(&unknown_state); | 1550 __ bind(&unknown_state); |
1507 __ stop("no cases left"); | 1551 __ stop("no cases left"); |
1508 } | 1552 } |
1509 | 1553 |
1510 | 1554 |
(...skipping 1339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2850 } | 2894 } |
2851 } | 2895 } |
2852 | 2896 |
2853 | 2897 |
2854 #undef __ | 2898 #undef __ |
2855 | 2899 |
2856 } // namespace internal | 2900 } // namespace internal |
2857 } // namespace v8 | 2901 } // namespace v8 |
2858 | 2902 |
2859 #endif // V8_TARGET_ARCH_MIPS | 2903 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |