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 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
6 | 6 |
7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
8 #include "src/compiler/gap-resolver.h" | 8 #include "src/compiler/gap-resolver.h" |
9 #include "src/compiler/node-matchers.h" | 9 #include "src/compiler/node-matchers.h" |
10 #include "src/ppc/macro-assembler-ppc.h" | 10 #include "src/ppc/macro-assembler-ppc.h" |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 549 __ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
550 __ Call(ip); | 550 __ Call(ip); |
551 AddSafepointAndDeopt(instr); | 551 AddSafepointAndDeopt(instr); |
552 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 552 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
553 break; | 553 break; |
554 } | 554 } |
555 case kArchJmp: | 555 case kArchJmp: |
556 AssembleArchJump(i.InputRpo(0)); | 556 AssembleArchJump(i.InputRpo(0)); |
557 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 557 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
558 break; | 558 break; |
| 559 case kArchLookupSwitch: |
| 560 AssembleArchLookupSwitch(instr); |
| 561 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 562 break; |
| 563 case kArchTableSwitch: |
| 564 AssembleArchTableSwitch(instr); |
| 565 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
| 566 break; |
559 case kArchNop: | 567 case kArchNop: |
560 // don't emit code for nops. | 568 // don't emit code for nops. |
561 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 569 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
562 break; | 570 break; |
563 case kArchRet: | 571 case kArchRet: |
564 AssembleReturn(); | 572 AssembleReturn(); |
565 DCHECK_EQ(LeaveRC, i.OutputRCBit()); | 573 DCHECK_EQ(LeaveRC, i.OutputRCBit()); |
566 break; | 574 break; |
567 case kArchStackPointer: | 575 case kArchStackPointer: |
568 __ mr(i.OutputRegister(), sp); | 576 __ mr(i.OutputRegister(), sp); |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 } | 1076 } |
1069 break; | 1077 break; |
1070 default: | 1078 default: |
1071 UNREACHABLE(); | 1079 UNREACHABLE(); |
1072 break; | 1080 break; |
1073 } | 1081 } |
1074 __ bind(&done); | 1082 __ bind(&done); |
1075 } | 1083 } |
1076 | 1084 |
1077 | 1085 |
| 1086 void CodeGenerator::AssembleArchLookupSwitch(Instruction* instr) { |
| 1087 PPCOperandConverter i(this, instr); |
| 1088 Register input = i.InputRegister(0); |
| 1089 for (size_t index = 2; index < instr->InputCount(); index += 2) { |
| 1090 __ Cmpi(input, Operand(i.InputInt32(static_cast<int>(index + 0))), r0); |
| 1091 __ beq(GetLabel(i.InputRpo(static_cast<int>(index + 1)))); |
| 1092 } |
| 1093 AssembleArchJump(i.InputRpo(1)); |
| 1094 } |
| 1095 |
| 1096 |
| 1097 void CodeGenerator::AssembleArchTableSwitch(Instruction* instr) { |
| 1098 PPCOperandConverter i(this, instr); |
| 1099 Register input = i.InputRegister(0); |
| 1100 int32_t const case_count = static_cast<int32_t>(instr->InputCount() - 2); |
| 1101 Label** cases = zone()->NewArray<Label*>(case_count); |
| 1102 for (int32_t index = 0; index < case_count; ++index) { |
| 1103 cases[index] = GetLabel(i.InputRpo(index + 2)); |
| 1104 } |
| 1105 Label* const table = AddJumpTable(cases, case_count); |
| 1106 __ Cmpli(input, Operand(case_count), r0); |
| 1107 __ bge(GetLabel(i.InputRpo(1))); |
| 1108 __ mov_label_addr(kScratchReg, table); |
| 1109 __ ShiftLeftImm(r0, input, Operand(kPointerSizeLog2)); |
| 1110 __ LoadPX(kScratchReg, MemOperand(kScratchReg, r0)); |
| 1111 __ Jump(kScratchReg); |
| 1112 } |
| 1113 |
| 1114 |
1078 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { | 1115 void CodeGenerator::AssembleDeoptimizerCall(int deoptimization_id) { |
1079 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 1116 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
1080 isolate(), deoptimization_id, Deoptimizer::LAZY); | 1117 isolate(), deoptimization_id, Deoptimizer::LAZY); |
1081 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 1118 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
1082 } | 1119 } |
1083 | 1120 |
1084 | 1121 |
1085 void CodeGenerator::AssemblePrologue() { | 1122 void CodeGenerator::AssemblePrologue() { |
1086 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1123 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1124 int stack_slots = frame()->GetSpillSlotCount(); |
1087 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1125 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1088 #if ABI_USES_FUNCTION_DESCRIPTORS | |
1089 __ function_descriptor(); | 1126 __ function_descriptor(); |
1090 #endif | |
1091 int register_save_area_size = 0; | 1127 int register_save_area_size = 0; |
1092 RegList frame_saves = fp.bit(); | 1128 RegList frame_saves = fp.bit(); |
1093 __ mflr(r0); | 1129 __ mflr(r0); |
1094 #if V8_OOL_CONSTANT_POOL | 1130 #if V8_OOL_CONSTANT_POOL |
1095 __ Push(r0, fp, kConstantPoolRegister); | 1131 __ Push(r0, fp, kConstantPoolRegister); |
1096 // Adjust FP to point to saved FP. | 1132 // Adjust FP to point to saved FP. |
1097 __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); | 1133 __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); |
1098 register_save_area_size += kPointerSize; | 1134 register_save_area_size += kPointerSize; |
1099 frame_saves |= kConstantPoolRegister.bit(); | 1135 frame_saves |= kConstantPoolRegister.bit(); |
1100 #else | 1136 #else |
1101 __ Push(r0, fp); | 1137 __ Push(r0, fp); |
1102 __ mr(fp, sp); | 1138 __ mr(fp, sp); |
1103 #endif | 1139 #endif |
1104 // Save callee-saved registers. | 1140 // Save callee-saved registers. |
1105 const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves; | 1141 const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves; |
1106 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | 1142 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
1107 if (!((1 << i) & saves)) continue; | 1143 if (!((1 << i) & saves)) continue; |
1108 register_save_area_size += kPointerSize; | 1144 register_save_area_size += kPointerSize; |
1109 } | 1145 } |
1110 frame()->SetRegisterSaveAreaSize(register_save_area_size); | 1146 frame()->SetRegisterSaveAreaSize(register_save_area_size); |
1111 __ MultiPush(saves); | 1147 __ MultiPush(saves); |
1112 } else if (descriptor->IsJSFunctionCall()) { | 1148 } else if (descriptor->IsJSFunctionCall()) { |
1113 CompilationInfo* info = this->info(); | 1149 CompilationInfo* info = this->info(); |
1114 __ Prologue(info->IsCodePreAgingActive()); | 1150 __ Prologue(info->IsCodePreAgingActive()); |
1115 frame()->SetRegisterSaveAreaSize( | 1151 frame()->SetRegisterSaveAreaSize( |
1116 StandardFrameConstants::kFixedFrameSizeFromFp); | 1152 StandardFrameConstants::kFixedFrameSizeFromFp); |
1117 } else { | 1153 } else if (stack_slots > 0) { |
1118 __ StubPrologue(); | 1154 __ StubPrologue(); |
1119 frame()->SetRegisterSaveAreaSize( | 1155 frame()->SetRegisterSaveAreaSize( |
1120 StandardFrameConstants::kFixedFrameSizeFromFp); | 1156 StandardFrameConstants::kFixedFrameSizeFromFp); |
1121 } | 1157 } |
1122 int stack_slots = frame()->GetSpillSlotCount(); | |
1123 | 1158 |
1124 if (info()->is_osr()) { | 1159 if (info()->is_osr()) { |
1125 // TurboFan OSR-compiled functions cannot be entered directly. | 1160 // TurboFan OSR-compiled functions cannot be entered directly. |
1126 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1161 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
1127 | 1162 |
1128 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1163 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
1129 // frame is still on the stack. Optimized code uses OSR values directly from | 1164 // frame is still on the stack. Optimized code uses OSR values directly from |
1130 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1165 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
1131 // remaining stack slots. | 1166 // remaining stack slots. |
1132 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1167 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
1133 osr_pc_offset_ = __ pc_offset(); | 1168 osr_pc_offset_ = __ pc_offset(); |
1134 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); | 1169 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); |
1135 stack_slots -= frame()->GetOsrStackSlotCount(); | 1170 stack_slots -= frame()->GetOsrStackSlotCount(); |
1136 } | 1171 } |
1137 | 1172 |
1138 if (stack_slots > 0) { | 1173 if (stack_slots > 0) { |
1139 __ Add(sp, sp, -stack_slots * kPointerSize, r0); | 1174 __ Add(sp, sp, -stack_slots * kPointerSize, r0); |
1140 } | 1175 } |
1141 } | 1176 } |
1142 | 1177 |
1143 | 1178 |
1144 void CodeGenerator::AssembleReturn() { | 1179 void CodeGenerator::AssembleReturn() { |
1145 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1180 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1181 int stack_slots = frame()->GetSpillSlotCount(); |
1146 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1182 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1147 if (frame()->GetRegisterSaveAreaSize() > 0) { | 1183 if (frame()->GetRegisterSaveAreaSize() > 0) { |
1148 // Remove this frame's spill slots first. | 1184 // Remove this frame's spill slots first. |
1149 int stack_slots = frame()->GetSpillSlotCount(); | |
1150 if (stack_slots > 0) { | 1185 if (stack_slots > 0) { |
1151 __ Add(sp, sp, stack_slots * kPointerSize, r0); | 1186 __ Add(sp, sp, stack_slots * kPointerSize, r0); |
1152 } | 1187 } |
1153 // Restore registers. | 1188 // Restore registers. |
1154 RegList frame_saves = fp.bit(); | 1189 RegList frame_saves = fp.bit(); |
1155 #if V8_OOL_CONSTANT_POOL | 1190 #if V8_OOL_CONSTANT_POOL |
1156 frame_saves |= kConstantPoolRegister.bit(); | 1191 frame_saves |= kConstantPoolRegister.bit(); |
1157 #endif | 1192 #endif |
1158 const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves; | 1193 const RegList saves = descriptor->CalleeSavedRegisters() & ~frame_saves; |
1159 if (saves != 0) { | 1194 if (saves != 0) { |
1160 __ MultiPop(saves); | 1195 __ MultiPop(saves); |
1161 } | 1196 } |
1162 } | 1197 } |
1163 __ LeaveFrame(StackFrame::MANUAL); | 1198 __ LeaveFrame(StackFrame::MANUAL); |
1164 __ Ret(); | 1199 __ Ret(); |
1165 } else { | 1200 } else if (descriptor->IsJSFunctionCall() || stack_slots > 0) { |
1166 int pop_count = descriptor->IsJSFunctionCall() | 1201 int pop_count = descriptor->IsJSFunctionCall() |
1167 ? static_cast<int>(descriptor->JSParameterCount()) | 1202 ? static_cast<int>(descriptor->JSParameterCount()) |
1168 : 0; | 1203 : 0; |
1169 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); | 1204 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); |
1170 __ Ret(); | 1205 __ Ret(); |
| 1206 } else { |
| 1207 __ Ret(); |
1171 } | 1208 } |
1172 } | 1209 } |
1173 | 1210 |
1174 | 1211 |
1175 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1212 void CodeGenerator::AssembleMove(InstructionOperand* source, |
1176 InstructionOperand* destination) { | 1213 InstructionOperand* destination) { |
1177 PPCOperandConverter g(this, NULL); | 1214 PPCOperandConverter g(this, NULL); |
1178 // Dispatch on the source and destination operand kinds. Not all | 1215 // Dispatch on the source and destination operand kinds. Not all |
1179 // combinations are possible. | 1216 // combinations are possible. |
1180 if (source->IsRegister()) { | 1217 if (source->IsRegister()) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1326 __ stfd(temp_0, dst); | 1363 __ stfd(temp_0, dst); |
1327 __ stfd(temp_1, src); | 1364 __ stfd(temp_1, src); |
1328 #endif | 1365 #endif |
1329 } else { | 1366 } else { |
1330 // No other combinations are possible. | 1367 // No other combinations are possible. |
1331 UNREACHABLE(); | 1368 UNREACHABLE(); |
1332 } | 1369 } |
1333 } | 1370 } |
1334 | 1371 |
1335 | 1372 |
| 1373 void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { |
| 1374 for (size_t index = 0; index < target_count; ++index) { |
| 1375 __ emit_label_addr(targets[index]); |
| 1376 } |
| 1377 } |
| 1378 |
| 1379 |
1336 void CodeGenerator::AddNopForSmiCodeInlining() { | 1380 void CodeGenerator::AddNopForSmiCodeInlining() { |
1337 // We do not insert nops for inlined Smi code. | 1381 // We do not insert nops for inlined Smi code. |
1338 } | 1382 } |
1339 | 1383 |
1340 | 1384 |
1341 void CodeGenerator::EnsureSpaceForLazyDeopt() { | 1385 void CodeGenerator::EnsureSpaceForLazyDeopt() { |
1342 int space_needed = Deoptimizer::patch_size(); | 1386 int space_needed = Deoptimizer::patch_size(); |
1343 if (!info()->IsStub()) { | 1387 if (!info()->IsStub()) { |
1344 // Ensure that we have enough space after the previous lazy-bailout | 1388 // Ensure that we have enough space after the previous lazy-bailout |
1345 // instruction for patching the code here. | 1389 // instruction for patching the code here. |
1346 int current_pc = masm()->pc_offset(); | 1390 int current_pc = masm()->pc_offset(); |
1347 if (current_pc < last_lazy_deopt_pc_ + space_needed) { | 1391 if (current_pc < last_lazy_deopt_pc_ + space_needed) { |
1348 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1392 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1349 DCHECK_EQ(0, padding_size % v8::internal::Assembler::kInstrSize); | 1393 DCHECK_EQ(0, padding_size % v8::internal::Assembler::kInstrSize); |
1350 while (padding_size > 0) { | 1394 while (padding_size > 0) { |
1351 __ nop(); | 1395 __ nop(); |
1352 padding_size -= v8::internal::Assembler::kInstrSize; | 1396 padding_size -= v8::internal::Assembler::kInstrSize; |
1353 } | 1397 } |
1354 } | 1398 } |
1355 } | 1399 } |
1356 MarkLazyDeoptSite(); | 1400 MarkLazyDeoptSite(); |
1357 } | 1401 } |
1358 | 1402 |
1359 #undef __ | 1403 #undef __ |
1360 | 1404 |
1361 } // namespace compiler | 1405 } // namespace compiler |
1362 } // namespace internal | 1406 } // namespace internal |
1363 } // namespace v8 | 1407 } // namespace v8 |
OLD | NEW |