| 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/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/compiler/osr.h" |
| 10 #include "src/scopes.h" | 11 #include "src/scopes.h" |
| 11 #include "src/x87/assembler-x87.h" | 12 #include "src/x87/assembler-x87.h" |
| 12 #include "src/x87/frames-x87.h" | 13 #include "src/x87/frames-x87.h" |
| 13 #include "src/x87/macro-assembler-x87.h" | 14 #include "src/x87/macro-assembler-x87.h" |
| 14 | 15 |
| 15 namespace v8 { | 16 namespace v8 { |
| 16 namespace internal { | 17 namespace internal { |
| 17 namespace compiler { | 18 namespace compiler { |
| 18 | 19 |
| 19 #define __ masm()-> | 20 #define __ masm()-> |
| (...skipping 1077 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1097 __ shl(i.OutputRegister(), 3); | 1098 __ shl(i.OutputRegister(), 3); |
| 1098 } else { | 1099 } else { |
| 1099 __ lea(i.OutputRegister(), i.MemoryOperand()); | 1100 __ lea(i.OutputRegister(), i.MemoryOperand()); |
| 1100 } | 1101 } |
| 1101 } else { | 1102 } else { |
| 1102 __ lea(i.OutputRegister(), i.MemoryOperand()); | 1103 __ lea(i.OutputRegister(), i.MemoryOperand()); |
| 1103 } | 1104 } |
| 1104 break; | 1105 break; |
| 1105 } | 1106 } |
| 1106 case kX87Push: | 1107 case kX87Push: |
| 1107 if (HasImmediateInput(instr, 0)) { | 1108 if (instr->InputAt(0)->IsDoubleRegister()) { |
| 1109 auto allocated = AllocatedOperand::cast(*instr->InputAt(0)); |
| 1110 if (allocated.machine_type() == kRepFloat32) { |
| 1111 __ sub(esp, Immediate(kDoubleSize)); |
| 1112 __ fst_s(Operand(esp, 0)); |
| 1113 } else { |
| 1114 DCHECK(allocated.machine_type() == kRepFloat64); |
| 1115 __ sub(esp, Immediate(kDoubleSize)); |
| 1116 __ fst_d(Operand(esp, 0)); |
| 1117 } |
| 1118 } else if (instr->InputAt(0)->IsDoubleStackSlot()) { |
| 1119 auto allocated = AllocatedOperand::cast(*instr->InputAt(0)); |
| 1120 if (allocated.machine_type() == kRepFloat32) { |
| 1121 __ sub(esp, Immediate(kDoubleSize)); |
| 1122 __ fld_s(i.InputOperand(0)); |
| 1123 __ fstp_s(MemOperand(esp, 0)); |
| 1124 } else { |
| 1125 DCHECK(allocated.machine_type() == kRepFloat64); |
| 1126 __ sub(esp, Immediate(kDoubleSize)); |
| 1127 __ fld_d(i.InputOperand(0)); |
| 1128 __ fstp_d(MemOperand(esp, 0)); |
| 1129 } |
| 1130 } else if (HasImmediateInput(instr, 0)) { |
| 1108 __ push(i.InputImmediate(0)); | 1131 __ push(i.InputImmediate(0)); |
| 1109 } else { | 1132 } else { |
| 1110 __ push(i.InputOperand(0)); | 1133 __ push(i.InputOperand(0)); |
| 1111 } | 1134 } |
| 1112 break; | 1135 break; |
| 1113 case kX87Poke: { | 1136 case kX87Poke: { |
| 1114 int const slot = MiscField::decode(instr->opcode()); | 1137 int const slot = MiscField::decode(instr->opcode()); |
| 1115 if (HasImmediateInput(instr, 0)) { | 1138 if (HasImmediateInput(instr, 0)) { |
| 1116 __ mov(Operand(esp, slot * kPointerSize), i.InputImmediate(0)); | 1139 __ mov(Operand(esp, slot * kPointerSize), i.InputImmediate(0)); |
| 1117 } else { | 1140 } else { |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1501 // | FP | RET | args | caller frame | | 1524 // | FP | RET | args | caller frame | |
| 1502 // ^ esp,ebp | 1525 // ^ esp,ebp |
| 1503 | 1526 |
| 1504 // --{ pop ebp }---------------------------------------------------------------- | 1527 // --{ pop ebp }---------------------------------------------------------------- |
| 1505 // | RET | args | caller frame | | 1528 // | RET | args | caller frame | |
| 1506 // ^ esp ^ ebp | 1529 // ^ esp ^ ebp |
| 1507 | 1530 |
| 1508 | 1531 |
| 1509 void CodeGenerator::AssemblePrologue() { | 1532 void CodeGenerator::AssemblePrologue() { |
| 1510 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1533 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1511 int stack_slots = frame()->GetSpillSlotCount(); | |
| 1512 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1534 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
| 1513 // Assemble a prologue similar the to cdecl calling convention. | 1535 // Assemble a prologue similar the to cdecl calling convention. |
| 1514 __ push(ebp); | 1536 __ push(ebp); |
| 1515 __ mov(ebp, esp); | 1537 __ mov(ebp, esp); |
| 1516 const RegList saves = descriptor->CalleeSavedRegisters(); | |
| 1517 if (saves != 0) { // Save callee-saved registers. | |
| 1518 int register_save_area_size = 0; | |
| 1519 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | |
| 1520 if (!((1 << i) & saves)) continue; | |
| 1521 __ push(Register::from_code(i)); | |
| 1522 register_save_area_size += kPointerSize; | |
| 1523 } | |
| 1524 frame()->SetRegisterSaveAreaSize(register_save_area_size); | |
| 1525 } | |
| 1526 } else if (descriptor->IsJSFunctionCall()) { | 1538 } else if (descriptor->IsJSFunctionCall()) { |
| 1527 // TODO(turbofan): this prologue is redundant with OSR, but needed for | 1539 // TODO(turbofan): this prologue is redundant with OSR, but needed for |
| 1528 // code aging. | 1540 // code aging. |
| 1529 CompilationInfo* info = this->info(); | 1541 CompilationInfo* info = this->info(); |
| 1530 __ Prologue(info->IsCodePreAgingActive()); | 1542 __ Prologue(info->IsCodePreAgingActive()); |
| 1531 frame()->SetRegisterSaveAreaSize( | |
| 1532 StandardFrameConstants::kFixedFrameSizeFromFp); | |
| 1533 } else if (needs_frame_) { | 1543 } else if (needs_frame_) { |
| 1534 __ StubPrologue(); | 1544 __ StubPrologue(); |
| 1535 frame()->SetRegisterSaveAreaSize( | 1545 } else { |
| 1536 StandardFrameConstants::kFixedFrameSizeFromFp); | 1546 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); |
| 1537 } | 1547 } |
| 1538 | 1548 |
| 1549 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
| 1539 if (info()->is_osr()) { | 1550 if (info()->is_osr()) { |
| 1540 // TurboFan OSR-compiled functions cannot be entered directly. | 1551 // TurboFan OSR-compiled functions cannot be entered directly. |
| 1541 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1552 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
| 1542 | 1553 |
| 1543 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1554 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
| 1544 // frame is still on the stack. Optimized code uses OSR values directly from | 1555 // frame is still on the stack. Optimized code uses OSR values directly from |
| 1545 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1556 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
| 1546 // remaining stack slots. | 1557 // remaining stack slots. |
| 1547 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1558 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
| 1548 osr_pc_offset_ = __ pc_offset(); | 1559 osr_pc_offset_ = __ pc_offset(); |
| 1549 // TODO(titzer): cannot address target function == local #-1 | 1560 // TODO(titzer): cannot address target function == local #-1 |
| 1550 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 1561 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 1551 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); | 1562 stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots(); |
| 1552 stack_slots -= frame()->GetOsrStackSlotCount(); | |
| 1553 } | 1563 } |
| 1554 | 1564 |
| 1555 if (stack_slots > 0) { | 1565 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 1556 // Allocate the stack slots used by this frame. | 1566 if (stack_shrink_slots > 0) { |
| 1557 __ sub(esp, Immediate(stack_slots * kPointerSize)); | 1567 __ sub(esp, Immediate(stack_shrink_slots * kPointerSize)); |
| 1568 } |
| 1569 |
| 1570 if (saves != 0) { // Save callee-saved registers. |
| 1571 DCHECK(!info()->is_osr()); |
| 1572 int pushed = 0; |
| 1573 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
| 1574 if (!((1 << i) & saves)) continue; |
| 1575 __ push(Register::from_code(i)); |
| 1576 ++pushed; |
| 1577 } |
| 1578 frame()->AllocateSavedCalleeRegisterSlots(pushed); |
| 1558 } | 1579 } |
| 1559 | 1580 |
| 1560 // Initailize FPU state. | 1581 // Initailize FPU state. |
| 1561 __ fninit(); | 1582 __ fninit(); |
| 1562 __ fld1(); | 1583 __ fld1(); |
| 1563 } | 1584 } |
| 1564 | 1585 |
| 1565 | 1586 |
| 1566 void CodeGenerator::AssembleReturn() { | 1587 void CodeGenerator::AssembleReturn() { |
| 1567 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1588 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1568 int stack_slots = frame()->GetSpillSlotCount(); | 1589 |
| 1569 int pop_count = static_cast<int>(descriptor->StackParameterCount()); | 1590 int pop_count = static_cast<int>(descriptor->StackParameterCount()); |
| 1591 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 1592 // Restore registers. |
| 1593 if (saves != 0) { |
| 1594 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 1595 if (!((1 << i) & saves)) continue; |
| 1596 __ pop(Register::from_code(i)); |
| 1597 } |
| 1598 } |
| 1599 |
| 1570 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1600 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
| 1571 const RegList saves = descriptor->CalleeSavedRegisters(); | 1601 __ mov(esp, ebp); // Move stack pointer back to frame pointer. |
| 1572 if (frame()->GetRegisterSaveAreaSize() > 0) { | 1602 __ pop(ebp); // Pop caller's frame pointer. |
| 1573 // Remove this frame's spill slots first. | |
| 1574 if (stack_slots > 0) { | |
| 1575 __ add(esp, Immediate(stack_slots * kPointerSize)); | |
| 1576 } | |
| 1577 // Restore registers. | |
| 1578 if (saves != 0) { | |
| 1579 for (int i = 0; i < Register::kNumRegisters; i++) { | |
| 1580 if (!((1 << i) & saves)) continue; | |
| 1581 __ pop(Register::from_code(i)); | |
| 1582 } | |
| 1583 } | |
| 1584 __ pop(ebp); // Pop caller's frame pointer. | |
| 1585 } else { | |
| 1586 // No saved registers. | |
| 1587 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | |
| 1588 __ pop(ebp); // Pop caller's frame pointer. | |
| 1589 } | |
| 1590 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { | 1603 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { |
| 1591 // Canonicalize JSFunction return sites for now. | 1604 // Canonicalize JSFunction return sites for now. |
| 1592 if (return_label_.is_bound()) { | 1605 if (return_label_.is_bound()) { |
| 1593 __ jmp(&return_label_); | 1606 __ jmp(&return_label_); |
| 1594 return; | 1607 return; |
| 1595 } else { | 1608 } else { |
| 1596 __ bind(&return_label_); | 1609 __ bind(&return_label_); |
| 1597 __ mov(esp, ebp); // Move stack pointer back to frame pointer. | 1610 __ mov(esp, ebp); // Move stack pointer back to frame pointer. |
| 1598 __ pop(ebp); // Pop caller's frame pointer. | 1611 __ pop(ebp); // Pop caller's frame pointer. |
| 1599 } | 1612 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1835 __ Nop(padding_size); | 1848 __ Nop(padding_size); |
| 1836 } | 1849 } |
| 1837 } | 1850 } |
| 1838 } | 1851 } |
| 1839 | 1852 |
| 1840 #undef __ | 1853 #undef __ |
| 1841 | 1854 |
| 1842 } // namespace compiler | 1855 } // namespace compiler |
| 1843 } // namespace internal | 1856 } // namespace internal |
| 1844 } // namespace v8 | 1857 } // namespace v8 |
| OLD | NEW |