| 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/ast/scopes.h" | 7 #include "src/ast/scopes.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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 __ pop(ebx); \ | 413 __ pop(ebx); \ |
| 414 /* Return value is in st(0) on x87. */ \ | 414 /* Return value is in st(0) on x87. */ \ |
| 415 __ lea(esp, Operand(esp, kDoubleSize)); \ | 415 __ lea(esp, Operand(esp, kDoubleSize)); \ |
| 416 } while (false) | 416 } while (false) |
| 417 | 417 |
| 418 void CodeGenerator::AssembleDeconstructFrame() { | 418 void CodeGenerator::AssembleDeconstructFrame() { |
| 419 __ mov(esp, ebp); | 419 __ mov(esp, ebp); |
| 420 __ pop(ebp); | 420 __ pop(ebp); |
| 421 } | 421 } |
| 422 | 422 |
| 423 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 423 void CodeGenerator::AssemblePrepareTailCall() { |
| 424 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
| 425 if (sp_slot_delta > 0) { | |
| 426 __ add(esp, Immediate(sp_slot_delta * kPointerSize)); | |
| 427 } | |
| 428 frame_access_state()->SetFrameAccessToDefault(); | |
| 429 } | |
| 430 | |
| 431 | |
| 432 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
| 433 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
| 434 if (sp_slot_delta < 0) { | |
| 435 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize)); | |
| 436 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
| 437 } | |
| 438 if (frame_access_state()->has_frame()) { | 424 if (frame_access_state()->has_frame()) { |
| 439 __ mov(ebp, MemOperand(ebp, 0)); | 425 __ mov(ebp, MemOperand(ebp, 0)); |
| 440 } | 426 } |
| 441 frame_access_state()->SetFrameAccessToSP(); | 427 frame_access_state()->SetFrameAccessToSP(); |
| 442 } | 428 } |
| 443 | 429 |
| 444 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, | 430 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, |
| 445 Register, Register, | 431 Register, Register, |
| 446 Register) { | 432 Register) { |
| 447 // There are not enough temp registers left on ia32 for a call instruction | 433 // There are not enough temp registers left on ia32 for a call instruction |
| (...skipping 24 matching lines...) Expand all Loading... |
| 472 ParameterCount callee_args_count(args_reg); | 458 ParameterCount callee_args_count(args_reg); |
| 473 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 459 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
| 474 scratch3, ReturnAddressState::kOnStack, scratch_count); | 460 scratch3, ReturnAddressState::kOnStack, scratch_count); |
| 475 __ pop(scratch3); | 461 __ pop(scratch3); |
| 476 __ pop(scratch2); | 462 __ pop(scratch2); |
| 477 __ pop(scratch1); | 463 __ pop(scratch1); |
| 478 | 464 |
| 479 __ bind(&done); | 465 __ bind(&done); |
| 480 } | 466 } |
| 481 | 467 |
| 468 namespace { |
| 469 |
| 470 void AdjustStackPointerForTailCall(MacroAssembler* masm, |
| 471 FrameAccessState* state, |
| 472 int new_slot_above_sp, |
| 473 bool allow_shrinkage = true) { |
| 474 int current_sp_offset = state->GetSPToFPSlotCount() + |
| 475 StandardFrameConstants::kFixedSlotCountAboveFp; |
| 476 int stack_slot_delta = new_slot_above_sp - current_sp_offset; |
| 477 if (stack_slot_delta > 0) { |
| 478 masm->sub(esp, Immediate(stack_slot_delta * kPointerSize)); |
| 479 state->IncreaseSPDelta(stack_slot_delta); |
| 480 } else if (allow_shrinkage && stack_slot_delta < 0) { |
| 481 masm->add(esp, Immediate(-stack_slot_delta * kPointerSize)); |
| 482 state->IncreaseSPDelta(stack_slot_delta); |
| 483 } |
| 484 } |
| 485 |
| 486 } // namespace |
| 487 |
| 488 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr, |
| 489 int first_unused_stack_slot) { |
| 490 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush); |
| 491 ZoneVector<MoveOperands*> pushes(zone()); |
| 492 GetPushCompatibleMoves(instr, flags, &pushes); |
| 493 |
| 494 if (!pushes.empty() && |
| 495 (LocationOperand::cast(pushes.back()->destination()).index() + 1 == |
| 496 first_unused_stack_slot)) { |
| 497 X87OperandConverter g(this, instr); |
| 498 for (auto move : pushes) { |
| 499 LocationOperand destination_location( |
| 500 LocationOperand::cast(move->destination())); |
| 501 InstructionOperand source(move->source()); |
| 502 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 503 destination_location.index()); |
| 504 if (source.IsStackSlot()) { |
| 505 LocationOperand source_location(LocationOperand::cast(source)); |
| 506 __ push(g.SlotToOperand(source_location.index())); |
| 507 } else if (source.IsRegister()) { |
| 508 LocationOperand source_location(LocationOperand::cast(source)); |
| 509 __ push(source_location.GetRegister()); |
| 510 } else if (source.IsImmediate()) { |
| 511 __ push(Immediate(ImmediateOperand::cast(source).inline_value())); |
| 512 } else { |
| 513 // Pushes of non-scalar data types is not supported. |
| 514 UNIMPLEMENTED(); |
| 515 } |
| 516 frame_access_state()->IncreaseSPDelta(1); |
| 517 move->Eliminate(); |
| 518 } |
| 519 } |
| 520 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 521 first_unused_stack_slot, false); |
| 522 } |
| 523 |
| 524 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr, |
| 525 int first_unused_stack_slot) { |
| 526 AdjustStackPointerForTailCall(masm(), frame_access_state(), |
| 527 first_unused_stack_slot); |
| 528 } |
| 529 |
| 482 // Assembles an instruction after register allocation, producing machine code. | 530 // Assembles an instruction after register allocation, producing machine code. |
| 483 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 531 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
| 484 Instruction* instr) { | 532 Instruction* instr) { |
| 485 X87OperandConverter i(this, instr); | 533 X87OperandConverter i(this, instr); |
| 486 InstructionCode opcode = instr->opcode(); | 534 InstructionCode opcode = instr->opcode(); |
| 487 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 535 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
| 488 | 536 |
| 489 switch (arch_opcode) { | 537 switch (arch_opcode) { |
| 490 case kArchCallCodeObject: { | 538 case kArchCallCodeObject: { |
| 491 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 539 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 517 } | 565 } |
| 518 frame_access_state()->ClearSPDelta(); | 566 frame_access_state()->ClearSPDelta(); |
| 519 break; | 567 break; |
| 520 } | 568 } |
| 521 case kArchTailCallCodeObjectFromJSFunction: | 569 case kArchTailCallCodeObjectFromJSFunction: |
| 522 case kArchTailCallCodeObject: { | 570 case kArchTailCallCodeObject: { |
| 523 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 571 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 524 __ VerifyX87StackDepth(1); | 572 __ VerifyX87StackDepth(1); |
| 525 } | 573 } |
| 526 __ fstp(0); | 574 __ fstp(0); |
| 527 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 528 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 529 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 575 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
| 530 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 576 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 531 no_reg, no_reg, no_reg); | 577 no_reg, no_reg, no_reg); |
| 532 } | 578 } |
| 533 if (HasImmediateInput(instr, 0)) { | 579 if (HasImmediateInput(instr, 0)) { |
| 534 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); | 580 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); |
| 535 __ jmp(code, RelocInfo::CODE_TARGET); | 581 __ jmp(code, RelocInfo::CODE_TARGET); |
| 536 } else { | 582 } else { |
| 537 Register reg = i.InputRegister(0); | 583 Register reg = i.InputRegister(0); |
| 538 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 584 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 539 __ jmp(reg); | 585 __ jmp(reg); |
| 540 } | 586 } |
| 541 frame_access_state()->ClearSPDelta(); | 587 frame_access_state()->ClearSPDelta(); |
| 588 frame_access_state()->SetFrameAccessToDefault(); |
| 542 break; | 589 break; |
| 543 } | 590 } |
| 544 case kArchTailCallAddress: { | 591 case kArchTailCallAddress: { |
| 545 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 546 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 547 CHECK(!HasImmediateInput(instr, 0)); | 592 CHECK(!HasImmediateInput(instr, 0)); |
| 548 Register reg = i.InputRegister(0); | 593 Register reg = i.InputRegister(0); |
| 549 __ jmp(reg); | 594 __ jmp(reg); |
| 550 frame_access_state()->ClearSPDelta(); | 595 frame_access_state()->ClearSPDelta(); |
| 596 frame_access_state()->SetFrameAccessToDefault(); |
| 551 break; | 597 break; |
| 552 } | 598 } |
| 553 case kArchCallJSFunction: { | 599 case kArchCallJSFunction: { |
| 554 EnsureSpaceForLazyDeopt(); | 600 EnsureSpaceForLazyDeopt(); |
| 555 Register func = i.InputRegister(0); | 601 Register func = i.InputRegister(0); |
| 556 if (FLAG_debug_code) { | 602 if (FLAG_debug_code) { |
| 557 // Check the function's context matches the context argument. | 603 // Check the function's context matches the context argument. |
| 558 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 604 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
| 559 __ Assert(equal, kWrongFunctionContext); | 605 __ Assert(equal, kWrongFunctionContext); |
| 560 } | 606 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 585 Register func = i.InputRegister(0); | 631 Register func = i.InputRegister(0); |
| 586 if (FLAG_debug_code) { | 632 if (FLAG_debug_code) { |
| 587 // Check the function's context matches the context argument. | 633 // Check the function's context matches the context argument. |
| 588 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); | 634 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); |
| 589 __ Assert(equal, kWrongFunctionContext); | 635 __ Assert(equal, kWrongFunctionContext); |
| 590 } | 636 } |
| 591 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 637 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 592 __ VerifyX87StackDepth(1); | 638 __ VerifyX87StackDepth(1); |
| 593 } | 639 } |
| 594 __ fstp(0); | 640 __ fstp(0); |
| 595 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
| 596 AssembleDeconstructActivationRecord(stack_param_delta); | |
| 597 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 641 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
| 598 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 642 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
| 599 no_reg, no_reg, no_reg); | 643 no_reg, no_reg, no_reg); |
| 600 } | 644 } |
| 601 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); | 645 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); |
| 602 frame_access_state()->ClearSPDelta(); | 646 frame_access_state()->ClearSPDelta(); |
| 647 frame_access_state()->SetFrameAccessToDefault(); |
| 603 break; | 648 break; |
| 604 } | 649 } |
| 605 case kArchPrepareCallCFunction: { | 650 case kArchPrepareCallCFunction: { |
| 606 // Frame alignment requires using FP-relative frame addressing. | 651 // Frame alignment requires using FP-relative frame addressing. |
| 607 frame_access_state()->SetFrameAccessToFP(); | 652 frame_access_state()->SetFrameAccessToFP(); |
| 608 int const num_parameters = MiscField::decode(instr->opcode()); | 653 int const num_parameters = MiscField::decode(instr->opcode()); |
| 609 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); | 654 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); |
| 610 break; | 655 break; |
| 611 } | 656 } |
| 612 case kArchPrepareTailCall: | 657 case kArchPrepareTailCall: |
| 613 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 658 AssemblePrepareTailCall(); |
| 614 break; | 659 break; |
| 615 case kArchCallCFunction: { | 660 case kArchCallCFunction: { |
| 616 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | 661 if (FLAG_debug_code && FLAG_enable_slow_asserts) { |
| 617 __ VerifyX87StackDepth(1); | 662 __ VerifyX87StackDepth(1); |
| 618 } | 663 } |
| 619 __ fstp(0); | 664 __ fstp(0); |
| 620 int const num_parameters = MiscField::decode(instr->opcode()); | 665 int const num_parameters = MiscField::decode(instr->opcode()); |
| 621 if (HasImmediateInput(instr, 0)) { | 666 if (HasImmediateInput(instr, 0)) { |
| 622 ExternalReference ref = i.InputExternalReference(0); | 667 ExternalReference ref = i.InputExternalReference(0); |
| 623 __ CallCFunction(ref, num_parameters); | 668 __ CallCFunction(ref, num_parameters); |
| (...skipping 2027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2651 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 2696 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; |
| 2652 __ Nop(padding_size); | 2697 __ Nop(padding_size); |
| 2653 } | 2698 } |
| 2654 } | 2699 } |
| 2655 | 2700 |
| 2656 #undef __ | 2701 #undef __ |
| 2657 | 2702 |
| 2658 } // namespace compiler | 2703 } // namespace compiler |
| 2659 } // namespace internal | 2704 } // namespace internal |
| 2660 } // namespace v8 | 2705 } // namespace v8 |
| OLD | NEW |