| Index: src/wasm/asm-wasm-builder.cc
|
| diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc
|
| index 359035994dd4a01808e5fba5074dc7084779020a..38077afe791339b5cc6b32e70f6b6601bcbdb332 100644
|
| --- a/src/wasm/asm-wasm-builder.cc
|
| +++ b/src/wasm/asm-wasm-builder.cc
|
| @@ -11,6 +11,7 @@
|
| #include <math.h>
|
|
|
| #include "src/wasm/asm-wasm-builder.h"
|
| +#include "src/wasm/switch-logic.h"
|
| #include "src/wasm/wasm-macro-gen.h"
|
| #include "src/wasm/wasm-opcodes.h"
|
|
|
| @@ -99,6 +100,11 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
| void VisitStatements(ZoneList<Statement*>* stmts) {
|
| for (int i = 0; i < stmts->length(); ++i) {
|
| Statement* stmt = stmts->at(i);
|
| + ExpressionStatement* e = stmt->AsExpressionStatement();
|
| + if (e != nullptr && e->expression()->IsUndefinedLiteral()) {
|
| + block_size_--;
|
| + continue;
|
| + }
|
| RECURSE(Visit(stmt));
|
| if (stmt->IsJump()) break;
|
| }
|
| @@ -235,52 +241,108 @@ class AsmWasmBuilderImpl : public AstVisitor {
|
|
|
| void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); }
|
|
|
| - void SetLocalTo(uint16_t index, int value) {
|
| - current_function_builder_->Emit(kExprSetLocal);
|
| - AddLeb128(index, true);
|
| - // TODO(bradnelson): variable size
|
| + void GenerateCaseComparisonCode(int value, WasmOpcode op,
|
| + VariableProxy* tag) {
|
| + current_function_builder_->Emit(kExprIfElse);
|
| + current_function_builder_->Emit(op);
|
| + VisitVariableProxy(tag);
|
| byte code[] = {WASM_I32V(value)};
|
| current_function_builder_->EmitCode(code, sizeof(code));
|
| - block_size_++;
|
| }
|
|
|
| - void CompileCase(CaseClause* clause, uint16_t fall_through,
|
| - VariableProxy* tag) {
|
| - Literal* label = clause->label()->AsLiteral();
|
| - DCHECK_NOT_NULL(label);
|
| - block_size_++;
|
| - current_function_builder_->Emit(kExprIf);
|
| - current_function_builder_->Emit(kExprI32Ior);
|
| - current_function_builder_->Emit(kExprI32Eq);
|
| - VisitVariableProxy(tag);
|
| - VisitLiteral(label);
|
| - current_function_builder_->Emit(kExprGetLocal);
|
| - AddLeb128(fall_through, true);
|
| - BlockVisitor visitor(this, nullptr, kExprBlock, false, 0);
|
| - SetLocalTo(fall_through, 1);
|
| - ZoneList<Statement*>* stmts = clause->statements();
|
| - block_size_ += stmts->length();
|
| - RECURSE(VisitStatements(stmts));
|
| + void HandleCase(CaseNode* node,
|
| + const ZoneMap<int, unsigned int>& case_to_block,
|
| + VariableProxy* tag, int default_block) {
|
| + if (node->left_ != nullptr) {
|
| + GenerateCaseComparisonCode(node->begin_, kExprI32LtS, tag);
|
| + HandleCase(node->left_, case_to_block, tag, default_block);
|
| + }
|
| + if (node->right_ != nullptr) {
|
| + GenerateCaseComparisonCode(node->end_, kExprI32GtS, tag);
|
| + HandleCase(node->right_, case_to_block, tag, default_block);
|
| + }
|
| + if (node->begin_ == node->end_) {
|
| + current_function_builder_->Emit(kExprIf);
|
| + current_function_builder_->Emit(kExprI32Eq);
|
| + VisitVariableProxy(tag);
|
| + byte code[] = {WASM_I32V(node->begin_)};
|
| + current_function_builder_->EmitCode(code, sizeof(code));
|
| + DCHECK(case_to_block.find(node->begin_) != case_to_block.end());
|
| + current_function_builder_->EmitWithVarInt(kExprBr,
|
| + case_to_block.at(node->begin_));
|
| + current_function_builder_->Emit(kExprNop);
|
| + } else {
|
| + current_function_builder_->Emit(kExprBrTable);
|
| + byte count[] = {U32V_1(node->end_ - node->begin_ + 1)};
|
| + current_function_builder_->EmitCode(count, sizeof(count));
|
| + for (int v = node->begin_; v <= node->end_; v++) {
|
| + if (case_to_block.find(v) != case_to_block.end()) {
|
| + byte break_code[] = {BR_TARGET(case_to_block.at(v))};
|
| + current_function_builder_->EmitCode(break_code, sizeof(break_code));
|
| + } else {
|
| + byte break_code[] = {BR_TARGET(default_block)};
|
| + current_function_builder_->EmitCode(break_code, sizeof(break_code));
|
| + }
|
| + }
|
| + byte break_code[] = {BR_TARGET(default_block)};
|
| + current_function_builder_->EmitCode(break_code, sizeof(break_code));
|
| + current_function_builder_->Emit(kExprI32Sub);
|
| + VisitVariableProxy(tag);
|
| + byte code[] = {WASM_I32V(node->begin_)};
|
| + current_function_builder_->EmitCode(code, sizeof(code));
|
| + }
|
| }
|
|
|
| void VisitSwitchStatement(SwitchStatement* stmt) {
|
| VariableProxy* tag = stmt->tag()->AsVariableProxy();
|
| DCHECK_NOT_NULL(tag);
|
| BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
|
| - 0);
|
| - uint16_t fall_through = current_function_builder_->AddLocal(kAstI32);
|
| - SetLocalTo(fall_through, 0);
|
| -
|
| + 1);
|
| ZoneList<CaseClause*>* clauses = stmt->cases();
|
| - for (int i = 0; i < clauses->length(); ++i) {
|
| + int case_count = clauses->length();
|
| + DCHECK(case_count > 0);
|
| + ZoneVector<BlockVisitor*> blocks(zone_);
|
| + ZoneVector<int32_t> cases(zone_);
|
| + ZoneMap<int, unsigned int> case_to_block(zone_);
|
| + int default_block = 0;
|
| + for (int i = case_count - 1; i >= 0; i--) {
|
| CaseClause* clause = clauses->at(i);
|
| + blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false,
|
| + clause->statements()->length() + 1));
|
| if (!clause->is_default()) {
|
| - CompileCase(clause, fall_through, tag);
|
| + Literal* label = clause->label()->AsLiteral();
|
| + Handle<Object> value = label->value();
|
| + DCHECK(value->IsNumber() &&
|
| + label->bounds().upper->Is(cache_.kAsmSigned));
|
| + int32_t label_value;
|
| + if (!value->ToInt32(&label_value)) {
|
| + UNREACHABLE();
|
| + }
|
| + case_to_block[label_value] = i;
|
| + cases.push_back(label_value);
|
| } else {
|
| - ZoneList<Statement*>* stmts = clause->statements();
|
| - block_size_ += stmts->length();
|
| - RECURSE(VisitStatements(stmts));
|
| + default_block = i;
|
| + }
|
| + }
|
| + if (case_count > 1) {
|
| + BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false, 1);
|
| + CaseNode* root = OrderCases(&cases, zone_);
|
| + HandleCase(root, case_to_block, tag, default_block);
|
| + if (root->left_ != nullptr || root->right_ != nullptr ||
|
| + root->begin_ == root->end_) {
|
| + block_size_++;
|
| + current_function_builder_->EmitWithVarInt(kExprBr, default_block);
|
| + current_function_builder_->Emit(kExprNop);
|
| }
|
| + } else {
|
| + block_size_--;
|
| + }
|
| + for (int i = 0; i < case_count; i++) {
|
| + CaseClause* clause = clauses->at(i);
|
| + RECURSE(VisitStatements(clause->statements()));
|
| + BlockVisitor* v = blocks.at(case_count - i - 1);
|
| + blocks.pop_back();
|
| + delete (v);
|
| }
|
| }
|
|
|
|
|