Chromium Code Reviews| Index: src/asmjs/asm-wasm-builder.cc |
| diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc |
| index 60bdd9a5a8473311ae54c694fd1ec53783f33e63..c4e64352b914e5e927bb35696a53768abbac5d9d 100644 |
| --- a/src/asmjs/asm-wasm-builder.cc |
| +++ b/src/asmjs/asm-wasm-builder.cc |
| @@ -19,6 +19,9 @@ |
| #include "src/ast/ast.h" |
| #include "src/ast/scopes.h" |
| #include "src/codegen.h" |
| +#include "src/compiler.h" |
| +#include "src/isolate.h" |
| +#include "src/parsing/parse-info.h" |
| namespace v8 { |
| namespace internal { |
| @@ -42,8 +45,8 @@ struct ForeignVariable { |
| class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| public: |
| - AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
| - AsmTyper* typer) |
| + AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, Script* script, |
| + FunctionLiteral* literal, AsmTyper* typer) |
| : local_variables_(ZoneHashMap::kDefaultHashMapCapacity, |
| ZoneAllocationPolicy(zone)), |
| functions_(ZoneHashMap::kDefaultHashMapCapacity, |
| @@ -56,12 +59,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| literal_(literal), |
| isolate_(isolate), |
| zone_(zone), |
| + script_(script), |
| typer_(typer), |
| + typer_failed_(false), |
| breakable_blocks_(zone), |
| foreign_variables_(zone), |
| init_function_(nullptr), |
| foreign_init_function_(nullptr), |
| - next_table_index_(0), |
| function_tables_(ZoneHashMap::kDefaultHashMapCapacity, |
| ZoneAllocationPolicy(zone)), |
| imported_function_table_(this) { |
| @@ -108,10 +112,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| return ret; |
| } |
| - void Build() { |
| + bool Build() { |
| InitializeInitFunction(); |
| - RECURSE(VisitFunctionLiteral(literal_)); |
| + if (!typer_->ValidatePhase1of2()) { |
| + return false; |
| + } |
| + DCHECK(!HasStackOverflow()); |
| + VisitFunctionLiteral(literal_); |
| + if (HasStackOverflow()) { |
| + return false; |
| + } |
| + if (typer_failed_) { |
| + return false; |
| + } |
| BuildForeignInitFunction(); |
| + return true; |
| } |
| void VisitVariableDeclaration(VariableDeclaration* decl) {} |
| @@ -119,9 +134,40 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| DCHECK_EQ(kModuleScope, scope_); |
| DCHECK_NULL(current_function_builder_); |
| + bool had_body; |
| + i::Zone zone(isolate_->allocator()); |
| + if (decl->fun()->body() == nullptr) { |
| + Handle<SharedFunctionInfo> shared = |
|
titzer
2016/10/07 12:56:59
Do we really need a shared function info here? See
bradn
2016/11/25 09:19:36
A large number of places in the parser assume a Sh
|
| + i::Compiler::NewSharedFunctionInfoFromLiteral( |
| + isolate_, decl->fun(), handle(script_, isolate_)); |
| + shared->set_is_toplevel(false); |
| + i::ParseInfo info(&zone, handle(script_, isolate_)); |
| + info.set_shared_info(shared); |
| + info.set_language_mode(decl->fun()->scope()->language_mode()); |
| + info.set_lazy(true); |
| + info.set_allow_lazy_parsing(false); |
| + info.set_script_scope(decl->fun()->scope()); |
| + if (!i::Compiler::ParseAndAnalyze(&info)) { |
| + typer_failed_ = true; |
| + return; |
| + } |
| + FunctionLiteral* func = info.literal(); |
| + DCHECK_NOT_NULL(func); |
| + decl->fun()->set_body(func->body()); |
| + had_body = false; |
| + } else { |
| + had_body = true; |
| + } |
| + if (!typer_->ValidateInnerFunction(decl)) { |
| + typer_failed_ = true; |
| + return; |
| + } |
| current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); |
| scope_ = kFuncScope; |
| RECURSE(Visit(decl->fun())); |
| + if (!had_body) { |
| + decl->fun()->set_body(nullptr); |
| + } |
| scope_ = kModuleScope; |
| current_function_builder_ = nullptr; |
| local_variables_.Clear(); |
| @@ -135,6 +181,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| continue; |
| } |
| RECURSE(Visit(stmt)); |
| + if (typer_failed_) break; |
| if (stmt->IsJump()) break; |
| } |
| } |
| @@ -454,8 +501,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| UNREACHABLE(); |
| } |
| } |
| - RECURSE(VisitStatements(expr->body())); |
| - RECURSE(VisitDeclarations(scope->declarations())); |
| + if (scope_ == kFuncScope) { |
|
titzer
2016/10/07 12:56:59
Why do we need to do the declarations after for a
bradn
2016/11/25 09:19:36
No good reason.
Both should be declarations then s
|
| + RECURSE(VisitStatements(expr->body())); |
| + RECURSE(VisitDeclarations(scope->declarations())); |
| + } else { |
| + RECURSE(VisitDeclarations(scope->declarations())); |
| + RECURSE(VisitStatements(expr->body())); |
| + } |
| } |
| void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| @@ -637,6 +689,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
| void VisitObjectLiteral(ObjectLiteral* expr) { |
| + if (!typer_->ValidatePhase2of2()) { |
| + typer_failed_ = true; |
| + return; |
| + } |
| + |
| ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
| for (int i = 0; i < props->length(); ++i) { |
| ObjectLiteralProperty* prop = props->at(i); |
| @@ -669,10 +726,22 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| current_function_builder_ = nullptr; |
| } |
| - void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| - auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); |
| - DCHECK_NOT_NULL(func_tbl_type); |
| - auto* func_type = func_tbl_type->signature()->AsFunctionType(); |
| + struct FunctionTableIndices : public ZoneObject { |
| + uint32_t start_index; |
| + uint32_t signature_index; |
| + }; |
| + |
| + FunctionTableIndices* LookupOrAddFunctionTable(VariableProxy* table, |
| + Property* p) { |
| + FunctionTableIndices* indices = LookupFunctionTable(table->var()); |
| + if (indices != nullptr) { |
| + // Already setup. |
| + return indices; |
| + } |
| + indices = new (zone()) FunctionTableIndices(); |
| + auto* func_type = typer_->TypeOf(p)->AsFunctionType(); |
| + auto* func_table_type = typer_->TypeOf(p->obj()->AsVariableProxy()->var()) |
| + ->AsFunctionTableType(); |
| const auto& arguments = func_type->Arguments(); |
| LocalType return_type = TypeFrom(func_type->ReturnType()); |
| FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| @@ -684,38 +753,37 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| sig.AddParam(TypeFrom(arg)); |
| } |
| uint32_t signature_index = builder_->AddSignature(sig.Build()); |
| - InsertFunctionTable(table->var(), next_table_index_, signature_index); |
| - next_table_index_ += funcs->values()->length(); |
| - for (int i = 0; i < funcs->values()->length(); ++i) { |
| - VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |
| - DCHECK_NOT_NULL(func); |
| - builder_->AddIndirectFunction( |
| - LookupOrInsertFunction(func->var())->func_index()); |
| - } |
| - } |
| - |
| - struct FunctionTableIndices : public ZoneObject { |
| - uint32_t start_index; |
| - uint32_t signature_index; |
| - }; |
| - |
| - void InsertFunctionTable(Variable* v, uint32_t start_index, |
| - uint32_t signature_index) { |
| - FunctionTableIndices* container = new (zone()) FunctionTableIndices(); |
| - container->start_index = start_index; |
| - container->signature_index = signature_index; |
| + indices->start_index = |
| + builder_->AllocateIndirectFunctions(func_table_type->length()); |
| + indices->signature_index = signature_index; |
| ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
| - v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); |
| - entry->value = container; |
| + table->var(), ComputePointerHash(table->var()), |
| + ZoneAllocationPolicy(zone())); |
| + entry->value = indices; |
| + return indices; |
| } |
| FunctionTableIndices* LookupFunctionTable(Variable* v) { |
| ZoneHashMap::Entry* entry = |
| function_tables_.Lookup(v, ComputePointerHash(v)); |
| - DCHECK_NOT_NULL(entry); |
| + if (entry == nullptr) { |
| + return nullptr; |
| + } |
| return reinterpret_cast<FunctionTableIndices*>(entry->value); |
| } |
| + void PopulateFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| + FunctionTableIndices* indices = LookupFunctionTable(table->var()); |
| + DCHECK_NOT_NULL(indices); |
| + for (int i = 0; i < funcs->values()->length(); ++i) { |
| + VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |
| + DCHECK_NOT_NULL(func); |
| + builder_->SetIndirectFunction( |
| + indices->start_index + i, |
| + LookupOrInsertFunction(func->var())->func_index()); |
| + } |
| + } |
| + |
| class ImportedFunctionTable { |
| private: |
| class ImportedFunctionIndices : public ZoneObject { |
| @@ -736,20 +804,33 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| ZoneAllocationPolicy(builder->zone())), |
| builder_(builder) {} |
| - void AddImport(Variable* v, const char* name, int name_length) { |
| - ImportedFunctionIndices* indices = new (builder_->zone()) |
| - ImportedFunctionIndices(name, name_length, builder_->zone()); |
| + ImportedFunctionIndices* LookupOrInsertImport(Variable* v) { |
| auto* entry = table_.LookupOrInsert( |
| v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |
| - entry->value = indices; |
| + ImportedFunctionIndices* indices; |
| + if (entry->value == nullptr) { |
| + indices = new (builder_->zone()) |
| + ImportedFunctionIndices(nullptr, 0, builder_->zone()); |
| + entry->value = indices; |
| + } else { |
| + indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value); |
| + } |
| + return indices; |
| + } |
| + |
| + void SetImportName(Variable* v, const char* name, int name_length) { |
| + auto* indices = LookupOrInsertImport(v); |
| + indices->name_ = name; |
| + indices->name_length_ = name_length; |
| + for (auto i : indices->signature_to_index_) { |
| + builder_->builder_->SetImportName(i.second, indices->name_, |
| + indices->name_length_); |
| + } |
| } |
| // Get a function's index (or allocate if new). |
| - uint32_t LookupOrInsertImport(Variable* v, FunctionSig* sig) { |
| - ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); |
| - DCHECK_NOT_NULL(entry); |
| - ImportedFunctionIndices* indices = |
| - reinterpret_cast<ImportedFunctionIndices*>(entry->value); |
| + uint32_t LookupOrInsertImportUse(Variable* v, FunctionSig* sig) { |
| + auto* indices = LookupOrInsertImport(v); |
| WasmModuleBuilder::SignatureMap::iterator pos = |
| indices->signature_to_index_.find(sig); |
| if (pos != indices->signature_to_index_.end()) { |
| @@ -910,7 +991,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
| const AstRawString* name = |
| prop->key()->AsLiteral()->AsRawPropertyName(); |
| - imported_function_table_.AddImport( |
| + imported_function_table_.SetImportName( |
| target->var(), reinterpret_cast<const char*>(name->raw_data()), |
| name->length()); |
| } |
| @@ -919,14 +1000,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| return; |
| } |
| ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| - if (funcs != nullptr && |
| - typer_->TypeOf(funcs) |
| - ->AsFunctionTableType() |
| - ->signature() |
| - ->AsFunctionType()) { |
| + if (funcs != nullptr) { |
| VariableProxy* target = expr->target()->AsVariableProxy(); |
| DCHECK_NOT_NULL(target); |
| - AddFunctionTable(target, funcs); |
| + PopulateFunctionTable(target, funcs); |
| // Only add to the function table. No init needed. |
| return; |
| } |
| @@ -1361,7 +1438,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| for (int i = 0; i < args->length(); ++i) { |
| sig.AddParam(TypeOf(args->at(i))); |
| } |
| - uint32_t index = imported_function_table_.LookupOrInsertImport( |
| + uint32_t index = imported_function_table_.LookupOrInsertImportUse( |
| vp->var(), sig.Build()); |
| VisitCallArgs(expr); |
| current_function_builder_->Emit(kExprCallFunction); |
| @@ -1382,7 +1459,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| DCHECK_NOT_NULL(p); |
| VariableProxy* var = p->obj()->AsVariableProxy(); |
| DCHECK_NOT_NULL(var); |
| - FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
| + FunctionTableIndices* indices = LookupOrAddFunctionTable(var, p); |
| Visit(p->key()); // TODO(titzer): should use RECURSE() |
| // We have to use a temporary for the correct order of evaluation. |
| @@ -1727,6 +1804,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| for (int i = 0; i < decls->length(); ++i) { |
| Declaration* decl = decls->at(i); |
| RECURSE(Visit(decl)); |
| + if (typer_failed_) { |
| + return; |
| + } |
| } |
| } |
| @@ -1854,7 +1934,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| FunctionLiteral* literal_; |
| Isolate* isolate_; |
| Zone* zone_; |
| + Script* script_; |
| AsmTyper* typer_; |
| + bool typer_failed_; |
| ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| ZoneVector<ForeignVariable> foreign_variables_; |
| WasmFunctionBuilder* init_function_; |
| @@ -1869,15 +1951,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| }; |
| -AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
| - FunctionLiteral* literal, AsmTyper* typer) |
| - : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} |
| +AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, Script* script, |
| + FunctionLiteral* literal) |
| + : isolate_(isolate), |
| + zone_(zone), |
| + script_(script), |
| + literal_(literal), |
| + typer_(isolate, zone, script, literal) {} |
| // 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. |
| ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { |
| - AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); |
| - impl.Build(); |
| + AsmWasmBuilderImpl impl(isolate_, zone_, script_, literal_, &typer_); |
| + if (!impl.Build()) { |
| + return nullptr; |
| + } |
| *foreign_args = impl.GetForeignArgs(); |
| ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); |
| impl.builder_->WriteTo(*buffer); |