diff options
Diffstat (limited to 'deps/v8/src/asmjs/asm-wasm-builder.cc')
-rw-r--r-- | deps/v8/src/asmjs/asm-wasm-builder.cc | 166 |
1 files changed, 87 insertions, 79 deletions
diff --git a/deps/v8/src/asmjs/asm-wasm-builder.cc b/deps/v8/src/asmjs/asm-wasm-builder.cc index 907e80fe4b..891cba3ef9 100644 --- a/deps/v8/src/asmjs/asm-wasm-builder.cc +++ b/deps/v8/src/asmjs/asm-wasm-builder.cc @@ -22,7 +22,9 @@ #include "src/codegen.h" #include "src/compilation-info.h" #include "src/compiler.h" +#include "src/counters.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/parsing/parse-info.h" namespace v8 { @@ -36,6 +38,8 @@ namespace wasm { if (HasStackOverflow()) return; \ } while (false) +namespace { + enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; enum ValueFate { kDrop, kLeaveOnStack }; @@ -45,6 +49,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, @@ -99,7 +107,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos)); ForeignVariable* fv = &foreign_variables_[pos]; uint32_t index = LookupOrInsertGlobal(fv->var, fv->type); - foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index); + foreign_init_function_->EmitWithVarUint(kExprSetGlobal, index); } foreign_init_function_->Emit(kExprEnd); } @@ -142,31 +150,36 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { DCHECK_EQ(kModuleScope, scope_); DCHECK_NULL(current_function_builder_); FunctionLiteral* old_func = decl->fun(); - Zone zone(isolate_->allocator(), ZONE_NAME); DeclarationScope* new_func_scope = nullptr; + std::unique_ptr<ParseInfo> info; if (decl->fun()->body() == nullptr) { // TODO(titzer/bradnelson): Reuse SharedFunctionInfos used here when // compiling the wasm module. Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfo(decl->fun(), script_, info_); shared->set_is_toplevel(false); - ParseInfo info(&zone, script_); - info.set_shared_info(shared); - info.set_toplevel(false); - info.set_language_mode(decl->fun()->scope()->language_mode()); - info.set_allow_lazy_parsing(false); - info.set_function_literal_id(shared->function_literal_id()); - info.set_ast_value_factory(ast_value_factory_); - info.set_ast_value_factory_owned(false); + info.reset(new ParseInfo(script_)); + info->set_shared_info(shared); + info->set_toplevel(false); + info->set_language_mode(decl->fun()->scope()->language_mode()); + info->set_allow_lazy_parsing(false); + info->set_function_literal_id(shared->function_literal_id()); + info->set_ast_value_factory(ast_value_factory_); + info->set_ast_value_factory_owned(false); // Create fresh function scope to use to parse the function in. - new_func_scope = new (info.zone()) DeclarationScope( - info.zone(), decl->fun()->scope()->outer_scope(), FUNCTION_SCOPE); - info.set_asm_function_scope(new_func_scope); - if (!Compiler::ParseAndAnalyze(&info)) { + new_func_scope = new (info->zone()) DeclarationScope( + info->zone(), decl->fun()->scope()->outer_scope(), FUNCTION_SCOPE); + info->set_asm_function_scope(new_func_scope); + if (!Compiler::ParseAndAnalyze(info.get())) { + decl->fun()->scope()->outer_scope()->RemoveInnerScope(new_func_scope); + if (isolate_->has_pending_exception()) { + isolate_->clear_pending_exception(); + } + typer_->TriggerParsingError(); typer_failed_ = true; return; } - FunctionLiteral* func = info.literal(); + FunctionLiteral* func = info->literal(); DCHECK_NOT_NULL(func); decl->set_fun(func); } @@ -226,7 +239,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())); @@ -239,10 +253,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); } @@ -290,9 +303,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())); } @@ -300,18 +312,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_->EmitWithVarUint(kExprBr, block_distance); return; } } @@ -319,11 +328,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) { @@ -361,7 +370,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); } @@ -371,7 +380,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); } @@ -382,8 +391,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); DCHECK(case_to_block.find(node->begin) != case_to_block.end()); current_function_builder_->Emit(kExprBr); - current_function_builder_->EmitVarInt(1 + if_depth + - case_to_block[node->begin]); + current_function_builder_->EmitVarUint(1 + if_depth + + case_to_block[node->begin]); current_function_builder_->Emit(kExprEnd); } else { if (node->begin != 0) { @@ -394,21 +403,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { VisitVariableProxy(tag); } current_function_builder_->Emit(kExprBrTable); - current_function_builder_->EmitVarInt(node->end - node->begin + 1); + current_function_builder_->EmitVarUint(node->end - node->begin + 1); for (int v = node->begin; v <= node->end; ++v) { if (case_to_block.find(v) != case_to_block.end()) { uint32_t target = if_depth + case_to_block[v]; - current_function_builder_->EmitVarInt(target); + current_function_builder_->EmitVarUint(target); } else { uint32_t target = if_depth + default_block; - current_function_builder_->EmitVarInt(target); + current_function_builder_->EmitVarUint(target); } if (v == kMaxInt) { break; } } uint32_t target = if_depth + default_block; - current_function_builder_->EmitVarInt(target); + current_function_builder_->EmitVarUint(target); } while (if_depth-- != prev_if_depth) { @@ -425,7 +434,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_); @@ -455,7 +465,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { if (root->left != nullptr || root->right != nullptr || root->begin == root->end) { current_function_builder_->Emit(kExprBr); - current_function_builder_->EmitVarInt(default_block); + current_function_builder_->EmitVarUint(default_block); } } for (int i = 0; i < case_count; ++i) { @@ -471,26 +481,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) { @@ -498,8 +510,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); @@ -557,8 +571,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: @@ -645,7 +659,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { ValueType var_type = TypeOf(expr); DCHECK_NE(kWasmStmt, var_type); if (var->IsContextSlot()) { - current_function_builder_->EmitWithVarInt( + current_function_builder_->EmitWithVarUint( kExprGetGlobal, LookupOrInsertGlobal(var, var_type)); } else { current_function_builder_->EmitGetLocal( @@ -671,35 +685,26 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { if (type->IsA(AsmType::Signed())) { int32_t i = 0; - if (!value->ToInt32(&i)) { - UNREACHABLE(); - } - byte code[] = {WASM_I32V(i)}; - current_function_builder_->EmitCode(code, sizeof(code)); + CHECK(value->ToInt32(&i)); + current_function_builder_->EmitI32Const(i); } else if (type->IsA(AsmType::Unsigned()) || type->IsA(AsmType::FixNum())) { uint32_t u = 0; - if (!value->ToUint32(&u)) { - UNREACHABLE(); - } - int32_t i = static_cast<int32_t>(u); - byte code[] = {WASM_I32V(i)}; - current_function_builder_->EmitCode(code, sizeof(code)); + CHECK(value->ToUint32(&u)); + current_function_builder_->EmitI32Const(bit_cast<int32_t>(u)); } else if (type->IsA(AsmType::Int())) { // The parser can collapse !0, !1 etc to true / false. // Allow these as int literals. if (expr->raw_value()->IsTrue()) { - byte code[] = {WASM_I32V(1)}; + byte code[] = {WASM_ONE}; current_function_builder_->EmitCode(code, sizeof(code)); } else if (expr->raw_value()->IsFalse()) { - byte code[] = {WASM_I32V(0)}; + byte code[] = {WASM_ZERO}; current_function_builder_->EmitCode(code, sizeof(code)); } else if (expr->raw_value()->IsNumber()) { // This can happen when -x becomes x * -1 (due to the parser). int32_t i = 0; - if (!value->ToInt32(&i) || i != -1) { - UNREACHABLE(); - } - byte code[] = {WASM_I32V(i)}; + CHECK(value->ToInt32(&i) && i == -1); + byte code[] = {WASM_I32V_1(-1)}; current_function_builder_->EmitCode(code, sizeof(code)); } else { UNREACHABLE(); @@ -949,9 +954,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { DCHECK_NE(kWasmStmt, var_type); if (var->IsContextSlot()) { uint32_t index = LookupOrInsertGlobal(var, var_type); - current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); + current_function_builder_->EmitWithVarUint(kExprSetGlobal, index); if (fate == kLeaveOnStack) { - current_function_builder_->EmitWithVarInt(kExprGetGlobal, index); + current_function_builder_->EmitWithVarUint(kExprGetGlobal, index); } } else { if (fate == kDrop) { @@ -1461,7 +1466,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { int parent_pos = returns_value ? parent_binop->position() : pos; current_function_builder_->AddAsmWasmOffset(pos, parent_pos); current_function_builder_->Emit(kExprCallFunction); - current_function_builder_->EmitVarInt(index); + current_function_builder_->EmitVarUint(index); } else { WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); VisitCallArgs(expr); @@ -1495,8 +1500,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { current_function_builder_->AddAsmWasmOffset(expr->position(), expr->position()); current_function_builder_->Emit(kExprCallIndirect); - current_function_builder_->EmitVarInt(indices->signature_index); - current_function_builder_->EmitVarInt(0); // table index + current_function_builder_->EmitVarUint(indices->signature_index); + current_function_builder_->EmitVarUint(0); // table index returns_value = builder_->GetSignature(indices->signature_index)->return_count() > 0; @@ -1964,7 +1969,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_; @@ -1988,6 +1993,9 @@ AsmWasmBuilder::AsmWasmBuilder(CompilationInfo* info) // TODO(aseemgarg): probably should take zone (to write wasm to) as input so // that zone in constructor may be thrown away once wasm module is written. AsmWasmBuilder::Result AsmWasmBuilder::Run(Handle<FixedArray>* foreign_args) { + HistogramTimerScope asm_wasm_time_scope( + info_->isolate()->counters()->asm_wasm_translation_time()); + Zone* zone = info_->zone(); AsmWasmBuilderImpl impl(info_->isolate(), zone, info_, info_->parse_info()->ast_value_factory(), |