| 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_MIPS64 | 5 #if V8_TARGET_ARCH_MIPS64 |
| 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 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 933 | 933 |
| 934 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 934 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
| 935 Generate_JSEntryTrampolineHelper(masm, false); | 935 Generate_JSEntryTrampolineHelper(masm, false); |
| 936 } | 936 } |
| 937 | 937 |
| 938 | 938 |
| 939 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 939 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
| 940 Generate_JSEntryTrampolineHelper(masm, true); | 940 Generate_JSEntryTrampolineHelper(masm, true); |
| 941 } | 941 } |
| 942 | 942 |
| 943 | |
| 944 // Generate code for entering a JS function with the interpreter. | 943 // Generate code for entering a JS function with the interpreter. |
| 945 // On entry to the function the receiver and arguments have been pushed on the | 944 // On entry to the function the receiver and arguments have been pushed on the |
| 946 // stack left to right. The actual argument count matches the formal parameter | 945 // stack left to right. The actual argument count matches the formal parameter |
| 947 // count expected by the function. | 946 // count expected by the function. |
| 948 // | 947 // |
| 949 // The live registers are: | 948 // The live registers are: |
| 950 // o a1: the JS function object being called. | 949 // o a1: the JS function object being called. |
| 951 // o a3: the new target | 950 // o a3: the new target |
| 952 // o cp: our context | 951 // o cp: our context |
| 953 // o fp: the caller's frame pointer | 952 // o fp: the caller's frame pointer |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 Operand(ExternalReference::interpreter_dispatch_table_address( | 1032 Operand(ExternalReference::interpreter_dispatch_table_address( |
| 1034 masm->isolate()))); | 1033 masm->isolate()))); |
| 1035 | 1034 |
| 1036 // Dispatch to the first bytecode handler for the function. | 1035 // Dispatch to the first bytecode handler for the function. |
| 1037 __ Daddu(a0, kInterpreterBytecodeArrayRegister, | 1036 __ Daddu(a0, kInterpreterBytecodeArrayRegister, |
| 1038 kInterpreterBytecodeOffsetRegister); | 1037 kInterpreterBytecodeOffsetRegister); |
| 1039 __ lbu(a0, MemOperand(a0)); | 1038 __ lbu(a0, MemOperand(a0)); |
| 1040 __ Dlsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2); | 1039 __ Dlsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2); |
| 1041 __ ld(at, MemOperand(at)); | 1040 __ ld(at, MemOperand(at)); |
| 1042 __ Call(at); | 1041 __ Call(at); |
| 1042 masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset()); |
| 1043 | 1043 |
| 1044 // Even though the first bytecode handler was called, we will never return. | 1044 // The return value is in v0. |
| 1045 __ Abort(kUnexpectedReturnFromBytecodeHandler); | 1045 |
| 1046 // Get the arguments + reciever count. |
| 1047 __ ld(t0, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 1048 __ lw(t0, FieldMemOperand(t0, BytecodeArray::kParameterSizeOffset)); |
| 1049 |
| 1050 // Leave the frame (also dropping the register file). |
| 1051 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 1052 |
| 1053 // Drop receiver + arguments and return. |
| 1054 __ Daddu(sp, sp, t0); |
| 1055 __ Jump(ra); |
| 1046 | 1056 |
| 1047 // Load debug copy of the bytecode array. | 1057 // Load debug copy of the bytecode array. |
| 1048 __ bind(&load_debug_bytecode_array); | 1058 __ bind(&load_debug_bytecode_array); |
| 1049 __ ld(kInterpreterBytecodeArrayRegister, | 1059 __ ld(kInterpreterBytecodeArrayRegister, |
| 1050 FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex)); | 1060 FieldMemOperand(debug_info, DebugInfo::kAbstractCodeIndex)); |
| 1051 __ Branch(&bytecode_array_loaded); | 1061 __ Branch(&bytecode_array_loaded); |
| 1052 | 1062 |
| 1053 // If the bytecode array is no longer present, then the underlying function | 1063 // If the bytecode array is no longer present, then the underlying function |
| 1054 // has been switched to a different kind of code and we heal the closure by | 1064 // has been switched to a different kind of code and we heal the closure by |
| 1055 // switching the code entry field over to the new code object as well. | 1065 // switching the code entry field over to the new code object as well. |
| 1056 __ bind(&bytecode_array_not_present); | 1066 __ bind(&bytecode_array_not_present); |
| 1057 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 1067 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
| 1058 __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 1068 __ ld(a4, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1059 __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kCodeOffset)); | 1069 __ ld(a4, FieldMemOperand(a4, SharedFunctionInfo::kCodeOffset)); |
| 1060 __ Daddu(a4, a4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1070 __ Daddu(a4, a4, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1061 __ sd(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); | 1071 __ sd(a4, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); |
| 1062 __ RecordWriteCodeEntryField(a1, a4, a5); | 1072 __ RecordWriteCodeEntryField(a1, a4, a5); |
| 1063 __ Jump(a4); | 1073 __ Jump(a4); |
| 1064 } | 1074 } |
| 1065 | 1075 |
| 1066 | |
| 1067 void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) { | |
| 1068 // The return value is in accumulator, which is already in v0. | |
| 1069 | |
| 1070 // Leave the frame (also dropping the register file). | |
| 1071 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | |
| 1072 | |
| 1073 // Drop receiver + arguments and return. | |
| 1074 __ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister, | |
| 1075 BytecodeArray::kParameterSizeOffset)); | |
| 1076 __ Daddu(sp, sp, at); | |
| 1077 __ Jump(ra); | |
| 1078 } | |
| 1079 | |
| 1080 | |
| 1081 // static | 1076 // static |
| 1082 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 1077 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 1083 MacroAssembler* masm, TailCallMode tail_call_mode) { | 1078 MacroAssembler* masm, TailCallMode tail_call_mode) { |
| 1084 // ----------- S t a t e ------------- | 1079 // ----------- S t a t e ------------- |
| 1085 // -- a0 : the number of arguments (not including the receiver) | 1080 // -- a0 : the number of arguments (not including the receiver) |
| 1086 // -- a2 : the address of the first argument to be pushed. Subsequent | 1081 // -- a2 : the address of the first argument to be pushed. Subsequent |
| 1087 // arguments should be consecutive above this, in the same order as | 1082 // arguments should be consecutive above this, in the same order as |
| 1088 // they are to be pushed onto the stack. | 1083 // they are to be pushed onto the stack. |
| 1089 // -- a1 : the target to call (can be any Object). | 1084 // -- a1 : the target to call (can be any Object). |
| 1090 // ----------------------------------- | 1085 // ----------------------------------- |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1103 __ push(t0); | 1098 __ push(t0); |
| 1104 __ bind(&loop_check); | 1099 __ bind(&loop_check); |
| 1105 __ Branch(&loop_header, gt, a2, Operand(a3)); | 1100 __ Branch(&loop_header, gt, a2, Operand(a3)); |
| 1106 | 1101 |
| 1107 // Call the target. | 1102 // Call the target. |
| 1108 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 1103 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 1109 tail_call_mode), | 1104 tail_call_mode), |
| 1110 RelocInfo::CODE_TARGET); | 1105 RelocInfo::CODE_TARGET); |
| 1111 } | 1106 } |
| 1112 | 1107 |
| 1113 | |
| 1114 // static | 1108 // static |
| 1115 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { | 1109 void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { |
| 1116 // ----------- S t a t e ------------- | 1110 // ----------- S t a t e ------------- |
| 1117 // -- a0 : argument count (not including receiver) | 1111 // -- a0 : argument count (not including receiver) |
| 1118 // -- a3 : new target | 1112 // -- a3 : new target |
| 1119 // -- a1 : constructor to call | 1113 // -- a1 : constructor to call |
| 1120 // -- a2 : address of the first argument | 1114 // -- a2 : address of the first argument |
| 1121 // ----------------------------------- | 1115 // ----------------------------------- |
| 1122 | 1116 |
| 1123 // Find the address of the last argument. | 1117 // Find the address of the last argument. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1134 __ ld(t1, MemOperand(a2)); | 1128 __ ld(t1, MemOperand(a2)); |
| 1135 __ Daddu(a2, a2, Operand(-kPointerSize)); | 1129 __ Daddu(a2, a2, Operand(-kPointerSize)); |
| 1136 __ push(t1); | 1130 __ push(t1); |
| 1137 __ bind(&loop_check); | 1131 __ bind(&loop_check); |
| 1138 __ Branch(&loop_header, gt, a2, Operand(t0)); | 1132 __ Branch(&loop_header, gt, a2, Operand(t0)); |
| 1139 | 1133 |
| 1140 // Call the constructor with a0, a1, and a3 unmodified. | 1134 // Call the constructor with a0, a1, and a3 unmodified. |
| 1141 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 1135 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 1142 } | 1136 } |
| 1143 | 1137 |
| 1138 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
| 1139 // Set the return address to the correct point in the interpreter entry |
| 1140 // trampoline. |
| 1141 Smi* interpreter_entry_return_pc_offset( |
| 1142 masm->isolate()->heap()->interpreter_entry_return_pc_offset()); |
| 1143 DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0)); |
| 1144 __ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline())); |
| 1145 __ Daddu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() + |
| 1146 Code::kHeaderSize - kHeapObjectTag)); |
| 1144 | 1147 |
| 1145 static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) { | |
| 1146 // Initialize the dispatch table register. | 1148 // Initialize the dispatch table register. |
| 1147 __ li(kInterpreterDispatchTableRegister, | 1149 __ li(kInterpreterDispatchTableRegister, |
| 1148 Operand(ExternalReference::interpreter_dispatch_table_address( | 1150 Operand(ExternalReference::interpreter_dispatch_table_address( |
| 1149 masm->isolate()))); | 1151 masm->isolate()))); |
| 1150 | 1152 |
| 1151 // Get the bytecode array pointer from the frame. | 1153 // Get the bytecode array pointer from the frame. |
| 1152 __ ld(kInterpreterBytecodeArrayRegister, | 1154 __ ld(kInterpreterBytecodeArrayRegister, |
| 1153 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 1155 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
| 1154 | 1156 |
| 1155 if (FLAG_debug_code) { | 1157 if (FLAG_debug_code) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1169 | 1171 |
| 1170 // Dispatch to the target bytecode. | 1172 // Dispatch to the target bytecode. |
| 1171 __ Daddu(a1, kInterpreterBytecodeArrayRegister, | 1173 __ Daddu(a1, kInterpreterBytecodeArrayRegister, |
| 1172 kInterpreterBytecodeOffsetRegister); | 1174 kInterpreterBytecodeOffsetRegister); |
| 1173 __ lbu(a1, MemOperand(a1)); | 1175 __ lbu(a1, MemOperand(a1)); |
| 1174 __ Dlsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2); | 1176 __ Dlsa(a1, kInterpreterDispatchTableRegister, a1, kPointerSizeLog2); |
| 1175 __ ld(a1, MemOperand(a1)); | 1177 __ ld(a1, MemOperand(a1)); |
| 1176 __ Jump(a1); | 1178 __ Jump(a1); |
| 1177 } | 1179 } |
| 1178 | 1180 |
| 1179 | |
| 1180 static void Generate_InterpreterNotifyDeoptimizedHelper( | |
| 1181 MacroAssembler* masm, Deoptimizer::BailoutType type) { | |
| 1182 // Enter an internal frame. | |
| 1183 { | |
| 1184 FrameScope scope(masm, StackFrame::INTERNAL); | |
| 1185 | |
| 1186 // Pass the deoptimization type to the runtime system. | |
| 1187 __ li(a1, Operand(Smi::FromInt(static_cast<int>(type)))); | |
| 1188 __ push(a1); | |
| 1189 __ CallRuntime(Runtime::kNotifyDeoptimized); | |
| 1190 // Tear down internal frame. | |
| 1191 } | |
| 1192 | |
| 1193 // Drop state (we don't use these for interpreter deopts) and and pop the | |
| 1194 // accumulator value into the accumulator register. | |
| 1195 __ Drop(1); | |
| 1196 __ Pop(kInterpreterAccumulatorRegister); | |
| 1197 | |
| 1198 // Enter the bytecode dispatch. | |
| 1199 Generate_EnterBytecodeDispatch(masm); | |
| 1200 } | |
| 1201 | |
| 1202 | |
| 1203 void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) { | |
| 1204 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER); | |
| 1205 } | |
| 1206 | |
| 1207 | |
| 1208 void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) { | |
| 1209 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT); | |
| 1210 } | |
| 1211 | |
| 1212 | |
| 1213 void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) { | |
| 1214 Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | |
| 1215 } | |
| 1216 | |
| 1217 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | |
| 1218 // Set the address of the interpreter entry trampoline as a return address. | |
| 1219 // This simulates the initial call to bytecode handlers in interpreter entry | |
| 1220 // trampoline. The return will never actually be taken, but our stack walker | |
| 1221 // uses this address to determine whether a frame is interpreted. | |
| 1222 __ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline())); | |
| 1223 | |
| 1224 Generate_EnterBytecodeDispatch(masm); | |
| 1225 } | |
| 1226 | |
| 1227 | |
| 1228 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 1181 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
| 1229 // ----------- S t a t e ------------- | 1182 // ----------- S t a t e ------------- |
| 1230 // -- a0 : argument count (preserved for callee) | 1183 // -- a0 : argument count (preserved for callee) |
| 1231 // -- a3 : new target (preserved for callee) | 1184 // -- a3 : new target (preserved for callee) |
| 1232 // -- a1 : target function (preserved for callee) | 1185 // -- a1 : target function (preserved for callee) |
| 1233 // ----------------------------------- | 1186 // ----------------------------------- |
| 1234 // First lookup code, maybe we don't need to compile! | 1187 // First lookup code, maybe we don't need to compile! |
| 1235 Label gotta_call_runtime, gotta_call_runtime_no_stack; | 1188 Label gotta_call_runtime, gotta_call_runtime_no_stack; |
| 1236 Label maybe_call_runtime; | 1189 Label maybe_call_runtime; |
| 1237 Label try_shared; | 1190 Label try_shared; |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 __ li(a0, Operand(Smi::FromInt(static_cast<int>(type)))); | 1467 __ li(a0, Operand(Smi::FromInt(static_cast<int>(type)))); |
| 1515 __ push(a0); | 1468 __ push(a0); |
| 1516 __ CallRuntime(Runtime::kNotifyDeoptimized); | 1469 __ CallRuntime(Runtime::kNotifyDeoptimized); |
| 1517 } | 1470 } |
| 1518 | 1471 |
| 1519 // Get the full codegen state from the stack and untag it -> a6. | 1472 // Get the full codegen state from the stack and untag it -> a6. |
| 1520 __ ld(a6, MemOperand(sp, 0 * kPointerSize)); | 1473 __ ld(a6, MemOperand(sp, 0 * kPointerSize)); |
| 1521 __ SmiUntag(a6); | 1474 __ SmiUntag(a6); |
| 1522 // Switch on the state. | 1475 // Switch on the state. |
| 1523 Label with_tos_register, unknown_state; | 1476 Label with_tos_register, unknown_state; |
| 1524 __ Branch(&with_tos_register, | 1477 __ Branch(&with_tos_register, ne, a6, |
| 1525 ne, a6, Operand(FullCodeGenerator::NO_REGISTERS)); | 1478 Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS))); |
| 1526 __ Ret(USE_DELAY_SLOT); | 1479 __ Ret(USE_DELAY_SLOT); |
| 1527 // Safe to fill delay slot Addu will emit one instruction. | 1480 // Safe to fill delay slot Addu will emit one instruction. |
| 1528 __ Daddu(sp, sp, Operand(1 * kPointerSize)); // Remove state. | 1481 __ Daddu(sp, sp, Operand(1 * kPointerSize)); // Remove state. |
| 1529 | 1482 |
| 1530 __ bind(&with_tos_register); | 1483 __ bind(&with_tos_register); |
| 1484 DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code()); |
| 1531 __ ld(v0, MemOperand(sp, 1 * kPointerSize)); | 1485 __ ld(v0, MemOperand(sp, 1 * kPointerSize)); |
| 1532 __ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG)); | 1486 __ Branch(&unknown_state, ne, t2, |
| 1487 Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER))); |
| 1533 | 1488 |
| 1534 __ Ret(USE_DELAY_SLOT); | 1489 __ Ret(USE_DELAY_SLOT); |
| 1535 // Safe to fill delay slot Addu will emit one instruction. | 1490 // Safe to fill delay slot Addu will emit one instruction. |
| 1536 __ Daddu(sp, sp, Operand(2 * kPointerSize)); // Remove state. | 1491 __ Daddu(sp, sp, Operand(2 * kPointerSize)); // Remove state. |
| 1537 | 1492 |
| 1538 __ bind(&unknown_state); | 1493 __ bind(&unknown_state); |
| 1539 __ stop("no cases left"); | 1494 __ stop("no cases left"); |
| 1540 } | 1495 } |
| 1541 | 1496 |
| 1542 | 1497 |
| (...skipping 1341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2884 } | 2839 } |
| 2885 } | 2840 } |
| 2886 | 2841 |
| 2887 | 2842 |
| 2888 #undef __ | 2843 #undef __ |
| 2889 | 2844 |
| 2890 } // namespace internal | 2845 } // namespace internal |
| 2891 } // namespace v8 | 2846 } // namespace v8 |
| 2892 | 2847 |
| 2893 #endif // V8_TARGET_ARCH_MIPS64 | 2848 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |