Commit 9cd0c8ea authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[turbofan] Introduce {DebugAbort} backend instruction.

This introduces a {DebugAbort} machine-level operator as well as the
corresponding {ArchDebugAbort} backend instruction. The goal of this is
to speed up snapshot generation due to cheaper "CSA-asserts".

R=jgruber@chromium.org
BUG=v8:6688

Bug: v8:6688
Change-Id: If45f7da0652d4bb920c51ab7a7c41f9670434bbb
Also-By: jgruber@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/628560Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47568}
parent 39eacf64
......@@ -2485,6 +2485,17 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r1 : message as String object
// -- lr : return address
// -----------------------------------
__ Push(r1);
__ Move(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : actual number of arguments
......
......@@ -2579,6 +2579,19 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
ASM_LOCATION("Builtins::Generate_AbortJS");
// ----------- S t a t e -------------
// -- x1 : message as String object
// -- lr : return address
// -----------------------------------
MacroAssembler::NoUseRealAbortsScope no_use_real_aborts(masm);
__ Push(x1);
__ Move(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline");
// ----------- S t a t e -------------
......
......@@ -232,6 +232,7 @@ namespace internal {
\
/* Abort */ \
ASM(Abort) \
ASM(AbortJS) \
\
/* Built-in functions for Javascript */ \
/* Special internal builtins */ \
......
......@@ -2651,6 +2651,19 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- edx : message as String object
// -- esp[0] : return address
// -----------------------------------
__ PopReturnAddressTo(ecx);
__ Push(edx);
__ PushReturnAddressFrom(ecx);
__ Move(esi, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : actual number of arguments
......
......@@ -2526,6 +2526,17 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : message as String object
// -- ra : return address
// -----------------------------------
__ Push(a0);
__ Move(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// State setup as expected by MacroAssembler::InvokePrologue.
// ----------- S t a t e -------------
......
......@@ -2550,6 +2550,17 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : message as String object
// -- ra : return address
// -----------------------------------
__ Push(a0);
__ Move(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// State setup as expected by MacroAssembler::InvokePrologue.
// ----------- S t a t e -------------
......
......@@ -2566,6 +2566,17 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r4 : message as String object
// -- lr : return address
// -----------------------------------
__ push(r4);
__ LoadSmiLiteral(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : actual number of arguments
......
......@@ -2564,6 +2564,17 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r3 : message as String object
// -- lr : return address
// -----------------------------------
__ push(r3);
__ LoadSmiLiteral(cp, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r2 : actual number of arguments
......
......@@ -2101,6 +2101,19 @@ void Builtins::Generate_Abort(MacroAssembler* masm) {
__ TailCallRuntime(Runtime::kAbort);
}
// static
void Builtins::Generate_AbortJS(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rdx : message as String object
// -- rsp[0] : return address
// -----------------------------------
__ PopReturnAddressTo(rcx);
__ Push(rdx);
__ PushReturnAddressFrom(rcx);
__ Move(rsi, Smi::kZero);
__ TailCallRuntime(Runtime::kAbortJS);
}
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : actual number of arguments
......
......@@ -92,6 +92,7 @@ void CodeStubAssembler::Check(const NodeGenerator& condition_body,
DCHECK_NOT_NULL(condition);
Branch(condition, &ok, &not_ok);
BIND(&not_ok);
Node* message_node;
if (message != nullptr) {
char chars[1024];
Vector<char> buffer(chars);
......@@ -100,8 +101,9 @@ void CodeStubAssembler::Check(const NodeGenerator& condition_body,
} else {
SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message);
}
CallRuntime(Runtime::kGlobalPrint, NoContextConstant(),
StringConstant(&(buffer[0])));
message_node = StringConstant(&(buffer[0]));
} else {
message_node = EmptyStringConstant();
}
#ifdef DEBUG
......@@ -113,7 +115,7 @@ void CodeStubAssembler::Check(const NodeGenerator& condition_body,
MaybePrintNodeWithName(this, extra_node5, extra_node5_name);
#endif
DebugBreak();
DebugAbort(message_node);
Goto(&ok);
BIND(&ok);
Comment("] Assert");
......
......@@ -780,6 +780,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
AssembleArchTableSwitch(instr);
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(r1));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ stop("kArchDebugAbort");
break;
case kArchDebugBreak:
__ stop("kArchDebugBreak");
break;
......
......@@ -419,6 +419,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
ArmOperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), r1));
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
ArmOperandGenerator g(this);
......
......@@ -798,6 +798,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchLookupSwitch:
AssembleArchLookupSwitch(instr);
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(x1));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ Debug("kArchDebugAbort", 0, BREAK);
break;
case kArchDebugBreak:
__ Debug("kArchDebugBreak", 0, BREAK);
break;
......
......@@ -549,6 +549,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
Arm64OperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), x1));
}
void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode,
ImmediateMode immediate_mode, MachineRepresentation rep,
Node* output = nullptr) {
......
......@@ -338,6 +338,10 @@ void CodeAssembler::ReturnIf(Node* condition, Node* value) {
Bind(&if_continue);
}
void CodeAssembler::DebugAbort(Node* message) {
raw_assembler()->DebugAbort(message);
}
void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
void CodeAssembler::Unreachable() {
......
......@@ -503,6 +503,7 @@ class V8_EXPORT_PRIVATE CodeAssembler {
void ReturnIf(Node* condition, Node* value);
void DebugAbort(Node* message);
void DebugBreak();
void Unreachable();
void Comment(const char* format, ...);
......
......@@ -1006,6 +1006,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ RecordComment(reinterpret_cast<const char*>(comment_string));
break;
}
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(edx));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ int3();
break;
case kArchDebugBreak:
__ int3();
break;
......
......@@ -221,6 +221,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
IA32OperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), edx));
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
......
......@@ -55,6 +55,7 @@ enum class RecordWriteMode { kValueIsMap, kValueIsPointer, kValueIsAny };
V(ArchLookupSwitch) \
V(ArchTableSwitch) \
V(ArchNop) \
V(ArchDebugAbort) \
V(ArchDebugBreak) \
V(ArchComment) \
V(ArchThrowTerminator) \
......
......@@ -308,6 +308,7 @@ int InstructionScheduler::GetInstructionFlags(const Instruction* instr) const {
case kArchLookupSwitch:
case kArchTableSwitch:
case kArchRet:
case kArchDebugAbort:
case kArchDebugBreak:
case kArchThrowTerminator:
return kIsBlockTerminator;
......
......@@ -1113,6 +1113,9 @@ void InstructionSelector::VisitNode(Node* node) {
case IrOpcode::kStateValues:
case IrOpcode::kObjectState:
return;
case IrOpcode::kDebugAbort:
VisitDebugAbort(node);
return;
case IrOpcode::kDebugBreak:
VisitDebugBreak(node);
return;
......
......@@ -450,6 +450,9 @@ class MachineRepresentationChecker {
case IrOpcode::kParameter:
case IrOpcode::kProjection:
break;
case IrOpcode::kDebugAbort:
CheckValueInputIsTagged(node, 0);
break;
case IrOpcode::kLoad:
case IrOpcode::kAtomicLoad:
CheckValueInputIsTaggedOrPointer(node, 0);
......
......@@ -648,6 +648,13 @@ struct MachineOperatorGlobalCache {
};
BitcastWordToTaggedOperator kBitcastWordToTagged;
struct DebugAbortOperator : public Operator {
DebugAbortOperator()
: Operator(IrOpcode::kDebugAbort, Operator::kNoThrow, "DebugAbort", 1,
1, 1, 0, 1, 0) {}
};
DebugAbortOperator kDebugAbort;
struct DebugBreakOperator : public Operator {
DebugBreakOperator()
: Operator(IrOpcode::kDebugBreak, Operator::kNoThrow, "DebugBreak", 0,
......@@ -816,6 +823,10 @@ const Operator* MachineOperatorBuilder::BitcastWordToTagged() {
return &cache_.kBitcastWordToTagged;
}
const Operator* MachineOperatorBuilder::DebugAbort() {
return &cache_.kDebugAbort;
}
const Operator* MachineOperatorBuilder::DebugBreak() {
return &cache_.kDebugBreak;
}
......
......@@ -228,6 +228,7 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
AlignmentRequirements::FullUnalignedAccessSupport());
const Operator* Comment(const char* msg);
const Operator* DebugAbort();
const Operator* DebugBreak();
const Operator* UnsafePointerAdd();
......
......@@ -734,6 +734,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchTableSwitch:
AssembleArchTableSwitch(instr);
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(a0));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ stop("kArchDebugAbort");
break;
case kArchDebugBreak:
__ stop("kArchDebugBreak");
break;
......
......@@ -267,6 +267,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(alignment)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
MipsOperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), a0));
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
MipsOperandGenerator g(this);
......
......@@ -775,6 +775,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchTableSwitch:
AssembleArchTableSwitch(instr);
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(a0));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ stop("kArchDebugAbort");
break;
case kArchDebugBreak:
__ stop("kArchDebugBreak");
break;
......
......@@ -363,6 +363,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(alignment)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
Mips64OperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), a0));
}
void EmitLoad(InstructionSelector* selector, Node* node, InstructionCode opcode,
Node* output = nullptr) {
Mips64OperandGenerator g(selector);
......
......@@ -508,6 +508,7 @@
MACHINE_FLOAT32_UNOP_LIST(V) \
MACHINE_FLOAT64_BINOP_LIST(V) \
MACHINE_FLOAT64_UNOP_LIST(V) \
V(DebugAbort) \
V(DebugBreak) \
V(Comment) \
V(Load) \
......
......@@ -1053,6 +1053,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
AssembleArchTableSwitch(instr);
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(r4));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ stop("kArchDebugAbort");
break;
case kArchDebugBreak:
__ stop("kArchDebugBreak");
break;
......
......@@ -183,6 +183,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
PPCOperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), r4));
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
PPCOperandGenerator g(this);
......
......@@ -164,6 +164,10 @@ void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2,
current_block_ = nullptr;
}
void RawMachineAssembler::DebugAbort(Node* message) {
AddNode(machine()->DebugAbort(), message);
}
void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
void RawMachineAssembler::Unreachable() {
......
......@@ -829,6 +829,7 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
void PopAndReturn(Node* pop, Node* v1, Node* v2, Node* v3);
void Bind(RawMachineLabel* label);
void Deoptimize(Node* state);
void DebugAbort(Node* message);
void DebugBreak();
void Unreachable();
void Comment(const char* msg);
......
......@@ -1250,6 +1250,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
case kArchTableSwitch:
AssembleArchTableSwitch(instr);
break;
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(r3));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ stop("kArchDebugAbort");
break;
case kArchDebugBreak:
__ stop("kArchDebugBreak");
break;
......
......@@ -708,6 +708,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
S390OperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), r3));
}
void InstructionSelector::VisitLoad(Node* node) {
S390OperandGenerator g(this);
ArchOpcode opcode = SelectLoadOpcode(node);
......
......@@ -770,6 +770,7 @@ void Verifier::Visitor::Check(Node* node) {
break;
case IrOpcode::kComment:
case IrOpcode::kDebugAbort:
case IrOpcode::kDebugBreak:
case IrOpcode::kRetain:
case IrOpcode::kUnsafePointerAdd:
......
......@@ -963,6 +963,20 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ RecordComment(reinterpret_cast<const char*>(comment_string));
break;
}
case kArchDebugAbort:
DCHECK(i.InputRegister(0).is(rdx));
if (!frame_access_state()->has_frame()) {
// We don't actually want to generate a pile of code for this, so just
// claim there is a stack frame, without generating one.
FrameScope scope(tasm(), StackFrame::NONE);
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
} else {
__ Call(isolate()->builtins()->builtin_handle(Builtins::kAbortJS),
RelocInfo::CODE_TARGET);
}
__ int3();
break;
case kArchDebugBreak:
__ int3();
break;
......
......@@ -284,6 +284,11 @@ void InstructionSelector::VisitStackSlot(Node* node) {
sequence()->AddImmediate(Constant(slot)), 0, nullptr);
}
void InstructionSelector::VisitDebugAbort(Node* node) {
X64OperandGenerator g(this);
Emit(kArchDebugAbort, g.NoOutput(), g.UseFixed(node->InputAt(0), rdx));
}
void InstructionSelector::VisitLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
X64OperandGenerator g(this);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment