Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Unified Diff: src/wasm/asm-wasm-builder.cc

Issue 1838973002: optimized switch implementation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « BUILD.gn ('k') | src/wasm/switch-logic.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/wasm/asm-wasm-builder.cc
diff --git a/src/wasm/asm-wasm-builder.cc b/src/wasm/asm-wasm-builder.cc
index d16d3a8bdd308e6aef95cb5c99cece7e34b73132..f7b7998e54c77636bab9cd6c049d4ba8e2fd850c 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,53 +241,124 @@ 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);
+ std::vector<uint8_t> count =
+ UnsignedLEB128From(node->end - node->begin + 1);
+ current_function_builder_->EmitCode(&count[0],
+ static_cast<uint32_t>(count.size()));
+ 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));
+ }
+ if (v == kMaxInt) {
+ break;
+ }
+ }
+ byte break_code[] = {BR_TARGET(default_block)};
+ current_function_builder_->EmitCode(break_code, sizeof(break_code));
+ // TODO(aseemgarg): remove the if once sub 0 is fixed
+ if (node->begin != 0) {
+ current_function_builder_->Emit(kExprI32Sub);
+ VisitVariableProxy(tag);
+ byte code[] = {WASM_I32V(node->begin)};
+ current_function_builder_->EmitCode(code, sizeof(code));
+ } else {
+ VisitVariableProxy(tag);
+ }
+ }
}
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);
-
ZoneList<CaseClause*>* clauses = stmt->cases();
- for (int i = 0; i < clauses->length(); ++i) {
+ int case_count = clauses->length();
+ if (case_count == 0) {
+ block_size_--;
+ return;
+ }
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
+ 1);
+ ZoneVector<BlockVisitor*> blocks(zone_);
+ ZoneVector<int32_t> cases(zone_);
+ ZoneMap<int, unsigned int> case_to_block(zone_);
+ bool has_default = false;
+ 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));
+ DCHECK_EQ(i, case_count - 1);
+ has_default = true;
}
}
+ if (!has_default || case_count > 1) {
+ int default_block = has_default ? case_count - 1 : case_count;
+ 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_ = clauses->at(0)->statements()->length();
+ }
+ 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;
+ }
}
void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
« no previous file with comments | « BUILD.gn ('k') | src/wasm/switch-logic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698