| 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 <limits> | |
| 8 | |
| 9 #include "src/compilation-info.h" | 7 #include "src/compilation-info.h" |
| 10 #include "src/compiler/code-generator-impl.h" | 8 #include "src/compiler/code-generator-impl.h" |
| 11 #include "src/compiler/gap-resolver.h" | 9 #include "src/compiler/gap-resolver.h" |
| 12 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
| 13 #include "src/compiler/osr.h" | 11 #include "src/compiler/osr.h" |
| 14 #include "src/wasm/wasm-module.h" | 12 #include "src/wasm/wasm-module.h" |
| 15 #include "src/x64/assembler-x64.h" | 13 #include "src/x64/assembler-x64.h" |
| 16 #include "src/x64/macro-assembler-x64.h" | 14 #include "src/x64/macro-assembler-x64.h" |
| 17 | 15 |
| 18 namespace v8 { | 16 namespace v8 { |
| (...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 913 int deopt_state_id = | 911 int deopt_state_id = |
| 914 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore()); | 912 BuildTranslation(instr, -1, 0, OutputFrameStateCombine::Ignore()); |
| 915 Deoptimizer::BailoutType bailout_type = | 913 Deoptimizer::BailoutType bailout_type = |
| 916 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); | 914 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); |
| 917 CodeGenResult result = AssembleDeoptimizerCall( | 915 CodeGenResult result = AssembleDeoptimizerCall( |
| 918 deopt_state_id, bailout_type, current_source_position_); | 916 deopt_state_id, bailout_type, current_source_position_); |
| 919 if (result != kSuccess) return result; | 917 if (result != kSuccess) return result; |
| 920 break; | 918 break; |
| 921 } | 919 } |
| 922 case kArchRet: | 920 case kArchRet: |
| 923 AssembleReturn(instr->InputAt(0)); | 921 AssembleReturn(); |
| 924 break; | 922 break; |
| 925 case kArchStackPointer: | 923 case kArchStackPointer: |
| 926 __ movq(i.OutputRegister(), rsp); | 924 __ movq(i.OutputRegister(), rsp); |
| 927 break; | 925 break; |
| 928 case kArchFramePointer: | 926 case kArchFramePointer: |
| 929 __ movq(i.OutputRegister(), rbp); | 927 __ movq(i.OutputRegister(), rbp); |
| 930 break; | 928 break; |
| 931 case kArchParentFramePointer: | 929 case kArchParentFramePointer: |
| 932 if (frame_access_state()->has_frame()) { | 930 if (frame_access_state()->has_frame()) { |
| 933 __ movq(i.OutputRegister(), Operand(rbp, 0)); | 931 __ movq(i.OutputRegister(), Operand(rbp, 0)); |
| (...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2442 | 2440 |
| 2443 const RegList saves = descriptor->CalleeSavedRegisters(); | 2441 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 2444 if (saves != 0) { // Save callee-saved registers. | 2442 if (saves != 0) { // Save callee-saved registers. |
| 2445 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | 2443 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
| 2446 if (!((1 << i) & saves)) continue; | 2444 if (!((1 << i) & saves)) continue; |
| 2447 __ pushq(Register::from_code(i)); | 2445 __ pushq(Register::from_code(i)); |
| 2448 } | 2446 } |
| 2449 } | 2447 } |
| 2450 } | 2448 } |
| 2451 | 2449 |
| 2452 void CodeGenerator::AssembleReturn(InstructionOperand* pop) { | 2450 |
| 2451 void CodeGenerator::AssembleReturn() { |
| 2453 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 2452 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 2454 | 2453 |
| 2455 // Restore registers. | 2454 // Restore registers. |
| 2456 const RegList saves = descriptor->CalleeSavedRegisters(); | 2455 const RegList saves = descriptor->CalleeSavedRegisters(); |
| 2457 if (saves != 0) { | 2456 if (saves != 0) { |
| 2458 for (int i = 0; i < Register::kNumRegisters; i++) { | 2457 for (int i = 0; i < Register::kNumRegisters; i++) { |
| 2459 if (!((1 << i) & saves)) continue; | 2458 if (!((1 << i) & saves)) continue; |
| 2460 __ popq(Register::from_code(i)); | 2459 __ popq(Register::from_code(i)); |
| 2461 } | 2460 } |
| 2462 } | 2461 } |
| 2463 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); | 2462 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); |
| 2464 if (saves_fp != 0) { | 2463 if (saves_fp != 0) { |
| 2465 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); | 2464 const uint32_t saves_fp_count = base::bits::CountPopulation32(saves_fp); |
| 2466 const int stack_size = saves_fp_count * kQuadWordSize; | 2465 const int stack_size = saves_fp_count * kQuadWordSize; |
| 2467 // Load the registers from the stack. | 2466 // Load the registers from the stack. |
| 2468 int slot_idx = 0; | 2467 int slot_idx = 0; |
| 2469 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | 2468 for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |
| 2470 if (!((1 << i) & saves_fp)) continue; | 2469 if (!((1 << i) & saves_fp)) continue; |
| 2471 __ movdqu(XMMRegister::from_code(i), | 2470 __ movdqu(XMMRegister::from_code(i), |
| 2472 Operand(rsp, kQuadWordSize * slot_idx)); | 2471 Operand(rsp, kQuadWordSize * slot_idx)); |
| 2473 slot_idx++; | 2472 slot_idx++; |
| 2474 } | 2473 } |
| 2475 // Adjust the stack pointer. | 2474 // Adjust the stack pointer. |
| 2476 __ addp(rsp, Immediate(stack_size)); | 2475 __ addp(rsp, Immediate(stack_size)); |
| 2477 } | 2476 } |
| 2478 | 2477 |
| 2479 unwinding_info_writer_.MarkBlockWillExit(); | 2478 unwinding_info_writer_.MarkBlockWillExit(); |
| 2480 | 2479 |
| 2481 // Might need rcx for scratch if pop_size is too big or if there is a variable | |
| 2482 // pop count. | |
| 2483 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rcx.bit()); | |
| 2484 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rdx.bit()); | |
| 2485 size_t pop_size = descriptor->StackParameterCount() * kPointerSize; | |
| 2486 X64OperandConverter g(this, nullptr); | |
| 2487 if (descriptor->IsCFunctionCall()) { | 2480 if (descriptor->IsCFunctionCall()) { |
| 2488 AssembleDeconstructFrame(); | 2481 AssembleDeconstructFrame(); |
| 2489 } else if (frame_access_state()->has_frame()) { | 2482 } else if (frame_access_state()->has_frame()) { |
| 2490 if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) { | 2483 // Canonicalize JSFunction return sites for now. |
| 2491 // Canonicalize JSFunction return sites for now. | 2484 if (return_label_.is_bound()) { |
| 2492 if (return_label_.is_bound()) { | 2485 __ jmp(&return_label_); |
| 2493 __ jmp(&return_label_); | 2486 return; |
| 2494 return; | |
| 2495 } else { | |
| 2496 __ bind(&return_label_); | |
| 2497 AssembleDeconstructFrame(); | |
| 2498 } | |
| 2499 } else { | 2487 } else { |
| 2488 __ bind(&return_label_); |
| 2500 AssembleDeconstructFrame(); | 2489 AssembleDeconstructFrame(); |
| 2501 } | 2490 } |
| 2502 } | 2491 } |
| 2503 | 2492 size_t pop_size = descriptor->StackParameterCount() * kPointerSize; |
| 2504 if (pop->IsImmediate()) { | 2493 // Might need rcx for scratch if pop_size is too big. |
| 2505 DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type()); | 2494 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & rcx.bit()); |
| 2506 pop_size += g.ToConstant(pop).ToInt32() * kPointerSize; | 2495 __ Ret(static_cast<int>(pop_size), rcx); |
| 2507 CHECK_LT(pop_size, std::numeric_limits<int>::max()); | |
| 2508 __ Ret(static_cast<int>(pop_size), rcx); | |
| 2509 } else { | |
| 2510 Register pop_reg = g.ToRegister(pop); | |
| 2511 Register scratch_reg = pop_reg.is(rcx) ? rdx : rcx; | |
| 2512 __ popq(scratch_reg); | |
| 2513 __ leaq(rsp, Operand(rsp, pop_reg, times_8, static_cast<int>(pop_size))); | |
| 2514 __ jmp(scratch_reg); | |
| 2515 } | |
| 2516 } | 2496 } |
| 2517 | 2497 |
| 2518 | 2498 |
| 2519 void CodeGenerator::AssembleMove(InstructionOperand* source, | 2499 void CodeGenerator::AssembleMove(InstructionOperand* source, |
| 2520 InstructionOperand* destination) { | 2500 InstructionOperand* destination) { |
| 2521 X64OperandConverter g(this, nullptr); | 2501 X64OperandConverter g(this, nullptr); |
| 2522 // Dispatch on the source and destination operand kinds. Not all | 2502 // Dispatch on the source and destination operand kinds. Not all |
| 2523 // combinations are possible. | 2503 // combinations are possible. |
| 2524 if (source->IsRegister()) { | 2504 if (source->IsRegister()) { |
| 2525 DCHECK(destination->IsRegister() || destination->IsStackSlot()); | 2505 DCHECK(destination->IsRegister() || destination->IsStackSlot()); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2753 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 2774 __ Nop(padding_size); | 2754 __ Nop(padding_size); |
| 2775 } | 2755 } |
| 2776 } | 2756 } |
| 2777 | 2757 |
| 2778 #undef __ | 2758 #undef __ |
| 2779 | 2759 |
| 2780 } // namespace compiler | 2760 } // namespace compiler |
| 2781 } // namespace internal | 2761 } // namespace internal |
| 2782 } // namespace v8 | 2762 } // namespace v8 |
| OLD | NEW |