OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
404 0, 1); \ | 404 0, 1); \ |
405 /* Move the result in the double result register. */ \ | 405 /* Move the result in the double result register. */ \ |
406 __ MovFromFloatResult(i.OutputDoubleRegister()); \ | 406 __ MovFromFloatResult(i.OutputDoubleRegister()); \ |
407 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ | 407 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
408 } while (0) | 408 } while (0) |
409 | 409 |
410 void CodeGenerator::AssembleDeconstructFrame() { | 410 void CodeGenerator::AssembleDeconstructFrame() { |
411 __ LeaveFrame(StackFrame::MANUAL); | 411 __ LeaveFrame(StackFrame::MANUAL); |
412 } | 412 } |
413 | 413 |
414 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { | 414 void CodeGenerator::AssemblePrepareTailCall() { |
415 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
416 if (sp_slot_delta > 0) { | |
417 __ add(sp, sp, Operand(sp_slot_delta * kPointerSize)); | |
418 } | |
419 frame_access_state()->SetFrameAccessToDefault(); | |
420 } | |
421 | |
422 | |
423 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { | |
424 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); | |
425 if (sp_slot_delta < 0) { | |
426 __ sub(sp, sp, Operand(-sp_slot_delta * kPointerSize)); | |
427 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); | |
428 } | |
429 if (frame_access_state()->has_frame()) { | 415 if (frame_access_state()->has_frame()) { |
430 if (FLAG_enable_embedded_constant_pool) { | 416 if (FLAG_enable_embedded_constant_pool) { |
431 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); | 417 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); |
432 } | 418 } |
433 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 419 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
434 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 420 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
435 } | 421 } |
436 frame_access_state()->SetFrameAccessToSP(); | 422 frame_access_state()->SetFrameAccessToSP(); |
437 } | 423 } |
438 | 424 |
(...skipping 15 matching lines...) Expand all Loading... | |
454 __ ldr(caller_args_count_reg, | 440 __ ldr(caller_args_count_reg, |
455 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 441 MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
456 __ SmiUntag(caller_args_count_reg); | 442 __ SmiUntag(caller_args_count_reg); |
457 | 443 |
458 ParameterCount callee_args_count(args_reg); | 444 ParameterCount callee_args_count(args_reg); |
459 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, | 445 __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2, |
460 scratch3); | 446 scratch3); |
461 __ bind(&done); | 447 __ bind(&done); |
462 } | 448 } |
463 | 449 |
450 namespace { | |
451 | |
452 void FlushPendingPushRegisters(MacroAssembler* masm, | |
453 FrameAccessState* frame_access_state, | |
454 ZoneVector<Register>* pending_pushes) { | |
455 switch (pending_pushes->size()) { | |
456 case 0: | |
457 break; | |
458 case 1: | |
459 masm->push((*pending_pushes)[0]); | |
Mircea Trofin
2016/06/30 15:32:34
pending_pushes->at(0)
same further down and else
danno
2016/07/01 07:31:57
Done.
| |
460 break; | |
461 case 2: | |
462 masm->Push((*pending_pushes)[0], (*pending_pushes)[1]); | |
463 break; | |
464 case 3: | |
465 masm->Push((*pending_pushes)[0], (*pending_pushes)[1], | |
466 (*pending_pushes)[2]); | |
467 break; | |
468 default: | |
469 UNREACHABLE(); | |
470 break; | |
471 } | |
472 frame_access_state->IncreaseSPDelta(pending_pushes->size()); | |
473 pending_pushes->resize(0); | |
474 } | |
475 | |
476 void AddPendingPushRegister(MacroAssembler* masm, | |
477 FrameAccessState* frame_access_state, | |
478 ZoneVector<Register>* pending_pushes, | |
479 Register reg) { | |
480 pending_pushes->push_back(reg); | |
481 if (pending_pushes->size() == 3 || reg.is(ip)) { | |
482 FlushPendingPushRegisters(masm, frame_access_state, pending_pushes); | |
483 } | |
484 } | |
485 | |
486 void AdjustStackPointerForGap(MacroAssembler* masm, FrameAccessState* state, | |
487 int new_slot_above_sp, | |
488 ZoneVector<Register>* pending_pushes = nullptr, | |
489 bool allow_shrinkage = true) { | |
490 int current_sp_offset = state->GetSPToFPSlotCount() + | |
491 StandardFrameConstants::kFixedSlotCountAboveFp; | |
492 int stack_slot_delta = new_slot_above_sp - current_sp_offset; | |
493 if (stack_slot_delta > 0) { | |
494 if (pending_pushes != nullptr) { | |
495 FlushPendingPushRegisters(masm, state, pending_pushes); | |
496 } | |
497 masm->sub(sp, sp, Operand(stack_slot_delta * kPointerSize)); | |
498 state->IncreaseSPDelta(stack_slot_delta); | |
499 } else if (allow_shrinkage && stack_slot_delta < 0) { | |
500 if (pending_pushes != nullptr) { | |
501 FlushPendingPushRegisters(masm, state, pending_pushes); | |
502 } | |
503 masm->add(sp, sp, Operand(-stack_slot_delta * kPointerSize)); | |
504 state->IncreaseSPDelta(stack_slot_delta); | |
505 } | |
506 } | |
507 | |
508 } // namespace | |
509 | |
510 void CodeGenerator::AssemblePreGaps(Instruction* instr) { | |
511 int first_unused_stack_slot; | |
512 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; | |
513 | |
514 GapResolver::PushTypeFlags flags(GapResolver::kImmediatePush | | |
515 GapResolver::kScalarPush); | |
516 ZoneVector<MoveOperands*> pushes(zone()); | |
517 resolver()->GetPushCompatibleMoves(zone(), instr, flags, &pushes); | |
518 | |
519 if (!pushes.empty() && | |
520 (LocationOperand::cast(pushes.back()->destination()).index() + 1 == | |
521 first_unused_stack_slot)) { | |
522 ArmOperandConverter g(this, instr); | |
523 ZoneVector<Register> pending_pushes(zone()); | |
524 for (auto move : pushes) { | |
525 LocationOperand destination_location( | |
526 LocationOperand::cast(move->destination())); | |
527 InstructionOperand source(move->source()); | |
528 AdjustStackPointerForGap( | |
529 masm(), frame_access_state(), | |
530 destination_location.index() - pending_pushes.size(), | |
531 &pending_pushes); | |
532 if (source.IsStackSlot()) { | |
533 LocationOperand source_location(LocationOperand::cast(source)); | |
534 __ ldr(ip, g.SlotToMemOperand(source_location.index())); | |
535 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, | |
536 ip); | |
537 } else if (source.IsRegister()) { | |
538 LocationOperand source_location(LocationOperand::cast(source)); | |
539 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, | |
540 source_location.GetRegister()); | |
541 } else if (source.IsImmediate()) { | |
542 AddPendingPushRegister(masm(), frame_access_state(), &pending_pushes, | |
543 ip); | |
544 } else { | |
545 // Pushes of non-scalar data types is not supported. | |
546 UNIMPLEMENTED(); | |
547 } | |
548 move->Eliminate(); | |
549 } | |
550 FlushPendingPushRegisters(masm(), frame_access_state(), &pending_pushes); | |
551 } | |
552 AdjustStackPointerForGap(masm(), frame_access_state(), | |
553 first_unused_stack_slot, nullptr, false); | |
554 } | |
555 | |
556 void CodeGenerator::AssemblePostGaps(Instruction* instr) { | |
557 int first_unused_stack_slot; | |
558 if (!GetSlotAboveSPAfterGap(instr, &first_unused_stack_slot)) return; | |
559 AdjustStackPointerForGap(masm(), frame_access_state(), | |
560 first_unused_stack_slot); | |
561 } | |
562 | |
464 // Assembles an instruction after register allocation, producing machine code. | 563 // Assembles an instruction after register allocation, producing machine code. |
465 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( | 564 CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
466 Instruction* instr) { | 565 Instruction* instr) { |
467 ArmOperandConverter i(this, instr); | 566 ArmOperandConverter i(this, instr); |
468 | 567 |
469 __ MaybeCheckConstPool(); | 568 __ MaybeCheckConstPool(); |
470 InstructionCode opcode = instr->opcode(); | 569 InstructionCode opcode = instr->opcode(); |
471 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); | 570 ArchOpcode arch_opcode = ArchOpcodeField::decode(opcode); |
472 switch (arch_opcode) { | 571 switch (arch_opcode) { |
473 case kArchCallCodeObject: { | 572 case kArchCallCodeObject: { |
474 EnsureSpaceForLazyDeopt(); | 573 EnsureSpaceForLazyDeopt(); |
475 if (instr->InputAt(0)->IsImmediate()) { | 574 if (instr->InputAt(0)->IsImmediate()) { |
476 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 575 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
477 RelocInfo::CODE_TARGET); | 576 RelocInfo::CODE_TARGET); |
478 } else { | 577 } else { |
479 __ add(ip, i.InputRegister(0), | 578 __ add(ip, i.InputRegister(0), |
480 Operand(Code::kHeaderSize - kHeapObjectTag)); | 579 Operand(Code::kHeaderSize - kHeapObjectTag)); |
481 __ Call(ip); | 580 __ Call(ip); |
482 } | 581 } |
483 RecordCallPosition(instr); | 582 RecordCallPosition(instr); |
484 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 583 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
485 frame_access_state()->ClearSPDelta(); | 584 frame_access_state()->ClearSPDelta(); |
486 break; | 585 break; |
487 } | 586 } |
488 case kArchTailCallCodeObjectFromJSFunction: | 587 case kArchTailCallCodeObjectFromJSFunction: |
489 case kArchTailCallCodeObject: { | 588 case kArchTailCallCodeObject: { |
490 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
491 AssembleDeconstructActivationRecord(stack_param_delta); | |
492 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 589 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
493 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 590 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
494 i.TempRegister(0), i.TempRegister(1), | 591 i.TempRegister(0), i.TempRegister(1), |
495 i.TempRegister(2)); | 592 i.TempRegister(2)); |
496 } | 593 } |
497 if (instr->InputAt(0)->IsImmediate()) { | 594 if (instr->InputAt(0)->IsImmediate()) { |
498 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 595 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
499 RelocInfo::CODE_TARGET); | 596 RelocInfo::CODE_TARGET); |
500 } else { | 597 } else { |
501 __ add(ip, i.InputRegister(0), | 598 __ add(ip, i.InputRegister(0), |
502 Operand(Code::kHeaderSize - kHeapObjectTag)); | 599 Operand(Code::kHeaderSize - kHeapObjectTag)); |
503 __ Jump(ip); | 600 __ Jump(ip); |
504 } | 601 } |
505 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 602 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
506 frame_access_state()->ClearSPDelta(); | 603 frame_access_state()->ClearSPDelta(); |
604 frame_access_state()->SetFrameAccessToDefault(); | |
507 break; | 605 break; |
508 } | 606 } |
509 case kArchTailCallAddress: { | 607 case kArchTailCallAddress: { |
510 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
511 AssembleDeconstructActivationRecord(stack_param_delta); | |
512 CHECK(!instr->InputAt(0)->IsImmediate()); | 608 CHECK(!instr->InputAt(0)->IsImmediate()); |
513 __ Jump(i.InputRegister(0)); | 609 __ Jump(i.InputRegister(0)); |
514 frame_access_state()->ClearSPDelta(); | 610 frame_access_state()->ClearSPDelta(); |
611 frame_access_state()->SetFrameAccessToDefault(); | |
515 break; | 612 break; |
516 } | 613 } |
517 case kArchCallJSFunction: { | 614 case kArchCallJSFunction: { |
518 EnsureSpaceForLazyDeopt(); | 615 EnsureSpaceForLazyDeopt(); |
519 Register func = i.InputRegister(0); | 616 Register func = i.InputRegister(0); |
520 if (FLAG_debug_code) { | 617 if (FLAG_debug_code) { |
521 // Check the function's context matches the context argument. | 618 // Check the function's context matches the context argument. |
522 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 619 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
523 __ cmp(cp, kScratchReg); | 620 __ cmp(cp, kScratchReg); |
524 __ Assert(eq, kWrongFunctionContext); | 621 __ Assert(eq, kWrongFunctionContext); |
525 } | 622 } |
526 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 623 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
527 __ Call(ip); | 624 __ Call(ip); |
528 RecordCallPosition(instr); | 625 RecordCallPosition(instr); |
529 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 626 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
530 frame_access_state()->ClearSPDelta(); | 627 frame_access_state()->ClearSPDelta(); |
531 break; | 628 break; |
532 } | 629 } |
533 case kArchTailCallJSFunctionFromJSFunction: | 630 case kArchTailCallJSFunctionFromJSFunction: |
534 case kArchTailCallJSFunction: { | 631 case kArchTailCallJSFunction: { |
535 Register func = i.InputRegister(0); | 632 Register func = i.InputRegister(0); |
536 if (FLAG_debug_code) { | 633 if (FLAG_debug_code) { |
537 // Check the function's context matches the context argument. | 634 // Check the function's context matches the context argument. |
538 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 635 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
539 __ cmp(cp, kScratchReg); | 636 __ cmp(cp, kScratchReg); |
540 __ Assert(eq, kWrongFunctionContext); | 637 __ Assert(eq, kWrongFunctionContext); |
541 } | 638 } |
542 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | |
543 AssembleDeconstructActivationRecord(stack_param_delta); | |
544 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { | 639 if (arch_opcode == kArchTailCallJSFunctionFromJSFunction) { |
545 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 640 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
546 i.TempRegister(0), i.TempRegister(1), | 641 i.TempRegister(0), i.TempRegister(1), |
547 i.TempRegister(2)); | 642 i.TempRegister(2)); |
548 } | 643 } |
549 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 644 __ ldr(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
550 __ Jump(ip); | 645 __ Jump(ip); |
551 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 646 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
552 frame_access_state()->ClearSPDelta(); | 647 frame_access_state()->ClearSPDelta(); |
648 frame_access_state()->SetFrameAccessToDefault(); | |
553 break; | 649 break; |
554 } | 650 } |
555 case kArchPrepareCallCFunction: { | 651 case kArchPrepareCallCFunction: { |
556 int const num_parameters = MiscField::decode(instr->opcode()); | 652 int const num_parameters = MiscField::decode(instr->opcode()); |
557 __ PrepareCallCFunction(num_parameters, kScratchReg); | 653 __ PrepareCallCFunction(num_parameters, kScratchReg); |
558 // Frame alignment requires using FP-relative frame addressing. | 654 // Frame alignment requires using FP-relative frame addressing. |
559 frame_access_state()->SetFrameAccessToFP(); | 655 frame_access_state()->SetFrameAccessToFP(); |
560 break; | 656 break; |
561 } | 657 } |
562 case kArchPrepareTailCall: | 658 case kArchPrepareTailCall: |
563 AssemblePrepareTailCall(i.InputInt32(instr->InputCount() - 1)); | 659 AssemblePrepareTailCall(); |
564 break; | 660 break; |
565 case kArchCallCFunction: { | 661 case kArchCallCFunction: { |
566 int const num_parameters = MiscField::decode(instr->opcode()); | 662 int const num_parameters = MiscField::decode(instr->opcode()); |
567 if (instr->InputAt(0)->IsImmediate()) { | 663 if (instr->InputAt(0)->IsImmediate()) { |
568 ExternalReference ref = i.InputExternalReference(0); | 664 ExternalReference ref = i.InputExternalReference(0); |
569 __ CallCFunction(ref, num_parameters); | 665 __ CallCFunction(ref, num_parameters); |
570 } else { | 666 } else { |
571 Register func = i.InputRegister(0); | 667 Register func = i.InputRegister(0); |
572 __ CallCFunction(func, num_parameters); | 668 __ CallCFunction(func, num_parameters); |
573 } | 669 } |
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1812 padding_size -= v8::internal::Assembler::kInstrSize; | 1908 padding_size -= v8::internal::Assembler::kInstrSize; |
1813 } | 1909 } |
1814 } | 1910 } |
1815 } | 1911 } |
1816 | 1912 |
1817 #undef __ | 1913 #undef __ |
1818 | 1914 |
1819 } // namespace compiler | 1915 } // namespace compiler |
1820 } // namespace internal | 1916 } // namespace internal |
1821 } // namespace v8 | 1917 } // namespace v8 |
OLD | NEW |