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