OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_S390 | 5 #if V8_TARGET_ARCH_S390 |
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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 __ LoadRR(r4, r2); | 417 __ LoadRR(r4, r2); |
418 | 418 |
419 // Restore target function and new target. | 419 // Restore target function and new target. |
420 __ Pop(r2, r3, r5); | 420 __ Pop(r2, r3, r5); |
421 __ SmiUntag(r2); | 421 __ SmiUntag(r2); |
422 } | 422 } |
423 __ AddP(ip, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); | 423 __ AddP(ip, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); |
424 __ JumpToJSEntry(ip); | 424 __ JumpToJSEntry(ip); |
425 } | 425 } |
426 | 426 |
427 void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) { | |
428 // Checking whether the queued function is ready for install is optional, | |
429 // since we come across interrupts and stack checks elsewhere. However, | |
430 // not checking may delay installing ready functions, and always checking | |
431 // would be quite expensive. A good compromise is to first check against | |
432 // stack limit as a cue for an interrupt signal. | |
433 Label ok; | |
434 __ CmpLogicalP(sp, RootMemOperand(Heap::kStackLimitRootIndex)); | |
435 __ bge(&ok, Label::kNear); | |
436 | |
437 GenerateTailCallToReturnedCode(masm, Runtime::kTryInstallOptimizedCode); | |
438 | |
439 __ bind(&ok); | |
440 GenerateTailCallToSharedCode(masm); | |
441 } | |
442 | |
443 namespace { | 427 namespace { |
444 | 428 |
445 void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { | 429 void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { |
446 Label post_instantiation_deopt_entry; | 430 Label post_instantiation_deopt_entry; |
447 // ----------- S t a t e ------------- | 431 // ----------- S t a t e ------------- |
448 // -- r2 : number of arguments | 432 // -- r2 : number of arguments |
449 // -- r3 : constructor function | 433 // -- r3 : constructor function |
450 // -- r5 : new target | 434 // -- r5 : new target |
451 // -- cp : context | 435 // -- cp : context |
452 // -- lr : return address | 436 // -- lr : return address |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); | 1006 MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp)); |
1023 __ LoadlW(args_count, | 1007 __ LoadlW(args_count, |
1024 FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset)); | 1008 FieldMemOperand(args_count, BytecodeArray::kParameterSizeOffset)); |
1025 | 1009 |
1026 // Leave the frame (also dropping the register file). | 1010 // Leave the frame (also dropping the register file). |
1027 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 1011 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
1028 | 1012 |
1029 __ AddP(sp, sp, args_count); | 1013 __ AddP(sp, sp, args_count); |
1030 } | 1014 } |
1031 | 1015 |
| 1016 // Tail-call |function_id| if |smi_entry| == |marker| |
| 1017 static void TailCallRuntimeIfMarkerEquals(MacroAssembler* masm, |
| 1018 Register smi_entry, |
| 1019 OptimizationMarker marker, |
| 1020 Runtime::FunctionId function_id) { |
| 1021 Label no_match; |
| 1022 __ CmpSmiLiteral(smi_entry, Smi::FromEnum(marker), r0); |
| 1023 __ bne(&no_match); |
| 1024 GenerateTailCallToReturnedCode(masm, function_id); |
| 1025 __ bind(&no_match); |
| 1026 } |
| 1027 |
| 1028 static void MaybeTailCallOptimizedCodeSlot(MacroAssembler* masm, |
| 1029 Register feedback_vector, |
| 1030 Register scratch1, Register scratch2, |
| 1031 Register scratch3) { |
| 1032 // ----------- S t a t e ------------- |
| 1033 // -- r0 : argument count (preserved for callee if needed, and caller) |
| 1034 // -- r3 : new target (preserved for callee if needed, and caller) |
| 1035 // -- r1 : target function (preserved for callee if needed, and caller) |
| 1036 // -- feedback vector (preserved for caller if needed) |
| 1037 // ----------------------------------- |
| 1038 DCHECK( |
| 1039 !AreAliased(feedback_vector, r2, r3, r5, scratch1, scratch2, scratch3)); |
| 1040 |
| 1041 Label optimized_code_slot_is_cell, fallthrough; |
| 1042 |
| 1043 Register closure = r3; |
| 1044 Register optimized_code_entry = scratch1; |
| 1045 |
| 1046 const int kOptimizedCodeCellOffset = |
| 1047 FeedbackVector::kOptimizedCodeIndex * kPointerSize + |
| 1048 FeedbackVector::kHeaderSize; |
| 1049 __ LoadP(optimized_code_entry, |
| 1050 FieldMemOperand(feedback_vector, kOptimizedCodeCellOffset)); |
| 1051 |
| 1052 // Check if the code entry is a Smi. If yes, we interpret it as an |
| 1053 // optimisation marker. Otherwise, interpret is as a weak cell to a code |
| 1054 // object. |
| 1055 __ JumpIfNotSmi(optimized_code_entry, &optimized_code_slot_is_cell); |
| 1056 |
| 1057 { |
| 1058 // Optimized code slot is a Smi optimization marker. |
| 1059 |
| 1060 // Fall through if no optimization trigger. |
| 1061 __ CmpSmiLiteral(optimized_code_entry, |
| 1062 Smi::FromEnum(OptimizationMarker::kNone), r0); |
| 1063 __ beq(&fallthrough); |
| 1064 |
| 1065 TailCallRuntimeIfMarkerEquals(masm, optimized_code_entry, |
| 1066 OptimizationMarker::kCompileOptimized, |
| 1067 Runtime::kCompileOptimized_NotConcurrent); |
| 1068 TailCallRuntimeIfMarkerEquals( |
| 1069 masm, optimized_code_entry, |
| 1070 OptimizationMarker::kCompileOptimizedConcurrent, |
| 1071 Runtime::kCompileOptimized_Concurrent); |
| 1072 |
| 1073 { |
| 1074 // Otherwise, the marker is InOptimizationQueue. |
| 1075 if (FLAG_debug_code) { |
| 1076 __ CmpSmiLiteral( |
| 1077 optimized_code_entry, |
| 1078 Smi::FromEnum(OptimizationMarker::kInOptimizationQueue), r0); |
| 1079 __ Assert(eq, kExpectedOptimizationSentinel); |
| 1080 } |
| 1081 |
| 1082 // Checking whether the queued function is ready for install is optional, |
| 1083 // since we come across interrupts and stack checks elsewhere. However, |
| 1084 // not checking may delay installing ready functions, and always checking |
| 1085 // would be quite expensive. A good compromise is to first check against |
| 1086 // stack limit as a cue for an interrupt signal. |
| 1087 __ CmpLogicalP(sp, RootMemOperand(Heap::kStackLimitRootIndex)); |
| 1088 __ bge(&fallthrough, Label::kNear); |
| 1089 GenerateTailCallToReturnedCode(masm, Runtime::kTryInstallOptimizedCode); |
| 1090 } |
| 1091 } |
| 1092 |
| 1093 { |
| 1094 // Optimized code slot is a WeakCell. |
| 1095 __ bind(&optimized_code_slot_is_cell); |
| 1096 |
| 1097 __ LoadP(optimized_code_entry, |
| 1098 FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset)); |
| 1099 __ JumpIfSmi(optimized_code_entry, &fallthrough); |
| 1100 |
| 1101 // Check if the optimized code is marked for deopt. If it is, call the |
| 1102 // runtime to clear it. |
| 1103 Label found_deoptimized_code; |
| 1104 __ LoadP(scratch2, FieldMemOperand(optimized_code_entry, |
| 1105 Code::kKindSpecificFlags1Offset)); |
| 1106 __ TestBit(scratch2, Code::kMarkedForDeoptimizationBit, r0); |
| 1107 __ bne(&found_deoptimized_code); |
| 1108 |
| 1109 // Optimized code is good, get it into the closure and link the closure into |
| 1110 // the optimized functions list, then tail call the optimized code. |
| 1111 // The feedback vector is no longer used, so re-use it as a scratch |
| 1112 // register. |
| 1113 ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, closure, |
| 1114 scratch2, scratch3, feedback_vector); |
| 1115 __ Jump(optimized_code_entry); |
| 1116 |
| 1117 // Optimized code slot contains deoptimized code, evict it and re-enter the |
| 1118 // closure's code. |
| 1119 __ bind(&found_deoptimized_code); |
| 1120 GenerateTailCallToReturnedCode(masm, Runtime::kEvictOptimizedCodeSlot); |
| 1121 } |
| 1122 |
| 1123 // Fall-through if the optimized code cell is clear and there is no |
| 1124 // optimization marker. |
| 1125 __ bind(&fallthrough); |
| 1126 } |
| 1127 |
1032 // Generate code for entering a JS function with the interpreter. | 1128 // Generate code for entering a JS function with the interpreter. |
1033 // On entry to the function the receiver and arguments have been pushed on the | 1129 // On entry to the function the receiver and arguments have been pushed on the |
1034 // stack left to right. The actual argument count matches the formal parameter | 1130 // stack left to right. The actual argument count matches the formal parameter |
1035 // count expected by the function. | 1131 // count expected by the function. |
1036 // | 1132 // |
1037 // The live registers are: | 1133 // The live registers are: |
1038 // o r3: the JS function object being called. | 1134 // o r3: the JS function object being called. |
1039 // o r5: the new target | 1135 // o r5: the new target |
1040 // o cp: our context | 1136 // o cp: our context |
1041 // o pp: the caller's constant pool pointer (if enabled) | 1137 // o pp: the caller's constant pool pointer (if enabled) |
1042 // o fp: the caller's frame pointer | 1138 // o fp: the caller's frame pointer |
1043 // o sp: stack pointer | 1139 // o sp: stack pointer |
1044 // o lr: return address | 1140 // o lr: return address |
1045 // | 1141 // |
1046 // The function builds an interpreter frame. See InterpreterFrameConstants in | 1142 // The function builds an interpreter frame. See InterpreterFrameConstants in |
1047 // frames.h for its layout. | 1143 // frames.h for its layout. |
1048 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { | 1144 void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) { |
1049 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 1145 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
1050 | 1146 |
| 1147 Register closure = r3; |
| 1148 Register feedback_vector = r4; |
| 1149 |
| 1150 // Load the feedback vector from the closure. |
| 1151 __ LoadP(feedback_vector, |
| 1152 FieldMemOperand(closure, JSFunction::kFeedbackVectorOffset)); |
| 1153 __ LoadP(feedback_vector, |
| 1154 FieldMemOperand(feedback_vector, Cell::kValueOffset)); |
| 1155 // Read off the optimized code slot in the feedback vector, and if there |
| 1156 // is optimized code or an optimization marker, call that instead. |
| 1157 MaybeTailCallOptimizedCodeSlot(masm, feedback_vector, r6, r8, r7); |
| 1158 |
1051 // Open a frame scope to indicate that there is a frame on the stack. The | 1159 // Open a frame scope to indicate that there is a frame on the stack. The |
1052 // MANUAL indicates that the scope shouldn't actually generate code to set up | 1160 // MANUAL indicates that the scope shouldn't actually generate code to set up |
1053 // the frame (that is done below). | 1161 // the frame (that is done below). |
1054 FrameScope frame_scope(masm, StackFrame::MANUAL); | 1162 FrameScope frame_scope(masm, StackFrame::MANUAL); |
1055 __ PushStandardFrame(r3); | 1163 __ PushStandardFrame(closure); |
1056 | |
1057 // First check if there is optimized code in the feedback vector which we | |
1058 // could call instead. | |
1059 Label switch_to_optimized_code; | |
1060 | |
1061 Register optimized_code_entry = r6; | |
1062 __ LoadP(r2, FieldMemOperand(r3, JSFunction::kFeedbackVectorOffset)); | |
1063 __ LoadP(r2, FieldMemOperand(r2, Cell::kValueOffset)); | |
1064 __ LoadP( | |
1065 optimized_code_entry, | |
1066 FieldMemOperand(r2, FeedbackVector::kOptimizedCodeIndex * kPointerSize + | |
1067 FeedbackVector::kHeaderSize)); | |
1068 __ LoadP(optimized_code_entry, | |
1069 FieldMemOperand(optimized_code_entry, WeakCell::kValueOffset)); | |
1070 __ JumpIfNotSmi(optimized_code_entry, &switch_to_optimized_code); | |
1071 | 1164 |
1072 // Get the bytecode array from the function object (or from the DebugInfo if | 1165 // Get the bytecode array from the function object (or from the DebugInfo if |
1073 // it is present) and load it into kInterpreterBytecodeArrayRegister. | 1166 // it is present) and load it into kInterpreterBytecodeArrayRegister. |
1074 Label maybe_load_debug_bytecode_array, bytecode_array_loaded; | 1167 Label maybe_load_debug_bytecode_array, bytecode_array_loaded; |
1075 __ LoadP(r2, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset)); | 1168 __ LoadP(r2, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset)); |
1076 // Load original bytecode array or the debug copy. | 1169 // Load original bytecode array or the debug copy. |
1077 __ LoadP(kInterpreterBytecodeArrayRegister, | 1170 __ LoadP(kInterpreterBytecodeArrayRegister, |
1078 FieldMemOperand(r2, SharedFunctionInfo::kFunctionDataOffset)); | 1171 FieldMemOperand(r2, SharedFunctionInfo::kFunctionDataOffset)); |
1079 __ LoadP(r4, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); | 1172 __ LoadP(r6, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); |
1080 | 1173 __ TestIfSmi(r6); |
1081 __ TestIfSmi(r4); | |
1082 __ bne(&maybe_load_debug_bytecode_array); | 1174 __ bne(&maybe_load_debug_bytecode_array); |
1083 __ bind(&bytecode_array_loaded); | 1175 __ bind(&bytecode_array_loaded); |
1084 | 1176 |
1085 // Check whether we should continue to use the interpreter. | 1177 // Check whether we should continue to use the interpreter. |
1086 // TODO(rmcilroy) Remove self healing once liveedit only has to deal with | 1178 // TODO(rmcilroy) Remove self healing once liveedit only has to deal with |
1087 // Ignition bytecode. | 1179 // Ignition bytecode. |
1088 Label switch_to_different_code_kind; | 1180 Label switch_to_different_code_kind; |
1089 __ LoadP(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset)); | 1181 __ LoadP(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset)); |
1090 __ CmpP(r2, Operand(masm->CodeObject())); // Self-reference to this code. | 1182 __ CmpP(r2, Operand(masm->CodeObject())); // Self-reference to this code. |
1091 __ bne(&switch_to_different_code_kind); | 1183 __ bne(&switch_to_different_code_kind); |
1092 | 1184 |
1093 // Increment invocation count for the function. | 1185 // Increment invocation count for the function. |
1094 __ LoadP(r6, FieldMemOperand(r3, JSFunction::kFeedbackVectorOffset)); | 1186 __ LoadP( |
1095 __ LoadP(r6, FieldMemOperand(r6, Cell::kValueOffset)); | 1187 r1, FieldMemOperand(feedback_vector, |
1096 __ LoadP(r1, FieldMemOperand( | 1188 FeedbackVector::kInvocationCountIndex * kPointerSize + |
1097 r6, FeedbackVector::kInvocationCountIndex * kPointerSize + | 1189 FeedbackVector::kHeaderSize)); |
1098 FeedbackVector::kHeaderSize)); | |
1099 __ AddSmiLiteral(r1, r1, Smi::FromInt(1), r0); | 1190 __ AddSmiLiteral(r1, r1, Smi::FromInt(1), r0); |
1100 __ StoreP(r1, FieldMemOperand( | 1191 __ StoreP( |
1101 r6, FeedbackVector::kInvocationCountIndex * kPointerSize + | 1192 r1, FieldMemOperand(feedback_vector, |
1102 FeedbackVector::kHeaderSize)); | 1193 FeedbackVector::kInvocationCountIndex * kPointerSize + |
| 1194 FeedbackVector::kHeaderSize)); |
1103 | 1195 |
1104 // Check function data field is actually a BytecodeArray object. | 1196 // Check function data field is actually a BytecodeArray object. |
1105 if (FLAG_debug_code) { | 1197 if (FLAG_debug_code) { |
1106 __ TestIfSmi(kInterpreterBytecodeArrayRegister); | 1198 __ TestIfSmi(kInterpreterBytecodeArrayRegister); |
1107 __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); | 1199 __ Assert(ne, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); |
1108 __ CompareObjectType(kInterpreterBytecodeArrayRegister, r2, no_reg, | 1200 __ CompareObjectType(kInterpreterBytecodeArrayRegister, r2, no_reg, |
1109 BYTECODE_ARRAY_TYPE); | 1201 BYTECODE_ARRAY_TYPE); |
1110 __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); | 1202 __ Assert(eq, kFunctionDataShouldBeBytecodeArrayOnInterpreterEntry); |
1111 } | 1203 } |
1112 | 1204 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1171 | 1263 |
1172 // The return value is in r2. | 1264 // The return value is in r2. |
1173 LeaveInterpreterFrame(masm, r4); | 1265 LeaveInterpreterFrame(masm, r4); |
1174 __ Ret(); | 1266 __ Ret(); |
1175 | 1267 |
1176 // Load debug copy of the bytecode array if it exists. | 1268 // Load debug copy of the bytecode array if it exists. |
1177 // kInterpreterBytecodeArrayRegister is already loaded with | 1269 // kInterpreterBytecodeArrayRegister is already loaded with |
1178 // SharedFunctionInfo::kFunctionDataOffset. | 1270 // SharedFunctionInfo::kFunctionDataOffset. |
1179 Label done; | 1271 Label done; |
1180 __ bind(&maybe_load_debug_bytecode_array); | 1272 __ bind(&maybe_load_debug_bytecode_array); |
1181 __ LoadP(ip, FieldMemOperand(r4, DebugInfo::kFlagsOffset)); | 1273 __ LoadP(ip, FieldMemOperand(r6, DebugInfo::kFlagsOffset)); |
1182 __ SmiUntag(ip); | 1274 __ SmiUntag(ip); |
1183 __ tmll(ip, Operand(DebugInfo::kHasBreakInfo)); | 1275 __ tmll(ip, Operand(DebugInfo::kHasBreakInfo)); |
1184 __ beq(&done); | 1276 __ beq(&done); |
1185 __ LoadP(kInterpreterBytecodeArrayRegister, | 1277 __ LoadP(kInterpreterBytecodeArrayRegister, |
1186 FieldMemOperand(r4, DebugInfo::kDebugBytecodeArrayOffset)); | 1278 FieldMemOperand(r6, DebugInfo::kDebugBytecodeArrayOffset)); |
1187 __ bind(&done); | 1279 __ bind(&done); |
1188 __ b(&bytecode_array_loaded); | 1280 __ b(&bytecode_array_loaded); |
1189 | 1281 |
1190 // If the shared code is no longer this entry trampoline, then the underlying | 1282 // If the shared code is no longer this entry trampoline, then the underlying |
1191 // function has been switched to a different kind of code and we heal the | 1283 // function has been switched to a different kind of code and we heal the |
1192 // closure by switching the code entry field over to the new code as well. | 1284 // closure by switching the code entry field over to the new code as well. |
1193 __ bind(&switch_to_different_code_kind); | 1285 __ bind(&switch_to_different_code_kind); |
1194 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | 1286 __ LeaveFrame(StackFrame::JAVA_SCRIPT); |
1195 __ LoadP(r6, FieldMemOperand(r3, JSFunction::kSharedFunctionInfoOffset)); | 1287 __ LoadP(r6, FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset)); |
1196 __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kCodeOffset)); | 1288 __ LoadP(r6, FieldMemOperand(r6, SharedFunctionInfo::kCodeOffset)); |
1197 __ AddP(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1289 __ AddP(r6, r6, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1198 __ StoreP(r6, FieldMemOperand(r3, JSFunction::kCodeEntryOffset), r0); | 1290 __ StoreP(r6, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0); |
1199 __ RecordWriteCodeEntryField(r3, r6, r7); | 1291 __ RecordWriteCodeEntryField(closure, r6, r7); |
1200 __ JumpToJSEntry(r6); | 1292 __ JumpToJSEntry(r6); |
1201 | |
1202 // If there is optimized code on the type feedback vector, check if it is good | |
1203 // to run, and if so, self heal the closure and call the optimized code. | |
1204 __ bind(&switch_to_optimized_code); | |
1205 __ LeaveFrame(StackFrame::JAVA_SCRIPT); | |
1206 Label gotta_call_runtime; | |
1207 | |
1208 // Check if the optimized code is marked for deopt. | |
1209 __ LoadlW(r7, FieldMemOperand(optimized_code_entry, | |
1210 Code::kKindSpecificFlags1Offset)); | |
1211 __ And(r0, r7, Operand(1 << Code::kMarkedForDeoptimizationBit)); | |
1212 __ bne(&gotta_call_runtime); | |
1213 | |
1214 // Optimized code is good, get it into the closure and link the closure into | |
1215 // the optimized functions list, then tail call the optimized code. | |
1216 ReplaceClosureEntryWithOptimizedCode(masm, optimized_code_entry, r3, r8, r7, | |
1217 r4); | |
1218 __ JumpToJSEntry(optimized_code_entry); | |
1219 | |
1220 // Optimized code is marked for deopt, bailout to the CompileLazy runtime | |
1221 // function which will clear the feedback vector's optimized code slot. | |
1222 __ bind(&gotta_call_runtime); | |
1223 GenerateTailCallToReturnedCode(masm, Runtime::kEvictOptimizedCodeSlot); | |
1224 } | 1293 } |
1225 | 1294 |
1226 static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, | 1295 static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, |
1227 Register scratch, | 1296 Register scratch, |
1228 Label* stack_overflow) { | 1297 Label* stack_overflow) { |
1229 // Check the stack for overflow. We are not trying to catch | 1298 // Check the stack for overflow. We are not trying to catch |
1230 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1299 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1231 // limit" is checked. | 1300 // limit" is checked. |
1232 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); | 1301 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); |
1233 // Make scratch the space we have left. The stack might already be overflowed | 1302 // Make scratch the space we have left. The stack might already be overflowed |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1447 __ StoreP(r4, | 1516 __ StoreP(r4, |
1448 MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); | 1517 MemOperand(fp, InterpreterFrameConstants::kBytecodeOffsetFromFp)); |
1449 | 1518 |
1450 Generate_InterpreterEnterBytecode(masm); | 1519 Generate_InterpreterEnterBytecode(masm); |
1451 } | 1520 } |
1452 | 1521 |
1453 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { | 1522 void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) { |
1454 Generate_InterpreterEnterBytecode(masm); | 1523 Generate_InterpreterEnterBytecode(masm); |
1455 } | 1524 } |
1456 | 1525 |
| 1526 void Builtins::Generate_CheckOptimizationMarker(MacroAssembler* masm) { |
| 1527 // ----------- S t a t e ------------- |
| 1528 // -- r3 : argument count (preserved for callee) |
| 1529 // -- r6 : new target (preserved for callee) |
| 1530 // -- r4 : target function (preserved for callee) |
| 1531 // ----------------------------------- |
| 1532 Register closure = r3; |
| 1533 |
| 1534 // Get the feedback vector. |
| 1535 Register feedback_vector = r4; |
| 1536 __ LoadP(feedback_vector, |
| 1537 FieldMemOperand(closure, JSFunction::kFeedbackVectorOffset)); |
| 1538 __ LoadP(feedback_vector, |
| 1539 FieldMemOperand(feedback_vector, Cell::kValueOffset)); |
| 1540 |
| 1541 // The feedback vector must be defined. |
| 1542 if (FLAG_debug_code) { |
| 1543 __ CompareRoot(feedback_vector, Heap::kUndefinedValueRootIndex); |
| 1544 __ Assert(ne, BailoutReason::kExpectedFeedbackVector); |
| 1545 } |
| 1546 |
| 1547 // Is there an optimization marker or optimized code in the feedback vector? |
| 1548 MaybeTailCallOptimizedCodeSlot(masm, feedback_vector, r6, r8, r7); |
| 1549 |
| 1550 // Otherwise, tail call the SFI code. |
| 1551 GenerateTailCallToSharedCode(masm); |
| 1552 } |
| 1553 |
1457 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { | 1554 void Builtins::Generate_CompileLazy(MacroAssembler* masm) { |
1458 // ----------- S t a t e ------------- | 1555 // ----------- S t a t e ------------- |
1459 // -- r2 : argument count (preserved for callee) | 1556 // -- r2 : argument count (preserved for callee) |
1460 // -- r5 : new target (preserved for callee) | 1557 // -- r5 : new target (preserved for callee) |
1461 // -- r3 : target function (preserved for callee) | 1558 // -- r3 : target function (preserved for callee) |
1462 // ----------------------------------- | 1559 // ----------------------------------- |
1463 // First lookup code, maybe we don't need to compile! | 1560 // First lookup code, maybe we don't need to compile! |
1464 Label gotta_call_runtime; | 1561 Label gotta_call_runtime; |
1465 Label try_shared; | |
1466 | 1562 |
1467 Register closure = r3; | 1563 Register closure = r3; |
1468 Register index = r4; | 1564 Register feedback_vector = r4; |
1469 | 1565 |
1470 // Do we have a valid feedback vector? | 1566 // Do we have a valid feedback vector? |
1471 __ LoadP(index, FieldMemOperand(closure, JSFunction::kFeedbackVectorOffset)); | 1567 __ LoadP(feedback_vector, |
1472 __ LoadP(index, FieldMemOperand(index, Cell::kValueOffset)); | 1568 FieldMemOperand(closure, JSFunction::kFeedbackVectorOffset)); |
1473 __ JumpIfRoot(index, Heap::kUndefinedValueRootIndex, &gotta_call_runtime); | 1569 __ LoadP(feedback_vector, |
| 1570 FieldMemOperand(feedback_vector, Cell::kValueOffset)); |
| 1571 __ JumpIfRoot(feedback_vector, Heap::kUndefinedValueRootIndex, |
| 1572 &gotta_call_runtime); |
1474 | 1573 |
1475 // Is optimized code available in the feedback vector? | 1574 // Is there an optimization marker or optimized code in the feedback vector? |
1476 Register entry = r6; | 1575 MaybeTailCallOptimizedCodeSlot(masm, feedback_vector, r6, r8, r7); |
1477 __ LoadP(entry, FieldMemOperand(index, FeedbackVector::kOptimizedCodeIndex * | |
1478 kPointerSize + | |
1479 FeedbackVector::kHeaderSize)); | |
1480 __ LoadP(entry, FieldMemOperand(entry, WeakCell::kValueOffset)); | |
1481 __ JumpIfSmi(entry, &try_shared); | |
1482 | |
1483 // Found code, check if it is marked for deopt, if so call into runtime to | |
1484 // clear the optimized code slot. | |
1485 __ LoadlW(r7, FieldMemOperand(entry, Code::kKindSpecificFlags1Offset)); | |
1486 __ And(r0, r7, Operand(1 << Code::kMarkedForDeoptimizationBit)); | |
1487 __ bne(&gotta_call_runtime); | |
1488 | |
1489 // Code is good, get it into the closure and tail call. | |
1490 ReplaceClosureEntryWithOptimizedCode(masm, entry, closure, r8, r7, r4); | |
1491 __ JumpToJSEntry(entry); | |
1492 | 1576 |
1493 // We found no optimized code. | 1577 // We found no optimized code. |
1494 __ bind(&try_shared); | 1578 Register entry = r6; |
1495 __ LoadP(entry, | 1579 __ LoadP(entry, |
1496 FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset)); | 1580 FieldMemOperand(closure, JSFunction::kSharedFunctionInfoOffset)); |
1497 // Is the shared function marked for tier up? | |
1498 __ LoadlW(r7, | |
1499 FieldMemOperand(entry, SharedFunctionInfo::kCompilerHintsOffset)); | |
1500 __ TestBit(r7, SharedFunctionInfo::MarkedForTierUpBit::kShift, r0); | |
1501 __ bne(&gotta_call_runtime); | |
1502 | 1581 |
1503 // If SFI points to anything other than CompileLazy, install that. | 1582 // If SFI points to anything other than CompileLazy, install that. |
1504 __ LoadP(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset)); | 1583 __ LoadP(entry, FieldMemOperand(entry, SharedFunctionInfo::kCodeOffset)); |
1505 __ mov(r7, Operand(masm->CodeObject())); | 1584 __ mov(r7, Operand(masm->CodeObject())); |
1506 __ CmpP(entry, r7); | 1585 __ CmpP(entry, r7); |
1507 __ beq(&gotta_call_runtime); | 1586 __ beq(&gotta_call_runtime); |
1508 | 1587 |
1509 // Install the SFI's code entry. | 1588 // Install the SFI's code entry. |
1510 __ AddP(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1589 __ AddP(entry, entry, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1511 __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0); | 1590 __ StoreP(entry, FieldMemOperand(closure, JSFunction::kCodeEntryOffset), r0); |
1512 __ RecordWriteCodeEntryField(closure, entry, r7); | 1591 __ RecordWriteCodeEntryField(closure, entry, r7); |
1513 __ JumpToJSEntry(entry); | 1592 __ JumpToJSEntry(entry); |
1514 | 1593 |
1515 __ bind(&gotta_call_runtime); | 1594 __ bind(&gotta_call_runtime); |
1516 GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); | 1595 GenerateTailCallToReturnedCode(masm, Runtime::kCompileLazy); |
1517 } | 1596 } |
1518 | 1597 |
1519 void Builtins::Generate_CompileOptimized(MacroAssembler* masm) { | |
1520 GenerateTailCallToReturnedCode(masm, | |
1521 Runtime::kCompileOptimized_NotConcurrent); | |
1522 } | |
1523 | |
1524 void Builtins::Generate_CompileOptimizedConcurrent(MacroAssembler* masm) { | |
1525 GenerateTailCallToReturnedCode(masm, Runtime::kCompileOptimized_Concurrent); | |
1526 } | |
1527 | |
1528 void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) { | 1598 void Builtins::Generate_InstantiateAsmJs(MacroAssembler* masm) { |
1529 // ----------- S t a t e ------------- | 1599 // ----------- S t a t e ------------- |
1530 // -- r2 : argument count (preserved for callee) | 1600 // -- r2 : argument count (preserved for callee) |
1531 // -- r3 : new target (preserved for callee) | 1601 // -- r3 : new target (preserved for callee) |
1532 // -- r5 : target function (preserved for callee) | 1602 // -- r5 : target function (preserved for callee) |
1533 // ----------------------------------- | 1603 // ----------------------------------- |
1534 Label failed; | 1604 Label failed; |
1535 { | 1605 { |
1536 FrameScope scope(masm, StackFrame::INTERNAL); | 1606 FrameScope scope(masm, StackFrame::INTERNAL); |
1537 // Preserve argument count for later compare. | 1607 // Preserve argument count for later compare. |
(...skipping 1603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3141 // Now jump to the instructions of the returned code object. | 3211 // Now jump to the instructions of the returned code object. |
3142 __ Jump(ip); | 3212 __ Jump(ip); |
3143 } | 3213 } |
3144 | 3214 |
3145 #undef __ | 3215 #undef __ |
3146 | 3216 |
3147 } // namespace internal | 3217 } // namespace internal |
3148 } // namespace v8 | 3218 } // namespace v8 |
3149 | 3219 |
3150 #endif // V8_TARGET_ARCH_S390 | 3220 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |