Index: src/asmjs/asm-wasm-builder.cc |
diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc |
index 5e89ed5fdb20db4eb109aaafa3f2d3eed9119273..f7f7bfcad042a8a77bbf850412f1f18ae9941a57 100644 |
--- a/src/asmjs/asm-wasm-builder.cc |
+++ b/src/asmjs/asm-wasm-builder.cc |
@@ -36,6 +36,8 @@ namespace wasm { |
if (HasStackOverflow()) return; \ |
} while (false) |
+namespace { |
+ |
enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
enum ValueFate { kDrop, kLeaveOnStack }; |
@@ -45,6 +47,10 @@ struct ForeignVariable { |
ValueType type; |
}; |
+enum TargetType : uint8_t { NoTarget, BreakTarget, ContinueTarget }; |
+ |
+} // namespace |
+ |
class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
public: |
AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, CompilationInfo* info, |
@@ -231,7 +237,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
} |
} |
if (scope_ == kFuncScope) { |
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
+ BreakTarget); |
RECURSE(VisitStatements(stmt->statements())); |
} else { |
RECURSE(VisitStatements(stmt->statements())); |
@@ -244,10 +251,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
public: |
BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
- WasmOpcode opcode) |
+ WasmOpcode opcode, TargetType target_type = NoTarget) |
: builder_(builder) { |
- builder_->breakable_blocks_.push_back( |
- std::make_pair(stmt, opcode == kExprLoop)); |
+ builder_->breakable_blocks_.emplace_back(stmt, target_type); |
// block and loops have a type immediate. |
builder_->current_function_builder_->EmitWithU8(opcode, kLocalVoid); |
} |
@@ -295,9 +301,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
void VisitIfStatement(IfStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
RECURSE(Visit(stmt->condition())); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
- // WASM ifs come with implement blocks for both arms. |
- breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
+ // Wasm ifs come with implicit blocks for both arms. |
+ BlockVisitor block(this, nullptr, kExprIf); |
if (stmt->HasThenStatement()) { |
RECURSE(Visit(stmt->then_statement())); |
} |
@@ -305,18 +310,15 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
current_function_builder_->Emit(kExprElse); |
RECURSE(Visit(stmt->else_statement())); |
} |
- current_function_builder_->Emit(kExprEnd); |
- breakable_blocks_.pop_back(); |
} |
- void DoBreakOrContinue(BreakableStatement* target, bool is_continue) { |
+ void DoBreakOrContinue(BreakableStatement* target, TargetType type) { |
DCHECK_EQ(kFuncScope, scope_); |
for (int i = static_cast<int>(breakable_blocks_.size()) - 1; i >= 0; --i) { |
auto elem = breakable_blocks_.at(i); |
- if (elem.first == target && elem.second == is_continue) { |
+ if (elem.first == target && elem.second == type) { |
int block_distance = static_cast<int>(breakable_blocks_.size() - i - 1); |
- current_function_builder_->Emit(kExprBr); |
- current_function_builder_->EmitVarInt(block_distance); |
+ current_function_builder_->EmitWithVarInt(kExprBr, block_distance); |
return; |
} |
} |
@@ -324,11 +326,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
} |
void VisitContinueStatement(ContinueStatement* stmt) { |
- DoBreakOrContinue(stmt->target(), true); |
+ DoBreakOrContinue(stmt->target(), ContinueTarget); |
} |
void VisitBreakStatement(BreakStatement* stmt) { |
- DoBreakOrContinue(stmt->target(), false); |
+ DoBreakOrContinue(stmt->target(), BreakTarget); |
} |
void VisitReturnStatement(ReturnStatement* stmt) { |
@@ -366,7 +368,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
current_function_builder_->Emit(kExprI32LtS); |
current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
if_depth++; |
- breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
+ breakable_blocks_.emplace_back(nullptr, NoTarget); |
HandleCase(node->left, case_to_block, tag, default_block, if_depth); |
current_function_builder_->Emit(kExprElse); |
} |
@@ -376,7 +378,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
current_function_builder_->Emit(kExprI32GtS); |
current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
if_depth++; |
- breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
+ breakable_blocks_.emplace_back(nullptr, NoTarget); |
HandleCase(node->right, case_to_block, tag, default_block, if_depth); |
current_function_builder_->Emit(kExprElse); |
} |
@@ -430,7 +432,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
if (case_count == 0) { |
return; |
} |
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
+ BreakTarget); |
ZoneVector<BlockVisitor*> blocks(zone_); |
ZoneVector<int32_t> cases(zone_); |
ZoneMap<int, unsigned int> case_to_block(zone_); |
@@ -476,26 +479,28 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
void VisitDoWhileStatement(DoWhileStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock, |
+ BreakTarget); |
BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
- RECURSE(Visit(stmt->body())); |
+ { |
+ BlockVisitor inner_block(this, stmt->AsBreakableStatement(), kExprBlock, |
+ ContinueTarget); |
+ RECURSE(Visit(stmt->body())); |
+ } |
RECURSE(Visit(stmt->cond())); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
- current_function_builder_->EmitWithU8(kExprBr, 1); |
- current_function_builder_->Emit(kExprEnd); |
+ current_function_builder_->EmitWithU8(kExprBrIf, 0); |
} |
void VisitWhileStatement(WhileStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
- BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock, |
+ BreakTarget); |
+ BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop, |
+ ContinueTarget); |
RECURSE(Visit(stmt->cond())); |
- breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ BlockVisitor if_block(this, nullptr, kExprIf); |
RECURSE(Visit(stmt->body())); |
current_function_builder_->EmitWithU8(kExprBr, 1); |
- current_function_builder_->Emit(kExprEnd); |
- breakable_blocks_.pop_back(); |
} |
void VisitForStatement(ForStatement* stmt) { |
@@ -503,8 +508,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
if (stmt->init() != nullptr) { |
RECURSE(Visit(stmt->init())); |
} |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
- BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock, |
+ BreakTarget); |
+ BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop, |
+ ContinueTarget); |
if (stmt->cond() != nullptr) { |
RECURSE(Visit(stmt->cond())); |
current_function_builder_->Emit(kExprI32Eqz); |
@@ -562,8 +569,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
void VisitConditional(Conditional* expr) { |
DCHECK_EQ(kFuncScope, scope_); |
RECURSE(Visit(expr->condition())); |
- // WASM ifs come with implicit blocks for both arms. |
- breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
+ // Wasm ifs come with implicit blocks for both arms. |
+ breakable_blocks_.emplace_back(nullptr, NoTarget); |
ValueTypeCode type; |
switch (TypeOf(expr)) { |
case kWasmI32: |
@@ -1969,7 +1976,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
AsmTyper* typer_; |
bool typer_failed_; |
bool typer_finished_; |
- ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
+ ZoneVector<std::pair<BreakableStatement*, TargetType>> breakable_blocks_; |
ZoneVector<ForeignVariable> foreign_variables_; |
WasmFunctionBuilder* init_function_; |
WasmFunctionBuilder* foreign_init_function_; |