Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: src/compiler/x87/code-generator-x87.cc

Issue 2120413002: X87: [turbofan]: Support using push instructions for setting up tail call parameters. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698