aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/asmjs/asm-wasm-builder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/asmjs/asm-wasm-builder.cc')
-rw-r--r--deps/v8/src/asmjs/asm-wasm-builder.cc465
1 files changed, 306 insertions, 159 deletions
diff --git a/deps/v8/src/asmjs/asm-wasm-builder.cc b/deps/v8/src/asmjs/asm-wasm-builder.cc
index cac6fbd8b3..907e80fe4b 100644
--- a/deps/v8/src/asmjs/asm-wasm-builder.cc
+++ b/deps/v8/src/asmjs/asm-wasm-builder.cc
@@ -19,6 +19,11 @@
#include "src/ast/ast.h"
#include "src/ast/scopes.h"
+#include "src/codegen.h"
+#include "src/compilation-info.h"
+#include "src/compiler.h"
+#include "src/isolate.h"
+#include "src/parsing/parse-info.h"
namespace v8 {
namespace internal {
@@ -37,13 +42,14 @@ enum ValueFate { kDrop, kLeaveOnStack };
struct ForeignVariable {
Handle<Name> name;
Variable* var;
- LocalType type;
+ ValueType type;
};
class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
public:
- AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
- AsmTyper* typer)
+ AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, CompilationInfo* info,
+ AstValueFactory* ast_value_factory, Handle<Script> script,
+ FunctionLiteral* literal, AsmTyper* typer)
: local_variables_(ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
functions_(ZoneHashMap::kDefaultHashMapCapacity,
@@ -56,15 +62,20 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
literal_(literal),
isolate_(isolate),
zone_(zone),
+ info_(info),
+ ast_value_factory_(ast_value_factory),
+ script_(script),
typer_(typer),
+ typer_failed_(false),
+ typer_finished_(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) {
+ imported_function_table_(this),
+ parent_binop_(nullptr) {
InitializeAstVisitor(isolate);
}
@@ -90,10 +101,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
uint32_t index = LookupOrInsertGlobal(fv->var, fv->type);
foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index);
}
+ foreign_init_function_->Emit(kExprEnd);
}
- 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 +114,26 @@ 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_finished_ && !typer_failed_) {
+ typer_->FailWithMessage("Module missing export section.");
+ typer_failed_ = true;
+ }
+ if (typer_failed_) {
+ return false;
+ }
BuildForeignInitFunction();
+ init_function_->Emit(kExprEnd); // finish init function.
+ return true;
}
void VisitVariableDeclaration(VariableDeclaration* decl) {}
@@ -113,12 +141,65 @@ 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(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);
+ // 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;
+
+ // Record start of the function, used as position for the stack check.
+ current_function_builder_->SetAsmFunctionStartPosition(
+ decl->fun()->start_position());
+
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,7 +210,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
continue;
}
RECURSE(Visit(stmt));
- if (stmt->IsJump()) break;
+ if (typer_failed_) break;
}
}
@@ -204,6 +285,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); }
+ void VisitGetIterator(GetIterator* expr) { UNREACHABLE(); }
+
void VisitIfStatement(IfStatement* stmt) {
DCHECK_EQ(kFuncScope, scope_);
RECURSE(Visit(stmt->condition()));
@@ -245,6 +328,16 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitReturnStatement(ReturnStatement* stmt) {
if (scope_ == kModuleScope) {
+ if (typer_finished_) {
+ typer_->FailWithMessage("Module has multiple returns.");
+ typer_failed_ = true;
+ return;
+ }
+ if (!typer_->ValidateAfterFunctionsPhase()) {
+ typer_failed_ = true;
+ return;
+ }
+ typer_finished_ = true;
scope_ = kExportScope;
RECURSE(Visit(stmt->expression()));
scope_ = kModuleScope;
@@ -440,16 +533,21 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// Add the parameters for the function.
const auto& arguments = func_type->Arguments();
for (int i = 0; i < expr->parameter_count(); ++i) {
- LocalType type = TypeFrom(arguments[i]);
- DCHECK_NE(kAstStmt, type);
+ ValueType type = TypeFrom(arguments[i]);
+ DCHECK_NE(kWasmStmt, type);
InsertParameter(scope->parameter(i), type, i);
}
} else {
UNREACHABLE();
}
}
- RECURSE(VisitStatements(expr->body()));
RECURSE(VisitDeclarations(scope->declarations()));
+ if (typer_failed_) return;
+ RECURSE(VisitStatements(expr->body()));
+ if (scope_ == kFuncScope) {
+ // Finish the function-body scope block.
+ current_function_builder_->Emit(kExprEnd);
+ }
}
void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
@@ -461,18 +559,18 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
RECURSE(Visit(expr->condition()));
// WASM ifs come with implicit blocks for both arms.
breakable_blocks_.push_back(std::make_pair(nullptr, false));
- LocalTypeCode type;
+ ValueTypeCode type;
switch (TypeOf(expr)) {
- case kAstI32:
+ case kWasmI32:
type = kLocalI32;
break;
- case kAstI64:
+ case kWasmI64:
type = kLocalI64;
break;
- case kAstF32:
+ case kWasmF32:
type = kLocalF32;
break;
- case kAstF64:
+ case kWasmF64:
type = kLocalF64;
break;
default:
@@ -544,8 +642,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (VisitStdlibConstant(var)) {
return;
}
- LocalType var_type = TypeOf(expr);
- DCHECK_NE(kAstStmt, var_type);
+ ValueType var_type = TypeOf(expr);
+ DCHECK_NE(kWasmStmt, var_type);
if (var->IsContextSlot()) {
current_function_builder_->EmitWithVarInt(
kExprGetGlobal, LookupOrInsertGlobal(var, var_type));
@@ -638,12 +736,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
Literal* name = prop->key()->AsLiteral();
DCHECK_NOT_NULL(name);
DCHECK(name->IsPropertyName());
- const AstRawString* raw_name = name->AsRawPropertyName();
+ Handle<String> function_name = name->AsPropertyName();
+ int length;
+ std::unique_ptr<char[]> utf8 = function_name->ToCString(
+ DISALLOW_NULLS, FAST_STRING_TRAVERSAL, &length);
if (var->is_function()) {
WasmFunctionBuilder* function = LookupOrInsertFunction(var);
- function->Export();
- function->SetName({reinterpret_cast<const char*>(raw_name->raw_data()),
- raw_name->length()});
+ function->ExportAs({utf8.get(), length});
}
}
}
@@ -660,53 +759,67 @@ 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,
+ ValueType return_type = TypeFrom(func_type->ReturnType());
+ FunctionSig::Builder sig(zone(), return_type == kWasmStmt ? 0 : 1,
arguments.size());
- if (return_type != kAstStmt) {
+ if (return_type != kWasmStmt) {
sig.AddReturn(return_type);
}
for (auto* arg : arguments) {
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());
+ // Ignore unused function tables.
+ if (indices == nullptr) {
+ return;
+ }
+ 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 +840,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()) {
@@ -819,8 +945,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (target_var != nullptr) {
// Left hand side is a local or a global variable.
Variable* var = target_var->var();
- LocalType var_type = TypeOf(expr);
- DCHECK_NE(kAstStmt, var_type);
+ ValueType var_type = TypeOf(expr);
+ DCHECK_NE(kWasmStmt, var_type);
if (var->IsContextSlot()) {
uint32_t index = LookupOrInsertGlobal(var, var_type);
current_function_builder_->EmitWithVarInt(kExprSetGlobal, index);
@@ -841,7 +967,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
Property* target_prop = expr->target()->AsProperty();
if (target_prop != nullptr) {
// Left hand side is a property access, i.e. the asm.js heap.
- if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() &&
+ if (TypeOf(expr->value()) == kWasmF64 && expr->target()->IsProperty() &&
typer_->TypeOf(expr->target()->AsProperty()->obj())
->IsA(AsmType::Float32Array())) {
current_function_builder_->Emit(kExprF32ConvertF64);
@@ -901,7 +1027,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 +1036,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,8 +1074,8 @@ 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();
- LocalType type = is_float ? kAstF64 : kAstI32;
+ Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
+ ValueType type = is_float ? kWasmF64 : kWasmI32;
foreign_variables_.push_back({name, var, type});
}
}
@@ -961,7 +1083,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitPropertyAndEmitIndex(Property* expr, AsmType** atype) {
Expression* obj = expr->obj();
*atype = typer_->TypeOf(obj);
- int size = (*atype)->ElementSizeInBytes();
+ int32_t size = (*atype)->ElementSizeInBytes();
if (size == 1) {
// Allow more general expression in byte arrays than the spec
// strictly permits.
@@ -974,7 +1096,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
Literal* value = expr->key()->AsLiteral();
if (value) {
DCHECK(value->raw_value()->IsNumber());
- DCHECK_EQ(kAstI32, TypeOf(value));
+ DCHECK_EQ(kWasmI32, TypeOf(value));
int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber());
// TODO(titzer): handle overflow here.
current_function_builder_->EmitI32Const(val * size);
@@ -984,14 +1106,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (binop) {
DCHECK_EQ(Token::SAR, binop->op());
DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber());
- DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral()));
+ DCHECK(kWasmI32 == TypeOf(binop->right()->AsLiteral()));
DCHECK_EQ(size,
1 << static_cast<int>(
binop->right()->AsLiteral()->raw_value()->AsNumber()));
// Mask bottom bits to match asm.js behavior.
- byte mask = static_cast<byte>(~(size - 1));
RECURSE(Visit(binop->left()));
- current_function_builder_->EmitWithU8(kExprI8Const, mask);
+ current_function_builder_->EmitI32Const(~(size - 1));
current_function_builder_->Emit(kExprI32And);
return;
}
@@ -1030,7 +1151,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
AsmTyper::StandardMember standard_object =
typer_->VariableAsStandardMember(var);
ZoneList<Expression*>* args = call->arguments();
- LocalType call_type = TypeOf(call);
+ ValueType call_type = TypeOf(call);
switch (standard_object) {
case AsmTyper::kNone: {
@@ -1038,57 +1159,57 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathAcos: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Acos);
break;
}
case AsmTyper::kMathAsin: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Asin);
break;
}
case AsmTyper::kMathAtan: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Atan);
break;
}
case AsmTyper::kMathCos: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Cos);
break;
}
case AsmTyper::kMathSin: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Sin);
break;
}
case AsmTyper::kMathTan: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Tan);
break;
}
case AsmTyper::kMathExp: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Exp);
break;
}
case AsmTyper::kMathLog: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Log);
break;
}
case AsmTyper::kMathCeil: {
VisitCallArgs(call);
- if (call_type == kAstF32) {
+ if (call_type == kWasmF32) {
current_function_builder_->Emit(kExprF32Ceil);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
current_function_builder_->Emit(kExprF64Ceil);
} else {
UNREACHABLE();
@@ -1097,9 +1218,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathFloor: {
VisitCallArgs(call);
- if (call_type == kAstF32) {
+ if (call_type == kWasmF32) {
current_function_builder_->Emit(kExprF32Floor);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
current_function_builder_->Emit(kExprF64Floor);
} else {
UNREACHABLE();
@@ -1108,9 +1229,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathSqrt: {
VisitCallArgs(call);
- if (call_type == kAstF32) {
+ if (call_type == kWasmF32) {
current_function_builder_->Emit(kExprF32Sqrt);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
current_function_builder_->Emit(kExprF64Sqrt);
} else {
UNREACHABLE();
@@ -1119,18 +1240,18 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathClz32: {
VisitCallArgs(call);
- DCHECK(call_type == kAstI32);
+ DCHECK(call_type == kWasmI32);
current_function_builder_->Emit(kExprI32Clz);
break;
}
case AsmTyper::kMathAbs: {
- if (call_type == kAstI32) {
- WasmTemporary tmp(current_function_builder_, kAstI32);
+ if (call_type == kWasmI32) {
+ WasmTemporary tmp(current_function_builder_, kWasmI32);
// if set_local(tmp, x) < 0
Visit(call->arguments()->at(0));
current_function_builder_->EmitTeeLocal(tmp.index());
- byte code[] = {WASM_I8(0)};
+ byte code[] = {WASM_ZERO};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->Emit(kExprI32LtS);
current_function_builder_->EmitWithU8(kExprIf, kLocalI32);
@@ -1146,10 +1267,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// end
current_function_builder_->Emit(kExprEnd);
- } else if (call_type == kAstF32) {
+ } else if (call_type == kWasmF32) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF32Abs);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF64Abs);
} else {
@@ -1159,9 +1280,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathMin: {
// TODO(bradnelson): Change wasm to match Math.min in asm.js mode.
- if (call_type == kAstI32) {
- WasmTemporary tmp_x(current_function_builder_, kAstI32);
- WasmTemporary tmp_y(current_function_builder_, kAstI32);
+ if (call_type == kWasmI32) {
+ WasmTemporary tmp_x(current_function_builder_, kWasmI32);
+ WasmTemporary tmp_y(current_function_builder_, kWasmI32);
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
@@ -1181,10 +1302,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
current_function_builder_->EmitGetLocal(tmp_y.index());
current_function_builder_->Emit(kExprEnd);
- } else if (call_type == kAstF32) {
+ } else if (call_type == kWasmF32) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF32Min);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF64Min);
} else {
@@ -1194,9 +1315,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathMax: {
// TODO(bradnelson): Change wasm to match Math.max in asm.js mode.
- if (call_type == kAstI32) {
- WasmTemporary tmp_x(current_function_builder_, kAstI32);
- WasmTemporary tmp_y(current_function_builder_, kAstI32);
+ if (call_type == kWasmI32) {
+ WasmTemporary tmp_x(current_function_builder_, kWasmI32);
+ WasmTemporary tmp_y(current_function_builder_, kWasmI32);
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
@@ -1217,10 +1338,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
current_function_builder_->EmitGetLocal(tmp_x.index());
current_function_builder_->Emit(kExprEnd);
- } else if (call_type == kAstF32) {
+ } else if (call_type == kWasmF32) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF32Max);
- } else if (call_type == kAstF64) {
+ } else if (call_type == kWasmF64) {
VisitCallArgs(call);
current_function_builder_->Emit(kExprF64Max);
} else {
@@ -1230,13 +1351,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
case AsmTyper::kMathAtan2: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Atan2);
break;
}
case AsmTyper::kMathPow: {
VisitCallArgs(call);
- DCHECK_EQ(kAstF64, call_type);
+ DCHECK_EQ(kWasmF64, call_type);
current_function_builder_->Emit(kExprF64Pow);
break;
}
@@ -1298,6 +1419,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
bool VisitCallExpression(Call* expr) {
Call::CallType call_type = expr->GetCallType();
bool returns_value = true;
+
+ // Save the parent now, it might be overwritten in VisitCallArgs.
+ BinaryOperation* parent_binop = parent_binop_;
+
switch (call_type) {
case Call::OTHER_CALL: {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
@@ -1313,11 +1438,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VariableProxy* vp = expr->expression()->AsVariableProxy();
DCHECK_NOT_NULL(vp);
if (typer_->TypeOf(vp)->AsFFIType() != nullptr) {
- LocalType return_type = TypeOf(expr);
+ ValueType return_type = TypeOf(expr);
ZoneList<Expression*>* args = expr->arguments();
- FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1,
+ FunctionSig::Builder sig(zone(), return_type == kWasmStmt ? 0 : 1,
args->length());
- if (return_type != kAstStmt) {
+ if (return_type != kWasmStmt) {
sig.AddReturn(return_type);
} else {
returns_value = false;
@@ -1325,16 +1450,23 @@ 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());
+ // For non-void functions, we must know the parent node.
+ DCHECK_IMPLIES(returns_value, parent_binop != nullptr);
+ DCHECK_IMPLIES(returns_value, parent_binop->left() == expr ||
+ parent_binop->right() == expr);
+ int pos = expr->position();
+ 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);
} else {
WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var());
VisitCallArgs(expr);
- current_function_builder_->AddAsmWasmOffset(expr->position());
+ current_function_builder_->AddAsmWasmOffset(expr->position(),
+ expr->position());
current_function_builder_->Emit(kExprCallFunction);
current_function_builder_->EmitDirectCallIndex(
function->func_index());
@@ -1348,19 +1480,20 @@ 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.
current_function_builder_->EmitI32Const(indices->start_index);
current_function_builder_->Emit(kExprI32Add);
- WasmTemporary tmp(current_function_builder_, kAstI32);
+ WasmTemporary tmp(current_function_builder_, kWasmI32);
current_function_builder_->EmitSetLocal(tmp.index());
VisitCallArgs(expr);
current_function_builder_->EmitGetLocal(tmp.index());
- current_function_builder_->AddAsmWasmOffset(expr->position());
+ 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
@@ -1383,7 +1516,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
RECURSE(Visit(expr->expression()));
switch (expr->op()) {
case Token::NOT: {
- DCHECK_EQ(kAstI32, TypeOf(expr->expression()));
+ DCHECK_EQ(kWasmI32, TypeOf(expr->expression()));
current_function_builder_->Emit(kExprI32Eqz);
break;
}
@@ -1398,10 +1531,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
int32_t val) {
DCHECK_NOT_NULL(expr->right());
if (expr->op() == op && expr->right()->IsLiteral() &&
- TypeOf(expr) == kAstI32) {
+ TypeOf(expr) == kWasmI32) {
Literal* right = expr->right()->AsLiteral();
- DCHECK(right->raw_value()->IsNumber());
- if (static_cast<int32_t>(right->raw_value()->AsNumber()) == val) {
+ if (right->raw_value()->IsNumber() &&
+ static_cast<int32_t>(right->raw_value()->AsNumber()) == val) {
return true;
}
}
@@ -1412,7 +1545,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
double val) {
DCHECK_NOT_NULL(expr->right());
if (expr->op() == op && expr->right()->IsLiteral() &&
- TypeOf(expr) == kAstF64) {
+ TypeOf(expr) == kWasmF64) {
Literal* right = expr->right()->AsLiteral();
DCHECK(right->raw_value()->IsNumber());
if (right->raw_value()->AsNumber() == val) {
@@ -1426,7 +1559,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
ConvertOperation MatchOr(BinaryOperation* expr) {
if (MatchIntBinaryOperation(expr, Token::BIT_OR, 0) &&
- (TypeOf(expr->left()) == kAstI32)) {
+ (TypeOf(expr->left()) == kWasmI32)) {
return kAsIs;
} else {
return kNone;
@@ -1436,7 +1569,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
ConvertOperation MatchShr(BinaryOperation* expr) {
if (MatchIntBinaryOperation(expr, Token::SHR, 0)) {
// TODO(titzer): this probably needs to be kToUint
- return (TypeOf(expr->left()) == kAstI32) ? kAsIs : kToInt;
+ return (TypeOf(expr->left()) == kWasmI32) ? kAsIs : kToInt;
} else {
return kNone;
}
@@ -1444,13 +1577,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
ConvertOperation MatchXor(BinaryOperation* expr) {
if (MatchIntBinaryOperation(expr, Token::BIT_XOR, 0xffffffff)) {
- DCHECK_EQ(kAstI32, TypeOf(expr->left()));
- DCHECK_EQ(kAstI32, TypeOf(expr->right()));
+ DCHECK_EQ(kWasmI32, TypeOf(expr->left()));
+ DCHECK_EQ(kWasmI32, TypeOf(expr->right()));
BinaryOperation* op = expr->left()->AsBinaryOperation();
if (op != nullptr) {
if (MatchIntBinaryOperation(op, Token::BIT_XOR, 0xffffffff)) {
- DCHECK_EQ(kAstI32, TypeOf(op->right()));
- if (TypeOf(op->left()) != kAstI32) {
+ DCHECK_EQ(kWasmI32, TypeOf(op->right()));
+ if (TypeOf(op->left()) != kWasmI32) {
return kToInt;
} else {
return kAsIs;
@@ -1463,8 +1596,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
ConvertOperation MatchMul(BinaryOperation* expr) {
if (MatchDoubleBinaryOperation(expr, Token::MUL, 1.0)) {
- DCHECK_EQ(kAstF64, TypeOf(expr->right()));
- if (TypeOf(expr->left()) != kAstF64) {
+ DCHECK_EQ(kWasmF64, TypeOf(expr->right()));
+ if (TypeOf(expr->left()) != kWasmF64) {
return kToDouble;
} else {
return kAsIs;
@@ -1532,6 +1665,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitBinaryOperation(BinaryOperation* expr) {
ConvertOperation convertOperation = MatchBinaryOperation(expr);
static const bool kDontIgnoreSign = false;
+ parent_binop_ = expr;
if (convertOperation == kToDouble) {
RECURSE(Visit(expr->left()));
TypeIndex type = TypeIndexOf(expr->left(), kDontIgnoreSign);
@@ -1694,6 +1828,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitDeclarations(Declaration::List* decls) {
for (Declaration* decl : *decls) {
RECURSE(Visit(decl));
+ if (typer_failed_) {
+ return;
+ }
}
}
@@ -1719,7 +1856,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
uint32_t index;
};
- uint32_t LookupOrInsertLocal(Variable* v, LocalType type) {
+ uint32_t LookupOrInsertLocal(Variable* v, ValueType type) {
DCHECK_NOT_NULL(current_function_builder_);
ZoneHashMap::Entry* entry =
local_variables_.Lookup(v, ComputePointerHash(v));
@@ -1736,7 +1873,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
return (reinterpret_cast<IndexContainer*>(entry->value))->index;
}
- void InsertParameter(Variable* v, LocalType type, uint32_t index) {
+ void InsertParameter(Variable* v, ValueType type, uint32_t index) {
DCHECK(v->IsParameter());
DCHECK_NOT_NULL(current_function_builder_);
ZoneHashMap::Entry* entry =
@@ -1749,7 +1886,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
entry->value = container;
}
- uint32_t LookupOrInsertGlobal(Variable* v, LocalType type) {
+ uint32_t LookupOrInsertGlobal(Variable* v, ValueType type) {
ZoneHashMap::Entry* entry =
global_variables_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
@@ -1770,14 +1907,14 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
auto* func_type = typer_->TypeOf(v)->AsFunctionType();
DCHECK_NOT_NULL(func_type);
// Build the signature for the function.
- LocalType return_type = TypeFrom(func_type->ReturnType());
+ ValueType return_type = TypeFrom(func_type->ReturnType());
const auto& arguments = func_type->Arguments();
- FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
+ FunctionSig::Builder b(zone(), return_type == kWasmStmt ? 0 : 1,
arguments.size());
- if (return_type != kAstStmt) b.AddReturn(return_type);
+ if (return_type != kWasmStmt) b.AddReturn(return_type);
for (int i = 0; i < static_cast<int>(arguments.size()); ++i) {
- LocalType type = TypeFrom(arguments[i]);
- DCHECK_NE(kAstStmt, type);
+ ValueType type = TypeFrom(arguments[i]);
+ DCHECK_NE(kWasmStmt, type);
b.AddParam(type);
}
@@ -1792,22 +1929,22 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
return (reinterpret_cast<WasmFunctionBuilder*>(entry->value));
}
- LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); }
+ ValueType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); }
- LocalType TypeFrom(AsmType* type) {
+ ValueType TypeFrom(AsmType* type) {
if (type->IsA(AsmType::Intish())) {
- return kAstI32;
+ return kWasmI32;
}
if (type->IsA(AsmType::Floatish())) {
- return kAstF32;
+ return kWasmF32;
}
if (type->IsA(AsmType::DoubleQ())) {
- return kAstF64;
+ return kWasmF64;
}
- return kAstStmt;
+ return kWasmStmt;
}
Zone* zone() { return zone_; }
@@ -1821,7 +1958,12 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
FunctionLiteral* literal_;
Isolate* isolate_;
Zone* zone_;
+ CompilationInfo* info_;
+ AstValueFactory* ast_value_factory_;
+ Handle<Script> script_;
AsmTyper* typer_;
+ bool typer_failed_;
+ bool typer_finished_;
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
ZoneVector<ForeignVariable> foreign_variables_;
WasmFunctionBuilder* init_function_;
@@ -1829,6 +1971,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
uint32_t next_table_index_;
ZoneHashMap function_tables_;
ImportedFunctionTable imported_function_table_;
+ // Remember the parent node for reporting the correct location for ToNumber
+ // conversions after calls.
+ BinaryOperation* parent_binop_;
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
@@ -1836,22 +1981,24 @@ 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(CompilationInfo* info)
+ : info_(info),
+ typer_(info->isolate(), info->zone(), info->script(), info->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) {
+ Zone* zone = info_->zone();
+ AsmWasmBuilderImpl impl(info_->isolate(), zone, info_,
+ info_->parse_info()->ast_value_factory(),
+ info_->script(), info_->literal(), &typer_);
+ bool success = impl.Build();
*foreign_args = impl.GetForeignArgs();
- ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_);
+ ZoneBuffer* module_buffer = new (zone) ZoneBuffer(zone);
impl.builder_->WriteTo(*module_buffer);
- ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_);
+ 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__";