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

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

Powered by Google App Engine
This is Rietveld 408576698