Commit ae194db8 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] [decoder] Extend interface methods

A minor refactoring of the decoder interface, which makes implementing
the baseline compiler easier.

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Ia5ae66e0e036329767b6e4f1cfcd3ed6a5e4cb74
Reviewed-on: https://chromium-review.googlesource.com/715636
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48498}
parent aabffe0b
...@@ -510,13 +510,14 @@ struct ControlWithNamedConstructors : public ControlBase<Value> { ...@@ -510,13 +510,14 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
F(StartFunction) \ F(StartFunction) \
F(StartFunctionBody, Control* block) \ F(StartFunctionBody, Control* block) \
F(FinishFunction) \ F(FinishFunction) \
F(OnFirstError) \
/* Control: */ \ /* Control: */ \
F(Block, Control* block) \ F(Block, Control* block) \
F(Loop, Control* block) \ F(Loop, Control* block) \
F(Try, Control* block) \ F(Try, Control* block) \
F(If, const Value& cond, Control* if_block) \ F(If, const Value& cond, Control* if_block) \
F(FallThruTo, Control* c) \ F(FallThruTo, Control* c) \
F(PopControl, const Control& block) \ F(PopControl, Control* block) \
F(EndControl, Control* block) \ F(EndControl, Control* block) \
/* Instructions: */ \ /* Instructions: */ \
F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \ F(UnOp, WasmOpcode opcode, FunctionSig*, const Value& value, Value* result) \
...@@ -526,7 +527,8 @@ struct ControlWithNamedConstructors : public ControlBase<Value> { ...@@ -526,7 +527,8 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
F(I64Const, Value* result, int64_t value) \ F(I64Const, Value* result, int64_t value) \
F(F32Const, Value* result, float value) \ F(F32Const, Value* result, float value) \
F(F64Const, Value* result, double value) \ F(F64Const, Value* result, double value) \
F(DoReturn, Vector<Value> values) \ F(Drop, const Value& value) \
F(DoReturn, Vector<Value> values, bool implicit) \
F(GetLocal, Value* result, const LocalIndexOperand<validate>& operand) \ F(GetLocal, Value* result, const LocalIndexOperand<validate>& operand) \
F(SetLocal, const Value& value, const LocalIndexOperand<validate>& operand) \ F(SetLocal, const Value& value, const LocalIndexOperand<validate>& operand) \
F(TeeLocal, const Value& value, Value* result, \ F(TeeLocal, const Value& value, Value* result, \
...@@ -537,8 +539,8 @@ struct ControlWithNamedConstructors : public ControlBase<Value> { ...@@ -537,8 +539,8 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
F(Unreachable) \ F(Unreachable) \
F(Select, const Value& cond, const Value& fval, const Value& tval, \ F(Select, const Value& cond, const Value& fval, const Value& tval, \
Value* result) \ Value* result) \
F(BreakTo, uint32_t depth) \ F(BreakTo, Control* target) \
F(BrIf, const Value& cond, uint32_t depth) \ F(BrIf, const Value& cond, Control* target) \
F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \ F(BrTable, const BranchTableOperand<validate>& operand, const Value& key) \
F(Else, Control* if_block) \ F(Else, Control* if_block) \
F(LoadMem, ValueType type, MachineType mem_type, \ F(LoadMem, ValueType type, MachineType mem_type, \
...@@ -1057,12 +1059,10 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1057,12 +1059,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
using Control = typename Interface::Control; using Control = typename Interface::Control;
using MergeValues = Merge<Value>; using MergeValues = Merge<Value>;
// All Value and Control types should be trivially copyable for // All Value types should be trivially copyable for performance. We push, pop,
// performance. We push and pop them, and store them in local variables. // and store them in local variables.
static_assert(IS_TRIVIALLY_COPYABLE(Value), static_assert(IS_TRIVIALLY_COPYABLE(Value),
"all Value<...> types should be trivially copyable"); "all Value<...> types should be trivially copyable");
static_assert(IS_TRIVIALLY_COPYABLE(Control),
"all Control<...> types should be trivially copyable");
public: public:
template <typename... InterfaceArgs> template <typename... InterfaceArgs>
...@@ -1166,7 +1166,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1166,7 +1166,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
inline Control* control_at(uint32_t depth) { inline Control* control_at(uint32_t depth) {
DCHECK_GT(control_.size(), depth); DCHECK_GT(control_.size(), depth);
return &control_[control_.size() - depth - 1]; return &control_.back() - depth;
} }
inline uint32_t stack_size() const { inline uint32_t stack_size() const {
...@@ -1410,7 +1410,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1410,7 +1410,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
// The result of the block is the return value. // The result of the block is the return value.
TRACE(" @%-8d #xx:%-20s|", startrel(this->pc_), TRACE(" @%-8d #xx:%-20s|", startrel(this->pc_),
"(implicit) return"); "(implicit) return");
DoReturn(); DoReturn(true);
TRACE("\n"); TRACE("\n");
} }
...@@ -1427,10 +1427,10 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1427,10 +1427,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
} }
case kExprBr: { case kExprBr: {
BreakDepthOperand<validate> operand(this, this->pc_); BreakDepthOperand<validate> operand(this, this->pc_);
if (this->Validate(this->pc_, operand, control_.size()) && if (!this->Validate(this->pc_, operand, control_.size())) break;
TypeCheckBreak(operand.depth)) { Control* c = control_at(operand.depth);
interface_.BreakTo(this, operand.depth); if (!TypeCheckBreak(c)) break;
} interface_.BreakTo(this, c);
len = 1 + operand.length; len = 1 + operand.length;
EndControl(); EndControl();
break; break;
...@@ -1438,10 +1438,10 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1438,10 +1438,10 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprBrIf: { case kExprBrIf: {
BreakDepthOperand<validate> operand(this, this->pc_); BreakDepthOperand<validate> operand(this, this->pc_);
auto cond = Pop(0, kWasmI32); auto cond = Pop(0, kWasmI32);
if (this->Validate(this->pc_, operand, control_.size()) && if (!this->Validate(this->pc_, operand, control_.size())) break;
TypeCheckBreak(operand.depth)) { Control* c = control_at(operand.depth);
interface_.BrIf(this, cond, operand.depth); if (!TypeCheckBreak(c)) break;
} interface_.BrIf(this, cond, c);
len = 1 + operand.length; len = 1 + operand.length;
break; break;
} }
...@@ -1470,7 +1470,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1470,7 +1470,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
" (previous was %u, this one %u)", " (previous was %u, this one %u)",
i, br_arity, arity); i, br_arity, arity);
} }
if (!TypeCheckBreak(target)) break; if (!TypeCheckBreak(c)) break;
} }
if (!VALIDATE(this->ok())) break; if (!VALIDATE(this->ok())) break;
...@@ -1481,7 +1481,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1481,7 +1481,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break; break;
} }
case kExprReturn: { case kExprReturn: {
DoReturn(); DoReturn(false);
break; break;
} }
case kExprUnreachable: { case kExprUnreachable: {
...@@ -1543,7 +1543,8 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1543,7 +1543,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break; break;
} }
case kExprDrop: { case kExprDrop: {
Pop(); auto value = Pop();
interface_.Drop(this, value);
break; break;
} }
case kExprGetGlobal: { case kExprGetGlobal: {
...@@ -1858,7 +1859,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -1858,7 +1859,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
void PopControl(Control* c) { void PopControl(Control* c) {
DCHECK_EQ(c, &control_.back()); DCHECK_EQ(c, &control_.back());
interface_.PopControl(this, *c); interface_.PopControl(this, c);
control_.pop_back(); control_.pop_back();
} }
...@@ -2053,7 +2054,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2053,7 +2054,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return len; return len;
} }
void DoReturn() { void DoReturn(bool implicit) {
// TODO(clemensh): Optimize memory usage here (it will be mostly 0 or 1 // TODO(clemensh): Optimize memory usage here (it will be mostly 0 or 1
// returned values). // returned values).
int return_count = static_cast<int>(this->sig_->return_count()); int return_count = static_cast<int>(this->sig_->return_count());
...@@ -2064,7 +2065,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2064,7 +2065,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
values[i] = Pop(i, this->sig_->GetReturn(i)); values[i] = Pop(i, this->sig_->GetReturn(i));
} }
interface_.DoReturn(this, vec2vec(values)); interface_.DoReturn(this, vec2vec(values), implicit);
EndControl(); EndControl();
} }
...@@ -2176,8 +2177,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2176,8 +2177,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return TypeCheckMergeValues(c); return TypeCheckMergeValues(c);
} }
bool TypeCheckBreak(unsigned depth) { bool TypeCheckBreak(Control* c) {
Control* c = control_at(depth);
if (c->is_loop()) { if (c->is_loop()) {
// This is the inner loop block, which does not have a value. // This is the inner loop block, which does not have a value.
return true; return true;
...@@ -2217,6 +2217,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2217,6 +2217,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
virtual void onFirstError() { virtual void onFirstError() {
this->end_ = this->pc_; // Terminate decoding loop. this->end_ = this->pc_; // Terminate decoding loop.
TRACE(" !%s\n", this->error_msg_.c_str()); TRACE(" !%s\n", this->error_msg_.c_str());
interface_.OnFirstError(this);
} }
inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) { inline void BuildSimpleOperator(WasmOpcode opcode, FunctionSig* sig) {
......
...@@ -157,6 +157,8 @@ class WasmGraphBuildingInterface { ...@@ -157,6 +157,8 @@ class WasmGraphBuildingInterface {
builder_->PatchInStackCheckIfNeeded(); builder_->PatchInStackCheckIfNeeded();
} }
void OnFirstError(Decoder* decoder) {}
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->end_env = ssa_env_; block->end_env = ssa_env_;
...@@ -205,9 +207,9 @@ class WasmGraphBuildingInterface { ...@@ -205,9 +207,9 @@ class WasmGraphBuildingInterface {
SetEnv(c->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.false_env, block.end_env); Goto(decoder, block->false_env, block->end_env);
} }
} }
...@@ -240,7 +242,9 @@ class WasmGraphBuildingInterface { ...@@ -240,7 +242,9 @@ class WasmGraphBuildingInterface {
result->node = builder_->Float64Constant(value); result->node = builder_->Float64Constant(value);
} }
void DoReturn(Decoder* decoder, Vector<Value> values) { void Drop(Decoder* decoder, const Value& value) {}
void DoReturn(Decoder* decoder, Vector<Value> values, bool implicit) {
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) {
...@@ -293,8 +297,7 @@ class WasmGraphBuildingInterface { ...@@ -293,8 +297,7 @@ class WasmGraphBuildingInterface {
ssa_env_->control = merge; ssa_env_->control = merge;
} }
void BreakTo(Decoder* decoder, uint32_t depth) { void BreakTo(Decoder* decoder, Control* target) {
Control* target = decoder->control_at(depth);
if (target->is_loop()) { if (target->is_loop()) {
Goto(decoder, ssa_env_, target->end_env); Goto(decoder, ssa_env_, target->end_env);
} else { } else {
...@@ -302,13 +305,13 @@ class WasmGraphBuildingInterface { ...@@ -302,13 +305,13 @@ class WasmGraphBuildingInterface {
} }
} }
void BrIf(Decoder* decoder, const Value& cond, uint32_t depth) { void BrIf(Decoder* decoder, const Value& cond, Control* target) {
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.node, &tenv->control, &fenv->control); BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
ssa_env_ = tenv; ssa_env_ = tenv;
BreakTo(decoder, depth); BreakTo(decoder, target);
ssa_env_ = fenv; ssa_env_ = fenv;
} }
...@@ -317,7 +320,7 @@ class WasmGraphBuildingInterface { ...@@ -317,7 +320,7 @@ class WasmGraphBuildingInterface {
if (operand.table_count == 0) { if (operand.table_count == 0) {
// Only a default target. Do the equivalent of br. // Only a default target. Do the equivalent of br.
uint32_t target = BranchTableIterator<true>(decoder, operand).next(); uint32_t target = BranchTableIterator<true>(decoder, operand).next();
BreakTo(decoder, target); BreakTo(decoder, decoder->control_at(target));
return; return;
} }
...@@ -334,7 +337,7 @@ class WasmGraphBuildingInterface { ...@@ -334,7 +337,7 @@ class WasmGraphBuildingInterface {
ssa_env_ = Split(decoder, copy); ssa_env_ = Split(decoder, copy);
ssa_env_->control = (i == operand.table_count) ? BUILD(IfDefault, sw) ssa_env_->control = (i == operand.table_count) ? BUILD(IfDefault, sw)
: BUILD(IfValue, i, sw); : BUILD(IfValue, i, sw);
BreakTo(decoder, target); BreakTo(decoder, decoder->control_at(target));
} }
DCHECK(decoder->ok()); DCHECK(decoder->ok());
ssa_env_ = break_env; ssa_env_ = break_env;
......
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