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/x64/assembler-x64.h" | 12 #include "src/x64/assembler-x64.h" |
12 #include "src/x64/macro-assembler-x64.h" | 13 #include "src/x64/macro-assembler-x64.h" |
13 | 14 |
14 namespace v8 { | 15 namespace v8 { |
15 namespace internal { | 16 namespace internal { |
16 namespace compiler { | 17 namespace compiler { |
17 | 18 |
18 #define __ masm()-> | 19 #define __ masm()-> |
19 | 20 |
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 | 1454 |
1454 | 1455 |
1455 void CodeGenerator::AssembleDeoptimizerCall( | 1456 void CodeGenerator::AssembleDeoptimizerCall( |
1456 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { | 1457 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { |
1457 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 1458 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
1458 isolate(), deoptimization_id, bailout_type); | 1459 isolate(), deoptimization_id, bailout_type); |
1459 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 1460 __ call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
1460 } | 1461 } |
1461 | 1462 |
1462 | 1463 |
| 1464 namespace { |
| 1465 |
| 1466 static const int kQuadWordSize = 16; |
| 1467 |
| 1468 } // namespace |
| 1469 |
| 1470 |
1463 void CodeGenerator::AssemblePrologue() { | 1471 void CodeGenerator::AssemblePrologue() { |
1464 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1472 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1465 int stack_slots = frame()->GetSpillSlotCount(); | |
1466 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1473 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1467 __ pushq(rbp); | 1474 __ pushq(rbp); |
1468 __ movq(rbp, rsp); | 1475 __ movq(rbp, rsp); |
1469 int register_save_area_size = 0; | |
1470 const RegList saves = descriptor->CalleeSavedRegisters(); | |
1471 if (saves != 0) { // Save callee-saved registers. | |
1472 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | |
1473 if (!((1 << i) & saves)) continue; | |
1474 __ pushq(Register::from_code(i)); | |
1475 register_save_area_size += kPointerSize; | |
1476 } | |
1477 } | |
1478 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); | |
1479 if (saves_fp != 0) { // Save callee-saved XMM registers. | |
1480 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); | |
1481 const int stack_size = saves_fp_count * 16; | |
1482 // Adjust the stack pointer. | |
1483 __ subp(rsp, Immediate(stack_size)); | |
1484 // Store the registers on the stack. | |
1485 int slot_idx = 0; | |
1486 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | |
1487 if (!((1 << i) & saves_fp)) continue; | |
1488 __ movdqu(Operand(rsp, 16 * slot_idx), XMMRegister::from_code(i)); | |
1489 slot_idx++; | |
1490 } | |
1491 register_save_area_size += stack_size; | |
1492 } | |
1493 if (register_save_area_size > 0) { | |
1494 frame()->SetRegisterSaveAreaSize(register_save_area_size); | |
1495 } | |
1496 } else if (descriptor->IsJSFunctionCall()) { | 1476 } else if (descriptor->IsJSFunctionCall()) { |
1497 CompilationInfo* info = this->info(); | 1477 CompilationInfo* info = this->info(); |
1498 __ Prologue(info->IsCodePreAgingActive()); | 1478 __ Prologue(info->IsCodePreAgingActive()); |
1499 frame()->SetRegisterSaveAreaSize( | |
1500 StandardFrameConstants::kFixedFrameSizeFromFp); | |
1501 } else if (needs_frame_) { | 1479 } else if (needs_frame_) { |
1502 __ StubPrologue(); | 1480 __ StubPrologue(); |
1503 frame()->SetRegisterSaveAreaSize( | 1481 } else { |
1504 StandardFrameConstants::kFixedFrameSizeFromFp); | 1482 frame()->SetElidedFrameSizeInSlots(kPCOnStackSize / kPointerSize); |
1505 } | 1483 } |
1506 | 1484 |
| 1485 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
1507 if (info()->is_osr()) { | 1486 if (info()->is_osr()) { |
1508 // TurboFan OSR-compiled functions cannot be entered directly. | 1487 // TurboFan OSR-compiled functions cannot be entered directly. |
1509 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1488 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
1510 | 1489 |
1511 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1490 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
1512 // frame is still on the stack. Optimized code uses OSR values directly from | 1491 // frame is still on the stack. Optimized code uses OSR values directly from |
1513 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1492 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
1514 // remaining stack slots. | 1493 // remaining stack slots. |
1515 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); | 1494 if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --"); |
1516 osr_pc_offset_ = __ pc_offset(); | 1495 osr_pc_offset_ = __ pc_offset(); |
1517 // TODO(titzer): cannot address target function == local #-1 | 1496 // TODO(titzer): cannot address target function == local #-1 |
1518 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 1497 __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1519 DCHECK(stack_slots >= frame()->GetOsrStackSlotCount()); | 1498 stack_shrink_slots -= |
1520 stack_slots -= frame()->GetOsrStackSlotCount(); | 1499 static_cast<int>(OsrHelper(info()).UnoptimizedFrameSlots()); |
1521 } | 1500 } |
1522 | 1501 |
1523 if (stack_slots > 0) { | 1502 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); |
1524 __ subq(rsp, Immediate(stack_slots * kPointerSize)); | 1503 if (saves_fp != 0) { |
| 1504 stack_shrink_slots += frame()->AlignSavedCalleeRegisterSlots(); |
| 1505 } |
| 1506 if (stack_shrink_slots > 0) { |
| 1507 __ subq(rsp, Immediate(stack_shrink_slots * kPointerSize)); |
| 1508 } |
| 1509 |
| 1510 if (saves_fp != 0) { // Save callee-saved XMM registers. |
| 1511 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); |
| 1512 const int stack_size = saves_fp_count * kQuadWordSize; |
| 1513 // Adjust the stack pointer. |
| 1514 __ subp(rsp, Immediate(stack_size)); |
| 1515 // Store the registers on the stack. |
| 1516 int slot_idx = 0; |
| 1517 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
| 1518 if (!((1 << i) & saves_fp)) continue; |
| 1519 __ movdqu(Operand(rsp, kQuadWordSize * slot_idx), |
| 1520 XMMRegister::from_code(i)); |
| 1521 slot_idx++; |
| 1522 } |
| 1523 frame()->AllocateSavedCalleeRegisterSlots(saves_fp_count * |
| 1524 (kQuadWordSize / kPointerSize)); |
| 1525 } |
| 1526 |
| 1527 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 1528 if (saves != 0) { // Save callee-saved registers. |
| 1529 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
| 1530 if (!((1 << i) & saves)) continue; |
| 1531 __ pushq(Register::from_code(i)); |
| 1532 frame()->AllocateSavedCalleeRegisterSlots(1); |
| 1533 } |
1525 } | 1534 } |
1526 } | 1535 } |
1527 | 1536 |
1528 | 1537 |
1529 void CodeGenerator::AssembleReturn() { | 1538 void CodeGenerator::AssembleReturn() { |
1530 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1539 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
1531 int stack_slots = frame()->GetSpillSlotCount(); | 1540 |
| 1541 // Restore registers. |
| 1542 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 1543 if (saves != 0) { |
| 1544 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 1545 if (!((1 << i) & saves)) continue; |
| 1546 __ popq(Register::from_code(i)); |
| 1547 } |
| 1548 } |
| 1549 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); |
| 1550 if (saves_fp != 0) { |
| 1551 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); |
| 1552 const int stack_size = saves_fp_count * kQuadWordSize; |
| 1553 // Load the registers from the stack. |
| 1554 int slot_idx = 0; |
| 1555 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
| 1556 if (!((1 << i) & saves_fp)) continue; |
| 1557 __ movdqu(XMMRegister::from_code(i), |
| 1558 Operand(rsp, kQuadWordSize * slot_idx)); |
| 1559 slot_idx++; |
| 1560 } |
| 1561 // Adjust the stack pointer. |
| 1562 __ addp(rsp, Immediate(stack_size)); |
| 1563 } |
| 1564 |
1532 if (descriptor->kind() == CallDescriptor::kCallAddress) { | 1565 if (descriptor->kind() == CallDescriptor::kCallAddress) { |
1533 if (frame()->GetRegisterSaveAreaSize() > 0) { | 1566 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. |
1534 // Remove this frame's spill slots first. | 1567 __ popq(rbp); // Pop caller's frame pointer. |
1535 if (stack_slots > 0) { | |
1536 __ addq(rsp, Immediate(stack_slots * kPointerSize)); | |
1537 } | |
1538 // Restore registers. | |
1539 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); | |
1540 if (saves_fp != 0) { | |
1541 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); | |
1542 const int stack_size = saves_fp_count * 16; | |
1543 // Load the registers from the stack. | |
1544 int slot_idx = 0; | |
1545 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | |
1546 if (!((1 << i) & saves_fp)) continue; | |
1547 __ movdqu(XMMRegister::from_code(i), Operand(rsp, 16 * slot_idx)); | |
1548 slot_idx++; | |
1549 } | |
1550 // Adjust the stack pointer. | |
1551 __ addp(rsp, Immediate(stack_size)); | |
1552 } | |
1553 const RegList saves = descriptor->CalleeSavedRegisters(); | |
1554 if (saves != 0) { | |
1555 for (int i = 0; i < Register::kNumRegisters; i++) { | |
1556 if (!((1 << i) & saves)) continue; | |
1557 __ popq(Register::from_code(i)); | |
1558 } | |
1559 } | |
1560 __ popq(rbp); // Pop caller's frame pointer. | |
1561 } else { | |
1562 // No saved registers. | |
1563 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. | |
1564 __ popq(rbp); // Pop caller's frame pointer. | |
1565 } | |
1566 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { | 1568 } else if (descriptor->IsJSFunctionCall() || needs_frame_) { |
1567 // Canonicalize JSFunction return sites for now. | 1569 // Canonicalize JSFunction return sites for now. |
1568 if (return_label_.is_bound()) { | 1570 if (return_label_.is_bound()) { |
1569 __ jmp(&return_label_); | 1571 __ jmp(&return_label_); |
1570 return; | 1572 return; |
1571 } else { | 1573 } else { |
1572 __ bind(&return_label_); | 1574 __ bind(&return_label_); |
1573 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. | 1575 __ movq(rsp, rbp); // Move stack pointer back to frame pointer. |
1574 __ popq(rbp); // Pop caller's frame pointer. | 1576 __ popq(rbp); // Pop caller's frame pointer. |
1575 } | 1577 } |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1768 __ Nop(padding_size); | 1770 __ Nop(padding_size); |
1769 } | 1771 } |
1770 } | 1772 } |
1771 } | 1773 } |
1772 | 1774 |
1773 #undef __ | 1775 #undef __ |
1774 | 1776 |
1775 } // namespace internal | 1777 } // namespace internal |
1776 } // namespace compiler | 1778 } // namespace compiler |
1777 } // namespace v8 | 1779 } // namespace v8 |
OLD | NEW |