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 |