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

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

Issue 2345593003: [wasm] Master CL for Binary 0xC changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix test failures and TSAN races. Created 4 years, 3 months 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-typer.cc ('k') | src/compiler/int64-lowering.cc » ('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 ac2585e6eaacc5453d317981309671a121c0ec22..d446c4e0a323aac07579442837fa5e4b5fc35274 100644
--- a/src/asmjs/asm-wasm-builder.cc
+++ b/src/asmjs/asm-wasm-builder.cc
@@ -32,6 +32,7 @@ namespace wasm {
} while (false)
enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope };
+enum ValueFate { kDrop, kLeaveOnStack };
struct ForeignVariable {
Handle<Name> name;
@@ -61,8 +62,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
typer_(typer),
breakable_blocks_(zone),
foreign_variables_(zone),
- init_function_index_(0),
- foreign_init_function_index_(0),
+ init_function_(nullptr),
+ foreign_init_function_(nullptr),
next_table_index_(0),
function_tables_(base::HashMap::PointersMatch,
ZoneHashMap::kDefaultHashMapCapacity,
@@ -72,35 +73,33 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
void InitializeInitFunction() {
- init_function_index_ = builder_->AddFunction();
FunctionSig::Builder b(zone(), 0, 0);
- current_function_builder_ = builder_->FunctionAt(init_function_index_);
- current_function_builder_->SetSignature(b.Build());
- builder_->MarkStartFunction(init_function_index_);
- current_function_builder_ = nullptr;
+ init_function_ = builder_->AddFunction(b.Build());
+ builder_->MarkStartFunction(init_function_);
}
void BuildForeignInitFunction() {
- foreign_init_function_index_ = builder_->AddFunction();
+ foreign_init_function_ = builder_->AddFunction();
FunctionSig::Builder b(zone(), 0, foreign_variables_.size());
for (auto i = foreign_variables_.begin(); i != foreign_variables_.end();
++i) {
b.AddParam(i->type);
}
- current_function_builder_ =
- builder_->FunctionAt(foreign_init_function_index_);
- current_function_builder_->SetExported();
- current_function_builder_->SetName(
+ foreign_init_function_->SetExported();
+ std::string raw_name = "__foreign_init__";
+ foreign_init_function_->SetName(
AsmWasmBuilder::foreign_init_name,
static_cast<int>(strlen(AsmWasmBuilder::foreign_init_name)));
- current_function_builder_->SetSignature(b.Build());
+
+ foreign_init_function_->SetName(raw_name.data(),
+ static_cast<int>(raw_name.size()));
+ foreign_init_function_->SetSignature(b.Build());
for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) {
- current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos));
+ foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos));
ForeignVariable* fv = &foreign_variables_[pos];
uint32_t index = LookupOrInsertGlobal(fv->var, fv->type);
- current_function_builder_->EmitWithVarInt(kExprSetGlobal, index);
+ foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index);
}
- current_function_builder_ = nullptr;
}
i::Handle<i::FixedArray> GetForeignArgs() {
@@ -113,7 +112,20 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
return ret;
}
+ void BuildImports() {
+ for (const AsmTyper::FFIUseSignature& ffi : typer_->FFIUseSignatures()) {
+ size_t ret_count = ffi.return_type_ == AsmType::Void() ? 0 : 1;
+ FunctionSig::Builder b(zone_, ret_count, ffi.arg_types_.size());
+ for (AsmType* arg : ffi.arg_types_) b.AddParam(TypeFrom(arg));
+ if (ffi.return_type_ != AsmType::Void()) {
+ b.AddReturn(TypeFrom(ffi.return_type_));
+ }
+ imported_function_table_.AddFunction(ffi.var, b.Build());
+ }
+ }
+
void Build() {
+ BuildImports();
InitializeInitFunction();
RECURSE(VisitFunctionLiteral(literal_));
BuildForeignInitFunction();
@@ -124,8 +136,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitFunctionDeclaration(FunctionDeclaration* decl) {
DCHECK_EQ(kModuleScope, scope_);
DCHECK_NULL(current_function_builder_);
- uint32_t index = LookupOrInsertFunction(decl->proxy()->var());
- current_function_builder_ = builder_->FunctionAt(index);
+ current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var());
scope_ = kFuncScope;
RECURSE(Visit(decl->fun()));
scope_ = kModuleScope;
@@ -157,8 +168,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
}
if (scope_ == kFuncScope) {
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock,
- false);
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock);
RECURSE(VisitStatements(stmt->statements()));
} else {
RECURSE(VisitStatements(stmt->statements()));
@@ -171,10 +181,12 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
public:
BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt,
- WasmOpcode opcode, bool is_loop)
+ WasmOpcode opcode)
: builder_(builder) {
- builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop));
- builder_->current_function_builder_->Emit(opcode);
+ builder_->breakable_blocks_.push_back(
+ std::make_pair(stmt, opcode == kExprLoop));
+ // block and loops have a type immediate.
+ builder_->current_function_builder_->EmitWithU8(opcode, kLocalVoid);
}
~BlockVisitor() {
builder_->current_function_builder_->Emit(kExprEnd);
@@ -183,7 +195,32 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
};
void VisitExpressionStatement(ExpressionStatement* stmt) {
- RECURSE(Visit(stmt->expression()));
+ VisitForEffect(stmt->expression());
+ }
+
+ void VisitForEffect(Expression* expr) {
+ if (expr->IsAssignment()) {
+ // Don't emit drops for assignments. Instead use SetLocal/GetLocal.
+ VisitAssignment(expr->AsAssignment(), kDrop);
+ return;
+ }
+ if (expr->IsCall()) {
+ // Only emit a drop if the call has a non-void return value.
+ if (VisitCallExpression(expr->AsCall()) && scope_ == kFuncScope) {
+ current_function_builder_->Emit(kExprDrop);
+ }
+ return;
+ }
+ if (expr->IsBinaryOperation()) {
+ BinaryOperation* binop = expr->AsBinaryOperation();
+ if (binop->op() == Token::COMMA) {
+ VisitForEffect(binop->left());
+ VisitForEffect(binop->right());
+ return;
+ }
+ }
+ RECURSE(Visit(expr));
+ if (scope_ == kFuncScope) current_function_builder_->Emit(kExprDrop);
}
void VisitEmptyStatement(EmptyStatement* stmt) {}
@@ -193,7 +230,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitIfStatement(IfStatement* stmt) {
DCHECK_EQ(kFuncScope, scope_);
RECURSE(Visit(stmt->condition()));
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
// WASM ifs come with implement blocks for both arms.
breakable_blocks_.push_back(std::make_pair(nullptr, false));
if (stmt->HasThenStatement()) {
@@ -207,48 +244,26 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
breakable_blocks_.pop_back();
}
- void VisitContinueStatement(ContinueStatement* stmt) {
+ void DoBreakOrContinue(BreakableStatement* target, bool is_continue) {
DCHECK_EQ(kFuncScope, scope_);
- DCHECK_NOT_NULL(stmt->target());
- int i = static_cast<int>(breakable_blocks_.size()) - 1;
- int block_distance = 0;
- for (; i >= 0; i--) {
+ for (int i = static_cast<int>(breakable_blocks_.size()) - 1; i >= 0; --i) {
auto elem = breakable_blocks_.at(i);
- if (elem.first == stmt->target()) {
- DCHECK(elem.second);
- break;
- } else if (elem.second) {
- block_distance += 2;
- } else {
- block_distance += 1;
+ if (elem.first == target && elem.second == is_continue) {
+ int block_distance = static_cast<int>(breakable_blocks_.size() - i - 1);
+ current_function_builder_->Emit(kExprBr);
+ current_function_builder_->EmitVarInt(block_distance);
+ return;
}
}
- DCHECK(i >= 0);
- current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
- current_function_builder_->EmitVarInt(block_distance);
+ UNREACHABLE(); // statement not found
+ }
+
+ void VisitContinueStatement(ContinueStatement* stmt) {
+ DoBreakOrContinue(stmt->target(), true);
}
void VisitBreakStatement(BreakStatement* stmt) {
- DCHECK_EQ(kFuncScope, scope_);
- DCHECK_NOT_NULL(stmt->target());
- int i = static_cast<int>(breakable_blocks_.size()) - 1;
- int block_distance = 0;
- for (; i >= 0; i--) {
- auto elem = breakable_blocks_.at(i);
- if (elem.first == stmt->target()) {
- if (elem.second) {
- block_distance++;
- }
- break;
- } else if (elem.second) {
- block_distance += 2;
- } else {
- block_distance += 1;
- }
- }
- DCHECK(i >= 0);
- current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
- current_function_builder_->EmitVarInt(block_distance);
+ DoBreakOrContinue(stmt->target(), false);
}
void VisitReturnStatement(ReturnStatement* stmt) {
@@ -258,9 +273,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
scope_ = kModuleScope;
} else if (scope_ == kFuncScope) {
RECURSE(Visit(stmt->expression()));
- uint8_t arity =
- TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1;
- current_function_builder_->EmitWithU8(kExprReturn, arity);
+ current_function_builder_->Emit(kExprReturn);
} else {
UNREACHABLE();
}
@@ -276,7 +289,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VisitVariableProxy(tag);
current_function_builder_->EmitI32Const(node->begin);
current_function_builder_->Emit(kExprI32LtS);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
if_depth++;
breakable_blocks_.push_back(std::make_pair(nullptr, false));
HandleCase(node->left, case_to_block, tag, default_block, if_depth);
@@ -286,7 +299,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VisitVariableProxy(tag);
current_function_builder_->EmitI32Const(node->end);
current_function_builder_->Emit(kExprI32GtS);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
if_depth++;
breakable_blocks_.push_back(std::make_pair(nullptr, false));
HandleCase(node->right, case_to_block, tag, default_block, if_depth);
@@ -296,9 +309,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VisitVariableProxy(tag);
current_function_builder_->EmitI32Const(node->begin);
current_function_builder_->Emit(kExprI32Eq);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
DCHECK(case_to_block.find(node->begin) != case_to_block.end());
- current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+ current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarInt(1 + if_depth +
case_to_block[node->begin]);
current_function_builder_->Emit(kExprEnd);
@@ -310,22 +323,22 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
} else {
VisitVariableProxy(tag);
}
- current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0);
+ current_function_builder_->Emit(kExprBrTable);
current_function_builder_->EmitVarInt(node->end - node->begin + 1);
- for (int v = node->begin; v <= node->end; v++) {
+ for (int v = node->begin; v <= node->end; ++v) {
if (case_to_block.find(v) != case_to_block.end()) {
- byte break_code[] = {BR_TARGET(if_depth + case_to_block[v])};
- current_function_builder_->EmitCode(break_code, sizeof(break_code));
+ uint32_t target = if_depth + case_to_block[v];
+ current_function_builder_->EmitVarInt(target);
} else {
- byte break_code[] = {BR_TARGET(if_depth + default_block)};
- current_function_builder_->EmitCode(break_code, sizeof(break_code));
+ uint32_t target = if_depth + default_block;
+ current_function_builder_->EmitVarInt(target);
}
if (v == kMaxInt) {
break;
}
}
- byte break_code[] = {BR_TARGET(if_depth + default_block)};
- current_function_builder_->EmitCode(break_code, sizeof(break_code));
+ uint32_t target = if_depth + default_block;
+ current_function_builder_->EmitVarInt(target);
}
while (if_depth-- != prev_if_depth) {
@@ -342,14 +355,14 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (case_count == 0) {
return;
}
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false);
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock);
ZoneVector<BlockVisitor*> blocks(zone_);
ZoneVector<int32_t> cases(zone_);
ZoneMap<int, unsigned int> case_to_block(zone_);
bool has_default = false;
- for (int i = case_count - 1; i >= 0; i--) {
+ for (int i = case_count - 1; i >= 0; --i) {
CaseClause* clause = clauses->at(i);
- blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false));
+ blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock));
if (!clause->is_default()) {
Literal* label = clause->label()->AsLiteral();
Handle<Object> value = label->value();
@@ -366,12 +379,12 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
if (!has_default || case_count > 1) {
int default_block = has_default ? case_count - 1 : case_count;
- BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false);
+ BlockVisitor switch_logic_block(this, nullptr, kExprBlock);
CaseNode* root = OrderCases(&cases, zone_);
HandleCase(root, case_to_block, tag, default_block, 0);
if (root->left != nullptr || root->right != nullptr ||
root->begin == root->end) {
- current_function_builder_->EmitWithU8(kExprBr, ARITY_0);
+ current_function_builder_->Emit(kExprBr);
current_function_builder_->EmitVarInt(default_block);
}
}
@@ -388,22 +401,24 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitDoWhileStatement(DoWhileStatement* stmt) {
DCHECK_EQ(kFuncScope, scope_);
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
+ BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
- current_function_builder_->Emit(kExprIf);
- current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
+ current_function_builder_->EmitWithU8(kExprBr, 1);
current_function_builder_->Emit(kExprEnd);
}
void VisitWhileStatement(WhileStatement* stmt) {
DCHECK_EQ(kFuncScope, scope_);
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
+ BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
RECURSE(Visit(stmt->cond()));
breakable_blocks_.push_back(std::make_pair(nullptr, false));
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
RECURSE(Visit(stmt->body()));
- current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1);
+ current_function_builder_->EmitWithU8(kExprBr, 1);
current_function_builder_->Emit(kExprEnd);
breakable_blocks_.pop_back();
}
@@ -413,13 +428,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (stmt->init() != nullptr) {
RECURSE(Visit(stmt->init()));
}
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true);
+ BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock);
+ BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop);
if (stmt->cond() != nullptr) {
RECURSE(Visit(stmt->cond()));
current_function_builder_->Emit(kExprI32Eqz);
- current_function_builder_->Emit(kExprIf);
- current_function_builder_->Emit(kExprNop);
- current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalVoid);
+ current_function_builder_->EmitWithU8(kExprBr, 2);
current_function_builder_->Emit(kExprEnd);
}
if (stmt->body() != nullptr) {
@@ -428,8 +443,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
if (stmt->next() != nullptr) {
RECURSE(Visit(stmt->next()));
}
- current_function_builder_->Emit(kExprNop);
- current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0);
+ current_function_builder_->EmitWithU8(kExprBr, 0);
}
void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); }
@@ -446,19 +460,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
DeclarationScope* scope = expr->scope();
if (scope_ == kFuncScope) {
if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) {
- // Build the signature for the function.
- LocalType return_type = TypeFrom(func_type->ReturnType());
+ // Add the parameters for the function.
const auto& arguments = func_type->Arguments();
- FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
- arguments.size());
- if (return_type != kAstStmt) b.AddReturn(return_type);
for (int i = 0; i < expr->parameter_count(); ++i) {
LocalType type = TypeFrom(arguments[i]);
DCHECK_NE(kAstStmt, type);
- b.AddParam(type);
InsertParameter(scope->parameter(i), type, i);
}
- current_function_builder_->SetSignature(b.Build());
} else {
UNREACHABLE();
}
@@ -476,7 +484,24 @@ 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));
- current_function_builder_->Emit(kExprIf);
+ LocalTypeCode type;
+ switch (TypeOf(expr)) {
+ case kAstI32:
+ type = kLocalI32;
+ break;
+ case kAstI64:
+ type = kLocalI64;
+ break;
+ case kAstF32:
+ type = kLocalF32;
+ break;
+ case kAstF64:
+ type = kLocalF64;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ current_function_builder_->EmitWithU8(kExprIf, type);
RECURSE(Visit(expr->then_expression()));
current_function_builder_->Emit(kExprElse);
RECURSE(Visit(expr->else_expression()));
@@ -554,9 +579,9 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
} else if (scope_ == kExportScope) {
Variable* var = expr->var();
DCHECK(var->is_function());
- uint32_t index = LookupOrInsertFunction(var);
- builder_->FunctionAt(index)->SetExported();
- builder_->FunctionAt(index)->SetName(
+ WasmFunctionBuilder* function = LookupOrInsertFunction(var);
+ function->SetExported();
+ function->SetName(
AsmWasmBuilder::single_function_name,
static_cast<int>(strlen(AsmWasmBuilder::single_function_name)));
}
@@ -609,11 +634,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
DCHECK(name->IsPropertyName());
const AstRawString* raw_name = name->AsRawPropertyName();
if (var->is_function()) {
- uint32_t index = LookupOrInsertFunction(var);
- builder_->FunctionAt(index)->SetExported();
- builder_->FunctionAt(index)->SetName(
- reinterpret_cast<const char*>(raw_name->raw_data()),
- raw_name->length());
+ WasmFunctionBuilder* function = LookupOrInsertFunction(var);
+ function->SetExported();
+ function->SetName(reinterpret_cast<const char*>(raw_name->raw_data()),
+ raw_name->length());
}
}
}
@@ -621,7 +645,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); }
void LoadInitFunction() {
- current_function_builder_ = builder_->FunctionAt(init_function_index_);
+ current_function_builder_ = init_function_;
scope_ = kInitScope;
}
@@ -650,7 +674,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
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()));
+ builder_->AddIndirectFunction(
+ LookupOrInsertFunction(func->var())->func_index());
}
}
@@ -680,12 +705,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
private:
class ImportedFunctionIndices : public ZoneObject {
public:
- const char* name_;
- int name_length_;
+ bool has_name_;
WasmModuleBuilder::SignatureMap signature_to_index_;
- ImportedFunctionIndices(const char* name, int name_length, Zone* zone)
- : name_(name), name_length_(name_length), signature_to_index_(zone) {}
+ explicit ImportedFunctionIndices(Zone* zone)
+ : has_name_(false), signature_to_index_(zone) {}
};
ZoneHashMap table_;
AsmWasmBuilderImpl* builder_;
@@ -697,30 +721,51 @@ 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());
- ZoneHashMap::Entry* entry = table_.LookupOrInsert(
- v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone()));
- entry->value = indices;
+ // Set the imported name of a variable. Must happen after all signatures
+ // (and thus import indices) are added for a given variable.
+ void SetImportName(Variable* v, const char* name, int name_length) {
+ auto indices = GetEntry(v);
+ if (indices) {
+ for (auto entry : indices->signature_to_index_) {
+ uint32_t index = entry.second;
+ builder_->builder_->SetImportName(index, name, name_length);
+ }
+ indices->has_name_ = true;
+ }
}
+ // Get a function's index. Does not insert new entries.
uint32_t GetFunctionIndex(Variable* v, FunctionSig* sig) {
- ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v));
- DCHECK_NOT_NULL(entry);
- ImportedFunctionIndices* indices =
- reinterpret_cast<ImportedFunctionIndices*>(entry->value);
- WasmModuleBuilder::SignatureMap::iterator pos =
- indices->signature_to_index_.find(sig);
- if (pos != indices->signature_to_index_.end()) {
- return pos->second;
- } else {
- uint32_t index = builder_->builder_->AddImport(
- indices->name_, indices->name_length_, sig);
+ auto indices = GetEntry(v);
+ DCHECK_NOT_NULL(indices);
+ auto pos = indices->signature_to_index_.find(sig);
+ DCHECK(pos != indices->signature_to_index_.end());
+ return pos->second;
+ }
+
+ // Add a function and register it as an import with the builder.
+ void AddFunction(Variable* v, FunctionSig* sig) {
+ auto entry = table_.LookupOrInsert(
+ v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone()));
+ if (entry->value == nullptr) {
+ entry->value =
+ new (builder_->zone()) ImportedFunctionIndices(builder_->zone());
+ }
+ auto indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value);
+ DCHECK(!indices->has_name_);
+ auto pos = indices->signature_to_index_.find(sig);
+ if (pos == indices->signature_to_index_.end()) {
+ // A new import. Name is not known up front.
+ uint32_t index = builder_->builder_->AddImport(nullptr, 0, sig);
indices->signature_to_index_[sig] = index;
- return index;
}
}
+
+ ImportedFunctionIndices* GetEntry(Variable* v) {
+ auto entry = table_.Lookup(v, ComputePointerHash(v));
+ if (entry == nullptr) return nullptr;
+ return reinterpret_cast<ImportedFunctionIndices*>(entry->value);
+ }
};
void EmitAssignmentLhs(Expression* target, MachineType* mtype) {
@@ -782,7 +827,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
RECURSE(Visit(value));
}
- void EmitAssignment(Assignment* expr, MachineType type) {
+ void EmitAssignment(Assignment* expr, MachineType type, ValueFate fate) {
// Match the left hand side of the assignment.
VariableProxy* target_var = expr->target()->AsVariableProxy();
if (target_var != nullptr) {
@@ -791,11 +836,19 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
LocalType var_type = TypeOf(expr);
DCHECK_NE(kAstStmt, var_type);
if (var->IsContextSlot()) {
- current_function_builder_->EmitWithVarInt(
- kExprSetGlobal, LookupOrInsertGlobal(var, var_type));
+ uint32_t index = LookupOrInsertGlobal(var, var_type);
+ current_function_builder_->EmitWithVarInt(kExprSetGlobal, index);
+ if (fate == kLeaveOnStack) {
+ current_function_builder_->EmitWithVarInt(kExprGetGlobal, index);
+ }
} else {
- current_function_builder_->EmitSetLocal(
- LookupOrInsertLocal(var, var_type));
+ if (fate == kDrop) {
+ current_function_builder_->EmitSetLocal(
+ LookupOrInsertLocal(var, var_type));
+ } else {
+ current_function_builder_->EmitTeeLocal(
+ LookupOrInsertLocal(var, var_type));
+ }
}
}
@@ -807,6 +860,7 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
->IsA(AsmType::Float32Array())) {
current_function_builder_->Emit(kExprF32ConvertF64);
}
+ // Note that unlike StoreMem, AsmjsStoreMem ignores out-of-bounds writes.
WasmOpcode opcode;
if (type == MachineType::Int8()) {
opcode = kExprI32AsmjsStoreMem8;
@@ -828,6 +882,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
UNREACHABLE();
}
current_function_builder_->Emit(opcode);
+ if (fate == kDrop) {
+ // Asm.js stores to memory leave their result on the stack.
+ current_function_builder_->Emit(kExprDrop);
+ }
}
if (target_var == nullptr && target_prop == nullptr) {
@@ -836,6 +894,10 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
void VisitAssignment(Assignment* expr) {
+ VisitAssignment(expr, kLeaveOnStack);
+ }
+
+ void VisitAssignment(Assignment* expr, ValueFate fate) {
bool as_init = false;
if (scope_ == kModuleScope) {
// Skip extra assignment inserted by the parser when in this form:
@@ -853,7 +915,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());
}
@@ -881,12 +943,12 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
if (as_init) LoadInitFunction();
- MachineType mtype;
+ MachineType mtype = MachineType::None();
bool is_nop = false;
EmitAssignmentLhs(expr->target(), &mtype);
EmitAssignmentRhs(expr->target(), expr->value(), &is_nop);
if (!is_nop) {
- EmitAssignment(expr, mtype);
+ EmitAssignment(expr, mtype, fate);
}
if (as_init) UnLoadInitFunction();
}
@@ -1111,11 +1173,11 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// if set_local(tmp, x) < 0
Visit(call->arguments()->at(0));
- current_function_builder_->EmitSetLocal(tmp.index());
+ current_function_builder_->EmitTeeLocal(tmp.index());
byte code[] = {WASM_I8(0)};
current_function_builder_->EmitCode(code, sizeof(code));
current_function_builder_->Emit(kExprI32LtS);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalI32);
// then (0 - tmp)
current_function_builder_->EmitCode(code, sizeof(code));
@@ -1147,13 +1209,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
- current_function_builder_->EmitSetLocal(tmp_x.index());
+ current_function_builder_->EmitTeeLocal(tmp_x.index());
Visit(call->arguments()->at(1));
- current_function_builder_->EmitSetLocal(tmp_y.index());
+ current_function_builder_->EmitTeeLocal(tmp_y.index());
current_function_builder_->Emit(kExprI32LeS);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalI32);
// then tmp_x
current_function_builder_->EmitGetLocal(tmp_x.index());
@@ -1183,13 +1245,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
// if set_local(tmp_x, x) < set_local(tmp_y, y)
Visit(call->arguments()->at(0));
- current_function_builder_->EmitSetLocal(tmp_x.index());
+ current_function_builder_->EmitTeeLocal(tmp_x.index());
Visit(call->arguments()->at(1));
- current_function_builder_->EmitSetLocal(tmp_y.index());
+ current_function_builder_->EmitTeeLocal(tmp_y.index());
current_function_builder_->Emit(kExprI32LeS);
- current_function_builder_->Emit(kExprIf);
+ current_function_builder_->EmitWithU8(kExprIf, kLocalI32);
// then tmp_y
current_function_builder_->EmitGetLocal(tmp_y.index());
@@ -1275,18 +1337,20 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
}
}
- void VisitCall(Call* expr) {
+ void VisitCall(Call* expr) { VisitCallExpression(expr); }
+
+ bool VisitCallExpression(Call* expr) {
Call::CallType call_type = expr->GetCallType();
+ bool returns_value = true;
switch (call_type) {
case Call::OTHER_CALL: {
DCHECK_EQ(kFuncScope, scope_);
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != nullptr) {
if (VisitStdlibFunction(expr, proxy)) {
- return;
+ return true;
}
}
- uint32_t index;
VariableProxy* vp = expr->expression()->AsVariableProxy();
DCHECK_NOT_NULL(vp);
if (typer_->TypeOf(vp)->AsFFIType() != nullptr) {
@@ -1296,22 +1360,23 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
args->length());
if (return_type != kAstStmt) {
sig.AddReturn(return_type);
+ } else {
+ returns_value = false;
}
for (int i = 0; i < args->length(); ++i) {
sig.AddParam(TypeOf(args->at(i)));
}
- index =
+ uint32_t index =
imported_function_table_.GetFunctionIndex(vp->var(), sig.Build());
VisitCallArgs(expr);
- current_function_builder_->Emit(kExprCallImport);
- current_function_builder_->EmitVarInt(expr->arguments()->length());
+ current_function_builder_->Emit(kExprCallFunction);
current_function_builder_->EmitVarInt(index);
} else {
- index = LookupOrInsertFunction(vp->var());
+ WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var());
VisitCallArgs(expr);
current_function_builder_->Emit(kExprCallFunction);
- current_function_builder_->EmitVarInt(expr->arguments()->length());
- current_function_builder_->EmitVarInt(index);
+ current_function_builder_->EmitVarInt(function->func_index());
+ returns_value = function->signature()->return_count() > 0;
}
break;
}
@@ -1322,18 +1387,28 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
VariableProxy* var = p->obj()->AsVariableProxy();
DCHECK_NOT_NULL(var);
FunctionTableIndices* indices = LookupFunctionTable(var->var());
- RECURSE(Visit(p->key()));
+ 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);
+ current_function_builder_->EmitSetLocal(tmp.index());
+
VisitCallArgs(expr);
+
+ current_function_builder_->EmitGetLocal(tmp.index());
current_function_builder_->Emit(kExprCallIndirect);
- current_function_builder_->EmitVarInt(expr->arguments()->length());
current_function_builder_->EmitVarInt(indices->signature_index);
+ returns_value =
+ builder_->GetSignature(indices->signature_index)->return_count() >
+ 0;
break;
}
default:
UNREACHABLE();
}
+ return returns_value;
}
void VisitCallNew(CallNew* expr) { UNREACHABLE(); }
@@ -1519,16 +1594,13 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
RECURSE(Visit(GetLeft(expr)));
} else {
if (expr->op() == Token::COMMA) {
- current_function_builder_->Emit(kExprBlock);
+ RECURSE(VisitForEffect(expr->left()));
+ RECURSE(Visit(expr->right()));
+ return;
}
-
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- if (expr->op() == Token::COMMA) {
- current_function_builder_->Emit(kExprEnd);
- }
-
switch (expr->op()) {
BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true);
BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true);
@@ -1728,18 +1800,33 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
return (reinterpret_cast<IndexContainer*>(entry->value))->index;
}
- uint32_t LookupOrInsertFunction(Variable* v) {
+ WasmFunctionBuilder* LookupOrInsertFunction(Variable* v) {
DCHECK_NOT_NULL(builder_);
ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v));
if (entry == nullptr) {
- uint32_t index = builder_->AddFunction();
- IndexContainer* container = new (zone()) IndexContainer();
- container->index = index;
+ 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());
+ const auto& arguments = func_type->Arguments();
+ FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1,
+ arguments.size());
+ if (return_type != kAstStmt) b.AddReturn(return_type);
+ for (int i = 0; i < static_cast<int>(arguments.size()); ++i) {
+ LocalType type = TypeFrom(arguments[i]);
+ DCHECK_NE(kAstStmt, type);
+ b.AddParam(type);
+ }
+
+ WasmFunctionBuilder* function = builder_->AddFunction(b.Build());
entry = functions_.LookupOrInsert(v, ComputePointerHash(v),
ZoneAllocationPolicy(zone()));
- entry->value = container;
+ function->SetName(
+ reinterpret_cast<const char*>(v->raw_name()->raw_data()),
+ v->raw_name()->length());
+ entry->value = function;
}
- return (reinterpret_cast<IndexContainer*>(entry->value))->index;
+ return (reinterpret_cast<WasmFunctionBuilder*>(entry->value));
}
LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); }
@@ -1774,8 +1861,8 @@ class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> {
AsmTyper* typer_;
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
ZoneVector<ForeignVariable> foreign_variables_;
- uint32_t init_function_index_;
- uint32_t foreign_init_function_index_;
+ WasmFunctionBuilder* init_function_;
+ WasmFunctionBuilder* foreign_init_function_;
uint32_t next_table_index_;
ZoneHashMap function_tables_;
ImportedFunctionTable imported_function_table_;
« no previous file with comments | « src/asmjs/asm-typer.cc ('k') | src/compiler/int64-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698