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/arm64/frames-arm64.h" | 7 #include "src/arm64/frames-arm64.h" |
8 #include "src/arm64/macro-assembler-arm64.h" | 8 #include "src/arm64/macro-assembler-arm64.h" |
9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
10 #include "src/compiler/code-generator-impl.h" | 10 #include "src/compiler/code-generator-impl.h" |
(...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 case kArchCallCodeObject: { | 523 case kArchCallCodeObject: { |
524 EnsureSpaceForLazyDeopt(); | 524 EnsureSpaceForLazyDeopt(); |
525 if (instr->InputAt(0)->IsImmediate()) { | 525 if (instr->InputAt(0)->IsImmediate()) { |
526 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 526 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
527 RelocInfo::CODE_TARGET); | 527 RelocInfo::CODE_TARGET); |
528 } else { | 528 } else { |
529 Register target = i.InputRegister(0); | 529 Register target = i.InputRegister(0); |
530 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); | 530 __ Add(target, target, Code::kHeaderSize - kHeapObjectTag); |
531 __ Call(target); | 531 __ Call(target); |
532 } | 532 } |
| 533 RecordCallPosition(instr); |
533 // TODO(titzer): this is ugly. JSSP should be a caller-save register | 534 // TODO(titzer): this is ugly. JSSP should be a caller-save register |
534 // in this case, but it is not possible to express in the register | 535 // in this case, but it is not possible to express in the register |
535 // allocator. | 536 // allocator. |
536 CallDescriptor::Flags flags = | 537 CallDescriptor::Flags flags(MiscField::decode(opcode)); |
537 static_cast<CallDescriptor::Flags>(MiscField::decode(opcode)); | |
538 if (flags & CallDescriptor::kRestoreJSSP) { | 538 if (flags & CallDescriptor::kRestoreJSSP) { |
539 __ mov(jssp, csp); | 539 __ Ldr(jssp, MemOperand(csp)); |
| 540 __ Mov(csp, jssp); |
| 541 } |
| 542 if (flags & CallDescriptor::kRestoreCSP) { |
| 543 __ Mov(csp, jssp); |
| 544 __ AssertCspAligned(); |
540 } | 545 } |
541 frame_access_state()->ClearSPDelta(); | 546 frame_access_state()->ClearSPDelta(); |
542 RecordCallPosition(instr); | |
543 break; | 547 break; |
544 } | 548 } |
545 case kArchTailCallCodeObjectFromJSFunction: | 549 case kArchTailCallCodeObjectFromJSFunction: |
546 case kArchTailCallCodeObject: { | 550 case kArchTailCallCodeObject: { |
547 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); | 551 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
548 AssembleDeconstructActivationRecord(stack_param_delta); | 552 AssembleDeconstructActivationRecord(stack_param_delta); |
549 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { | 553 if (arch_opcode == kArchTailCallCodeObjectFromJSFunction) { |
550 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, | 554 AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister, |
551 i.TempRegister(0), i.TempRegister(1), | 555 i.TempRegister(0), i.TempRegister(1), |
552 i.TempRegister(2)); | 556 i.TempRegister(2)); |
(...skipping 15 matching lines...) Expand all Loading... |
568 if (FLAG_debug_code) { | 572 if (FLAG_debug_code) { |
569 // Check the function's context matches the context argument. | 573 // Check the function's context matches the context argument. |
570 UseScratchRegisterScope scope(masm()); | 574 UseScratchRegisterScope scope(masm()); |
571 Register temp = scope.AcquireX(); | 575 Register temp = scope.AcquireX(); |
572 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 576 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
573 __ cmp(cp, temp); | 577 __ cmp(cp, temp); |
574 __ Assert(eq, kWrongFunctionContext); | 578 __ Assert(eq, kWrongFunctionContext); |
575 } | 579 } |
576 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 580 __ Ldr(x10, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
577 __ Call(x10); | 581 __ Call(x10); |
| 582 RecordCallPosition(instr); |
578 // TODO(titzer): this is ugly. JSSP should be a caller-save register | 583 // TODO(titzer): this is ugly. JSSP should be a caller-save register |
579 // in this case, but it is not possible to express in the register | 584 // in this case, but it is not possible to express in the register |
580 // allocator. | 585 // allocator. |
581 CallDescriptor::Flags flags = | 586 CallDescriptor::Flags flags(MiscField::decode(opcode)); |
582 static_cast<CallDescriptor::Flags>(MiscField::decode(opcode)); | |
583 if (flags & CallDescriptor::kRestoreJSSP) { | 587 if (flags & CallDescriptor::kRestoreJSSP) { |
584 __ mov(jssp, csp); | 588 __ Ldr(jssp, MemOperand(csp)); |
| 589 __ Mov(csp, jssp); |
| 590 } |
| 591 if (flags & CallDescriptor::kRestoreCSP) { |
| 592 __ Mov(csp, jssp); |
| 593 __ AssertCspAligned(); |
585 } | 594 } |
586 frame_access_state()->ClearSPDelta(); | 595 frame_access_state()->ClearSPDelta(); |
587 RecordCallPosition(instr); | |
588 break; | 596 break; |
589 } | 597 } |
590 case kArchTailCallJSFunctionFromJSFunction: | 598 case kArchTailCallJSFunctionFromJSFunction: |
591 case kArchTailCallJSFunction: { | 599 case kArchTailCallJSFunction: { |
592 Register func = i.InputRegister(0); | 600 Register func = i.InputRegister(0); |
593 if (FLAG_debug_code) { | 601 if (FLAG_debug_code) { |
594 // Check the function's context matches the context argument. | 602 // Check the function's context matches the context argument. |
595 UseScratchRegisterScope scope(masm()); | 603 UseScratchRegisterScope scope(masm()); |
596 Register temp = scope.AcquireX(); | 604 Register temp = scope.AcquireX(); |
597 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); | 605 __ Ldr(temp, FieldMemOperand(func, JSFunction::kContextOffset)); |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 i.InputInt6(3)); | 968 i.InputInt6(3)); |
961 break; | 969 break; |
962 case kArm64TestAndBranch32: | 970 case kArm64TestAndBranch32: |
963 case kArm64TestAndBranch: | 971 case kArm64TestAndBranch: |
964 // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch. | 972 // Pseudo instructions turned into tbz/tbnz in AssembleArchBranch. |
965 break; | 973 break; |
966 case kArm64CompareAndBranch32: | 974 case kArm64CompareAndBranch32: |
967 // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch. | 975 // Pseudo instruction turned into cbz/cbnz in AssembleArchBranch. |
968 break; | 976 break; |
969 case kArm64ClaimCSP: { | 977 case kArm64ClaimCSP: { |
970 int count = i.InputInt32(0); | 978 int count = RoundUp(i.InputInt32(0), 2); |
971 Register prev = __ StackPointer(); | 979 Register prev = __ StackPointer(); |
972 if (prev.Is(jssp)) { | 980 if (prev.Is(jssp)) { |
973 __ AlignAndSetCSPForFrame(); | 981 // TODO(titzer): make this a macro-assembler method. |
| 982 // Align the CSP and store the previous JSSP on the stack. |
| 983 UseScratchRegisterScope scope(masm()); |
| 984 Register tmp = scope.AcquireX(); |
| 985 |
| 986 int sp_alignment = __ ActivationFrameAlignment(); |
| 987 __ Sub(tmp, jssp, kPointerSize); |
| 988 __ And(tmp, tmp, Operand(~static_cast<uint64_t>(sp_alignment - 1))); |
| 989 __ Mov(csp, tmp); |
| 990 __ Str(jssp, MemOperand(csp)); |
| 991 if (count > 0) { |
| 992 __ SetStackPointer(csp); |
| 993 __ Claim(count); |
| 994 __ SetStackPointer(prev); |
| 995 } |
| 996 } else { |
| 997 __ AssertCspAligned(); |
| 998 if (count > 0) { |
| 999 __ Claim(count); |
| 1000 frame_access_state()->IncreaseSPDelta(count); |
| 1001 } |
974 } | 1002 } |
975 if (count > 0) { | |
976 __ Claim(count); | |
977 } | |
978 __ SetStackPointer(prev); | |
979 frame_access_state()->IncreaseSPDelta(count); | |
980 break; | 1003 break; |
981 } | 1004 } |
982 case kArm64ClaimJSSP: { | 1005 case kArm64ClaimJSSP: { |
983 int count = i.InputInt32(0); | 1006 int count = i.InputInt32(0); |
984 if (csp.Is(__ StackPointer())) { | 1007 if (csp.Is(__ StackPointer())) { |
985 // No JSP is set up. Compute it from the CSP. | 1008 // No JSSP is set up. Compute it from the CSP. |
986 int even = RoundUp(count, 2); | 1009 __ AssertCspAligned(); |
987 __ Sub(jssp, csp, count * kPointerSize); | 1010 if (count > 0) { |
988 __ Sub(csp, csp, even * kPointerSize); // Must always be aligned. | 1011 int even = RoundUp(count, 2); |
989 frame_access_state()->IncreaseSPDelta(even); | 1012 __ Sub(jssp, csp, count * kPointerSize); |
| 1013 __ Sub(csp, csp, even * kPointerSize); // Must always be aligned. |
| 1014 frame_access_state()->IncreaseSPDelta(even); |
| 1015 } else { |
| 1016 __ Mov(jssp, csp); |
| 1017 } |
990 } else { | 1018 } else { |
991 // JSSP is the current stack pointer, just use regular Claim(). | 1019 // JSSP is the current stack pointer, just use regular Claim(). |
992 __ Claim(count); | 1020 __ Claim(count); |
993 frame_access_state()->IncreaseSPDelta(count); | 1021 frame_access_state()->IncreaseSPDelta(count); |
994 } | 1022 } |
995 break; | 1023 break; |
996 } | 1024 } |
997 case kArm64PokeCSP: // fall through | 1025 case kArm64PokeCSP: // fall through |
998 case kArm64PokeJSSP: { | 1026 case kArm64PokeJSSP: { |
999 Register prev = __ StackPointer(); | 1027 Register prev = __ StackPointer(); |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1460 void CodeGenerator::AssembleDeoptimizerCall( | 1488 void CodeGenerator::AssembleDeoptimizerCall( |
1461 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { | 1489 int deoptimization_id, Deoptimizer::BailoutType bailout_type) { |
1462 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( | 1490 Address deopt_entry = Deoptimizer::GetDeoptimizationEntry( |
1463 isolate(), deoptimization_id, bailout_type); | 1491 isolate(), deoptimization_id, bailout_type); |
1464 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); | 1492 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); |
1465 } | 1493 } |
1466 | 1494 |
1467 | 1495 |
1468 void CodeGenerator::AssemblePrologue() { | 1496 void CodeGenerator::AssemblePrologue() { |
1469 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 1497 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 1498 if (descriptor->UseNativeStack()) { |
| 1499 __ AssertCspAligned(); |
| 1500 } |
| 1501 |
1470 frame()->AlignFrame(16); | 1502 frame()->AlignFrame(16); |
1471 int stack_shrink_slots = frame()->GetSpillSlotCount(); | 1503 int stack_shrink_slots = frame()->GetSpillSlotCount(); |
1472 if (frame()->needs_frame()) { | 1504 if (frame()->needs_frame()) { |
1473 if (descriptor->IsJSFunctionCall()) { | 1505 if (descriptor->IsJSFunctionCall()) { |
1474 DCHECK(!descriptor->UseNativeStack()); | 1506 DCHECK(!descriptor->UseNativeStack()); |
1475 __ SetStackPointer(jssp); | 1507 __ SetStackPointer(jssp); |
1476 __ Prologue(this->info()->GeneratePreagedPrologue()); | 1508 __ Prologue(this->info()->GeneratePreagedPrologue()); |
1477 } else { | 1509 } else { |
1478 if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) { | 1510 if (descriptor->UseNativeStack() || descriptor->IsCFunctionCall()) { |
1479 __ SetStackPointer(csp); | 1511 __ SetStackPointer(csp); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1572 pop_count += (pop_count & 1); // align | 1604 pop_count += (pop_count & 1); // align |
1573 } else { | 1605 } else { |
1574 __ Mov(jssp, fp); | 1606 __ Mov(jssp, fp); |
1575 } | 1607 } |
1576 __ Pop(fp, lr); | 1608 __ Pop(fp, lr); |
1577 } | 1609 } |
1578 } else if (descriptor->UseNativeStack()) { | 1610 } else if (descriptor->UseNativeStack()) { |
1579 pop_count += (pop_count & 1); // align | 1611 pop_count += (pop_count & 1); // align |
1580 } | 1612 } |
1581 __ Drop(pop_count); | 1613 __ Drop(pop_count); |
| 1614 |
| 1615 if (descriptor->UseNativeStack()) { |
| 1616 __ AssertCspAligned(); |
| 1617 } |
1582 __ Ret(); | 1618 __ Ret(); |
1583 } | 1619 } |
1584 | 1620 |
1585 | 1621 |
1586 void CodeGenerator::AssembleMove(InstructionOperand* source, | 1622 void CodeGenerator::AssembleMove(InstructionOperand* source, |
1587 InstructionOperand* destination) { | 1623 InstructionOperand* destination) { |
1588 Arm64OperandConverter g(this, nullptr); | 1624 Arm64OperandConverter g(this, nullptr); |
1589 // Dispatch on the source and destination operand kinds. Not all | 1625 // Dispatch on the source and destination operand kinds. Not all |
1590 // combinations are possible. | 1626 // combinations are possible. |
1591 if (source->IsRegister()) { | 1627 if (source->IsRegister()) { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1765 padding_size -= kInstructionSize; | 1801 padding_size -= kInstructionSize; |
1766 } | 1802 } |
1767 } | 1803 } |
1768 } | 1804 } |
1769 | 1805 |
1770 #undef __ | 1806 #undef __ |
1771 | 1807 |
1772 } // namespace compiler | 1808 } // namespace compiler |
1773 } // namespace internal | 1809 } // namespace internal |
1774 } // namespace v8 | 1810 } // namespace v8 |
OLD | NEW |