mirror of https://github.com/lukechilds/node.git
Browse Source
PR-URL: https://github.com/nodejs/node/pull/3351 Reviewed-By: indutny - Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: bnoordhuis - Ben Noordhuis <info@bnoordhuis.nl>v5.x
Michaël Zasso
9 years ago
committed by
Ali Ijaz Sheikh
1058 changed files with 47033 additions and 33242 deletions
@ -0,0 +1,51 @@ |
|||
#!/usr/bin/env python |
|||
# Copyright 2015 the V8 project authors. All rights reserved. |
|||
# Copyright 2015 The Chromium Authors. All rights reserved. |
|||
# Use of this source code is governed by a BSD-style license that can be |
|||
# found in the LICENSE file. |
|||
|
|||
"""Script to download LLVM gold plugin from google storage.""" |
|||
|
|||
import json |
|||
import os |
|||
import shutil |
|||
import subprocess |
|||
import sys |
|||
import zipfile |
|||
|
|||
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) |
|||
CHROME_SRC = os.path.abspath(os.path.join(SCRIPT_DIR, os.pardir)) |
|||
sys.path.insert(0, os.path.join(CHROME_SRC, 'tools')) |
|||
|
|||
import find_depot_tools |
|||
|
|||
DEPOT_PATH = find_depot_tools.add_depot_tools_to_path() |
|||
GSUTIL_PATH = os.path.join(DEPOT_PATH, 'gsutil.py') |
|||
|
|||
LLVM_BUILD_PATH = os.path.join(CHROME_SRC, 'third_party', 'llvm-build', |
|||
'Release+Asserts') |
|||
CLANG_UPDATE_PY = os.path.join(CHROME_SRC, 'tools', 'clang', 'scripts', |
|||
'update.py') |
|||
CLANG_REVISION = os.popen(CLANG_UPDATE_PY + ' --print-revision').read().rstrip() |
|||
|
|||
CLANG_BUCKET = 'gs://chromium-browser-clang/Linux_x64' |
|||
|
|||
def main(): |
|||
targz_name = 'llvmgold-%s.tgz' % CLANG_REVISION |
|||
remote_path = '%s/%s' % (CLANG_BUCKET, targz_name) |
|||
|
|||
os.chdir(LLVM_BUILD_PATH) |
|||
|
|||
# TODO(pcc): Fix gsutil.py cp url file < /dev/null 2>&0 |
|||
# (currently aborts with exit code 1, |
|||
# https://github.com/GoogleCloudPlatform/gsutil/issues/289) or change the |
|||
# stdin->stderr redirect in update.py to do something else (crbug.com/494442). |
|||
subprocess.check_call(['python', GSUTIL_PATH, |
|||
'cp', remote_path, targz_name], |
|||
stderr=open('/dev/null', 'w')) |
|||
subprocess.check_call(['tar', 'xzf', targz_name]) |
|||
os.remove(targz_name) |
|||
return 0 |
|||
|
|||
if __name__ == '__main__': |
|||
sys.exit(main()) |
@ -1 +0,0 @@ |
|||
This directory contains v8 project-wide configurations for infra services. |
@ -1,23 +0,0 @@ |
|||
# Defines buckets on cr-buildbucket.appspot.com, used to schedule builds |
|||
# on buildbot. In particular, CQ uses some of these buckets to schedule tryjobs. |
|||
# |
|||
# See http://luci-config.appspot.com/schemas/projects:buildbucket.cfg for |
|||
# schema of this file and documentation. |
|||
# |
|||
# Please keep this list sorted by bucket name. |
|||
|
|||
buckets { |
|||
name: "master.tryserver.v8" |
|||
acls { |
|||
role: READER |
|||
group: "all" |
|||
} |
|||
acls { |
|||
role: SCHEDULER |
|||
group: "service-account-cq" |
|||
} |
|||
acls { |
|||
role: WRITER |
|||
group: "service-account-v8-master" |
|||
} |
|||
} |
@ -1,248 +0,0 @@ |
|||
// Copyright 2012 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "src/v8.h" |
|||
|
|||
#if V8_TARGET_ARCH_ARM |
|||
|
|||
#include "src/codegen.h" |
|||
#include "src/debug.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
void BreakLocation::SetDebugBreakAtReturn() { |
|||
// Patch the code changing the return from JS function sequence from
|
|||
// mov sp, fp
|
|||
// ldmia sp!, {fp, lr}
|
|||
// add sp, sp, #4
|
|||
// bx lr
|
|||
// to a call to the debug break return code.
|
|||
// ldr ip, [pc, #0]
|
|||
// blx ip
|
|||
// <debug break return code entry point address>
|
|||
// bkpt 0
|
|||
CodePatcher patcher(pc(), Assembler::kJSReturnSequenceInstructions); |
|||
patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); |
|||
patcher.masm()->blx(v8::internal::ip); |
|||
patcher.Emit( |
|||
debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry()); |
|||
patcher.masm()->bkpt(0); |
|||
} |
|||
|
|||
|
|||
void BreakLocation::SetDebugBreakAtSlot() { |
|||
DCHECK(IsDebugBreakSlot()); |
|||
// Patch the code changing the debug break slot code from
|
|||
// mov r2, r2
|
|||
// mov r2, r2
|
|||
// mov r2, r2
|
|||
// to a call to the debug break slot code.
|
|||
// ldr ip, [pc, #0]
|
|||
// blx ip
|
|||
// <debug break slot code entry point address>
|
|||
CodePatcher patcher(pc(), Assembler::kDebugBreakSlotInstructions); |
|||
patcher.masm()->ldr(v8::internal::ip, MemOperand(v8::internal::pc, 0)); |
|||
patcher.masm()->blx(v8::internal::ip); |
|||
patcher.Emit( |
|||
debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry()); |
|||
} |
|||
|
|||
|
|||
#define __ ACCESS_MASM(masm) |
|||
|
|||
|
|||
static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
|||
RegList object_regs, |
|||
RegList non_object_regs) { |
|||
{ |
|||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
|||
|
|||
// Load padding words on stack.
|
|||
__ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingValue))); |
|||
for (int i = 0; i < LiveEdit::kFramePaddingInitialSize; i++) { |
|||
__ push(ip); |
|||
} |
|||
__ mov(ip, Operand(Smi::FromInt(LiveEdit::kFramePaddingInitialSize))); |
|||
__ push(ip); |
|||
|
|||
// Store the registers containing live values on the expression stack to
|
|||
// make sure that these are correctly updated during GC. Non object values
|
|||
// are stored as a smi causing it to be untouched by GC.
|
|||
DCHECK((object_regs & ~kJSCallerSaved) == 0); |
|||
DCHECK((non_object_regs & ~kJSCallerSaved) == 0); |
|||
DCHECK((object_regs & non_object_regs) == 0); |
|||
if ((object_regs | non_object_regs) != 0) { |
|||
for (int i = 0; i < kNumJSCallerSaved; i++) { |
|||
int r = JSCallerSavedCode(i); |
|||
Register reg = { r }; |
|||
if ((non_object_regs & (1 << r)) != 0) { |
|||
if (FLAG_debug_code) { |
|||
__ tst(reg, Operand(0xc0000000)); |
|||
__ Assert(eq, kUnableToEncodeValueAsSmi); |
|||
} |
|||
__ SmiTag(reg); |
|||
} |
|||
} |
|||
__ stm(db_w, sp, object_regs | non_object_regs); |
|||
} |
|||
|
|||
#ifdef DEBUG |
|||
__ RecordComment("// Calling from debug break to runtime - come in - over"); |
|||
#endif |
|||
__ mov(r0, Operand::Zero()); // no arguments
|
|||
__ mov(r1, Operand(ExternalReference::debug_break(masm->isolate()))); |
|||
|
|||
CEntryStub ceb(masm->isolate(), 1); |
|||
__ CallStub(&ceb); |
|||
|
|||
// Restore the register values from the expression stack.
|
|||
if ((object_regs | non_object_regs) != 0) { |
|||
__ ldm(ia_w, sp, object_regs | non_object_regs); |
|||
for (int i = 0; i < kNumJSCallerSaved; i++) { |
|||
int r = JSCallerSavedCode(i); |
|||
Register reg = { r }; |
|||
if ((non_object_regs & (1 << r)) != 0) { |
|||
__ SmiUntag(reg); |
|||
} |
|||
if (FLAG_debug_code && |
|||
(((object_regs |non_object_regs) & (1 << r)) == 0)) { |
|||
__ mov(reg, Operand(kDebugZapValue)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Don't bother removing padding bytes pushed on the stack
|
|||
// as the frame is going to be restored right away.
|
|||
|
|||
// Leave the internal frame.
|
|||
} |
|||
|
|||
// Now that the break point has been handled, resume normal execution by
|
|||
// jumping to the target address intended by the caller and that was
|
|||
// overwritten by the address of DebugBreakXXX.
|
|||
ExternalReference after_break_target = |
|||
ExternalReference::debug_after_break_target_address(masm->isolate()); |
|||
__ mov(ip, Operand(after_break_target)); |
|||
__ ldr(ip, MemOperand(ip)); |
|||
__ Jump(ip); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |
|||
// Register state for CallICStub
|
|||
// ----------- S t a t e -------------
|
|||
// -- r1 : function
|
|||
// -- r3 : slot in feedback array (smi)
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, r1.bit() | r3.bit(), 0); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
|||
// In places other than IC call sites it is expected that r0 is TOS which
|
|||
// is an object - this is not generally the case so this should be used with
|
|||
// care.
|
|||
Generate_DebugBreakCallHelper(masm, r0.bit(), 0); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |
|||
// Register state for CallFunctionStub (from code-stubs-arm.cc).
|
|||
// ----------- S t a t e -------------
|
|||
// -- r1 : function
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, r1.bit(), 0); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |
|||
// Calling convention for CallConstructStub (from code-stubs-arm.cc)
|
|||
// ----------- S t a t e -------------
|
|||
// -- r0 : number of arguments (not smi)
|
|||
// -- r1 : constructor function
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, r1.bit(), r0.bit()); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |
|||
MacroAssembler* masm) { |
|||
// Calling convention for CallConstructStub (from code-stubs-arm.cc)
|
|||
// ----------- S t a t e -------------
|
|||
// -- r0 : number of arguments (not smi)
|
|||
// -- r1 : constructor function
|
|||
// -- r2 : feedback array
|
|||
// -- r3 : feedback slot (smi)
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, r1.bit() | r2.bit() | r3.bit(), r0.bit()); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
|||
// Generate enough nop's to make space for a call instruction. Avoid emitting
|
|||
// the constant pool in the debug break slot code.
|
|||
Assembler::BlockConstPoolScope block_const_pool(masm); |
|||
Label check_codesize; |
|||
__ bind(&check_codesize); |
|||
__ RecordDebugBreakSlot(); |
|||
for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
|||
__ nop(MacroAssembler::DEBUG_BREAK_NOP); |
|||
} |
|||
DCHECK_EQ(Assembler::kDebugBreakSlotInstructions, |
|||
masm->InstructionsGeneratedSince(&check_codesize)); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
|||
// In the places where a debug break slot is inserted no registers can contain
|
|||
// object pointers.
|
|||
Generate_DebugBreakCallHelper(masm, 0, 0); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
|||
__ Ret(); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
|||
ExternalReference restarter_frame_function_slot = |
|||
ExternalReference::debug_restarter_frame_function_pointer_address( |
|||
masm->isolate()); |
|||
__ mov(ip, Operand(restarter_frame_function_slot)); |
|||
__ mov(r1, Operand::Zero()); |
|||
__ str(r1, MemOperand(ip, 0)); |
|||
|
|||
// Load the function pointer off of our current stack frame.
|
|||
__ ldr(r1, MemOperand(fp, |
|||
StandardFrameConstants::kConstantPoolOffset - kPointerSize)); |
|||
|
|||
// Pop return address, frame and constant pool pointer (if
|
|||
// FLAG_enable_embedded_constant_pool).
|
|||
__ LeaveFrame(StackFrame::INTERNAL); |
|||
|
|||
{ ConstantPoolUnavailableScope constant_pool_unavailable(masm); |
|||
// Load context from the function.
|
|||
__ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
|||
|
|||
// Get function code.
|
|||
__ ldr(ip, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
|||
__ ldr(ip, FieldMemOperand(ip, SharedFunctionInfo::kCodeOffset)); |
|||
__ add(ip, ip, Operand(Code::kHeaderSize - kHeapObjectTag)); |
|||
|
|||
// Re-run JSFunction, r1 is function, cp is context.
|
|||
__ Jump(ip); |
|||
} |
|||
} |
|||
|
|||
|
|||
const bool LiveEdit::kFrameDropperSupported = true; |
|||
|
|||
#undef __ |
|||
|
|||
} // namespace internal
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_TARGET_ARCH_ARM
|
@ -1,305 +0,0 @@ |
|||
// Copyright 2013 the V8 project authors. All rights reserved.
|
|||
// Use of this source code is governed by a BSD-style license that can be
|
|||
// found in the LICENSE file.
|
|||
|
|||
#include "src/v8.h" |
|||
|
|||
#if V8_TARGET_ARCH_ARM64 |
|||
|
|||
#include "src/codegen.h" |
|||
#include "src/debug.h" |
|||
|
|||
namespace v8 { |
|||
namespace internal { |
|||
|
|||
|
|||
#define __ ACCESS_MASM(masm) |
|||
|
|||
|
|||
void BreakLocation::SetDebugBreakAtReturn() { |
|||
// Patch the code emitted by FullCodeGenerator::EmitReturnSequence, changing
|
|||
// the return from JS function sequence from
|
|||
// mov sp, fp
|
|||
// ldp fp, lr, [sp] #16
|
|||
// lrd ip0, [pc, #(3 * kInstructionSize)]
|
|||
// add sp, sp, ip0
|
|||
// ret
|
|||
// <number of paramters ...
|
|||
// ... plus one (64 bits)>
|
|||
// to a call to the debug break return code.
|
|||
// ldr ip0, [pc, #(3 * kInstructionSize)]
|
|||
// blr ip0
|
|||
// hlt kHltBadCode @ code should not return, catch if it does.
|
|||
// <debug break return code ...
|
|||
// ... entry point address (64 bits)>
|
|||
|
|||
// The patching code must not overflow the space occupied by the return
|
|||
// sequence.
|
|||
STATIC_ASSERT(Assembler::kJSReturnSequenceInstructions >= 5); |
|||
PatchingAssembler patcher(reinterpret_cast<Instruction*>(pc()), 5); |
|||
byte* entry = |
|||
debug_info_->GetIsolate()->builtins()->Return_DebugBreak()->entry(); |
|||
|
|||
// The first instruction of a patched return sequence must be a load literal
|
|||
// loading the address of the debug break return code.
|
|||
patcher.ldr_pcrel(ip0, (3 * kInstructionSize) >> kLoadLiteralScaleLog2); |
|||
// TODO(all): check the following is correct.
|
|||
// The debug break return code will push a frame and call statically compiled
|
|||
// code. By using blr, even though control will not return after the branch,
|
|||
// this call site will be registered in the frame (lr being saved as the pc
|
|||
// of the next instruction to execute for this frame). The debugger can now
|
|||
// iterate on the frames to find call to debug break return code.
|
|||
patcher.blr(ip0); |
|||
patcher.hlt(kHltBadCode); |
|||
patcher.dc64(reinterpret_cast<int64_t>(entry)); |
|||
} |
|||
|
|||
|
|||
void BreakLocation::SetDebugBreakAtSlot() { |
|||
// Patch the code emitted by DebugCodegen::GenerateSlots, changing the debug
|
|||
// break slot code from
|
|||
// mov x0, x0 @ nop DEBUG_BREAK_NOP
|
|||
// mov x0, x0 @ nop DEBUG_BREAK_NOP
|
|||
// mov x0, x0 @ nop DEBUG_BREAK_NOP
|
|||
// mov x0, x0 @ nop DEBUG_BREAK_NOP
|
|||
// to a call to the debug slot code.
|
|||
// ldr ip0, [pc, #(2 * kInstructionSize)]
|
|||
// blr ip0
|
|||
// <debug break slot code ...
|
|||
// ... entry point address (64 bits)>
|
|||
|
|||
// TODO(all): consider adding a hlt instruction after the blr as we don't
|
|||
// expect control to return here. This implies increasing
|
|||
// kDebugBreakSlotInstructions to 5 instructions.
|
|||
|
|||
// The patching code must not overflow the space occupied by the return
|
|||
// sequence.
|
|||
STATIC_ASSERT(Assembler::kDebugBreakSlotInstructions >= 4); |
|||
PatchingAssembler patcher(reinterpret_cast<Instruction*>(pc()), 4); |
|||
byte* entry = |
|||
debug_info_->GetIsolate()->builtins()->Slot_DebugBreak()->entry(); |
|||
|
|||
// The first instruction of a patched debug break slot must be a load literal
|
|||
// loading the address of the debug break slot code.
|
|||
patcher.ldr_pcrel(ip0, (2 * kInstructionSize) >> kLoadLiteralScaleLog2); |
|||
// TODO(all): check the following is correct.
|
|||
// The debug break slot code will push a frame and call statically compiled
|
|||
// code. By using blr, event hough control will not return after the branch,
|
|||
// this call site will be registered in the frame (lr being saved as the pc
|
|||
// of the next instruction to execute for this frame). The debugger can now
|
|||
// iterate on the frames to find call to debug break slot code.
|
|||
patcher.blr(ip0); |
|||
patcher.dc64(reinterpret_cast<int64_t>(entry)); |
|||
} |
|||
|
|||
|
|||
static void Generate_DebugBreakCallHelper(MacroAssembler* masm, |
|||
RegList object_regs, |
|||
RegList non_object_regs, |
|||
Register scratch) { |
|||
{ |
|||
FrameScope scope(masm, StackFrame::INTERNAL); |
|||
|
|||
// Load padding words on stack.
|
|||
__ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingValue)); |
|||
__ PushMultipleTimes(scratch, LiveEdit::kFramePaddingInitialSize); |
|||
__ Mov(scratch, Smi::FromInt(LiveEdit::kFramePaddingInitialSize)); |
|||
__ Push(scratch); |
|||
|
|||
// Any live values (object_regs and non_object_regs) in caller-saved
|
|||
// registers (or lr) need to be stored on the stack so that their values are
|
|||
// safely preserved for a call into C code.
|
|||
//
|
|||
// Also:
|
|||
// * object_regs may be modified during the C code by the garbage
|
|||
// collector. Every object register must be a valid tagged pointer or
|
|||
// SMI.
|
|||
//
|
|||
// * non_object_regs will be converted to SMIs so that the garbage
|
|||
// collector doesn't try to interpret them as pointers.
|
|||
//
|
|||
// TODO(jbramley): Why can't this handle callee-saved registers?
|
|||
DCHECK((~kCallerSaved.list() & object_regs) == 0); |
|||
DCHECK((~kCallerSaved.list() & non_object_regs) == 0); |
|||
DCHECK((object_regs & non_object_regs) == 0); |
|||
DCHECK((scratch.Bit() & object_regs) == 0); |
|||
DCHECK((scratch.Bit() & non_object_regs) == 0); |
|||
DCHECK((masm->TmpList()->list() & (object_regs | non_object_regs)) == 0); |
|||
STATIC_ASSERT(kSmiValueSize == 32); |
|||
|
|||
CPURegList non_object_list = |
|||
CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs); |
|||
while (!non_object_list.IsEmpty()) { |
|||
// Store each non-object register as two SMIs.
|
|||
Register reg = Register(non_object_list.PopLowestIndex()); |
|||
__ Lsr(scratch, reg, 32); |
|||
__ SmiTagAndPush(scratch, reg); |
|||
|
|||
// Stack:
|
|||
// jssp[12]: reg[63:32]
|
|||
// jssp[8]: 0x00000000 (SMI tag & padding)
|
|||
// jssp[4]: reg[31:0]
|
|||
// jssp[0]: 0x00000000 (SMI tag & padding)
|
|||
STATIC_ASSERT(kSmiTag == 0); |
|||
STATIC_ASSERT(static_cast<unsigned>(kSmiShift) == kWRegSizeInBits); |
|||
} |
|||
|
|||
if (object_regs != 0) { |
|||
__ PushXRegList(object_regs); |
|||
} |
|||
|
|||
#ifdef DEBUG |
|||
__ RecordComment("// Calling from debug break to runtime - come in - over"); |
|||
#endif |
|||
__ Mov(x0, 0); // No arguments.
|
|||
__ Mov(x1, ExternalReference::debug_break(masm->isolate())); |
|||
|
|||
CEntryStub stub(masm->isolate(), 1); |
|||
__ CallStub(&stub); |
|||
|
|||
// Restore the register values from the expression stack.
|
|||
if (object_regs != 0) { |
|||
__ PopXRegList(object_regs); |
|||
} |
|||
|
|||
non_object_list = |
|||
CPURegList(CPURegister::kRegister, kXRegSizeInBits, non_object_regs); |
|||
while (!non_object_list.IsEmpty()) { |
|||
// Load each non-object register from two SMIs.
|
|||
// Stack:
|
|||
// jssp[12]: reg[63:32]
|
|||
// jssp[8]: 0x00000000 (SMI tag & padding)
|
|||
// jssp[4]: reg[31:0]
|
|||
// jssp[0]: 0x00000000 (SMI tag & padding)
|
|||
Register reg = Register(non_object_list.PopHighestIndex()); |
|||
__ Pop(scratch, reg); |
|||
__ Bfxil(reg, scratch, 32, 32); |
|||
} |
|||
|
|||
// Don't bother removing padding bytes pushed on the stack
|
|||
// as the frame is going to be restored right away.
|
|||
|
|||
// Leave the internal frame.
|
|||
} |
|||
|
|||
// Now that the break point has been handled, resume normal execution by
|
|||
// jumping to the target address intended by the caller and that was
|
|||
// overwritten by the address of DebugBreakXXX.
|
|||
ExternalReference after_break_target = |
|||
ExternalReference::debug_after_break_target_address(masm->isolate()); |
|||
__ Mov(scratch, after_break_target); |
|||
__ Ldr(scratch, MemOperand(scratch)); |
|||
__ Br(scratch); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallICStubDebugBreak(MacroAssembler* masm) { |
|||
// Register state for CallICStub
|
|||
// ----------- S t a t e -------------
|
|||
// -- x1 : function
|
|||
// -- x3 : slot in feedback array
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, x1.Bit() | x3.Bit(), 0, x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateReturnDebugBreak(MacroAssembler* masm) { |
|||
// In places other than IC call sites it is expected that r0 is TOS which
|
|||
// is an object - this is not generally the case so this should be used with
|
|||
// care.
|
|||
Generate_DebugBreakCallHelper(masm, x0.Bit(), 0, x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallFunctionStubDebugBreak(MacroAssembler* masm) { |
|||
// Register state for CallFunctionStub (from code-stubs-arm64.cc).
|
|||
// ----------- S t a t e -------------
|
|||
// -- x1 : function
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, x1.Bit(), 0, x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallConstructStubDebugBreak(MacroAssembler* masm) { |
|||
// Calling convention for CallConstructStub (from code-stubs-arm64.cc).
|
|||
// ----------- S t a t e -------------
|
|||
// -- x0 : number of arguments (not smi)
|
|||
// -- x1 : constructor function
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper(masm, x1.Bit(), x0.Bit(), x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateCallConstructStubRecordDebugBreak( |
|||
MacroAssembler* masm) { |
|||
// Calling convention for CallConstructStub (from code-stubs-arm64.cc).
|
|||
// ----------- S t a t e -------------
|
|||
// -- x0 : number of arguments (not smi)
|
|||
// -- x1 : constructor function
|
|||
// -- x2 : feedback array
|
|||
// -- x3 : feedback slot (smi)
|
|||
// -----------------------------------
|
|||
Generate_DebugBreakCallHelper( |
|||
masm, x1.Bit() | x2.Bit() | x3.Bit(), x0.Bit(), x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateSlot(MacroAssembler* masm) { |
|||
// Generate enough nop's to make space for a call instruction. Avoid emitting
|
|||
// the constant pool in the debug break slot code.
|
|||
InstructionAccurateScope scope(masm, Assembler::kDebugBreakSlotInstructions); |
|||
|
|||
__ RecordDebugBreakSlot(); |
|||
for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { |
|||
__ nop(Assembler::DEBUG_BREAK_NOP); |
|||
} |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateSlotDebugBreak(MacroAssembler* masm) { |
|||
// In the places where a debug break slot is inserted no registers can contain
|
|||
// object pointers.
|
|||
Generate_DebugBreakCallHelper(masm, 0, 0, x10); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GeneratePlainReturnLiveEdit(MacroAssembler* masm) { |
|||
__ Ret(); |
|||
} |
|||
|
|||
|
|||
void DebugCodegen::GenerateFrameDropperLiveEdit(MacroAssembler* masm) { |
|||
ExternalReference restarter_frame_function_slot = |
|||
ExternalReference::debug_restarter_frame_function_pointer_address( |
|||
masm->isolate()); |
|||
UseScratchRegisterScope temps(masm); |
|||
Register scratch = temps.AcquireX(); |
|||
|
|||
__ Mov(scratch, restarter_frame_function_slot); |
|||
__ Str(xzr, MemOperand(scratch)); |
|||
|
|||
// We do not know our frame height, but set sp based on fp.
|
|||
__ Sub(masm->StackPointer(), fp, kPointerSize); |
|||
__ AssertStackConsistency(); |
|||
|
|||
__ Pop(x1, fp, lr); // Function, Frame, Return address.
|
|||
|
|||
// Load context from the function.
|
|||
__ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset)); |
|||
|
|||
// Get function code.
|
|||
__ Ldr(scratch, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); |
|||
__ Ldr(scratch, FieldMemOperand(scratch, SharedFunctionInfo::kCodeOffset)); |
|||
__ Add(scratch, scratch, Code::kHeaderSize - kHeapObjectTag); |
|||
|
|||
// Re-run JSFunction, x1 is function, cp is context.
|
|||
__ Br(scratch); |
|||
} |
|||
|
|||
|
|||
const bool LiveEdit::kFrameDropperSupported = true; |
|||
|
|||
} // namespace internal
|
|||
} // namespace v8
|
|||
|
|||
#endif // V8_TARGET_ARCH_ARM64
|
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue