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); |