1f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
7fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#if V8_TARGET_ARCH_ARM64
8f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h"
11f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
12f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace v8 {
13f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgnamespace internal {
14f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
15f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
16f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#define __ ACCESS_MASM(masm)
17f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
18f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool BreakLocationIterator::IsDebugBreakAtReturn() {
19f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return Debug::IsDebugBreakAtReturn(rinfo());
20f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
21f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
22f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
23f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid BreakLocationIterator::SetDebugBreakAtReturn() {
24f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Patch the code emitted by FullCodeGenerator::EmitReturnSequence, changing
25f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the return from JS function sequence from
26f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   mov sp, fp
27f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   ldp fp, lr, [sp] #16
28f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   lrd ip0, [pc, #(3 * kInstructionSize)]
29f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   add sp, sp, ip0
30f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   ret
31f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   <number of paramters ...
32f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //    ... plus one (64 bits)>
33f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // to a call to the debug break return code.
34f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   ldr ip0, [pc, #(3 * kInstructionSize)]
35f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   blr ip0
36f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   hlt kHltBadCode    @ code should not return, catch if it does.
37f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   <debug break return code ...
38f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //    ... entry point address (64 bits)>
39f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
40f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The patching code must not overflow the space occupied by the return
41f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // sequence.
42f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  STATIC_ASSERT(Assembler::kJSRetSequenceInstructions >= 5);
43f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PatchingAssembler patcher(reinterpret_cast<Instruction*>(rinfo()->pc()), 5);
44f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  byte* entry =
45af6f699b0be532b73bc2f6c9e1cf40a57fa7e234machenbach@chromium.org      debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry();
46f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
47f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The first instruction of a patched return sequence must be a load literal
48f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // loading the address of the debug break return code.
49e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  patcher.ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2);
50f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): check the following is correct.
51f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The debug break return code will push a frame and call statically compiled
52f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // code. By using blr, even though control will not return after the branch,
53f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // this call site will be registered in the frame (lr being saved as the pc
54f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // of the next instruction to execute for this frame). The debugger can now
55f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // iterate on the frames to find call to debug break return code.
56f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  patcher.blr(ip0);
57f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  patcher.hlt(kHltBadCode);
58f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  patcher.dc64(reinterpret_cast<int64_t>(entry));
59f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
60f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
61f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
62f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid BreakLocationIterator::ClearDebugBreakAtReturn() {
63f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Reset the code emitted by EmitReturnSequence to its original state.
64f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  rinfo()->PatchCode(original_rinfo()->pc(),
65f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     Assembler::kJSRetSequenceInstructions);
66f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
67f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
68f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
69f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool Debug::IsDebugBreakAtReturn(RelocInfo* rinfo) {
70e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(RelocInfo::IsJSReturn(rinfo->rmode()));
71f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return rinfo->IsPatchedReturnSequence();
72f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
73f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
74f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
75f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgbool BreakLocationIterator::IsDebugBreakAtSlot() {
76e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsDebugBreakSlot());
77f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Check whether the debug break slot instructions have been patched.
78f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  return rinfo()->IsPatchedDebugBreakSlotSequence();
79f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
80f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
81f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
82f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid BreakLocationIterator::SetDebugBreakAtSlot() {
83d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // Patch the code emitted by DebugCodegen::GenerateSlots, changing the debug
84d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  // break slot code from
85f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   mov x0, x0    @ nop DEBUG_BREAK_NOP
86f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   mov x0, x0    @ nop DEBUG_BREAK_NOP
87f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   mov x0, x0    @ nop DEBUG_BREAK_NOP
88f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   mov x0, x0    @ nop DEBUG_BREAK_NOP
89f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // to a call to the debug slot code.
90f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   ldr ip0, [pc, #(2 * kInstructionSize)]
91f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   blr ip0
92f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //   <debug break slot code ...
93f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //    ... entry point address (64 bits)>
94f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): consider adding a hlt instruction after the blr as we don't
96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // expect control to return here. This implies increasing
97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // kDebugBreakSlotInstructions to 5 instructions.
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The patching code must not overflow the space occupied by the return
100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // sequence.
101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  STATIC_ASSERT(Assembler::kDebugBreakSlotInstructions >= 4);
102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  PatchingAssembler patcher(reinterpret_cast<Instruction*>(rinfo()->pc()), 4);
103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  byte* entry =
104af6f699b0be532b73bc2f6c9e1cf40a57fa7e234machenbach@chromium.org      debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry();
105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The first instruction of a patched debug break slot must be a load literal
107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // loading the address of the debug break slot code.
108e7a6d372100022f492c88886898add6a51e66977machenbach@chromium.org  patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2);
109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // TODO(all): check the following is correct.
110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // The debug break slot code will push a frame and call statically compiled
111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // code. By using blr, event hough control will not return after the branch,
112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // this call site will be registered in the frame (lr being saved as the pc
113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // of the next instruction to execute for this frame). The debugger can now
114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // iterate on the frames to find call to debug break slot code.
115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  patcher.blr(ip0);
116f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  patcher.dc64(reinterpret_cast<int64_t>(entry));
117f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
118f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
119f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
120f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgvoid BreakLocationIterator::ClearDebugBreakAtSlot() {
121e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(IsDebugBreakSlot());
122f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  rinfo()->PatchCode(original_rinfo()->pc(),
123f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                     Assembler::kDebugBreakSlotInstructions);
124f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
125f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
126f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
127f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.orgstatic void Generate_DebugBreakCallHelper(MacroAssembler* masm,
128f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                          RegList object_regs,
129f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                          RegList non_object_regs,
130f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org                                          Register scratch) {
131f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  {
132f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    FrameScope scope(masm, StackFrame::INTERNAL);
133f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
134975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    // Load padding words on stack.
13508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue));
13608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    __ PushMultipleTimes(scratch, LiveEdit::kFramePaddingInitialSize);
13708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    __ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize));
13808e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org    __ Push(scratch);
139975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
140f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Any live values (object_regs and non_object_regs) in caller-saved
141f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // registers (or lr) need to be stored on the stack so that their values are
142f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // safely preserved for a call into C code.
143f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //
144f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Also:
145f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //  * object_regs may be modified during the C code by the garbage
146f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //    collector. Every object register must be a valid tagged pointer or
147f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //    SMI.
148f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //
149f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //  * non_object_regs will be converted to SMIs so that the garbage
150f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //    collector doesn't try to interpret them as pointers.
151f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    //
152f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // TODO(jbramley): Why can't this handle callee-saved registers?
153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((~kCallerSaved.list() & object_regs) == 0);
154e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((~kCallerSaved.list() & non_object_regs) == 0);
155e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((object_regs & non_object_regs) == 0);
156e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((scratch.Bit() & object_regs) == 0);
157e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((scratch.Bit() & non_object_regs) == 0);
158e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK((masm->TmpList()->list() & (object_regs | non_object_regs)) == 0);
159f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    STATIC_ASSERT(kSmiValueSize == 32);
160f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
161f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CPURegList non_object_list =
16297b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org        CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs);
163f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    while (!non_object_list.IsEmpty()) {
164f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Store each non-object register as two SMIs.
165f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Register reg = Register(non_object_list.PopLowestIndex());
1661e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org      __ Lsr(scratch, reg, 32);
1671e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org      __ SmiTagAndPush(scratch, reg);
1681e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org
169f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Stack:
170f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[12]: reg[63:32]
171f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[8]: 0x00000000 (SMI tag & padding)
172f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[4]: reg[31:0]
173f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[0]: 0x00000000 (SMI tag & padding)
1745366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      STATIC_ASSERT(kSmiTag == 0);
1755366bfdf41c98cd70820c1633b031dc290ec1cd6machenbach@chromium.org      STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == kWRegSizeInBits);
176f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
177f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
178f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (object_regs != 0) {
179f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ PushXRegList(object_regs);
180f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
181f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
182f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#ifdef DEBUG
183f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ RecordComment("// Calling from debug break to runtime - come in - over");
184f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org#endif
185f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ Mov(x0, 0);  // No arguments.
1867010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org    __ Mov(x1, ExternalReference::debug_break(masm->isolate()));
187f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
188f2f0489407bbb5e50d16ae791442df29513b53b5machenbach@chromium.org    CEntryStub stub(masm->isolate(), 1);
189f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ CallStub(&stub);
190f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
191f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Restore the register values from the expression stack.
192f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (object_regs != 0) {
193f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ PopXRegList(object_regs);
194f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
195f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
196f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    non_object_list =
19797b98c9169c85693801d4d59089450695ad82e2dmachenbach@chromium.org        CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs);
198f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    while (!non_object_list.IsEmpty()) {
199f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Load each non-object register from two SMIs.
200f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      // Stack:
201f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[12]: reg[63:32]
202f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[8]: 0x00000000 (SMI tag & padding)
203f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[4]: reg[31:0]
204f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      //  jssp[0]: 0x00000000 (SMI tag & padding)
205f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      Register reg = Register(non_object_list.PopHighestIndex());
206f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ Pop(scratch, reg);
207f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      __ Bfxil(reg, scratch, 32, 32);
208f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
209f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
210975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    // Don't bother removing padding bytes pushed on the stack
211975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org    // as the frame is going to be restored right away.
212975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
213f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Leave the internal frame.
214f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
215f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
216f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Now that the break point has been handled, resume normal execution by
217f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // jumping to the target address intended by the caller and that was
218f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // overwritten by the address of DebugBreakXXX.
219fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org  ExternalReference after_break_target =
220fb547e07aef43e02715c5d6c1530e84bb3cbba02machenbach@chromium.org      ExternalReference::debug_after_break_target_address(masm->isolate());
2217010a2d84de67daace72568ffcde315a3e510ab5machenbach@chromium.org  __ Mov(scratch, after_break_target);
222f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Ldr(scratch, MemOperand(scratch));
223f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ Br(scratch);
224f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
225f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
226f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
227d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) {
228a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // Register state for CallICStub
229a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // ----------- S t a t e -------------
230a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  //  -- x1 : function
231a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  //  -- x3 : slot in feedback array
232a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  // -----------------------------------
233a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org  Generate_DebugBreakCallHelper(masm, x1.Bit() | x3.Bit(), 0, x10);
234a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org}
235a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org
236a86d416fb652b1936026eee315eccd4f17ca1002machenbach@chromium.org
237d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateLoadICDebugBreak(MacroAssembler* masm) {
238f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Calling convention for IC load (from ic-arm.cc).
2399aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register receiver = LoadDescriptor::ReceiverRegister();
2409aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register name = LoadDescriptor::NameRegister();
241248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  Generate_DebugBreakCallHelper(masm, receiver.Bit() | name.Bit(), 0, x10);
242f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
243f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
244f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
245d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateStoreICDebugBreak(MacroAssembler* masm) {
24670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Calling convention for IC store (from ic-arm64.cc).
2479aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register receiver = StoreDescriptor::ReceiverRegister();
2489aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register name = StoreDescriptor::NameRegister();
2499aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register value = StoreDescriptor::ValueRegister();
25070d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  Generate_DebugBreakCallHelper(
25170d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      masm, receiver.Bit() | name.Bit() | value.Bit(), 0, x10);
252f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
253f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
254f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
255d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
256248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  // Calling convention for keyed IC load (from ic-arm.cc).
2575de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org  GenerateLoadICDebugBreak(masm);
258f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
259f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
260f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
261d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
26270d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  // Calling convention for IC keyed store call (from ic-arm64.cc).
2639aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register receiver = StoreDescriptor::ReceiverRegister();
2649aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register name = StoreDescriptor::NameRegister();
2659aaa825cf89e1bcfece269a453300ebf4a26d64dmachenbach@chromium.org  Register value = StoreDescriptor::ValueRegister();
26670d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org  Generate_DebugBreakCallHelper(
26770d29e1ad7a6f1c163f625252ca32ecc522cb155machenbach@chromium.org      masm, receiver.Bit() | name.Bit() | value.Bit(), 0, x10);
268f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
269f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
270f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
271d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateCompareNilICDebugBreak(MacroAssembler* masm) {
272f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Register state for CompareNil IC
273f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // ----------- S t a t e -------------
274f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- r0    : value
275f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // -----------------------------------
276f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(masm, x0.Bit(), 0, x10);
277f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
278f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
279f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
280d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) {
281f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // In places other than IC call sites it is expected that r0 is TOS which
282f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // is an object - this is not generally the case so this should be used with
283f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // care.
284f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(masm, x0.Bit(), 0, x10);
285f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
286f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
287f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
288d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) {
289fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Register state for CallFunctionStub (from code-stubs-arm64.cc).
290f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // ----------- S t a t e -------------
291f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x1 : function
292f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // -----------------------------------
293f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(masm, x1.Bit(), 0, x10);
294f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
295f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
296f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
297d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) {
298fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Calling convention for CallConstructStub (from code-stubs-arm64.cc).
299f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // ----------- S t a t e -------------
300f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x0 : number of arguments (not smi)
301f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x1 : constructor function
302f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // -----------------------------------
303f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(masm, x1.Bit(), x0.Bit(), x10);
304f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
305f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
306f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
307d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateCallConstructStubRecordDebugBreak(
308d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    MacroAssembler* masm) {
309fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org  // Calling convention for CallConstructStub (from code-stubs-arm64.cc).
310f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // ----------- S t a t e -------------
311f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x0 : number of arguments (not smi)
312f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x1 : constructor function
313f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x2     : feedback array
314f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  //  -- x3     : feedback slot (smi)
315f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // -----------------------------------
316f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(
317f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      masm, x1.Bit() | x2.Bit() | x3.Bit(), x0.Bit(), x10);
318f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
319f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
320f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
321d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateSlot(MacroAssembler* masm) {
322f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // Generate enough nop's to make space for a call instruction. Avoid emitting
323f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // the constant pool in the debug break slot code.
324f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  InstructionAccurateScope scope(masm, Assembler::kDebugBreakSlotInstructions);
325f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
326f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  __ RecordDebugBreakSlot();
327f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
328f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    __ nop(Assembler::DEBUG_BREAK_NOP);
329f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
330f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
331f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
332f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
333d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) {
334f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // In the places where a debug break slot is inserted no registers can contain
335f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // object pointers.
336f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  Generate_DebugBreakCallHelper(masm, 0, 0, x10);
337f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
338f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
339f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
340d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) {
341975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  __ Ret();
342f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
343f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
344f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
345d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.orgvoid DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) {
346975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  ExternalReference restarter_frame_function_slot =
347975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org      ExternalReference::debug_restarter_frame_function_pointer_address(
348975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org          masm->isolate());
34908e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  UseScratchRegisterScope temps(masm);
35008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  Register scratch = temps.AcquireX();
35108e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org
35208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Mov(scratch, restarter_frame_function_slot);
35308e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Str(xzr, MemOperand(scratch));
354975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
355975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  // We do not know our frame height, but set sp based on fp.
35608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Sub(masm->StackPointer(), fp, kPointerSize);
35708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ AssertStackConsistency();
358975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
359975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  __ Pop(x1, fp, lr);  // Function, Frame, Return address.
360975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
361975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  // Load context from the function.
36208e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
363975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
364975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  // Get function code.
36508e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Ldr(scratch, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
36608e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Ldr(scratch, FieldMemOperand(scratch, SharedFunctionInfo::kCodeOffset));
36708e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag);
368975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org
369975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.org  // Re-run JSFunction, x1 is function, cp is context.
37008e7569a10f8edbb47b8fe70a6e160a4e0c9cd30machenbach@chromium.org  __ Br(scratch);
371f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org}
372f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
373e31b63e9608909e17e35a3330b0075140af2fe91machenbach@chromium.org
374975b940441085887fc02bebf8877d5ec97e1e06cmachenbach@chromium.orgconst bool LiveEdit::kFrameDropperSupported = true;
375f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
376f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org} }  // namespace v8::internal
377f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
378fa0c3c69b9d632e5730bdd9c745c375beef5e54dmachenbach@chromium.org#endif  // V8_TARGET_ARCH_ARM64
379