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/compilation-info.h" | 7 #include "src/compilation-info.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 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 __ lea(esp, Operand(esp, kPointerSize)); | 739 __ lea(esp, Operand(esp, kPointerSize)); |
740 | 740 |
741 Deoptimizer::BailoutType bailout_type = | 741 Deoptimizer::BailoutType bailout_type = |
742 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); | 742 Deoptimizer::BailoutType(MiscField::decode(instr->opcode())); |
743 CodeGenResult result = AssembleDeoptimizerCall( | 743 CodeGenResult result = AssembleDeoptimizerCall( |
744 deopt_state_id, bailout_type, current_source_position_); | 744 deopt_state_id, bailout_type, current_source_position_); |
745 if (result != kSuccess) return result; | 745 if (result != kSuccess) return result; |
746 break; | 746 break; |
747 } | 747 } |
748 case kArchRet: | 748 case kArchRet: |
749 AssembleReturn(); | 749 AssembleReturn(instr->InputAt(0)); |
750 break; | 750 break; |
751 case kArchFramePointer: | 751 case kArchFramePointer: |
752 __ mov(i.OutputRegister(), ebp); | 752 __ mov(i.OutputRegister(), ebp); |
753 break; | 753 break; |
754 case kArchStackPointer: | 754 case kArchStackPointer: |
755 __ mov(i.OutputRegister(), esp); | 755 __ mov(i.OutputRegister(), esp); |
756 break; | 756 break; |
757 case kArchParentFramePointer: | 757 case kArchParentFramePointer: |
758 if (frame_access_state()->has_frame()) { | 758 if (frame_access_state()->has_frame()) { |
759 __ mov(i.OutputRegister(), Operand(ebp, 0)); | 759 __ mov(i.OutputRegister(), Operand(ebp, 0)); |
(...skipping 1677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 DCHECK(!info()->is_osr()); | 2437 DCHECK(!info()->is_osr()); |
2438 int pushed = 0; | 2438 int pushed = 0; |
2439 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { | 2439 for (int i = Register::kNumRegisters - 1; i >= 0; i--) { |
2440 if (!((1 << i) & saves)) continue; | 2440 if (!((1 << i) & saves)) continue; |
2441 __ push(Register::from_code(i)); | 2441 __ push(Register::from_code(i)); |
2442 ++pushed; | 2442 ++pushed; |
2443 } | 2443 } |
2444 } | 2444 } |
2445 } | 2445 } |
2446 | 2446 |
2447 | 2447 void CodeGenerator::AssembleReturn(InstructionOperand* pop) { |
2448 void CodeGenerator::AssembleReturn() { | |
2449 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 2448 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
2450 | 2449 |
2451 // Clear the FPU stack only if there is no return value in the stack. | 2450 // Clear the FPU stack only if there is no return value in the stack. |
2452 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 2451 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
2453 __ VerifyX87StackDepth(1); | 2452 __ VerifyX87StackDepth(1); |
2454 } | 2453 } |
2455 bool clear_stack = true; | 2454 bool clear_stack = true; |
2456 for (int i = 0; i < descriptor->ReturnCount(); i++) { | 2455 for (int i = 0; i < descriptor->ReturnCount(); i++) { |
2457 MachineRepresentation rep = descriptor->GetReturnType(i).representation(); | 2456 MachineRepresentation rep = descriptor->GetReturnType(i).representation(); |
2458 LinkageLocation loc = descriptor->GetReturnLocation(i); | 2457 LinkageLocation loc = descriptor->GetReturnLocation(i); |
2459 if (IsFloatingPoint(rep) && loc == LinkageLocation::ForRegister(0)) { | 2458 if (IsFloatingPoint(rep) && loc == LinkageLocation::ForRegister(0)) { |
2460 clear_stack = false; | 2459 clear_stack = false; |
2461 break; | 2460 break; |
2462 } | 2461 } |
2463 } | 2462 } |
2464 if (clear_stack) __ fstp(0); | 2463 if (clear_stack) __ fstp(0); |
2465 | 2464 |
2466 int pop_count = static_cast<int>(descriptor->StackParameterCount()); | |
2467 const RegList saves = descriptor->CalleeSavedRegisters(); | 2465 const RegList saves = descriptor->CalleeSavedRegisters(); |
2468 // Restore registers. | 2466 // Restore registers. |
2469 if (saves != 0) { | 2467 if (saves != 0) { |
2470 for (int i = 0; i < Register::kNumRegisters; i++) { | 2468 for (int i = 0; i < Register::kNumRegisters; i++) { |
2471 if (!((1 << i) & saves)) continue; | 2469 if (!((1 << i) & saves)) continue; |
2472 __ pop(Register::from_code(i)); | 2470 __ pop(Register::from_code(i)); |
2473 } | 2471 } |
2474 } | 2472 } |
2475 | 2473 |
| 2474 // Might need ecx for scratch if pop_size is too big or if there is a variable |
| 2475 // pop count. |
| 2476 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit()); |
| 2477 size_t pop_size = descriptor->StackParameterCount() * kPointerSize; |
| 2478 X87OperandConverter g(this, nullptr); |
2476 if (descriptor->IsCFunctionCall()) { | 2479 if (descriptor->IsCFunctionCall()) { |
2477 AssembleDeconstructFrame(); | 2480 AssembleDeconstructFrame(); |
2478 } else if (frame_access_state()->has_frame()) { | 2481 } else if (frame_access_state()->has_frame()) { |
2479 // Canonicalize JSFunction return sites for now. | 2482 // Canonicalize JSFunction return sites for now if they always have the same |
2480 if (return_label_.is_bound()) { | 2483 // number of return args. |
2481 __ jmp(&return_label_); | 2484 if (pop->IsImmediate() && g.ToConstant(pop).ToInt32() == 0) { |
2482 return; | 2485 if (return_label_.is_bound()) { |
| 2486 __ jmp(&return_label_); |
| 2487 return; |
| 2488 } else { |
| 2489 __ bind(&return_label_); |
| 2490 AssembleDeconstructFrame(); |
| 2491 } |
2483 } else { | 2492 } else { |
2484 __ bind(&return_label_); | |
2485 AssembleDeconstructFrame(); | 2493 AssembleDeconstructFrame(); |
2486 } | 2494 } |
2487 } | 2495 } |
2488 if (pop_count == 0) { | 2496 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & edx.bit()); |
2489 __ ret(0); | 2497 DCHECK_EQ(0u, descriptor->CalleeSavedRegisters() & ecx.bit()); |
| 2498 if (pop->IsImmediate()) { |
| 2499 DCHECK_EQ(Constant::kInt32, g.ToConstant(pop).type()); |
| 2500 pop_size += g.ToConstant(pop).ToInt32() * kPointerSize; |
| 2501 __ Ret(static_cast<int>(pop_size), ecx); |
2490 } else { | 2502 } else { |
2491 __ Ret(pop_count * kPointerSize, ebx); | 2503 Register pop_reg = g.ToRegister(pop); |
| 2504 Register scratch_reg = pop_reg.is(ecx) ? edx : ecx; |
| 2505 __ pop(scratch_reg); |
| 2506 __ lea(esp, Operand(esp, pop_reg, times_4, static_cast<int>(pop_size))); |
| 2507 __ jmp(scratch_reg); |
2492 } | 2508 } |
2493 } | 2509 } |
2494 | 2510 |
2495 | 2511 |
2496 void CodeGenerator::AssembleMove(InstructionOperand* source, | 2512 void CodeGenerator::AssembleMove(InstructionOperand* source, |
2497 InstructionOperand* destination) { | 2513 InstructionOperand* destination) { |
2498 X87OperandConverter g(this, nullptr); | 2514 X87OperandConverter g(this, nullptr); |
2499 // Dispatch on the source and destination operand kinds. Not all | 2515 // Dispatch on the source and destination operand kinds. Not all |
2500 // combinations are possible. | 2516 // combinations are possible. |
2501 if (source->IsRegister()) { | 2517 if (source->IsRegister()) { |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2714 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2730 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
2715 __ Nop(padding_size); | 2731 __ Nop(padding_size); |
2716 } | 2732 } |
2717 } | 2733 } |
2718 | 2734 |
2719 #undef __ | 2735 #undef __ |
2720 | 2736 |
2721 } // namespace compiler | 2737 } // namespace compiler |
2722 } // namespace internal | 2738 } // namespace internal |
2723 } // namespace v8 | 2739 } // namespace v8 |
OLD | NEW |