| 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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |