Commit 2234c4d5 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[csa] Add scoped exception handler support for non-PLabels

In the process, move the rest of the implementation PLabels into the
CodeAssembler for consistency.

Change-Id: I56872d9fc756db066f0d13d87aeb55ec04de2495
Reviewed-on: https://chromium-review.googlesource.com/c/1329687
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57474}
parent 019494b3
......@@ -2539,7 +2539,6 @@ v8_source_set("v8_base") {
"src/third_party/utf8-decoder/utf8-decoder.h",
"src/thread-id.cc",
"src/thread-id.h",
"src/torque-assembler.h",
"src/tracing/trace-event.cc",
"src/tracing/trace-event.h",
"src/tracing/traced-value.cc",
......
......@@ -966,10 +966,10 @@ TNode<BoolT> CodeStubAssembler::WordIsWordAligned(SloppyTNode<WordT> word) {
void CodeStubAssembler::Bind(Label* label, AssemblerDebugInfo debug_info) {
CodeAssembler::Bind(label, debug_info);
}
#else
void CodeStubAssembler::Bind(Label* label) { CodeAssembler::Bind(label); }
#endif // DEBUG
void CodeStubAssembler::Bind(Label* label) { CodeAssembler::Bind(label); }
TNode<Float64T> CodeStubAssembler::LoadDoubleWithHoleCheck(
TNode<FixedDoubleArray> array, TNode<Smi> index, Label* if_hole) {
return LoadFixedDoubleArrayElement(array, index, MachineType::Float64(), 0,
......
......@@ -776,9 +776,14 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
#if DEBUG
void Bind(Label* label, AssemblerDebugInfo debug_info);
#else
void Bind(Label* label);
#endif // DEBUG
void Bind(Label* label);
template <class... T>
void Bind(compiler::CodeAssemblerParameterizedLabel<T...>* label,
TNode<T>*... phis) {
CodeAssembler::Bind(label, phis...);
}
void BranchIfSmiEqual(TNode<Smi> a, TNode<Smi> b, Label* if_true,
Label* if_false) {
......
......@@ -98,9 +98,9 @@ CodeAssembler::~CodeAssembler() = default;
void CodeAssemblerState::PrintCurrentBlock(std::ostream& os) {
raw_assembler_->PrintCurrentBlock(os);
}
#endif
bool CodeAssemblerState::InsideBlock() { return raw_assembler_->InsideBlock(); }
#endif
void CodeAssemblerState::SetInitialDebugInformation(const char* msg,
const char* file,
......@@ -1866,6 +1866,51 @@ void CodeAssemblerState::PopExceptionHandler() {
exception_handler_labels_.pop_back();
}
CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label)
: has_handler_(label != nullptr),
assembler_(assembler),
compatibility_label_(nullptr),
exception_(nullptr) {
if (has_handler_) {
assembler_->state()->PushExceptionHandler(label);
}
}
CodeAssemblerScopedExceptionHandler::CodeAssemblerScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerLabel* label,
TypedCodeAssemblerVariable<Object>* exception)
: has_handler_(label != nullptr),
assembler_(assembler),
compatibility_label_(label),
exception_(exception) {
if (has_handler_) {
label_ = base::make_unique<CodeAssemblerExceptionHandlerLabel>(
assembler, CodeAssemblerLabel::kDeferred);
assembler_->state()->PushExceptionHandler(label_.get());
}
}
CodeAssemblerScopedExceptionHandler::~CodeAssemblerScopedExceptionHandler() {
if (has_handler_) {
assembler_->state()->PopExceptionHandler();
}
if (label_ && label_->is_used()) {
CodeAssembler::Label skip(assembler_);
bool inside_block = assembler_->state()->InsideBlock();
if (inside_block) {
assembler_->Goto(&skip);
}
TNode<Object> e;
assembler_->Bind(label_.get(), &e);
*exception_ = e;
assembler_->Goto(compatibility_label_);
if (inside_block) {
assembler_->Bind(&skip);
}
}
}
} // namespace compiler
Address CheckObjectType(Object* value, Address raw_type, String* location) {
......
......@@ -60,7 +60,6 @@ class PromiseFulfillReactionJobTask;
class PromiseReaction;
class PromiseReactionJobTask;
class PromiseRejectReactionJobTask;
class TorqueAssembler;
class WeakFactoryCleanupJobTask;
class Zone;
......@@ -830,11 +829,27 @@ class V8_EXPORT_PRIVATE CodeAssembler {
void Branch(SloppyTNode<IntegralT> condition, Label* true_label,
Label* false_label);
template <class... Ts>
using PLabel = compiler::CodeAssemblerParameterizedLabel<Ts...>;
template <class T>
TNode<T> Uninitialized() {
return {};
}
template <class... T>
void Bind(CodeAssemblerParameterizedLabel<T...>* label, TNode<T>*... phis) {
Bind(label->plain_label());
label->CreatePhis(phis...);
}
template <class... T, class... Args>
void Branch(TNode<BoolT> condition,
CodeAssemblerParameterizedLabel<T...>* if_true,
CodeAssemblerParameterizedLabel<T...>* if_false, Args... args) {
if_true->AddInputs(args...);
if_false->AddInputs(args...);
Branch(condition, if_true->plain_label(), if_false->plain_label());
}
template <class... T, class... Args>
void Goto(PLabel<T...>* label, Args... args) {
void Goto(CodeAssemblerParameterizedLabel<T...>* label, Args... args) {
label->AddInputs(args...);
Goto(label->plain_label());
}
......@@ -1530,7 +1545,6 @@ class CodeAssemblerParameterizedLabel
: CodeAssemblerParameterizedLabelBase(assembler, kArity, type) {}
private:
friend class internal::TorqueAssembler;
friend class CodeAssembler;
void AddInputs(TNode<Types>... inputs) {
......@@ -1578,8 +1592,8 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
#if DEBUG
void PrintCurrentBlock(std::ostream& os);
bool InsideBlock();
#endif // DEBUG
bool InsideBlock();
void SetInitialDebugInformation(const char* msg, const char* file, int line);
private:
......@@ -1618,18 +1632,23 @@ class V8_EXPORT_PRIVATE CodeAssemblerState {
class CodeAssemblerScopedExceptionHandler {
public:
CodeAssemblerScopedExceptionHandler(CodeAssembler* assembler,
CodeAssemblerExceptionHandlerLabel* label)
: assembler_(assembler) {
assembler_->state()->PushExceptionHandler(label);
}
CodeAssemblerScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerExceptionHandlerLabel* label);
~CodeAssemblerScopedExceptionHandler() {
assembler_->state()->PopExceptionHandler();
}
// Use this constructor for compatability/ports of old CSA code only. New code
// should use the CodeAssemblerExceptionHandlerLabel version.
CodeAssemblerScopedExceptionHandler(
CodeAssembler* assembler, CodeAssemblerLabel* label,
TypedCodeAssemblerVariable<Object>* exception);
~CodeAssemblerScopedExceptionHandler();
private:
bool has_handler_;
CodeAssembler* assembler_;
CodeAssemblerLabel* compatibility_label_;
std::unique_ptr<CodeAssemblerExceptionHandlerLabel> label_;
TypedCodeAssemblerVariable<Object>* exception_;
};
} // namespace compiler
......
......@@ -478,14 +478,14 @@ void RawMachineAssembler::PrintCurrentBlock(std::ostream& os) {
os << CurrentBlock();
}
bool RawMachineAssembler::InsideBlock() { return current_block_ != nullptr; }
void RawMachineAssembler::SetInitialDebugInformation(
AssemblerDebugInfo debug_info) {
CurrentBlock()->set_debug_info(debug_info);
}
#endif // DEBUG
bool RawMachineAssembler::InsideBlock() { return current_block_ != nullptr; }
BasicBlock* RawMachineAssembler::CurrentBlock() {
DCHECK(current_block_);
return current_block_;
......
......@@ -938,8 +938,8 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
void Bind(RawMachineLabel* label, AssemblerDebugInfo info);
void SetInitialDebugInformation(AssemblerDebugInfo info);
void PrintCurrentBlock(std::ostream& os);
bool InsideBlock();
#endif // DEBUG
bool InsideBlock();
// Add success / exception successor blocks and ends the current block ending
// in a potentially throwing call node.
......
// Copyright 2018 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.
#ifndef V8_TORQUE_ASSEMBLER_H_
#define V8_TORQUE_ASSEMBLER_H_
#include <deque>
#include <vector>
#include "src/code-stub-assembler.h"
#include "src/base/optional.h"
namespace v8 {
namespace internal {
class TorqueAssembler : public CodeStubAssembler {
public:
using CodeStubAssembler::CodeStubAssembler;
protected:
template <class... Ts>
using PLabel = compiler::CodeAssemblerParameterizedLabel<Ts...>;
template <class T>
TNode<T> Uninitialized() {
return {};
}
template <class... T>
void Bind(PLabel<T...>* label, TNode<T>*... phis) {
Bind(label->plain_label());
label->CreatePhis(phis...);
}
void Bind(Label* label) { CodeAssembler::Bind(label); }
using CodeStubAssembler::Bind;
template <class... T, class... Args>
void Branch(TNode<BoolT> condition, PLabel<T...>* if_true,
PLabel<T...>* if_false, Args... args) {
if_true->AddInputs(args...);
if_false->AddInputs(args...);
CodeStubAssembler::Branch(condition, if_true->plain_label(),
if_false->plain_label());
}
using CodeStubAssembler::Branch;
};
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_ASSEMBLER_H_
......@@ -75,6 +75,8 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
<< "using Node = compiler::Node;\n"
<< "using CatchLabel = compiler::CodeAssemblerExceptionHandlerLabel;\n"
<< "using ScopedCatch = compiler::CodeAssemblerScopedExceptionHandler;\n"
<< "template <class... Ts>\n"
<< "using PLabel = compiler::CodeAssemblerParameterizedLabel<Ts...>;\n"
<< "\n";
std::string upper_name(nspace->name());
......@@ -84,7 +86,7 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
std::string("V8_TORQUE_") + upper_name + "_FROM_DSL_BASE_H__";
header << "#ifndef " << headerDefine << "\n";
header << "#define " << headerDefine << "\n\n";
header << "#include \"src/torque-assembler.h\"";
header << "#include \"src/code-stub-assembler.h\"";
header << "\n\n ";
header << "namespace v8 {\n"
......@@ -92,11 +94,11 @@ void ImplementationVisitor::BeginNamespaceFile(Namespace* nspace) {
<< "\n";
header << "class " << nspace->ExternalName()
<< ": public TorqueAssembler {\n";
<< ": public CodeStubAssembler {\n";
header << " public:\n";
header
<< " explicit " << nspace->ExternalName()
<< "(compiler::CodeAssemblerState* state) : TorqueAssembler(state) {}\n";
header << " explicit " << nspace->ExternalName()
<< "(compiler::CodeAssemblerState* state) : CodeStubAssembler(state) "
"{}\n";
header << "\n";
header << " using Node = compiler::Node;\n";
......
......@@ -560,6 +560,28 @@ TEST(GotoIfExceptionMultiple) {
CHECK(constructor->SameValue(*isolate->type_error_function()));
}
TEST(ExceptionHandler) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 0;
CodeAssemblerTester asm_tester(isolate, kNumParams);
CodeAssembler m(asm_tester.state());
CodeAssembler::TVariable<Object> var(m.SmiConstant(0), &m);
Label exception(&m, {&var}, Label::kDeferred);
{
CodeAssemblerScopedExceptionHandler handler(&m, &exception, &var);
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
m.CallRuntime(Runtime::kThrow, context, m.SmiConstant(2));
}
m.Return(m.SmiConstant(1));
m.Bind(&exception);
m.Return(var.value());
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
CHECK_EQ(2, ft.CallChecked<Smi>()->value());
}
} // namespace compiler
} // namespace internal
} // namespace v8
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