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

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: Fix comments 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 | « src/compiler/gap-resolver.cc ('k') | src/compiler/instruction-selector.h » ('j') | 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 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 AdjustStackPointerForTailCall(MacroAssembler* masm,
451 FrameAccessState* state,
452 int new_slot_above_sp,
453 bool allow_shrinkage = true) {
454 int current_sp_offset = state->GetSPToFPSlotCount() +
455 StandardFrameConstants::kFixedSlotCountAboveFp;
456 int stack_slot_delta = new_slot_above_sp - current_sp_offset;
457 if (stack_slot_delta > 0) {
458 masm->sub(esp, Immediate(stack_slot_delta * kPointerSize));
459 state->IncreaseSPDelta(stack_slot_delta);
460 } else if (allow_shrinkage && stack_slot_delta < 0) {
461 masm->add(esp, Immediate(-stack_slot_delta * kPointerSize));
462 state->IncreaseSPDelta(stack_slot_delta);
463 }
464 }
465
466 } // namespace
467
468 void CodeGenerator::AssembleTailCallBeforeGap(Instruction* instr,
469 int first_unused_stack_slot) {
470 CodeGenerator::PushTypeFlags flags(kImmediatePush | kScalarPush);
471 ZoneVector<MoveOperands*> pushes(zone());
472 GetPushCompatibleMoves(instr, flags, &pushes);
473
474 if (!pushes.empty() &&
475 (LocationOperand::cast(pushes.back()->destination()).index() + 1 ==
476 first_unused_stack_slot)) {
477 IA32OperandConverter g(this, instr);
478 for (auto move : pushes) {
479 LocationOperand destination_location(
480 LocationOperand::cast(move->destination()));
481 InstructionOperand source(move->source());
482 AdjustStackPointerForTailCall(masm(), frame_access_state(),
483 destination_location.index());
484 if (source.IsStackSlot()) {
485 LocationOperand source_location(LocationOperand::cast(source));
486 __ push(g.SlotToOperand(source_location.index()));
487 } else if (source.IsRegister()) {
488 LocationOperand source_location(LocationOperand::cast(source));
489 __ push(source_location.GetRegister());
490 } else if (source.IsImmediate()) {
491 __ push(Immediate(ImmediateOperand::cast(source).inline_value()));
492 } else {
493 // Pushes of non-scalar data types is not supported.
494 UNIMPLEMENTED();
495 }
496 frame_access_state()->IncreaseSPDelta(1);
497 move->Eliminate();
498 }
499 }
500 AdjustStackPointerForTailCall(masm(), frame_access_state(),
501 first_unused_stack_slot, false);
502 }
503
504 void CodeGenerator::AssembleTailCallAfterGap(Instruction* instr,
505 int first_unused_stack_slot) {
506 AdjustStackPointerForTailCall(masm(), frame_access_state(),
507 first_unused_stack_slot);
508 }
509
462 // Assembles an instruction after register allocation, producing machine code. 510 // Assembles an instruction after register allocation, producing machine code.
463 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( 511 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
464 Instruction* instr) { 512 Instruction* instr) {
465 IA32OperandConverter i(this, instr); 513 IA32OperandConverter i(this, instr);
466 InstructionCode opcode = instr->opcode(); 514 InstructionCode opcode = instr->opcode();
467 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); 515 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode);
468 switch (arch_opcode) { 516 switch (arch_opcode) {
469 case kArchCallCodeObject: { 517 case kArchCallCodeObject: {
470 EnsureSpaceForLazyDeopt(); 518 EnsureSpaceForLazyDeopt();
471 if (HasImmediateInput(instr, 0)) { 519 if (HasImmediateInput(instr, 0)) {
472 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 520 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
473 __ call(code, RelocInfo::CODE_TARGET); 521 __ call(code, RelocInfo::CODE_TARGET);
474 } else { 522 } else {
475 Register reg = i.InputRegister(0); 523 Register reg = i.InputRegister(0);
476 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 524 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
477 __ call(reg); 525 __ call(reg);
478 } 526 }
479 RecordCallPosition(instr); 527 RecordCallPosition(instr);
480 frame_access_state()->ClearSPDelta(); 528 frame_access_state()->ClearSPDelta();
481 break; 529 break;
482 } 530 }
483 case kArchTailCallCodeObjectFromJSFunction: 531 case kArchTailCallCodeObjectFromJSFunction:
484 case kArchTailCallCodeObject: { 532 case kArchTailCallCodeObject: {
485 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
486 AssembleDeconstructActivationRecord(stack_param_delta);
487 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { 533 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) {
488 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 534 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
489 no_reg, no_reg, no_reg); 535 no_reg, no_reg, no_reg);
490 } 536 }
491 if (HasImmediateInput(instr, 0)) { 537 if (HasImmediateInput(instr, 0)) {
492 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0)); 538 Handle<Code> code = Handle<Code>::cast(i.InputHeapObject(0));
493 __ jmp(code, RelocInfo::CODE_TARGET); 539 __ jmp(code, RelocInfo::CODE_TARGET);
494 } else { 540 } else {
495 Register reg = i.InputRegister(0); 541 Register reg = i.InputRegister(0);
496 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag)); 542 __ add(reg, Immediate(Code::kHeaderSize - kHeapObjectTag));
497 __ jmp(reg); 543 __ jmp(reg);
498 } 544 }
499 frame_access_state()->ClearSPDelta(); 545 frame_access_state()->ClearSPDelta();
546 frame_access_state()->SetFrameAccessToDefault();
500 break; 547 break;
501 } 548 }
502 case kArchTailCallAddress: { 549 case kArchTailCallAddress: {
503 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
504 AssembleDeconstructActivationRecord(stack_param_delta);
505 CHECK(!HasImmediateInput(instr, 0)); 550 CHECK(!HasImmediateInput(instr, 0));
506 Register reg = i.InputRegister(0); 551 Register reg = i.InputRegister(0);
507 __ jmp(reg); 552 __ jmp(reg);
508 frame_access_state()->ClearSPDelta(); 553 frame_access_state()->ClearSPDelta();
554 frame_access_state()->SetFrameAccessToDefault();
509 break; 555 break;
510 } 556 }
511 case kArchCallJSFunction: { 557 case kArchCallJSFunction: {
512 EnsureSpaceForLazyDeopt(); 558 EnsureSpaceForLazyDeopt();
513 Register func = i.InputRegister(0); 559 Register func = i.InputRegister(0);
514 if (FLAG_debug_code) { 560 if (FLAG_debug_code) {
515 // Check the function's context matches the context argument. 561 // Check the function's context matches the context argument.
516 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 562 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
517 __ Assert(equal, kWrongFunctionContext); 563 __ Assert(equal, kWrongFunctionContext);
518 } 564 }
519 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset)); 565 __ call(FieldOperand(func, JSFunction::kCodeEntryOffset));
520 RecordCallPosition(instr); 566 RecordCallPosition(instr);
521 frame_access_state()->ClearSPDelta(); 567 frame_access_state()->ClearSPDelta();
522 break; 568 break;
523 } 569 }
524 case kArchTailCallJSFunctionFromJSFunction: 570 case kArchTailCallJSFunctionFromJSFunction:
525 case kArchTailCallJSFunction: { 571 case kArchTailCallJSFunction: {
526 Register func = i.InputRegister(0); 572 Register func = i.InputRegister(0);
527 if (FLAG_debug_code) { 573 if (FLAG_debug_code) {
528 // Check the function's context matches the context argument. 574 // Check the function's context matches the context argument.
529 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset)); 575 __ cmp(esi, FieldOperand(func, JSFunction::kContextOffset));
530 __ Assert(equal, kWrongFunctionContext); 576 __ Assert(equal, kWrongFunctionContext);
531 } 577 }
532 int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
533 AssembleDeconstructActivationRecord(stack_param_delta);
534 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { 578 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) {
535 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, 579 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
536 no_reg, no_reg, no_reg); 580 no_reg, no_reg, no_reg);
537 } 581 }
538 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset)); 582 __ jmp(FieldOperand(func, JSFunction::kCodeEntryOffset));
539 frame_access_state()->ClearSPDelta(); 583 frame_access_state()->ClearSPDelta();
584 frame_access_state()->SetFrameAccessToDefault();
540 break; 585 break;
541 } 586 }
542 case kArchPrepareCallCFunction: { 587 case kArchPrepareCallCFunction: {
543 // Frame alignment requires using FP-relative frame addressing. 588 // Frame alignment requires using FP-relative frame addressing.
544 frame_access_state()->SetFrameAccessToFP(); 589 frame_access_state()->SetFrameAccessToFP();
545 int const num_parameters = MiscField::decode(instr->opcode()); 590 int const num_parameters = MiscField::decode(instr->opcode());
546 __ PrepareCallCFunction(num_parameters, i.TempRegister(0)); 591 __ PrepareCallCFunction(num_parameters, i.TempRegister(0));
547 break; 592 break;
548 } 593 }
549 case kArchPrepareTailCall: 594 case kArchPrepareTailCall:
550 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); 595 AssemblePrepareTailCall();
551 break; 596 break;
552 case kArchCallCFunction: { 597 case kArchCallCFunction: {
553 int const num_parameters = MiscField::decode(instr->opcode()); 598 int const num_parameters = MiscField::decode(instr->opcode());
554 if (HasImmediateInput(instr, 0)) { 599 if (HasImmediateInput(instr, 0)) {
555 ExternalReference ref = i.InputExternalReference(0); 600 ExternalReference ref = i.InputExternalReference(0);
556 __ CallCFunction(ref, num_parameters); 601 __ CallCFunction(ref, num_parameters);
557 } else { 602 } else {
558 Register func = i.InputRegister(0); 603 Register func = i.InputRegister(0);
559 __ CallCFunction(func, num_parameters); 604 __ CallCFunction(func, num_parameters);
560 } 605 }
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; 2106 int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc;
2062 __ Nop(padding_size); 2107 __ Nop(padding_size);
2063 } 2108 }
2064 } 2109 }
2065 2110
2066 #undef __ 2111 #undef __
2067 2112
2068 } // namespace compiler 2113 } // namespace compiler
2069 } // namespace internal 2114 } // namespace internal
2070 } // namespace v8 2115 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/gap-resolver.cc ('k') | src/compiler/instruction-selector.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698