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

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

Issue 2082263002: [turbofan]: Support using push instructions for setting up tail call parameters (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Review feedback 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
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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 __ fstp_d(Operand(esp, 0)); \ 393 __ fstp_d(Operand(esp, 0)); \
394 __ movsd(i.OutputDoubleRegister(), Operand(esp, 0)); \ 394 __ movsd(i.OutputDoubleRegister(), Operand(esp, 0)); \
395 __ add(esp, Immediate(kDoubleSize)); \ 395 __ add(esp, Immediate(kDoubleSize)); \
396 } while (false) 396 } while (false)
397 397
398 void CodeGenerator::AssembleDeconstructFrame() { 398 void CodeGenerator::AssembleDeconstructFrame() {
399 __ mov(esp, ebp); 399 __ mov(esp, ebp);
400 __ pop(ebp); 400 __ pop(ebp);
401 } 401 }
402 402
403 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 403 void CodeGenerator::AssemblePrepareTailCall() {
404 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
405 if (sp_slot_delta > 0) {
406 __ add(esp, Immediate(sp_slot_delta * kPointerSize));
407 }
408 frame_access_state()->SetFrameAccessToDefault();
409 }
410
411
412 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
413 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
414 if (sp_slot_delta < 0) {
415 __ sub(esp, Immediate(-sp_slot_delta * kPointerSize));
416 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
417 }
418 if (frame_access_state()->has_frame()) { 404 if (frame_access_state()->has_frame()) {
419 __ mov(ebp, MemOperand(ebp, 0)); 405 __ mov(ebp, MemOperand(ebp, 0));
420 } 406 }
421 frame_access_state()->SetFrameAccessToSP(); 407 frame_access_state()->SetFrameAccessToSP();
422 } 408 }
423 409
424 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, 410 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
425 Register, Register, 411 Register, Register,
426 Register) { 412 Register) {
427 // There are not enough temp registers left on ia32 for a call instruction 413 // There are not enough temp registers left on ia32 for a call instruction
(...skipping 24 matching lines...) Expand all
452 ParameterCount callee_args_count(args_reg); 438 ParameterCount callee_args_count(args_reg);
453 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, 439 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
454 scratch3, ReturnAddressState::kOnStack, scratch_count); 440 scratch3, ReturnAddressState::kOnStack, scratch_count);
455 __ pop(scratch3); 441 __ pop(scratch3);
456 __ pop(scratch2); 442 __ pop(scratch2);
457 __ pop(scratch1); 443 __ pop(scratch1);
458 444
459 __ bind(&done); 445 __ bind(&done);
460 } 446 }
461 447
448 namespace {
449
450 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state,
451 int new_slot_above_sp,
452 bool allow_shrinkage = true) {
453 int current_sp_offset = state->GetSPToFPSlotCount() +
454 StandardFrameConstants::kFixedSlotCountAboveFp;
455 int stack_slot_delta = new_slot_above_sp - current_sp_offset;
456 if (stack_slot_delta > 0) {
457 masm->sub(esp, Immediate(stack_slot_delta * kPointerSize));
458 state->IncreaseSPDelta(stack_slot_delta);
459 } else if (allow_shrinkage && stack_slot_delta < 0) {
460 masm->add(esp, Immediate(-stack_slot_delta * kPointerSize));
461 state->IncreaseSPDelta(stack_slot_delta);
462 }
463 }
464
465 } // namespace
466
467 void CodeGenerator::AssemblePreGaps(Instruction* instr) {
468 int first_unused_stack_slot;
469 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return;
470
471 GapResolver::PushTypeFlags flags(GapResolver::kImmediatePush |
472 GapResolver::kScalarPush);
473 ZoneVector<MoveOperands*> pushes(zone());
474 resolver()->GetPushCompatibleMoves(zone(), instr, flags, &pushes);
475
476 if (!pushes.empty() &&
477 (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
478 first_unused_stack_slot)) {
479 IA32OperandConverter g(this, instr);
480 for (auto move : pushes) {
481 LocationOperand destination_location(
482 LocationOperand::cast(move->destination()));
483 InstructionOperand source(move->source());
484 AdjustStackPointerForGap(masm(), frame_access_state(),
485 destination_location.index());
486 if (source.IsStackSlot()) {
487 LocationOperand source_location(LocationOperand::cast(source));
488 __ push(g.SlotToOperand(source_location.index()));
489 } else if (source.IsRegister()) {
490 LocationOperand source_location(LocationOperand::cast(source));
491 __ push(source_location.GetRegister());
492 } else if (source.IsImmediate()) {
493 __ push(Immediate(ImmediateOperand::cast(source).inline_value()));
494 } else {
495 // Pushes of non-scalar data types is not supported.
496 UNIMPLEMENTED();
497 }
498 frame_access_state()->IncreaseSPDelta(1);
499 move->Eliminate();
500 }
501 }
502 AdjustStackPointerForGap(masm(), frame_access_state(),
503 first_unused_stack_slot, false);
504 }
505
506 void CodeGenerator::AssemblePostGaps(Instruction* instr) {
507 int first_unused_stack_slot;
508 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return;
509 AdjustStackPointerForGap(masm(), frame_access_state(),
510 first_unused_stack_slot);
511 }
512
462 // Assembles an instruction after register allocation, producing machine code. 513 // Assembles an instruction after register allocation, producing machine code.
463 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( 514 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
464 Instruction* instr) { 515 Instruction* instr) {
465 IA32OperandConverter i(this, instr); 516 IA32OperandConverter i(this, instr);
466 InstructionCode opcode = instr->opcode(); 517 InstructionCode opcode = instr->opcode();
467 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); 518 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
468 switch (arch_opcode) { 519 switch (arch_opcode) {
469 case kArchCallCodeObject: { 520 case kArchCallCodeObject: {
470 EnsureSpaceForLazyDeopt(); 521 EnsureSpaceForLazyDeopt();
471 if (HasImmediateInput(instr, 0)) { 522 if (HasImmediateInput(instr, 0)) {
472 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 523 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
473 __ call(code, RelocInfo::CODE_TARGET); 524 __ call(code, RelocInfo::CODE_TARGET);
474 } else { 525 } else {
475 Register reg = i.InputRegister(0); 526 Register reg = i.InputRegister(0);
476 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 527 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
477 __ call(reg); 528 __ call(reg);
478 } 529 }
479 RecordCallPosition(instr); 530 RecordCallPosition(instr);
480 frame_access_state()->ClearSPDelta(); 531 frame_access_state()->ClearSPDelta();
481 break; 532 break;
482 } 533 }
483 case kArchTailCallCodeObjectFromJSFunction: 534 case kArchTailCallCodeObjectFromJSFunction:
484 case kArchTailCallCodeObject: { 535 case kArchTailCallCodeObject: {
485 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
486 AssembleDeconstructActivationRecord(stack_param_delta);
487 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { 536 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
488 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 537 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
489 no_reg, no_reg, no_reg); 538 no_reg, no_reg, no_reg);
490 } 539 }
491 if (HasImmediateInput(instr, 0)) { 540 if (HasImmediateInput(instr, 0)) {
492 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 541 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
493 __ jmp(code, RelocInfo::CODE_TARGET); 542 __ jmp(code, RelocInfo::CODE_TARGET);
494 } else { 543 } else {
495 Register reg = i.InputRegister(0); 544 Register reg = i.InputRegister(0);
496 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 545 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
497 __ jmp(reg); 546 __ jmp(reg);
498 } 547 }
499 frame_access_state()->ClearSPDelta(); 548 frame_access_state()->ClearSPDelta();
549 frame_access_state()->SetFrameAccessToDefault();
500 break; 550 break;
501 } 551 }
502 case kArchTailCallAddress: { 552 case kArchTailCallAddress: {
503 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
504 AssembleDeconstructActivationRecord(stack_param_delta);
505 CHECK(!HasImmediateInput(instr, 0)); 553 CHECK(!HasImmediateInput(instr, 0));
506 Register reg = i.InputRegister(0); 554 Register reg = i.InputRegister(0);
507 __ jmp(reg); 555 __ jmp(reg);
508 frame_access_state()->ClearSPDelta(); 556 frame_access_state()->ClearSPDelta();
557 frame_access_state()->SetFrameAccessToDefault();
509 break; 558 break;
510 } 559 }
511 case kArchCallJSFunction: { 560 case kArchCallJSFunction: {
512 EnsureSpaceForLazyDeopt(); 561 EnsureSpaceForLazyDeopt();
513 Register func = i.InputRegister(0); 562 Register func = i.InputRegister(0);
514 if (FLAG_debug_code) { 563 if (FLAG_debug_code) {
515 // Check the function's context matches the context argument. 564 // Check the function's context matches the context argument.
516 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 565 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
517 __ Assert(equal, kWrongFunctionContext); 566 __ Assert(equal, kWrongFunctionContext);
518 } 567 }
519 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); 568 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
520 RecordCallPosition(instr); 569 RecordCallPosition(instr);
521 frame_access_state()->ClearSPDelta(); 570 frame_access_state()->ClearSPDelta();
522 break; 571 break;
523 } 572 }
524 case kArchTailCallJSFunctionFromJSFunction: 573 case kArchTailCallJSFunctionFromJSFunction:
525 case kArchTailCallJSFunction: { 574 case kArchTailCallJSFunction: {
526 Register func = i.InputRegister(0); 575 Register func = i.InputRegister(0);
527 if (FLAG_debug_code) { 576 if (FLAG_debug_code) {
528 // Check the function's context matches the context argument. 577 // Check the function's context matches the context argument.
529 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 578 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
530 __ Assert(equal, kWrongFunctionContext); 579 __ Assert(equal, kWrongFunctionContext);
531 } 580 }
532 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
533 AssembleDeconstructActivationRecord(stack_param_delta);
534 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { 581 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
535 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 582 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
536 no_reg, no_reg, no_reg); 583 no_reg, no_reg, no_reg);
537 } 584 }
538 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); 585 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
539 frame_access_state()->ClearSPDelta(); 586 frame_access_state()->ClearSPDelta();
587 frame_access_state()->SetFrameAccessToDefault();
540 break; 588 break;
541 } 589 }
542 case kArchPrepareCallCFunction: { 590 case kArchPrepareCallCFunction: {
543 // Frame alignment requires using FP-relative frame addressing. 591 // Frame alignment requires using FP-relative frame addressing.
544 frame_access_state()->SetFrameAccessToFP(); 592 frame_access_state()->SetFrameAccessToFP();
545 int const num_parameters = MiscField::decode(instr->opcode()); 593 int const num_parameters = MiscField::decode(instr->opcode());
546 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); 594 __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
547 break; 595 break;
548 } 596 }
549 case kArchPrepareTailCall: 597 case kArchPrepareTailCall:
550 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 598 AssemblePrepareTailCall();
551 break; 599 break;
552 case kArchCallCFunction: { 600 case kArchCallCFunction: {
553 int const num_parameters = MiscField::decode(instr->opcode()); 601 int const num_parameters = MiscField::decode(instr->opcode());
554 if (HasImmediateInput(instr, 0)) { 602 if (HasImmediateInput(instr, 0)) {
555 ExternalReference ref = i.InputExternalReference(0); 603 ExternalReference ref = i.InputExternalReference(0);
556 __ CallCFunction(ref, num_parameters); 604 __ CallCFunction(ref, num_parameters);
557 } else { 605 } else {
558 Register func = i.InputRegister(0); 606 Register func = i.InputRegister(0);
559 __ CallCFunction(func, num_parameters); 607 __ CallCFunction(func, num_parameters);
560 } 608 }
(...skipping 1491 matching lines...) Expand 10 before | Expand all | Expand 10 after
2052 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; 2100 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
2053 __ Nop(padding_size); 2101 __ Nop(padding_size);
2054 } 2102 }
2055 } 2103 }
2056 2104
2057 #undef __ 2105 #undef __
2058 2106
2059 } // namespace compiler 2107 } // namespace compiler
2060 } // namespace internal 2108 } // namespace internal
2061 } // namespace v8 2109 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698