2018-10-04 20:45:31 +00:00
|
|
|
// 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_INSTRUCTIONS_H_
|
|
|
|
#define V8_TORQUE_INSTRUCTIONS_H_
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
#include "src/torque/ast.h"
|
|
|
|
#include "src/torque/source-positions.h"
|
|
|
|
#include "src/torque/types.h"
|
|
|
|
#include "src/torque/utils.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
namespace torque {
|
|
|
|
|
|
|
|
class Block;
|
|
|
|
class Builtin;
|
|
|
|
class ControlFlowGraph;
|
2018-11-21 15:20:40 +00:00
|
|
|
class Intrinsic;
|
2018-10-04 20:45:31 +00:00
|
|
|
class Macro;
|
2018-11-13 13:00:34 +00:00
|
|
|
class NamespaceConstant;
|
2018-10-04 20:45:31 +00:00
|
|
|
class RuntimeFunction;
|
|
|
|
|
|
|
|
#define TORQUE_INSTRUCTION_LIST(V) \
|
|
|
|
V(PeekInstruction) \
|
|
|
|
V(PokeInstruction) \
|
|
|
|
V(DeleteRangeInstruction) \
|
|
|
|
V(PushUninitializedInstruction) \
|
2018-12-17 13:20:16 +00:00
|
|
|
V(PushBuiltinPointerInstruction) \
|
2019-04-11 13:36:05 +00:00
|
|
|
V(CreateFieldReferenceInstruction) \
|
|
|
|
V(LoadReferenceInstruction) \
|
|
|
|
V(StoreReferenceInstruction) \
|
2018-10-04 20:45:31 +00:00
|
|
|
V(CallCsaMacroInstruction) \
|
2018-11-21 15:20:40 +00:00
|
|
|
V(CallIntrinsicInstruction) \
|
2018-11-13 13:00:34 +00:00
|
|
|
V(NamespaceConstantInstruction) \
|
2018-10-04 20:45:31 +00:00
|
|
|
V(CallCsaMacroAndBranchInstruction) \
|
|
|
|
V(CallBuiltinInstruction) \
|
|
|
|
V(CallRuntimeInstruction) \
|
|
|
|
V(CallBuiltinPointerInstruction) \
|
|
|
|
V(BranchInstruction) \
|
|
|
|
V(ConstexprBranchInstruction) \
|
|
|
|
V(GotoInstruction) \
|
|
|
|
V(GotoExternalInstruction) \
|
|
|
|
V(ReturnInstruction) \
|
|
|
|
V(PrintConstantStringInstruction) \
|
2018-11-02 12:54:22 +00:00
|
|
|
V(AbortInstruction) \
|
2018-10-04 20:45:31 +00:00
|
|
|
V(UnsafeCastInstruction)
|
|
|
|
|
|
|
|
#define TORQUE_INSTRUCTION_BOILERPLATE() \
|
|
|
|
static const InstructionKind kKind; \
|
|
|
|
std::unique_ptr<InstructionBase> Clone() const override; \
|
|
|
|
void Assign(const InstructionBase& other) override; \
|
|
|
|
void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) \
|
|
|
|
const override;
|
|
|
|
|
|
|
|
enum class InstructionKind {
|
|
|
|
#define ENUM_ITEM(name) k##name,
|
|
|
|
TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
|
|
|
|
#undef ENUM_ITEM
|
|
|
|
};
|
|
|
|
|
|
|
|
struct InstructionBase {
|
|
|
|
InstructionBase() : pos(CurrentSourcePosition::Get()) {}
|
|
|
|
virtual std::unique_ptr<InstructionBase> Clone() const = 0;
|
|
|
|
virtual void Assign(const InstructionBase& other) = 0;
|
|
|
|
virtual ~InstructionBase() = default;
|
|
|
|
|
|
|
|
virtual void TypeInstruction(Stack<const Type*>* stack,
|
|
|
|
ControlFlowGraph* cfg) const = 0;
|
2018-10-27 11:56:57 +00:00
|
|
|
void InvalidateTransientTypes(Stack<const Type*>* stack) const;
|
2018-10-04 20:45:31 +00:00
|
|
|
virtual bool IsBlockTerminator() const { return false; }
|
|
|
|
virtual void AppendSuccessorBlocks(std::vector<Block*>* block_list) const {}
|
|
|
|
|
|
|
|
SourcePosition pos;
|
|
|
|
};
|
|
|
|
|
|
|
|
class Instruction {
|
|
|
|
public:
|
|
|
|
template <class T>
|
|
|
|
Instruction(T instr) // NOLINT(runtime/explicit)
|
|
|
|
: kind_(T::kKind), instruction_(new T(std::move(instr))) {}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T& Cast() {
|
|
|
|
DCHECK(Is<T>());
|
|
|
|
return static_cast<T&>(*instruction_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
const T& Cast() const {
|
|
|
|
DCHECK(Is<T>());
|
|
|
|
return static_cast<const T&>(*instruction_);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
bool Is() const {
|
|
|
|
return kind_ == T::kKind;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
T* DynamicCast() {
|
|
|
|
if (Is<T>()) return &Cast<T>();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
const T* DynamicCast() const {
|
|
|
|
if (Is<T>()) return &Cast<T>();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-10 13:20:21 +00:00
|
|
|
Instruction(const Instruction& other) V8_NOEXCEPT
|
|
|
|
: kind_(other.kind_),
|
|
|
|
instruction_(other.instruction_->Clone()) {}
|
|
|
|
Instruction& operator=(const Instruction& other) V8_NOEXCEPT {
|
2018-10-04 20:45:31 +00:00
|
|
|
if (kind_ == other.kind_) {
|
|
|
|
instruction_->Assign(*other.instruction_);
|
|
|
|
} else {
|
|
|
|
kind_ = other.kind_;
|
|
|
|
instruction_ = other.instruction_->Clone();
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
InstructionKind kind() const { return kind_; }
|
[torque] Implement methods and constructors for structs and classes
With the changes in this patch, it is now possible to add methods to
both Torque's class and struct types. As a special case, "constructor"
methods are used to initialize the values of classes and structs when
they are constructed.
The functionality in this patch includes:
- The refactoring of class- and struct-handling code to share field
and method declaration code between both.
- Addition of the "%Allocate" intrinsic that allocates raw bytes to be
allocated from the V8 GC's NewSpace heap as the basis for freshly
created, initialized class objects.
- An implementation of a CallMethodExpression AST node that enables
calling methods and constructors, including special handling of
passing through the "this" pointer for method calls on structs by
reference. The syntax for struct construction using "{}" remains as
before, but now calls the struct's matching constructor rather than
implicitly initializing the struct fields with the initialization
arguments. A new syntax for allocation classes is introduced: "new
ClassName{constructor_param1, constructor_param1, ...}", which
de-sugars to an %Allocate call followed by a call to the matching
constructor.
- class constructors can use the "super" keyword to initialize their
super class.
- If classes and struct do not have a constructor, Torque creates a
default constructor for them based on their field declarations,
where each field's initial value is assigned to a same-typed
parameter to the the default constructor. The default constructor's
parameters are in field-declaration order, and for derived classes,
the default constructor automatically uses a "super" initialization
call to initialize inherited fields.
- Class field declarations now automatically create ".field" and
".field=" operators that create CSA-compatible object accessors.
- Addition of a no-argument constructor for JSArrays that creates an
empty, PACKED_SMI_ELEMENTS JSArray using the machinery added
elsewhere in this patch.
Bug: v8:7793
Change-Id: I31ce5f4b444656ab999555d780aeeba605666bfa
Reviewed-on: https://chromium-review.googlesource.com/c/1392192
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58860}
2019-01-16 16:25:29 +00:00
|
|
|
const char* Mnemonic() const {
|
|
|
|
switch (kind()) {
|
|
|
|
#define ENUM_ITEM(name) \
|
|
|
|
case InstructionKind::k##name: \
|
|
|
|
return #name;
|
|
|
|
TORQUE_INSTRUCTION_LIST(ENUM_ITEM)
|
|
|
|
#undef ENUM_ITEM
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
}
|
2018-10-04 20:45:31 +00:00
|
|
|
void TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const {
|
|
|
|
return instruction_->TypeInstruction(stack, cfg);
|
|
|
|
}
|
|
|
|
|
|
|
|
InstructionBase* operator->() { return instruction_.get(); }
|
|
|
|
const InstructionBase* operator->() const { return instruction_.get(); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
InstructionKind kind_;
|
|
|
|
std::unique_ptr<InstructionBase> instruction_;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PeekInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
|
|
|
|
PeekInstruction(BottomOffset slot, base::Optional<const Type*> widened_type)
|
|
|
|
: slot(slot), widened_type(widened_type) {}
|
|
|
|
|
|
|
|
BottomOffset slot;
|
|
|
|
base::Optional<const Type*> widened_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PokeInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
|
|
|
|
PokeInstruction(BottomOffset slot, base::Optional<const Type*> widened_type)
|
|
|
|
: slot(slot), widened_type(widened_type) {}
|
|
|
|
|
|
|
|
BottomOffset slot;
|
|
|
|
base::Optional<const Type*> widened_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Preserve the top {preserved_slots} number of slots, and delete
|
|
|
|
// {deleted_slots} number or slots below.
|
|
|
|
struct DeleteRangeInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
explicit DeleteRangeInstruction(StackRange range) : range(range) {}
|
|
|
|
|
|
|
|
StackRange range;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PushUninitializedInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
explicit PushUninitializedInstruction(const Type* type) : type(type) {}
|
|
|
|
|
|
|
|
const Type* type;
|
|
|
|
};
|
|
|
|
|
2018-12-17 13:20:16 +00:00
|
|
|
struct PushBuiltinPointerInstruction : InstructionBase {
|
2018-10-04 20:45:31 +00:00
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2018-12-17 13:20:16 +00:00
|
|
|
PushBuiltinPointerInstruction(std::string external_name, const Type* type)
|
2018-10-04 20:45:31 +00:00
|
|
|
: external_name(std::move(external_name)), type(type) {
|
2018-12-17 13:20:16 +00:00
|
|
|
DCHECK(type->IsBuiltinPointerType());
|
2018-10-04 20:45:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string external_name;
|
|
|
|
const Type* type;
|
|
|
|
};
|
|
|
|
|
2018-11-13 13:00:34 +00:00
|
|
|
struct NamespaceConstantInstruction : InstructionBase {
|
2018-10-04 20:45:31 +00:00
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2018-11-13 13:00:34 +00:00
|
|
|
explicit NamespaceConstantInstruction(NamespaceConstant* constant)
|
2018-10-04 20:45:31 +00:00
|
|
|
: constant(constant) {}
|
|
|
|
|
2018-11-13 13:00:34 +00:00
|
|
|
NamespaceConstant* constant;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
2019-04-11 13:36:05 +00:00
|
|
|
struct CreateFieldReferenceInstruction : InstructionBase {
|
2019-01-10 13:20:21 +00:00
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2019-12-09 10:59:33 +00:00
|
|
|
CreateFieldReferenceInstruction(const ClassType* type, std::string field_name)
|
|
|
|
: type(type), field_name(std::move(field_name)) {
|
|
|
|
// Trigger errors early.
|
|
|
|
this->type->LookupField(this->field_name);
|
|
|
|
}
|
|
|
|
const ClassType* type;
|
2019-01-10 13:20:21 +00:00
|
|
|
std::string field_name;
|
|
|
|
};
|
|
|
|
|
2019-04-11 13:36:05 +00:00
|
|
|
struct LoadReferenceInstruction : InstructionBase {
|
2019-01-10 13:20:21 +00:00
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2019-04-11 13:36:05 +00:00
|
|
|
explicit LoadReferenceInstruction(const Type* type) : type(type) {}
|
|
|
|
const Type* type;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct StoreReferenceInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
explicit StoreReferenceInstruction(const Type* type) : type(type) {}
|
|
|
|
const Type* type;
|
2019-01-10 13:20:21 +00:00
|
|
|
};
|
|
|
|
|
2018-11-21 15:20:40 +00:00
|
|
|
struct CallIntrinsicInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
CallIntrinsicInstruction(Intrinsic* intrinsic,
|
2019-01-23 20:31:26 +00:00
|
|
|
TypeVector specialization_types,
|
2018-11-21 15:20:40 +00:00
|
|
|
std::vector<std::string> constexpr_arguments)
|
2019-01-23 20:31:26 +00:00
|
|
|
: intrinsic(intrinsic),
|
|
|
|
specialization_types(std::move(specialization_types)),
|
|
|
|
constexpr_arguments(constexpr_arguments) {}
|
2018-11-21 15:20:40 +00:00
|
|
|
|
|
|
|
Intrinsic* intrinsic;
|
2019-01-23 20:31:26 +00:00
|
|
|
TypeVector specialization_types;
|
2018-11-21 15:20:40 +00:00
|
|
|
std::vector<std::string> constexpr_arguments;
|
|
|
|
};
|
|
|
|
|
2018-10-04 20:45:31 +00:00
|
|
|
struct CallCsaMacroInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
CallCsaMacroInstruction(Macro* macro,
|
2018-10-31 13:00:51 +00:00
|
|
|
std::vector<std::string> constexpr_arguments,
|
|
|
|
base::Optional<Block*> catch_block)
|
|
|
|
: macro(macro),
|
|
|
|
constexpr_arguments(constexpr_arguments),
|
|
|
|
catch_block(catch_block) {}
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
if (catch_block) block_list->push_back(*catch_block);
|
|
|
|
}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
Macro* macro;
|
|
|
|
std::vector<std::string> constexpr_arguments;
|
2018-10-31 13:00:51 +00:00
|
|
|
base::Optional<Block*> catch_block;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CallCsaMacroAndBranchInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
CallCsaMacroAndBranchInstruction(Macro* macro,
|
|
|
|
std::vector<std::string> constexpr_arguments,
|
|
|
|
base::Optional<Block*> return_continuation,
|
2018-10-31 13:00:51 +00:00
|
|
|
std::vector<Block*> label_blocks,
|
|
|
|
base::Optional<Block*> catch_block)
|
2018-10-04 20:45:31 +00:00
|
|
|
: macro(macro),
|
|
|
|
constexpr_arguments(constexpr_arguments),
|
|
|
|
return_continuation(return_continuation),
|
2018-10-31 13:00:51 +00:00
|
|
|
label_blocks(label_blocks),
|
|
|
|
catch_block(catch_block) {}
|
2018-10-04 20:45:31 +00:00
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
2018-10-31 13:00:51 +00:00
|
|
|
if (catch_block) block_list->push_back(*catch_block);
|
2018-10-04 20:45:31 +00:00
|
|
|
if (return_continuation) block_list->push_back(*return_continuation);
|
|
|
|
for (Block* block : label_blocks) block_list->push_back(block);
|
|
|
|
}
|
|
|
|
|
|
|
|
Macro* macro;
|
|
|
|
std::vector<std::string> constexpr_arguments;
|
|
|
|
base::Optional<Block*> return_continuation;
|
|
|
|
std::vector<Block*> label_blocks;
|
2018-10-31 13:00:51 +00:00
|
|
|
base::Optional<Block*> catch_block;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CallBuiltinInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return is_tailcall; }
|
2018-10-31 13:00:51 +00:00
|
|
|
CallBuiltinInstruction(bool is_tailcall, Builtin* builtin, size_t argc,
|
|
|
|
base::Optional<Block*> catch_block)
|
|
|
|
: is_tailcall(is_tailcall),
|
|
|
|
builtin(builtin),
|
|
|
|
argc(argc),
|
|
|
|
catch_block(catch_block) {}
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
if (catch_block) block_list->push_back(*catch_block);
|
|
|
|
}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
bool is_tailcall;
|
|
|
|
Builtin* builtin;
|
|
|
|
size_t argc;
|
2018-10-31 13:00:51 +00:00
|
|
|
base::Optional<Block*> catch_block;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct CallBuiltinPointerInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return is_tailcall; }
|
2018-11-05 10:37:49 +00:00
|
|
|
CallBuiltinPointerInstruction(bool is_tailcall,
|
2018-12-17 13:20:16 +00:00
|
|
|
const BuiltinPointerType* type, size_t argc)
|
2018-11-05 10:37:49 +00:00
|
|
|
: is_tailcall(is_tailcall), type(type), argc(argc) {}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
bool is_tailcall;
|
2018-12-17 13:20:16 +00:00
|
|
|
const BuiltinPointerType* type;
|
2018-10-04 20:45:31 +00:00
|
|
|
size_t argc;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CallRuntimeInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2018-10-16 21:14:05 +00:00
|
|
|
bool IsBlockTerminator() const override;
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
CallRuntimeInstruction(bool is_tailcall, RuntimeFunction* runtime_function,
|
2018-10-31 13:00:51 +00:00
|
|
|
size_t argc, base::Optional<Block*> catch_block)
|
2018-10-04 20:45:31 +00:00
|
|
|
: is_tailcall(is_tailcall),
|
|
|
|
runtime_function(runtime_function),
|
2018-10-31 13:00:51 +00:00
|
|
|
argc(argc),
|
|
|
|
catch_block(catch_block) {}
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
if (catch_block) block_list->push_back(*catch_block);
|
|
|
|
}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
bool is_tailcall;
|
|
|
|
RuntimeFunction* runtime_function;
|
|
|
|
size_t argc;
|
2018-10-31 13:00:51 +00:00
|
|
|
base::Optional<Block*> catch_block;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct BranchInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
block_list->push_back(if_true);
|
|
|
|
block_list->push_back(if_false);
|
|
|
|
}
|
|
|
|
|
|
|
|
BranchInstruction(Block* if_true, Block* if_false)
|
|
|
|
: if_true(if_true), if_false(if_false) {}
|
|
|
|
|
|
|
|
Block* if_true;
|
|
|
|
Block* if_false;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ConstexprBranchInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
block_list->push_back(if_true);
|
|
|
|
block_list->push_back(if_false);
|
|
|
|
}
|
|
|
|
|
|
|
|
ConstexprBranchInstruction(std::string condition, Block* if_true,
|
|
|
|
Block* if_false)
|
|
|
|
: condition(condition), if_true(if_true), if_false(if_false) {}
|
|
|
|
|
|
|
|
std::string condition;
|
|
|
|
Block* if_true;
|
|
|
|
Block* if_false;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GotoInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
void AppendSuccessorBlocks(std::vector<Block*>* block_list) const override {
|
|
|
|
block_list->push_back(destination);
|
|
|
|
}
|
|
|
|
|
|
|
|
explicit GotoInstruction(Block* destination) : destination(destination) {}
|
|
|
|
|
|
|
|
Block* destination;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct GotoExternalInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
|
|
|
|
GotoExternalInstruction(std::string destination,
|
|
|
|
std::vector<std::string> variable_names)
|
|
|
|
: destination(std::move(destination)),
|
|
|
|
variable_names(std::move(variable_names)) {}
|
|
|
|
|
|
|
|
std::string destination;
|
|
|
|
std::vector<std::string> variable_names;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ReturnInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
bool IsBlockTerminator() const override { return true; }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PrintConstantStringInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2019-01-24 12:34:25 +00:00
|
|
|
explicit PrintConstantStringInstruction(std::string message)
|
|
|
|
: message(std::move(message)) {}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
|
|
|
std::string message;
|
|
|
|
};
|
|
|
|
|
2018-11-02 12:54:22 +00:00
|
|
|
struct AbortInstruction : InstructionBase {
|
2018-10-04 20:45:31 +00:00
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
2018-11-02 12:54:22 +00:00
|
|
|
enum class Kind { kDebugBreak, kUnreachable, kAssertionFailure };
|
|
|
|
bool IsBlockTerminator() const override { return kind != Kind::kDebugBreak; }
|
2019-01-24 12:34:25 +00:00
|
|
|
explicit AbortInstruction(Kind kind, std::string message = "")
|
|
|
|
: kind(kind), message(std::move(message)) {}
|
2018-10-04 20:45:31 +00:00
|
|
|
|
2018-11-02 12:54:22 +00:00
|
|
|
Kind kind;
|
|
|
|
std::string message;
|
2018-10-04 20:45:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct UnsafeCastInstruction : InstructionBase {
|
|
|
|
TORQUE_INSTRUCTION_BOILERPLATE()
|
|
|
|
explicit UnsafeCastInstruction(const Type* destination_type)
|
|
|
|
: destination_type(destination_type) {}
|
|
|
|
|
|
|
|
const Type* destination_type;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace torque
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|
|
|
|
|
|
|
|
#endif // V8_TORQUE_INSTRUCTIONS_H_
|