OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
9 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 Label done; \ | 323 Label done; \ |
324 __ j(above_equal, &done, Label::kNear); \ | 324 __ j(above_equal, &done, Label::kNear); \ |
325 if (instr->InputAt(2)->IsRegister()) { \ | 325 if (instr->InputAt(2)->IsRegister()) { \ |
326 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ | 326 __ asm_instr(i.MemoryOperand(3), i.InputRegister(2)); \ |
327 } else { \ | 327 } else { \ |
328 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ | 328 __ asm_instr(i.MemoryOperand(3), i.InputImmediate(2)); \ |
329 } \ | 329 } \ |
330 __ bind(&done); \ | 330 __ bind(&done); \ |
331 } while (false) | 331 } while (false) |
332 | 332 |
| 333 void CodeGenerator::AssembleDeconstructFrame() { |
| 334 __ mov(esp, ebp); |
| 335 __ pop(ebp); |
| 336 } |
| 337 |
| 338 void CodeGenerator::SetupStackPointer() {} |
333 | 339 |
334 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 340 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { |
335 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 341 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
336 if (sp_slot_delta > 0) { | 342 if (sp_slot_delta > 0) { |
337 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); | 343 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); |
338 } | 344 } |
339 frame_access_state()->SetFrameAccessToDefault(); | 345 frame_access_state()->SetFrameAccessToDefault(); |
340 } | 346 } |
341 | 347 |
342 | 348 |
343 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | 349 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { |
344 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | 350 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); |
345 if (sp_slot_delta < 0) { | 351 if (sp_slot_delta < 0) { |
346 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | 352 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); |
347 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | 353 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); |
348 } | 354 } |
349 if (frame()->needs_frame()) { | 355 if (frame_access_state()->has_frame()) { |
350 __ mov(ebp, MemOperand(ebp, 0)); | 356 __ mov(ebp, MemOperand(ebp, 0)); |
351 } | 357 } |
352 frame_access_state()->SetFrameAccessToSP(); | 358 frame_access_state()->SetFrameAccessToSP(); |
353 } | 359 } |
354 | 360 |
355 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 361 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
356 Register, Register, | 362 Register, Register, |
357 Register) { | 363 Register) { |
358 // There are not enough temp registers left on ia32 for a call instruction | 364 // There are not enough temp registers left on ia32 for a call instruction |
359 // so we pick some scratch registers and save/restore them manually here. | 365 // so we pick some scratch registers and save/restore them manually here. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 case kArchRet: | 513 case kArchRet: |
508 AssembleReturn(); | 514 AssembleReturn(); |
509 break; | 515 break; |
510 case kArchStackPointer: | 516 case kArchStackPointer: |
511 __ mov(i.OutputRegister(), esp); | 517 __ mov(i.OutputRegister(), esp); |
512 break; | 518 break; |
513 case kArchFramePointer: | 519 case kArchFramePointer: |
514 __ mov(i.OutputRegister(), ebp); | 520 __ mov(i.OutputRegister(), ebp); |
515 break; | 521 break; |
516 case kArchParentFramePointer: | 522 case kArchParentFramePointer: |
517 if (frame_access_state()->frame()->needs_frame()) { | 523 if (frame_access_state()->has_frame()) { |
518 __ mov(i.OutputRegister(), Operand(ebp, 0)); | 524 __ mov(i.OutputRegister(), Operand(ebp, 0)); |
519 } else { | 525 } else { |
520 __ mov(i.OutputRegister(), ebp); | 526 __ mov(i.OutputRegister(), ebp); |
521 } | 527 } |
522 break; | 528 break; |
523 case kArchTruncateDoubleToI: { | 529 case kArchTruncateDoubleToI: { |
524 auto result = i.OutputRegister(); | 530 auto result = i.OutputRegister(); |
525 auto input = i.InputDoubleRegister(0); | 531 auto input = i.InputDoubleRegister(0); |
526 auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input); | 532 auto ool = new (zone()) OutOfLineTruncateDoubleToI(this, result, input); |
527 __ cvttsd2si(result, Operand(input)); | 533 __ cvttsd2si(result, Operand(input)); |
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1281 case kCheckedLoadWord64: | 1287 case kCheckedLoadWord64: |
1282 case kCheckedStoreWord64: | 1288 case kCheckedStoreWord64: |
1283 UNREACHABLE(); // currently unsupported checked int64 load/store. | 1289 UNREACHABLE(); // currently unsupported checked int64 load/store. |
1284 break; | 1290 break; |
1285 } | 1291 } |
1286 } // NOLINT(readability/fn_size) | 1292 } // NOLINT(readability/fn_size) |
1287 | 1293 |
1288 | 1294 |
1289 // Assembles a branch after an instruction. | 1295 // Assembles a branch after an instruction. |
1290 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { | 1296 void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) { |
| 1297 AssembleDeconstructFrameIfNeeded(); |
1291 IA32OperandConverter i(this, instr); | 1298 IA32OperandConverter i(this, instr); |
1292 Label::Distance flabel_distance = | 1299 Label::Distance flabel_distance = |
1293 branch->fallthru ? Label::kNear : Label::kFar; | 1300 branch->fallthru ? Label::kNear : Label::kFar; |
1294 Label* tlabel = branch->true_label; | 1301 Label* tlabel = branch->true_label; |
1295 Label* flabel = branch->false_label; | 1302 Label* flabel = branch->false_label; |
1296 switch (branch->condition) { | 1303 switch (branch->condition) { |
1297 case kUnorderedEqual: | 1304 case kUnorderedEqual: |
1298 __ j(parity_even, flabel, flabel_distance); | 1305 __ j(parity_even, flabel, flabel_distance); |
1299 // Fall through. | 1306 // Fall through. |
1300 case kEqual: | 1307 case kEqual: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 default: | 1346 default: |
1340 UNREACHABLE(); | 1347 UNREACHABLE(); |
1341 break; | 1348 break; |
1342 } | 1349 } |
1343 // Add a jump if not falling through to the next block. | 1350 // Add a jump if not falling through to the next block. |
1344 if (!branch->fallthru) __ jmp(flabel); | 1351 if (!branch->fallthru) __ jmp(flabel); |
1345 } | 1352 } |
1346 | 1353 |
1347 | 1354 |
1348 void CodeGenerator::AssembleArchJump(RpoNumber target) { | 1355 void CodeGenerator::AssembleArchJump(RpoNumber target) { |
| 1356 AssembleDeconstructFrameIfNeeded(); |
1349 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); | 1357 if (!IsNextInAssemblyOrder(target)) __ jmp(GetLabel(target)); |
1350 } | 1358 } |
1351 | 1359 |
1352 | 1360 |
1353 // Assembles boolean materializations after an instruction. | 1361 // Assembles boolean materializations after an instruction. |
1354 void CodeGenerator::AssembleArchBoolean(Instruction* instr, | 1362 void CodeGenerator::AssembleArchBoolean(Instruction* instr, |
1355 FlagsCondition condition) { | 1363 FlagsCondition condition) { |
1356 IA32OperandConverter i(this, instr); | 1364 IA32OperandConverter i(this, instr); |
1357 Label done; | 1365 Label done; |
1358 | 1366 |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 // | FP | RET | args | caller frame | | 1596 // | FP | RET | args | caller frame | |
1589 // ^ esp,ebp | 1597 // ^ esp,ebp |
1590 | 1598 |
1591 // --{ pop ebp }---------------------------------------------------------------- | 1599 // --{ pop ebp }---------------------------------------------------------------- |
1592 // | RET | args | caller frame | | 1600 // | RET | args | caller frame | |
1593 // ^ esp ^ ebp | 1601 // ^ esp ^ ebp |
1594 | 1602 |
1595 | 1603 |
1596 void CodeGenerator::AssemblePrologue() { | 1604 void CodeGenerator::AssemblePrologue() { |
1597 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1605 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1598 if (frame()->needs_frame()) { | 1606 if (frame_access_state()->has_frame()) { |
1599 if (descriptor->IsCFunctionCall()) { | 1607 if (descriptor->IsCFunctionCall()) { |
1600 __ push(ebp); | 1608 __ push(ebp); |
1601 __ mov(ebp, esp); | 1609 __ mov(ebp, esp); |
1602 } else if (descriptor->IsJSFunctionCall()) { | 1610 } else if (descriptor->IsJSFunctionCall()) { |
1603 __ Prologue(this->info()->GeneratePreagedPrologue()); | 1611 __ Prologue(this->info()->GeneratePreagedPrologue()); |
1604 } else { | 1612 } else { |
1605 __ StubPrologue(info()->GetOutputStackFrameType()); | 1613 __ StubPrologue(info()->GetOutputStackFrameType()); |
1606 } | 1614 } |
1607 } else { | |
1608 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); | |
1609 } | 1615 } |
1610 frame_access_state()->SetFrameAccessToDefault(); | |
1611 | |
1612 int stack_shrink_slots = frame()->GetSpillSlotCount(); | 1616 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
1613 if (info()->is_osr()) { | 1617 if (info()->is_osr()) { |
1614 // TurboFan OSR-compiled functions cannot be entered directly. | 1618 // TurboFan OSR-compiled functions cannot be entered directly. |
1615 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1619 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
1616 | 1620 |
1617 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1621 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
1618 // frame is still on the stack. Optimized code uses OSR values directly from | 1622 // frame is still on the stack. Optimized code uses OSR values directly from |
1619 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1623 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
1620 // remaining stack slots. | 1624 // remaining stack slots. |
1621 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1625 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
(...skipping 25 matching lines...) Expand all Loading... |
1647 const RegList saves = descriptor->CalleeSavedRegisters(); | 1651 const RegList saves = descriptor->CalleeSavedRegisters(); |
1648 // Restore registers. | 1652 // Restore registers. |
1649 if (saves != 0) { | 1653 if (saves != 0) { |
1650 for (int i = 0; i < Register::kNumRegisters; i++) { | 1654 for (int i = 0; i < Register::kNumRegisters; i++) { |
1651 if (!((1 << i) & saves)) continue; | 1655 if (!((1 << i) & saves)) continue; |
1652 __ pop(Register::from_code(i)); | 1656 __ pop(Register::from_code(i)); |
1653 } | 1657 } |
1654 } | 1658 } |
1655 | 1659 |
1656 if (descriptor->IsCFunctionCall()) { | 1660 if (descriptor->IsCFunctionCall()) { |
1657 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | 1661 AssembleDeconstructFrameIfNeeded(); |
1658 __ pop(ebp); // Pop caller's frame pointer. | 1662 } else if (frame_access_state()->has_frame()) { |
1659 } else if (frame()->needs_frame()) { | 1663 if (AssembleDeconstructFrameUsingReturnLabel()) return; |
1660 // Canonicalize JSFunction return sites for now. | |
1661 if (return_label_.is_bound()) { | |
1662 __ jmp(&return_label_); | |
1663 return; | |
1664 } else { | |
1665 __ bind(&return_label_); | |
1666 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | |
1667 __ pop(ebp); // Pop caller's frame pointer. | |
1668 } | |
1669 } | 1664 } |
1670 size_t pop_size = descriptor->StackParameterCount() * kPointerSize; | 1665 size_t pop_size = descriptor->StackParameterCount() * kPointerSize; |
1671 // Might need ecx for scratch if pop_size is too big. | 1666 // Might need ecx for scratch if pop_size is too big. |
1672 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit()); | 1667 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit()); |
1673 __ Ret(static_cast<int>(pop_size), ecx); | 1668 __ Ret(static_cast<int>(pop_size), ecx); |
1674 } | 1669 } |
1675 | 1670 |
1676 | 1671 |
1677 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1672 void CodeGenerator::AssembleMove(InstructionOperand* source, |
1678 InstructionOperand* destination) { | 1673 InstructionOperand* destination) { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 1869 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
1875 __ Nop(padding_size); | 1870 __ Nop(padding_size); |
1876 } | 1871 } |
1877 } | 1872 } |
1878 | 1873 |
1879 #undef __ | 1874 #undef __ |
1880 | 1875 |
1881 } // namespace compiler | 1876 } // namespace compiler |
1882 } // namespace internal | 1877 } // namespace internal |
1883 } // namespace v8 | 1878 } // namespace v8 |
OLD | NEW |