| Index: src/asmjs/asm-wasm-builder.cc
|
| diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc
|
| index cac6fbd8b372c43cea8d43edec72199a2195ca42..f820e1c20f31c7984d3b4a99286163a7fe5845cd 100644
|
| --- a/src/asmjs/asm-wasm-builder.cc
|
| +++ b/src/asmjs/asm-wasm-builder.cc
|
| @@ -19,6 +19,10 @@
|
|
|
| #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 +46,9 @@ struct ForeignVariable {
|
|
|
| class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| public:
|
| - AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
|
| - AsmTyper* typer)
|
| + AsmWasmBuilderImpl(Isolate* isolate, Zone* zone,
|
| + AstValueFactory* ast_value_factory, Script* script,
|
| + FunctionLiteral* literal, AsmTyper* typer)
|
| : local_variables_(ZoneHashMap::kDefaultHashMapCapacity,
|
| ZoneAllocationPolicy(zone)),
|
| functions_(ZoneHashMap::kDefaultHashMapCapacity,
|
| @@ -56,12 +61,14 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| literal_(literal),
|
| isolate_(isolate),
|
| zone_(zone),
|
| + ast_value_factory_(ast_value_factory),
|
| + 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) {
|
| @@ -102,10 +109,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| return ret;
|
| }
|
|
|
| - void Build() {
|
| + bool Build() {
|
| InitializeInitFunction();
|
| - RECURSE(VisitFunctionLiteral(literal_));
|
| + if (!typer_->ValidateBeforeFunctionsPhase()) {
|
| + return false;
|
| + }
|
| + DCHECK(!HasStackOverflow());
|
| + VisitFunctionLiteral(literal_);
|
| + if (HasStackOverflow()) {
|
| + return false;
|
| + }
|
| + if (typer_failed_) {
|
| + return false;
|
| + }
|
| BuildForeignInitFunction();
|
| + return true;
|
| }
|
|
|
| void VisitVariableDeclaration(VariableDeclaration* decl) {}
|
| @@ -113,9 +131,46 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| void VisitFunctionDeclaration(FunctionDeclaration* decl) {
|
| DCHECK_EQ(kModuleScope, scope_);
|
| DCHECK_NULL(current_function_builder_);
|
| + FunctionLiteral* old_func = decl->fun();
|
| + i::Zone zone(isolate_->allocator(), ZONE_NAME);
|
| + if (decl->fun()->body() == nullptr) {
|
| + // TODO(bradnelson): Refactor parser so we don't need a
|
| + // SharedFunctionInfo to parse a single function,
|
| + // or squirrel away the SharedFunctionInfo to use later.
|
| + Handle<SharedFunctionInfo> shared =
|
| + isolate_->factory()->NewSharedFunctionInfoForLiteral(
|
| + decl->fun(), handle(script_, isolate_));
|
| + shared->set_is_toplevel(false);
|
| + i::ParseInfo info(&zone, handle(script_, isolate_));
|
| + 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_ast_value_factory(ast_value_factory_);
|
| + info.set_ast_value_factory_owned(false);
|
| + // Create fresh function scope to use to parse the function in.
|
| + DeclarationScope* 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 (!i::Compiler::ParseAndAnalyze(&info)) {
|
| + typer_failed_ = true;
|
| + return;
|
| + }
|
| + FunctionLiteral* func = info.literal();
|
| + DCHECK_NOT_NULL(func);
|
| + decl->set_fun(func);
|
| + }
|
| + if (!typer_->ValidateInnerFunction(decl)) {
|
| + typer_failed_ = true;
|
| + decl->set_fun(old_func);
|
| + decl->scope()->RemoveInnerScope(decl->scope()->inner_scope());
|
| + return;
|
| + }
|
| current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var());
|
| scope_ = kFuncScope;
|
| RECURSE(Visit(decl->fun()));
|
| + decl->set_fun(old_func);
|
| + decl->scope()->RemoveInnerScope(decl->scope()->inner_scope());
|
| scope_ = kModuleScope;
|
| current_function_builder_ = nullptr;
|
| local_variables_.Clear();
|
| @@ -129,6 +184,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| continue;
|
| }
|
| RECURSE(Visit(stmt));
|
| + if (typer_failed_) break;
|
| if (stmt->IsJump()) break;
|
| }
|
| }
|
| @@ -245,6 +301,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
|
|
| void VisitReturnStatement(ReturnStatement* stmt) {
|
| if (scope_ == kModuleScope) {
|
| + if (!typer_->ValidateAfterFunctionsPhase()) {
|
| + typer_failed_ = true;
|
| + return;
|
| + }
|
| scope_ = kExportScope;
|
| RECURSE(Visit(stmt->expression()));
|
| scope_ = kModuleScope;
|
| @@ -448,8 +508,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| UNREACHABLE();
|
| }
|
| }
|
| - RECURSE(VisitStatements(expr->body()));
|
| RECURSE(VisitDeclarations(scope->declarations()));
|
| + if (typer_failed_) return;
|
| + RECURSE(VisitStatements(expr->body()));
|
| }
|
|
|
| void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
|
| @@ -660,10 +721,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,
|
| @@ -675,38 +748,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(
|
| + static_cast<uint32_t>(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 {
|
| @@ -727,20 +799,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()) {
|
| @@ -901,7 +986,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());
|
| }
|
| @@ -910,14 +995,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;
|
| }
|
| @@ -1325,7 +1406,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_->AddAsmWasmOffset(expr->position());
|
| @@ -1348,7 +1429,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.
|
| @@ -1694,6 +1775,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| void VisitDeclarations(Declaration::List* decls) {
|
| for (Declaration* decl : *decls) {
|
| RECURSE(Visit(decl));
|
| + if (typer_failed_) {
|
| + return;
|
| + }
|
| }
|
| }
|
|
|
| @@ -1821,7 +1905,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| FunctionLiteral* literal_;
|
| Isolate* isolate_;
|
| Zone* zone_;
|
| + AstValueFactory* ast_value_factory_;
|
| + Script* script_;
|
| AsmTyper* typer_;
|
| + bool typer_failed_;
|
| ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
|
| ZoneVector<ForeignVariable> foreign_variables_;
|
| WasmFunctionBuilder* init_function_;
|
| @@ -1837,21 +1924,28 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
|
| };
|
|
|
| AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
|
| - FunctionLiteral* literal, AsmTyper* typer)
|
| - : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {}
|
| + AstValueFactory* ast_value_factory,
|
| + Script* script, FunctionLiteral* literal)
|
| + : isolate_(isolate),
|
| + zone_(zone),
|
| + ast_value_factory_(ast_value_factory),
|
| + 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.
|
| AsmWasmBuilder::Result AsmWasmBuilder::Run(
|
| i::Handle<i::FixedArray>* foreign_args) {
|
| - AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_);
|
| - impl.Build();
|
| + AsmWasmBuilderImpl impl(isolate_, zone_, ast_value_factory_, script_,
|
| + literal_, &typer_);
|
| + bool success = impl.Build();
|
| *foreign_args = impl.GetForeignArgs();
|
| ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_);
|
| impl.builder_->WriteTo(*module_buffer);
|
| ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_);
|
| impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer);
|
| - return {module_buffer, asm_offsets_buffer};
|
| + return {module_buffer, asm_offsets_buffer, success};
|
| }
|
|
|
| const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__";
|
|
|