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

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

Issue 2398023002: [wasm] asm.js - Parse and convert asm.js to wasm a function at a time. (Closed)
Patch Set: fix Created 4 years, 1 month 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 | « src/asmjs/asm-wasm-builder.h ('k') | src/ast/scopes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..bb9f14dea33b7e12950287d17482a1485bbf71c2 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) {
@@ -92,8 +99,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
}
- i::Handle<i::FixedArray> GetForeignArgs() {
- i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray(
+ Handle<FixedArray> GetForeignArgs() {
+ Handle<FixedArray> ret = isolate_->factory()->NewFixedArray(
static_cast<int>(foreign_variables_.size()));
for (size_t i = 0; i < foreign_variables_.size(); ++i) {
ForeignVariable* fv = &foreign_variables_[i];
@@ -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,12 +131,62 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitFunctionDeclaration(FunctionDeclaration* decl) {
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;
+ 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);
+ 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_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)) {
+ 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);
+ if (new_func_scope != nullptr) {
+ DCHECK_EQ(new_func_scope, decl->scope()->inner_scope());
+ if (!decl->scope()->RemoveInnerScope(new_func_scope)) {
+ UNREACHABLE();
+ }
+ }
+ return;
+ }
current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var());
scope_ = kFuncScope;
RECURSE(Visit(decl->fun()));
+ decl->set_fun(old_func);
+ if (new_func_scope != nullptr) {
+ DCHECK_EQ(new_func_scope, decl->scope()->inner_scope());
+ if (!decl->scope()->RemoveInnerScope(new_func_scope)) {
+ UNREACHABLE();
+ }
+ }
scope_ = kModuleScope;
current_function_builder_ = nullptr;
local_variables_.Clear();
+ typer_->ClearFunctionNodeTypes();
}
void VisitStatements(ZoneList<Statement*>* stmts) {
@@ -129,6 +197,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
continue;
}
RECURSE(Visit(stmt));
+ if (typer_failed_) break;
if (stmt->IsJump()) break;
}
}
@@ -245,6 +314,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 +521,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 +734,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 +761,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 +812,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 +999,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 +1008,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;
}
@@ -952,7 +1046,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
DCHECK_NOT_NULL(key_literal);
if (!key_literal->value().is_null()) {
Handle<Name> name =
- i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
+ Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
LocalType type = is_float ? kAstF64 : kAstI32;
foreign_variables_.push_back({name, var, type});
}
@@ -1325,7 +1419,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 +1442,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 +1788,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 +1918,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 +1937,27 @@ 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();
+AsmWasmBuilder::Result AsmWasmBuilder::Run(Handle<FixedArray>* foreign_args) {
+ 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__";
« no previous file with comments | « src/asmjs/asm-wasm-builder.h ('k') | src/ast/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698