Commit b24e4a1b authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] use same mechanism as CSA_ASSERT for asserts and checks

Bug: v8:8393
Change-Id: I6ab34cbe6c17f358c570e0bd27bf2de917f71b71
Reviewed-on: https://chromium-review.googlesource.com/c/1309764
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57211}
parent 0b4350ae
......@@ -116,27 +116,9 @@ void CodeStubAssembler::Check(const BranchGenerator& branch,
branch(&ok, &not_ok);
BIND(&not_ok);
DCHECK_NOT_NULL(message);
char chars[1024];
Vector<char> buffer(chars);
if (file != nullptr) {
SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file, line);
} else {
SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message);
}
Node* message_node = StringConstant(&(buffer[0]));
#ifdef DEBUG
// Only print the extra nodes in debug builds.
MaybePrintNodeWithName(this, extra_node1, extra_node1_name);
MaybePrintNodeWithName(this, extra_node2, extra_node2_name);
MaybePrintNodeWithName(this, extra_node3, extra_node3_name);
MaybePrintNodeWithName(this, extra_node4, extra_node4_name);
MaybePrintNodeWithName(this, extra_node5, extra_node5_name);
#endif
DebugAbort(message_node);
Unreachable();
FailAssert(message, file, line, extra_node1, extra_node1_name, extra_node2,
extra_node2_name, extra_node3, extra_node3_name, extra_node4,
extra_node4_name, extra_node5, extra_node5_name);
BIND(&ok);
Comment("] Assert");
......@@ -168,6 +150,36 @@ void CodeStubAssembler::FastCheck(TNode<BoolT> condition) {
BIND(&ok);
}
void CodeStubAssembler::FailAssert(
const char* message, const char* file, int line, Node* extra_node1,
const char* extra_node1_name, Node* extra_node2,
const char* extra_node2_name, Node* extra_node3,
const char* extra_node3_name, Node* extra_node4,
const char* extra_node4_name, Node* extra_node5,
const char* extra_node5_name) {
DCHECK_NOT_NULL(message);
char chars[1024];
Vector<char> buffer(chars);
if (file != nullptr) {
SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file, line);
} else {
SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message);
}
Node* message_node = StringConstant(&(buffer[0]));
#ifdef DEBUG
// Only print the extra nodes in debug builds.
MaybePrintNodeWithName(this, extra_node1, extra_node1_name);
MaybePrintNodeWithName(this, extra_node2, extra_node2_name);
MaybePrintNodeWithName(this, extra_node3, extra_node3_name);
MaybePrintNodeWithName(this, extra_node4, extra_node4_name);
MaybePrintNodeWithName(this, extra_node5, extra_node5_name);
#endif
DebugAbort(message_node);
Unreachable();
}
Node* CodeStubAssembler::SelectImpl(TNode<BoolT> condition,
const NodeGenerator& true_body,
const NodeGenerator& false_body,
......
......@@ -680,6 +680,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* extra_node3 = nullptr, const char* extra_node3_name = "",
Node* extra_node4 = nullptr, const char* extra_node4_name = "",
Node* extra_node5 = nullptr, const char* extra_node5_name = "");
void FailAssert(
const char* message = nullptr, const char* file = nullptr, int line = 0,
Node* extra_node1 = nullptr, const char* extra_node1_name = "",
Node* extra_node2 = nullptr, const char* extra_node2_name = "",
Node* extra_node3 = nullptr, const char* extra_node3_name = "",
Node* extra_node4 = nullptr, const char* extra_node4_name = "",
Node* extra_node5 = nullptr, const char* extra_node5_name = "");
void FastCheck(TNode<BoolT> condition);
// The following Call wrappers call an object according to the semantics that
......@@ -3410,7 +3418,6 @@ class ToDirectStringAssembler : public CodeStubAssembler {
const Flags flags_;
};
DEFINE_OPERATORS_FOR_FLAGS(CodeStubAssembler::AllocationFlags);
} // namespace internal
......
......@@ -140,9 +140,18 @@ void CfgAssembler::Print(std::string s) {
Emit(PrintConstantStringInstruction{std::move(s)});
}
void CfgAssembler::Unreachable() { Emit(DebugBreakInstruction{true}); }
void CfgAssembler::AssertionFailure(std::string message) {
Emit(AbortInstruction{AbortInstruction::Kind::kAssertionFailure,
std::move(message)});
}
void CfgAssembler::Unreachable() {
Emit(AbortInstruction{AbortInstruction::Kind::kUnreachable});
}
void CfgAssembler::DebugBreak() { Emit(DebugBreakInstruction{false}); }
void CfgAssembler::DebugBreak() {
Emit(AbortInstruction{AbortInstruction::Kind::kDebugBreak});
}
} // namespace torque
} // namespace internal
......
......@@ -133,6 +133,7 @@ class CfgAssembler {
void Poke(StackRange destination, StackRange origin,
base::Optional<const Type*> type);
void Print(std::string s);
void AssertionFailure(std::string message);
void Unreachable();
void DebugBreak();
......
......@@ -523,12 +523,24 @@ void CSAGenerator::EmitInstruction(
out_ << " Print(" << StringLiteralQuote(instruction.message) << ");\n";
}
void CSAGenerator::EmitInstruction(const DebugBreakInstruction& instruction,
void CSAGenerator::EmitInstruction(const AbortInstruction& instruction,
Stack<std::string>* stack) {
if (instruction.never_continues) {
out_ << " Unreachable();\n";
} else {
out_ << " DebugBreak();\n";
switch (instruction.kind) {
case AbortInstruction::Kind::kUnreachable:
DCHECK(instruction.message.empty());
out_ << " Unreachable();\n";
break;
case AbortInstruction::Kind::kDebugBreak:
DCHECK(instruction.message.empty());
out_ << " DebugBreak();\n";
break;
case AbortInstruction::Kind::kAssertionFailure: {
std::string file =
StringLiteralQuote(SourceFileMap::GetSource(instruction.pos.source));
out_ << " FailAssert(" << StringLiteralQuote(instruction.message)
<< ", " << file << ", " << instruction.pos.line + 1 << ");\n";
break;
}
}
}
......
......@@ -881,7 +881,9 @@ const Type* ImplementationVisitor::Visit(DebugStatement* stmt) {
stmt->reason + "' at " +
PositionAsString(stmt->pos)});
#endif
assembler().Emit(DebugBreakInstruction{stmt->never_continues});
assembler().Emit(AbortInstruction{stmt->never_continues
? AbortInstruction::Kind::kUnreachable
: AbortInstruction::Kind::kDebugBreak});
if (stmt->never_continues) {
return TypeOracle::GetNeverType();
} else {
......@@ -927,10 +929,10 @@ const Type* ImplementationVisitor::Visit(AssertStatement* stmt) {
GenerateExpressionBranch(stmt->expression, true_block, false_block);
assembler().Bind(false_block);
assembler().Emit(PrintConstantStringInstruction{
"assert '" + FormatAssertSource(stmt->source) + "' failed at " +
PositionAsString(stmt->pos)});
assembler().Emit(DebugBreakInstruction{true});
assembler().Emit(AbortInstruction{
AbortInstruction::Kind::kAssertionFailure,
"Torque assert '" + FormatAssertSource(stmt->source) + "' failed"});
assembler().Bind(true_block);
}
......
......@@ -256,8 +256,8 @@ void ReturnInstruction::TypeInstruction(Stack<const Type*>* stack,
void PrintConstantStringInstruction::TypeInstruction(
Stack<const Type*>* stack, ControlFlowGraph* cfg) const {}
void DebugBreakInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {}
void AbortInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {}
void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack,
ControlFlowGraph* cfg) const {
......
......@@ -41,7 +41,7 @@ class RuntimeFunction;
V(GotoExternalInstruction) \
V(ReturnInstruction) \
V(PrintConstantStringInstruction) \
V(DebugBreakInstruction) \
V(AbortInstruction) \
V(UnsafeCastInstruction)
#define TORQUE_INSTRUCTION_BOILERPLATE() \
......@@ -355,13 +355,17 @@ struct PrintConstantStringInstruction : InstructionBase {
std::string message;
};
struct DebugBreakInstruction : InstructionBase {
struct AbortInstruction : InstructionBase {
TORQUE_INSTRUCTION_BOILERPLATE()
bool IsBlockTerminator() const override { return never_continues; }
explicit DebugBreakInstruction(bool never_continues)
: never_continues(never_continues) {}
enum class Kind { kDebugBreak, kUnreachable, kAssertionFailure };
bool IsBlockTerminator() const override { return kind != Kind::kDebugBreak; }
explicit AbortInstruction(Kind kind, std::string message = "") : kind(kind) {
// The normal way to write this triggers a bug in Clang on Windows.
this->message = std::move(message);
}
bool never_continues;
Kind kind;
std::string message;
};
struct UnsafeCastInstruction : InstructionBase {
......
......@@ -49,7 +49,7 @@ std::string StringLiteralUnquote(const std::string& s) {
std::string StringLiteralQuote(const std::string& s) {
std::stringstream result;
result << '"';
for (size_t i = 0; i < s.length() - 1; ++i) {
for (size_t i = 0; i < s.length(); ++i) {
switch (s[i]) {
case '\n':
result << "\\n";
......
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