Commit 71b7c4c0 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] [decoder] Use inheritance instead of composition

... for AbstractValue and AbstractControl. This allows to access the
fields directly instead of via {interface_data}, and hence makes the code
more readable. Also, it makes AbstractValue and AbstractControl
non-templates. They are also renamed to ValueBase and ControlBase.
Unfortunately, it requires the introduction of new templates
ValueWithNamedConstructors and ControlWithNamedConstructors, in order to
provide correctly typed named constructors (we cannot define implicit
conversion from {Value,Control}Base to a subtype because of our style
guide, checked by a presubmit check).

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Icb7796d040afbf92309333a03d4286fc782f8d1b
Reviewed-on: https://chromium-review.googlesource.com/643392Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47747}
parent b1c12289
...@@ -375,31 +375,25 @@ struct Simd8x16ShuffleOperand { ...@@ -375,31 +375,25 @@ struct Simd8x16ShuffleOperand {
}; };
// An entry on the value stack. // An entry on the value stack.
template <typename Interface> struct ValueBase {
struct AbstractValue {
const byte* pc; const byte* pc;
ValueType type; ValueType type;
typename Interface::IValue interface_data;
// Named constructors. // Named constructors.
static AbstractValue Unreachable(const byte* pc) { static ValueBase Unreachable(const byte* pc) { return {pc, kWasmVar}; }
return {pc, kWasmVar, Interface::IValue::Unreachable()};
}
static AbstractValue New(const byte* pc, ValueType type) { static ValueBase New(const byte* pc, ValueType type) { return {pc, type}; }
return {pc, type, Interface::IValue::New()};
}
}; };
template <typename Interface> template <typename Value>
struct AbstractMerge { struct Merge {
uint32_t arity; uint32_t arity;
union { union {
AbstractValue<Interface>* array; Value* array;
AbstractValue<Interface> first; Value first;
} vals; // Either multiple values or a single value. } vals; // Either multiple values or a single value.
AbstractValue<Interface>& operator[](size_t i) { Value& operator[](size_t i) {
DCHECK_GT(arity, i); DCHECK_GT(arity, i);
return arity == 1 ? vals.first : vals.array[i]; return arity == 1 ? vals.first : vals.array[i];
} }
...@@ -415,16 +409,15 @@ enum ControlKind { ...@@ -415,16 +409,15 @@ enum ControlKind {
}; };
// An entry on the control stack (i.e. if, block, loop, or try). // An entry on the control stack (i.e. if, block, loop, or try).
template <typename Interface> template <typename Value>
struct AbstractControl { struct ControlBase {
const byte* pc; const byte* pc;
ControlKind kind; ControlKind kind;
size_t stack_depth; // stack height at the beginning of the construct. size_t stack_depth; // stack height at the beginning of the construct.
typename Interface::IControl interface_data; bool unreachable; // The current block has been ended.
bool unreachable; // The current block has been ended.
// Values merged into the end of this control construct. // Values merged into the end of this control construct.
AbstractMerge<Interface> merge; Merge<Value> merge;
inline bool is_if() const { return is_onearmed_if() || is_if_else(); } inline bool is_if() const { return is_onearmed_if() || is_if_else(); }
inline bool is_onearmed_if() const { return kind == kControlIf; } inline bool is_onearmed_if() const { return kind == kControlIf; }
...@@ -436,26 +429,59 @@ struct AbstractControl { ...@@ -436,26 +429,59 @@ struct AbstractControl {
inline bool is_try_catch() const { return kind == kControlTryCatch; } inline bool is_try_catch() const { return kind == kControlTryCatch; }
// Named constructors. // Named constructors.
static AbstractControl Block(const byte* pc, size_t stack_depth) { static ControlBase Block(const byte* pc, size_t stack_depth) {
return {pc, kControlBlock, stack_depth, Interface::IControl::Block(), false, return {pc, kControlBlock, stack_depth, false, {}};
{}};
} }
static AbstractControl If(const byte* pc, size_t stack_depth) { static ControlBase If(const byte* pc, size_t stack_depth) {
return {pc, kControlIf, stack_depth, Interface::IControl::If(), false, {}}; return {pc, kControlIf, stack_depth, false, {}};
} }
static AbstractControl Loop(const byte* pc, size_t stack_depth) { static ControlBase Loop(const byte* pc, size_t stack_depth) {
return {pc, kControlLoop, stack_depth, Interface::IControl::Loop(), false, return {pc, kControlLoop, stack_depth, false, {}};
{}};
} }
static AbstractControl Try(const byte* pc, size_t stack_depth) { static ControlBase Try(const byte* pc, size_t stack_depth) {
return {pc, kControlTry, stack_depth, Interface::IControl::Try(), return {pc, kControlTry, stack_depth, false, {}};
false, {}};
} }
}; };
#define CONCRETE_NAMED_CONSTRUCTOR(concrete_type, abstract_type, name) \
template <typename... Args> \
static concrete_type name(Args&&... args) { \
concrete_type val; \
static_cast<abstract_type&>(val) = \
abstract_type::name(std::forward<Args>(args)...); \
return val; \
}
// Provide the default named constructors, which default-initialize the
// ConcreteType and the initialize the fields of ValueBase correctly.
// Use like this:
// struct Value : public ValueWithNamedConstructors<Value> { int new_field; };
template <typename ConcreteType>
struct ValueWithNamedConstructors : public ValueBase {
// Named constructors.
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, Unreachable)
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ValueBase, New)
};
// Provide the default named constructors, which default-initialize the
// ConcreteType and the initialize the fields of ControlBase correctly.
// Use like this:
// struct Control : public ControlWithNamedConstructors<Control, Value> {
// int my_uninitialized_field;
// char* other_field = nullptr;
// };
template <typename ConcreteType, typename Value>
struct ControlWithNamedConstructors : public ControlBase<Value> {
// Named constructors.
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Block)
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, If)
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Loop)
CONCRETE_NAMED_CONSTRUCTOR(ConcreteType, ControlBase<Value>, Try)
};
// This is the list of callback functions that an interface for the // This is the list of callback functions that an interface for the
// WasmFullDecoder should implement. // WasmFullDecoder should implement.
// F(Name, args...) // F(Name, args...)
...@@ -972,9 +998,9 @@ class WasmDecoder : public Decoder { ...@@ -972,9 +998,9 @@ class WasmDecoder : public Decoder {
template <bool validate, typename Interface> template <bool validate, typename Interface>
class WasmFullDecoder : public WasmDecoder<validate> { class WasmFullDecoder : public WasmDecoder<validate> {
using Value = AbstractValue<Interface>; using Value = typename Interface::Value;
using Control = AbstractControl<Interface>; using Control = typename Interface::Control;
using MergeValues = AbstractMerge<Interface>; using MergeValues = Merge<Value>;
// All Value and Control types should be trivially copyable for // All Value and Control types should be trivially copyable for
// performance. We push and pop them, and store them in local variables. // performance. We push and pop them, and store them in local variables.
...@@ -2125,28 +2151,12 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2125,28 +2151,12 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
}; };
template <bool decoder_validate, typename Interface> class EmptyInterface {
class InterfaceTemplate {
public:
constexpr static bool validate = decoder_validate;
using Decoder = WasmFullDecoder<validate, Interface>;
using Control = AbstractControl<Interface>;
using Value = AbstractValue<Interface>;
using MergeValues = AbstractMerge<Interface>;
};
class EmptyInterface : public InterfaceTemplate<true, EmptyInterface> {
public: public:
struct IValue { constexpr static bool validate = true;
static IValue Unreachable() { return {}; } using Value = ValueBase;
static IValue New() { return {}; } using Control = ControlBase<Value>;
}; using Decoder = WasmFullDecoder<validate, EmptyInterface>;
struct IControl {
static IControl Block() { return {}; }
static IControl If() { return {}; }
static IControl Loop() { return {}; }
static IControl Try() { return {}; }
};
#define DEFINE_EMPTY_CALLBACK(name, ...) \ #define DEFINE_EMPTY_CALLBACK(name, ...) \
void name(Decoder* decoder, ##__VA_ARGS__) {} void name(Decoder* decoder, ##__VA_ARGS__) {}
......
...@@ -60,14 +60,12 @@ struct SsaEnv { ...@@ -60,14 +60,12 @@ struct SsaEnv {
constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1); constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
class WasmGraphBuildingInterface class WasmGraphBuildingInterface {
: public InterfaceTemplate<true, WasmGraphBuildingInterface> {
public: public:
struct IValue { using Decoder = WasmFullDecoder<true, WasmGraphBuildingInterface>;
TFNode* node;
static IValue Unreachable() { return {nullptr}; } struct Value : public ValueWithNamedConstructors<Value> {
static IValue New() { return {nullptr}; } TFNode* node;
}; };
struct TryInfo : public ZoneObject { struct TryInfo : public ZoneObject {
...@@ -77,16 +75,11 @@ class WasmGraphBuildingInterface ...@@ -77,16 +75,11 @@ class WasmGraphBuildingInterface
explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {} explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
}; };
struct IControl { struct Control : public ControlWithNamedConstructors<Control, Value> {
SsaEnv* end_env; // end environment for the construct. SsaEnv* end_env; // end environment for the construct.
SsaEnv* false_env; // false environment (only for if). SsaEnv* false_env; // false environment (only for if).
TryInfo* try_info; // information used for compiling try statements. TryInfo* try_info; // information used for compiling try statements.
int32_t previous_catch; // previous Control (on the stack) with a catch. int32_t previous_catch; // previous Control (on the stack) with a catch.
static IControl Block() { return {}; }
static IControl If() { return {}; }
static IControl Loop() { return {}; }
static IControl Try() { return {}; }
}; };
explicit WasmGraphBuildingInterface(TFBuilder* builder) : builder_(builder) {} explicit WasmGraphBuildingInterface(TFBuilder* builder) : builder_(builder) {}
...@@ -124,7 +117,7 @@ class WasmGraphBuildingInterface ...@@ -124,7 +117,7 @@ class WasmGraphBuildingInterface
void StartFunctionBody(Decoder* decoder, Control* block) { void StartFunctionBody(Decoder* decoder, Control* block) {
SsaEnv* break_env = ssa_env_; SsaEnv* break_env = ssa_env_;
SetEnv(Steal(decoder->zone(), break_env)); SetEnv(Steal(decoder->zone(), break_env));
block->interface_data.end_env = break_env; block->end_env = break_env;
} }
void FinishFunction(Decoder* decoder) { void FinishFunction(Decoder* decoder) {
...@@ -133,13 +126,13 @@ class WasmGraphBuildingInterface ...@@ -133,13 +126,13 @@ class WasmGraphBuildingInterface
void Block(Decoder* decoder, Control* block) { void Block(Decoder* decoder, Control* block) {
// The break environment is the outer environment. // The break environment is the outer environment.
block->interface_data.end_env = ssa_env_; block->end_env = ssa_env_;
SetEnv(Steal(decoder->zone(), ssa_env_)); SetEnv(Steal(decoder->zone(), ssa_env_));
} }
void Loop(Decoder* decoder, Control* block) { void Loop(Decoder* decoder, Control* block) {
SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_); SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
block->interface_data.end_env = finish_try_env; block->end_env = finish_try_env;
// The continue environment is the inner environment. // The continue environment is the inner environment.
SetEnv(PrepareForLoop(decoder, finish_try_env)); SetEnv(PrepareForLoop(decoder, finish_try_env));
ssa_env_->SetNotMerged(); ssa_env_->SetNotMerged();
...@@ -151,35 +144,34 @@ class WasmGraphBuildingInterface ...@@ -151,35 +144,34 @@ class WasmGraphBuildingInterface
SsaEnv* catch_env = UnreachableEnv(decoder->zone()); SsaEnv* catch_env = UnreachableEnv(decoder->zone());
SetEnv(try_env); SetEnv(try_env);
TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env); TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
block->interface_data.end_env = outer_env; block->end_env = outer_env;
block->interface_data.try_info = try_info; block->try_info = try_info;
block->interface_data.previous_catch = current_catch_; block->previous_catch = current_catch_;
current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1); current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
} }
void If(Decoder* decoder, const Value& cond, Control* if_block) { void If(Decoder* decoder, const Value& cond, Control* if_block) {
TFNode* if_true = nullptr; TFNode* if_true = nullptr;
TFNode* if_false = nullptr; TFNode* if_false = nullptr;
BUILD(BranchNoHint, cond.interface_data.node, &if_true, &if_false); BUILD(BranchNoHint, cond.node, &if_true, &if_false);
SsaEnv* end_env = ssa_env_; SsaEnv* end_env = ssa_env_;
SsaEnv* false_env = Split(decoder, ssa_env_); SsaEnv* false_env = Split(decoder, ssa_env_);
false_env->control = if_false; false_env->control = if_false;
SsaEnv* true_env = Steal(decoder->zone(), ssa_env_); SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
true_env->control = if_true; true_env->control = if_true;
if_block->interface_data.end_env = end_env; if_block->end_env = end_env;
if_block->interface_data.false_env = false_env; if_block->false_env = false_env;
SetEnv(true_env); SetEnv(true_env);
} }
void FallThruTo(Decoder* decoder, Control* c) { void FallThruTo(Decoder* decoder, Control* c) {
MergeValuesInto(decoder, c); MergeValuesInto(decoder, c);
SetEnv(c->interface_data.end_env); SetEnv(c->end_env);
} }
void PopControl(Decoder* decoder, Control& block) { void PopControl(Decoder* decoder, Control& block) {
if (block.is_onearmed_if()) { if (block.is_onearmed_if()) {
Goto(decoder, block.interface_data.false_env, Goto(decoder, block.false_env, block.end_env);
block.interface_data.end_env);
} }
} }
...@@ -187,38 +179,36 @@ class WasmGraphBuildingInterface ...@@ -187,38 +179,36 @@ class WasmGraphBuildingInterface
void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig, void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
const Value& value, Value* result) { const Value& value, Value* result) {
result->interface_data.node = result->node = BUILD(Unop, opcode, value.node, decoder->position());
BUILD(Unop, opcode, value.interface_data.node, decoder->position());
} }
void BinOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig, void BinOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
const Value& lhs, const Value& rhs, Value* result) { const Value& lhs, const Value& rhs, Value* result) {
result->interface_data.node = result->node =
BUILD(Binop, opcode, lhs.interface_data.node, rhs.interface_data.node, BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
decoder->position());
} }
void I32Const(Decoder* decoder, Value* result, int32_t value) { void I32Const(Decoder* decoder, Value* result, int32_t value) {
result->interface_data.node = builder_->Int32Constant(value); result->node = builder_->Int32Constant(value);
} }
void I64Const(Decoder* decoder, Value* result, int64_t value) { void I64Const(Decoder* decoder, Value* result, int64_t value) {
result->interface_data.node = builder_->Int64Constant(value); result->node = builder_->Int64Constant(value);
} }
void F32Const(Decoder* decoder, Value* result, float value) { void F32Const(Decoder* decoder, Value* result, float value) {
result->interface_data.node = builder_->Float32Constant(value); result->node = builder_->Float32Constant(value);
} }
void F64Const(Decoder* decoder, Value* result, double value) { void F64Const(Decoder* decoder, Value* result, double value) {
result->interface_data.node = builder_->Float64Constant(value); result->node = builder_->Float64Constant(value);
} }
void DoReturn(Decoder* decoder, Vector<Value> values) { void DoReturn(Decoder* decoder, Vector<Value> values) {
size_t num_values = values.size(); size_t num_values = values.size();
TFNode** buffer = GetNodes(values); TFNode** buffer = GetNodes(values);
for (size_t i = 0; i < num_values; ++i) { for (size_t i = 0; i < num_values; ++i) {
buffer[i] = values[i].interface_data.node; buffer[i] = values[i].node;
} }
BUILD(Return, static_cast<unsigned>(values.size()), buffer); BUILD(Return, static_cast<unsigned>(values.size()), buffer);
} }
...@@ -226,30 +216,30 @@ class WasmGraphBuildingInterface ...@@ -226,30 +216,30 @@ class WasmGraphBuildingInterface
void GetLocal(Decoder* decoder, Value* result, void GetLocal(Decoder* decoder, Value* result,
const LocalIndexOperand<true>& operand) { const LocalIndexOperand<true>& operand) {
if (!ssa_env_->locals) return; // unreachable if (!ssa_env_->locals) return; // unreachable
result->interface_data.node = ssa_env_->locals[operand.index]; result->node = ssa_env_->locals[operand.index];
} }
void SetLocal(Decoder* decoder, const Value& value, void SetLocal(Decoder* decoder, const Value& value,
const LocalIndexOperand<true>& operand) { const LocalIndexOperand<true>& operand) {
if (!ssa_env_->locals) return; // unreachable if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.interface_data.node; ssa_env_->locals[operand.index] = value.node;
} }
void TeeLocal(Decoder* decoder, const Value& value, Value* result, void TeeLocal(Decoder* decoder, const Value& value, Value* result,
const LocalIndexOperand<true>& operand) { const LocalIndexOperand<true>& operand) {
result->interface_data.node = value.interface_data.node; result->node = value.node;
if (!ssa_env_->locals) return; // unreachable if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.interface_data.node; ssa_env_->locals[operand.index] = value.node;
} }
void GetGlobal(Decoder* decoder, Value* result, void GetGlobal(Decoder* decoder, Value* result,
const GlobalIndexOperand<true>& operand) { const GlobalIndexOperand<true>& operand) {
result->interface_data.node = BUILD(GetGlobal, operand.index); result->node = BUILD(GetGlobal, operand.index);
} }
void SetGlobal(Decoder* decoder, const Value& value, void SetGlobal(Decoder* decoder, const Value& value,
const GlobalIndexOperand<true>& operand) { const GlobalIndexOperand<true>& operand) {
BUILD(SetGlobal, operand.index, value.interface_data.node); BUILD(SetGlobal, operand.index, value.node);
} }
void Unreachable(Decoder* decoder) { void Unreachable(Decoder* decoder) {
...@@ -259,17 +249,17 @@ class WasmGraphBuildingInterface ...@@ -259,17 +249,17 @@ class WasmGraphBuildingInterface
void Select(Decoder* decoder, const Value& cond, const Value& fval, void Select(Decoder* decoder, const Value& cond, const Value& fval,
const Value& tval, Value* result) { const Value& tval, Value* result) {
TFNode* controls[2]; TFNode* controls[2];
BUILD(BranchNoHint, cond.interface_data.node, &controls[0], &controls[1]); BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
TFNode* merge = BUILD(Merge, 2, controls); TFNode* merge = BUILD(Merge, 2, controls);
TFNode* vals[2] = {tval.interface_data.node, fval.interface_data.node}; TFNode* vals[2] = {tval.node, fval.node};
TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge); TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
result->interface_data.node = phi; result->node = phi;
ssa_env_->control = merge; ssa_env_->control = merge;
} }
void BreakTo(Decoder* decoder, Control* block) { void BreakTo(Decoder* decoder, Control* block) {
if (block->is_loop()) { if (block->is_loop()) {
Goto(decoder, ssa_env_, block->interface_data.end_env); Goto(decoder, ssa_env_, block->end_env);
} else { } else {
MergeValuesInto(decoder, block); MergeValuesInto(decoder, block);
} }
...@@ -279,8 +269,7 @@ class WasmGraphBuildingInterface ...@@ -279,8 +269,7 @@ class WasmGraphBuildingInterface
SsaEnv* fenv = ssa_env_; SsaEnv* fenv = ssa_env_;
SsaEnv* tenv = Split(decoder, fenv); SsaEnv* tenv = Split(decoder, fenv);
fenv->SetNotMerged(); fenv->SetNotMerged();
BUILD(BranchNoHint, cond.interface_data.node, &tenv->control, BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
&fenv->control);
ssa_env_ = tenv; ssa_env_ = tenv;
BreakTo(decoder, block); BreakTo(decoder, block);
ssa_env_ = fenv; ssa_env_ = fenv;
...@@ -290,8 +279,7 @@ class WasmGraphBuildingInterface ...@@ -290,8 +279,7 @@ class WasmGraphBuildingInterface
const Value& key) { const Value& key) {
SsaEnv* break_env = ssa_env_; SsaEnv* break_env = ssa_env_;
// Build branches to the various blocks based on the table. // Build branches to the various blocks based on the table.
TFNode* sw = TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
BUILD(Switch, operand.table_count + 1, key.interface_data.node);
SsaEnv* copy = Steal(decoder->zone(), break_env); SsaEnv* copy = Steal(decoder->zone(), break_env);
ssa_env_ = copy; ssa_env_ = copy;
...@@ -309,30 +297,29 @@ class WasmGraphBuildingInterface ...@@ -309,30 +297,29 @@ class WasmGraphBuildingInterface
} }
void Else(Decoder* decoder, Control* if_block) { void Else(Decoder* decoder, Control* if_block) {
SetEnv(if_block->interface_data.false_env); SetEnv(if_block->false_env);
} }
void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type, void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type,
const MemoryAccessOperand<true>& operand, const Value& index, const MemoryAccessOperand<true>& operand, const Value& index,
Value* result) { Value* result) {
result->interface_data.node = result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
BUILD(LoadMem, type, mem_type, index.interface_data.node, operand.alignment, decoder->position());
operand.offset, operand.alignment, decoder->position());
} }
void StoreMem(Decoder* decoder, ValueType type, MachineType mem_type, void StoreMem(Decoder* decoder, ValueType type, MachineType mem_type,
const MemoryAccessOperand<true>& operand, const Value& index, const MemoryAccessOperand<true>& operand, const Value& index,
const Value& value) { const Value& value) {
BUILD(StoreMem, mem_type, index.interface_data.node, operand.offset, BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
operand.alignment, value.interface_data.node, decoder->position()); value.node, decoder->position());
} }
void CurrentMemoryPages(Decoder* decoder, Value* result) { void CurrentMemoryPages(Decoder* decoder, Value* result) {
result->interface_data.node = BUILD(CurrentMemoryPages); result->node = BUILD(CurrentMemoryPages);
} }
void GrowMemory(Decoder* decoder, const Value& value, Value* result) { void GrowMemory(Decoder* decoder, const Value& value, Value* result) {
result->interface_data.node = BUILD(GrowMemory, value.interface_data.node); result->node = BUILD(GrowMemory, value.node);
} }
void CallDirect(Decoder* decoder, const CallFunctionOperand<true>& operand, void CallDirect(Decoder* decoder, const CallFunctionOperand<true>& operand,
...@@ -343,40 +330,36 @@ class WasmGraphBuildingInterface ...@@ -343,40 +330,36 @@ class WasmGraphBuildingInterface
void CallIndirect(Decoder* decoder, const Value& index, void CallIndirect(Decoder* decoder, const Value& index,
const CallIndirectOperand<true>& operand, const CallIndirectOperand<true>& operand,
const Value args[], Value returns[]) { const Value args[], Value returns[]) {
DoCall(decoder, index.interface_data.node, operand, args, returns, true); DoCall(decoder, index.node, operand, args, returns, true);
} }
void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args, void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
Value* result) { Value* result) {
TFNode** inputs = GetNodes(args); TFNode** inputs = GetNodes(args);
TFNode* node = BUILD(SimdOp, opcode, inputs); TFNode* node = BUILD(SimdOp, opcode, inputs);
if (result) result->interface_data.node = node; if (result) result->node = node;
} }
void SimdLaneOp(Decoder* decoder, WasmOpcode opcode, void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
const SimdLaneOperand<true> operand, Vector<Value> inputs, const SimdLaneOperand<true> operand, Vector<Value> inputs,
Value* result) { Value* result) {
TFNode** nodes = GetNodes(inputs); TFNode** nodes = GetNodes(inputs);
result->interface_data.node = result->node = BUILD(SimdLaneOp, opcode, operand.lane, nodes);
BUILD(SimdLaneOp, opcode, operand.lane, nodes);
} }
void SimdShiftOp(Decoder* decoder, WasmOpcode opcode, void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
const SimdShiftOperand<true> operand, const Value& input, const SimdShiftOperand<true> operand, const Value& input,
Value* result) { Value* result) {
TFNode* inputs[] = {input.interface_data.node}; TFNode* inputs[] = {input.node};
result->interface_data.node = result->node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
BUILD(SimdShiftOp, opcode, operand.shift, inputs);
} }
void Simd8x16ShuffleOp(Decoder* decoder, void Simd8x16ShuffleOp(Decoder* decoder,
const Simd8x16ShuffleOperand<true>& operand, const Simd8x16ShuffleOperand<true>& operand,
const Value& input0, const Value& input1, const Value& input0, const Value& input1,
Value* result) { Value* result) {
TFNode* input_nodes[] = {input0.interface_data.node, TFNode* input_nodes[] = {input0.node, input1.node};
input1.interface_data.node}; result->node = BUILD(Simd8x16ShuffleOp, operand.shuffle, input_nodes);
result->interface_data.node =
BUILD(Simd8x16ShuffleOp, operand.shuffle, input_nodes);
} }
TFNode* GetExceptionTag(Decoder* decoder, TFNode* GetExceptionTag(Decoder* decoder,
...@@ -393,13 +376,13 @@ class WasmGraphBuildingInterface ...@@ -393,13 +376,13 @@ class WasmGraphBuildingInterface
void Catch(Decoder* decoder, const ExceptionIndexOperand<true>& operand, void Catch(Decoder* decoder, const ExceptionIndexOperand<true>& operand,
Control* block) { Control* block) {
DCHECK(block->is_try_catch()); DCHECK(block->is_try_catch());
current_catch_ = block->interface_data.previous_catch; current_catch_ = block->previous_catch;
SsaEnv* catch_env = block->interface_data.try_info->catch_env; SsaEnv* catch_env = block->try_info->catch_env;
SetEnv(catch_env); SetEnv(catch_env);
// Get the exception and see if wanted exception. // Get the exception and see if wanted exception.
TFNode* exception_as_i32 = BUILD( TFNode* exception_as_i32 =
Catch, block->interface_data.try_info->exception, decoder->position()); BUILD(Catch, block->try_info->exception, decoder->position());
TFNode* exception_tag = GetExceptionTag(decoder, operand); TFNode* exception_tag = GetExceptionTag(decoder, operand);
TFNode* compare_i32 = BUILD(Binop, kExprI32Eq, exception_as_i32, TFNode* compare_i32 = BUILD(Binop, kExprI32Eq, exception_as_i32,
exception_tag, decoder->position()); exception_tag, decoder->position());
...@@ -410,10 +393,10 @@ class WasmGraphBuildingInterface ...@@ -410,10 +393,10 @@ class WasmGraphBuildingInterface
false_env->control = if_false; false_env->control = if_false;
SsaEnv* true_env = Steal(decoder->zone(), catch_env); SsaEnv* true_env = Steal(decoder->zone(), catch_env);
true_env->control = if_true; true_env->control = if_true;
block->interface_data.try_info->catch_env = false_env; block->try_info->catch_env = false_env;
// Generate code to re-throw the exception. // Generate code to re-throw the exception.
DCHECK_NOT_NULL(block->interface_data.try_info->catch_env); DCHECK_NOT_NULL(block->try_info->catch_env);
SetEnv(false_env); SetEnv(false_env);
BUILD(Rethrow); BUILD(Rethrow);
FallThruTo(decoder, block); FallThruTo(decoder, block);
...@@ -426,7 +409,7 @@ class WasmGraphBuildingInterface ...@@ -426,7 +409,7 @@ class WasmGraphBuildingInterface
Value* result) { Value* result) {
TFNode** inputs = GetNodes(args); TFNode** inputs = GetNodes(args);
TFNode* node = BUILD(AtomicOp, opcode, inputs, decoder->position()); TFNode* node = BUILD(AtomicOp, opcode, inputs, decoder->position());
if (result) result->interface_data.node = node; if (result) result->node = node;
} }
private: private:
...@@ -438,13 +421,13 @@ class WasmGraphBuildingInterface ...@@ -438,13 +421,13 @@ class WasmGraphBuildingInterface
TryInfo* current_try_info(Decoder* decoder) { TryInfo* current_try_info(Decoder* decoder) {
return decoder->control_at(decoder->control_depth() - 1 - current_catch_) return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
->interface_data.try_info; ->try_info;
} }
TFNode** GetNodes(Value* values, size_t count) { TFNode** GetNodes(Value* values, size_t count) {
TFNode** nodes = builder_->Buffer(count); TFNode** nodes = builder_->Buffer(count);
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
nodes[i] = values[i].interface_data.node; nodes[i] = values[i].node;
} }
return nodes; return nodes;
} }
...@@ -541,7 +524,7 @@ class WasmGraphBuildingInterface ...@@ -541,7 +524,7 @@ class WasmGraphBuildingInterface
void MergeValuesInto(Decoder* decoder, Control* c) { void MergeValuesInto(Decoder* decoder, Control* c) {
if (!ssa_env_->go()) return; if (!ssa_env_->go()) return;
SsaEnv* target = c->interface_data.end_env; SsaEnv* target = c->end_env;
const bool first = target->state == SsaEnv::kUnreachable; const bool first = target->state == SsaEnv::kUnreachable;
Goto(decoder, ssa_env_, target); Goto(decoder, ssa_env_, target);
...@@ -550,15 +533,11 @@ class WasmGraphBuildingInterface ...@@ -550,15 +533,11 @@ class WasmGraphBuildingInterface
for (size_t i = start; i < c->merge.arity; ++i) { for (size_t i = start; i < c->merge.arity; ++i) {
auto& val = decoder->GetMergeValueFromStack(c, i); auto& val = decoder->GetMergeValueFromStack(c, i);
auto& old = c->merge[i]; auto& old = c->merge[i];
DCHECK_NOT_NULL(val.interface_data.node); DCHECK_NOT_NULL(val.node);
// TODO(clemensh): Remove first.
DCHECK_EQ(first, old.interface_data.node == nullptr);
DCHECK(val.type == old.type || val.type == kWasmVar); DCHECK(val.type == old.type || val.type == kWasmVar);
old.interface_data.node = old.node = first ? val.node
first ? val.interface_data.node : CreateOrMergeIntoPhi(old.type, target->control,
: CreateOrMergeIntoPhi(old.type, target->control, old.node, val.node);
old.interface_data.node,
val.interface_data.node);
} }
} }
...@@ -744,7 +723,7 @@ class WasmGraphBuildingInterface ...@@ -744,7 +723,7 @@ class WasmGraphBuildingInterface
TFNode** return_nodes = nullptr; TFNode** return_nodes = nullptr;
arg_nodes[0] = index_node; arg_nodes[0] = index_node;
for (int i = 0; i < param_count; ++i) { for (int i = 0; i < param_count; ++i) {
arg_nodes[i + 1] = args[i].interface_data.node; arg_nodes[i + 1] = args[i].node;
} }
if (is_indirect) { if (is_indirect) {
builder_->CallIndirect(operand.index, arg_nodes, &return_nodes, builder_->CallIndirect(operand.index, arg_nodes, &return_nodes,
...@@ -755,7 +734,7 @@ class WasmGraphBuildingInterface ...@@ -755,7 +734,7 @@ class WasmGraphBuildingInterface
} }
int return_count = static_cast<int>(operand.sig->return_count()); int return_count = static_cast<int>(operand.sig->return_count());
for (int i = 0; i < return_count; ++i) { for (int i = 0; i < return_count; ++i) {
returns[i].interface_data.node = return_nodes[i]; returns[i].node = return_nodes[i];
} }
} }
}; };
......
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