Index: src/asmjs/asm-wasm-builder.cc |
diff --git a/src/asmjs/asm-wasm-builder.cc b/src/asmjs/asm-wasm-builder.cc |
index d446c4e0a323aac07579442837fa5e4b5fc35274..ac2585e6eaacc5453d317981309671a121c0ec22 100644 |
--- a/src/asmjs/asm-wasm-builder.cc |
+++ b/src/asmjs/asm-wasm-builder.cc |
@@ -32,7 +32,6 @@ |
} while (false) |
enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
-enum ValueFate { kDrop, kLeaveOnStack }; |
struct ForeignVariable { |
Handle<Name> name; |
@@ -62,8 +61,8 @@ |
typer_(typer), |
breakable_blocks_(zone), |
foreign_variables_(zone), |
- init_function_(nullptr), |
- foreign_init_function_(nullptr), |
+ init_function_index_(0), |
+ foreign_init_function_index_(0), |
next_table_index_(0), |
function_tables_(base::HashMap::PointersMatch, |
ZoneHashMap::kDefaultHashMapCapacity, |
@@ -73,33 +72,35 @@ |
} |
void InitializeInitFunction() { |
+ init_function_index_ = builder_->AddFunction(); |
FunctionSig::Builder b(zone(), 0, 0); |
- init_function_ = builder_->AddFunction(b.Build()); |
- builder_->MarkStartFunction(init_function_); |
+ current_function_builder_ = builder_->FunctionAt(init_function_index_); |
+ current_function_builder_->SetSignature(b.Build()); |
+ builder_->MarkStartFunction(init_function_index_); |
+ current_function_builder_ = nullptr; |
} |
void BuildForeignInitFunction() { |
- foreign_init_function_ = builder_->AddFunction(); |
+ foreign_init_function_index_ = 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); |
} |
- foreign_init_function_->SetExported(); |
- std::string raw_name = "__foreign_init__"; |
- foreign_init_function_->SetName( |
+ current_function_builder_ = |
+ builder_->FunctionAt(foreign_init_function_index_); |
+ current_function_builder_->SetExported(); |
+ current_function_builder_->SetName( |
AsmWasmBuilder::foreign_init_name, |
static_cast<int>(strlen(AsmWasmBuilder::foreign_init_name))); |
- |
- foreign_init_function_->SetName(raw_name.data(), |
- static_cast<int>(raw_name.size())); |
- foreign_init_function_->SetSignature(b.Build()); |
+ current_function_builder_->SetSignature(b.Build()); |
for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) { |
- foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos)); |
+ current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos)); |
ForeignVariable* fv = &foreign_variables_[pos]; |
uint32_t index = LookupOrInsertGlobal(fv->var, fv->type); |
- foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index); |
- } |
+ current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); |
+ } |
+ current_function_builder_ = nullptr; |
} |
i::Handle<i::FixedArray> GetForeignArgs() { |
@@ -112,20 +113,7 @@ |
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(); |
@@ -136,7 +124,8 @@ |
void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
DCHECK_EQ(kModuleScope, scope_); |
DCHECK_NULL(current_function_builder_); |
- current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); |
+ uint32_t index = LookupOrInsertFunction(decl->proxy()->var()); |
+ current_function_builder_ = builder_->FunctionAt(index); |
scope_ = kFuncScope; |
RECURSE(Visit(decl->fun())); |
scope_ = kModuleScope; |
@@ -168,7 +157,8 @@ |
} |
} |
if (scope_ == kFuncScope) { |
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
+ false); |
RECURSE(VisitStatements(stmt->statements())); |
} else { |
RECURSE(VisitStatements(stmt->statements())); |
@@ -181,12 +171,10 @@ |
public: |
BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
- WasmOpcode opcode) |
+ WasmOpcode opcode, bool is_loop) |
: builder_(builder) { |
- 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); |
+ builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |
+ builder_->current_function_builder_->Emit(opcode); |
} |
~BlockVisitor() { |
builder_->current_function_builder_->Emit(kExprEnd); |
@@ -195,32 +183,7 @@ |
}; |
void VisitExpressionStatement(ExpressionStatement* stmt) { |
- 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); |
+ RECURSE(Visit(stmt->expression())); |
} |
void VisitEmptyStatement(EmptyStatement* stmt) {} |
@@ -230,7 +193,7 @@ |
void VisitIfStatement(IfStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
RECURSE(Visit(stmt->condition())); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ current_function_builder_->Emit(kExprIf); |
// WASM ifs come with implement blocks for both arms. |
breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
if (stmt->HasThenStatement()) { |
@@ -244,26 +207,48 @@ |
breakable_blocks_.pop_back(); |
} |
- void DoBreakOrContinue(BreakableStatement* target, bool is_continue) { |
+ void VisitContinueStatement(ContinueStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
- for (int i = static_cast<int>(breakable_blocks_.size()) - 1; i >= 0; --i) { |
+ 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 == 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; |
- } |
- } |
- UNREACHABLE(); // statement not found |
- } |
- |
- void VisitContinueStatement(ContinueStatement* stmt) { |
- DoBreakOrContinue(stmt->target(), true); |
+ if (elem.first == stmt->target()) { |
+ DCHECK(elem.second); |
+ 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); |
} |
void VisitBreakStatement(BreakStatement* stmt) { |
- DoBreakOrContinue(stmt->target(), false); |
+ 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); |
} |
void VisitReturnStatement(ReturnStatement* stmt) { |
@@ -273,7 +258,9 @@ |
scope_ = kModuleScope; |
} else if (scope_ == kFuncScope) { |
RECURSE(Visit(stmt->expression())); |
- current_function_builder_->Emit(kExprReturn); |
+ uint8_t arity = |
+ TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1; |
+ current_function_builder_->EmitWithU8(kExprReturn, arity); |
} else { |
UNREACHABLE(); |
} |
@@ -289,7 +276,7 @@ |
VisitVariableProxy(tag); |
current_function_builder_->EmitI32Const(node->begin); |
current_function_builder_->Emit(kExprI32LtS); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ current_function_builder_->Emit(kExprIf); |
if_depth++; |
breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
HandleCase(node->left, case_to_block, tag, default_block, if_depth); |
@@ -299,7 +286,7 @@ |
VisitVariableProxy(tag); |
current_function_builder_->EmitI32Const(node->end); |
current_function_builder_->Emit(kExprI32GtS); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ current_function_builder_->Emit(kExprIf); |
if_depth++; |
breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
HandleCase(node->right, case_to_block, tag, default_block, if_depth); |
@@ -309,9 +296,9 @@ |
VisitVariableProxy(tag); |
current_function_builder_->EmitI32Const(node->begin); |
current_function_builder_->Emit(kExprI32Eq); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ current_function_builder_->Emit(kExprIf); |
DCHECK(case_to_block.find(node->begin) != case_to_block.end()); |
- current_function_builder_->Emit(kExprBr); |
+ current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
current_function_builder_->EmitVarInt(1 + if_depth + |
case_to_block[node->begin]); |
current_function_builder_->Emit(kExprEnd); |
@@ -323,22 +310,22 @@ |
} else { |
VisitVariableProxy(tag); |
} |
- current_function_builder_->Emit(kExprBrTable); |
+ current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0); |
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()) { |
- uint32_t target = if_depth + case_to_block[v]; |
- current_function_builder_->EmitVarInt(target); |
+ byte break_code[] = {BR_TARGET(if_depth + case_to_block[v])}; |
+ current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
} else { |
- uint32_t target = if_depth + default_block; |
- current_function_builder_->EmitVarInt(target); |
+ byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
+ current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
} |
if (v == kMaxInt) { |
break; |
} |
} |
- uint32_t target = if_depth + default_block; |
- current_function_builder_->EmitVarInt(target); |
+ byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
+ current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
} |
while (if_depth-- != prev_if_depth) { |
@@ -355,14 +342,14 @@ |
if (case_count == 0) { |
return; |
} |
- BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |
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)); |
+ blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); |
if (!clause->is_default()) { |
Literal* label = clause->label()->AsLiteral(); |
Handle<Object> value = label->value(); |
@@ -379,12 +366,12 @@ |
} |
if (!has_default || case_count > 1) { |
int default_block = has_default ? case_count - 1 : case_count; |
- BlockVisitor switch_logic_block(this, nullptr, kExprBlock); |
+ BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); |
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_->Emit(kExprBr); |
+ current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
current_function_builder_->EmitVarInt(default_block); |
} |
} |
@@ -401,24 +388,22 @@ |
void VisitDoWhileStatement(DoWhileStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
- BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
RECURSE(Visit(stmt->body())); |
RECURSE(Visit(stmt->cond())); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
- current_function_builder_->EmitWithU8(kExprBr, 1); |
+ current_function_builder_->Emit(kExprIf); |
+ current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
current_function_builder_->Emit(kExprEnd); |
} |
void VisitWhileStatement(WhileStatement* stmt) { |
DCHECK_EQ(kFuncScope, scope_); |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
- BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
RECURSE(Visit(stmt->cond())); |
breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
+ current_function_builder_->Emit(kExprIf); |
RECURSE(Visit(stmt->body())); |
- current_function_builder_->EmitWithU8(kExprBr, 1); |
+ current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
current_function_builder_->Emit(kExprEnd); |
breakable_blocks_.pop_back(); |
} |
@@ -428,13 +413,13 @@ |
if (stmt->init() != nullptr) { |
RECURSE(Visit(stmt->init())); |
} |
- BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); |
- BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); |
+ BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
if (stmt->cond() != nullptr) { |
RECURSE(Visit(stmt->cond())); |
current_function_builder_->Emit(kExprI32Eqz); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); |
- current_function_builder_->EmitWithU8(kExprBr, 2); |
+ current_function_builder_->Emit(kExprIf); |
+ current_function_builder_->Emit(kExprNop); |
+ current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2); |
current_function_builder_->Emit(kExprEnd); |
} |
if (stmt->body() != nullptr) { |
@@ -443,7 +428,8 @@ |
if (stmt->next() != nullptr) { |
RECURSE(Visit(stmt->next())); |
} |
- current_function_builder_->EmitWithU8(kExprBr, 0); |
+ current_function_builder_->Emit(kExprNop); |
+ current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0); |
} |
void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |
@@ -460,13 +446,19 @@ |
DeclarationScope* scope = expr->scope(); |
if (scope_ == kFuncScope) { |
if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) { |
- // Add the parameters for the function. |
+ // 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 < 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(); |
} |
@@ -484,24 +476,7 @@ |
RECURSE(Visit(expr->condition())); |
// WASM ifs come with implicit blocks for both arms. |
breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
- 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); |
+ current_function_builder_->Emit(kExprIf); |
RECURSE(Visit(expr->then_expression())); |
current_function_builder_->Emit(kExprElse); |
RECURSE(Visit(expr->else_expression())); |
@@ -579,9 +554,9 @@ |
} else if (scope_ == kExportScope) { |
Variable* var = expr->var(); |
DCHECK(var->is_function()); |
- WasmFunctionBuilder* function = LookupOrInsertFunction(var); |
- function->SetExported(); |
- function->SetName( |
+ uint32_t index = LookupOrInsertFunction(var); |
+ builder_->FunctionAt(index)->SetExported(); |
+ builder_->FunctionAt(index)->SetName( |
AsmWasmBuilder::single_function_name, |
static_cast<int>(strlen(AsmWasmBuilder::single_function_name))); |
} |
@@ -634,10 +609,11 @@ |
DCHECK(name->IsPropertyName()); |
const AstRawString* raw_name = name->AsRawPropertyName(); |
if (var->is_function()) { |
- WasmFunctionBuilder* function = LookupOrInsertFunction(var); |
- function->SetExported(); |
- function->SetName(reinterpret_cast<const char*>(raw_name->raw_data()), |
- raw_name->length()); |
+ uint32_t index = LookupOrInsertFunction(var); |
+ builder_->FunctionAt(index)->SetExported(); |
+ builder_->FunctionAt(index)->SetName( |
+ reinterpret_cast<const char*>(raw_name->raw_data()), |
+ raw_name->length()); |
} |
} |
} |
@@ -645,7 +621,7 @@ |
void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
void LoadInitFunction() { |
- current_function_builder_ = init_function_; |
+ current_function_builder_ = builder_->FunctionAt(init_function_index_); |
scope_ = kInitScope; |
} |
@@ -674,8 +650,7 @@ |
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()); |
+ builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); |
} |
} |
@@ -705,11 +680,12 @@ |
private: |
class ImportedFunctionIndices : public ZoneObject { |
public: |
- bool has_name_; |
+ const char* name_; |
+ int name_length_; |
WasmModuleBuilder::SignatureMap signature_to_index_; |
- explicit ImportedFunctionIndices(Zone* zone) |
- : has_name_(false), signature_to_index_(zone) {} |
+ ImportedFunctionIndices(const char* name, int name_length, Zone* zone) |
+ : name_(name), name_length_(name_length), signature_to_index_(zone) {} |
}; |
ZoneHashMap table_; |
AsmWasmBuilderImpl* builder_; |
@@ -721,50 +697,29 @@ |
ZoneAllocationPolicy(builder->zone())), |
builder_(builder) {} |
- // 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. |
+ 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; |
+ } |
+ |
uint32_t GetFunctionIndex(Variable* v, FunctionSig* 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); |
+ 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); |
indices->signature_to_index_[sig] = index; |
- } |
- } |
- |
- ImportedFunctionIndices* GetEntry(Variable* v) { |
- auto entry = table_.Lookup(v, ComputePointerHash(v)); |
- if (entry == nullptr) return nullptr; |
- return reinterpret_cast<ImportedFunctionIndices*>(entry->value); |
+ return index; |
+ } |
} |
}; |
@@ -827,7 +782,7 @@ |
RECURSE(Visit(value)); |
} |
- void EmitAssignment(Assignment* expr, MachineType type, ValueFate fate) { |
+ void EmitAssignment(Assignment* expr, MachineType type) { |
// Match the left hand side of the assignment. |
VariableProxy* target_var = expr->target()->AsVariableProxy(); |
if (target_var != nullptr) { |
@@ -836,19 +791,11 @@ |
LocalType var_type = TypeOf(expr); |
DCHECK_NE(kAstStmt, var_type); |
if (var->IsContextSlot()) { |
- uint32_t index = LookupOrInsertGlobal(var, var_type); |
- current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); |
- if (fate == kLeaveOnStack) { |
- current_function_builder_->EmitWithVarInt(kExprGetGlobal, index); |
- } |
+ current_function_builder_->EmitWithVarInt( |
+ kExprSetGlobal, LookupOrInsertGlobal(var, var_type)); |
} else { |
- if (fate == kDrop) { |
- current_function_builder_->EmitSetLocal( |
- LookupOrInsertLocal(var, var_type)); |
- } else { |
- current_function_builder_->EmitTeeLocal( |
- LookupOrInsertLocal(var, var_type)); |
- } |
+ current_function_builder_->EmitSetLocal( |
+ LookupOrInsertLocal(var, var_type)); |
} |
} |
@@ -860,7 +807,6 @@ |
->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; |
@@ -882,10 +828,6 @@ |
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) { |
@@ -894,10 +836,6 @@ |
} |
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: |
@@ -915,7 +853,7 @@ |
if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
const AstRawString* name = |
prop->key()->AsLiteral()->AsRawPropertyName(); |
- imported_function_table_.SetImportName( |
+ imported_function_table_.AddImport( |
target->var(), reinterpret_cast<const char*>(name->raw_data()), |
name->length()); |
} |
@@ -943,12 +881,12 @@ |
} |
if (as_init) LoadInitFunction(); |
- MachineType mtype = MachineType::None(); |
+ MachineType mtype; |
bool is_nop = false; |
EmitAssignmentLhs(expr->target(), &mtype); |
EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
if (!is_nop) { |
- EmitAssignment(expr, mtype, fate); |
+ EmitAssignment(expr, mtype); |
} |
if (as_init) UnLoadInitFunction(); |
} |
@@ -1173,11 +1111,11 @@ |
// if set_local(tmp, x) < 0 |
Visit(call->arguments()->at(0)); |
- current_function_builder_->EmitTeeLocal(tmp.index()); |
+ current_function_builder_->EmitSetLocal(tmp.index()); |
byte code[] = {WASM_I8(0)}; |
current_function_builder_->EmitCode(code, sizeof(code)); |
current_function_builder_->Emit(kExprI32LtS); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalI32); |
+ current_function_builder_->Emit(kExprIf); |
// then (0 - tmp) |
current_function_builder_->EmitCode(code, sizeof(code)); |
@@ -1209,13 +1147,13 @@ |
// if set_local(tmp_x, x) < set_local(tmp_y, y) |
Visit(call->arguments()->at(0)); |
- current_function_builder_->EmitTeeLocal(tmp_x.index()); |
+ current_function_builder_->EmitSetLocal(tmp_x.index()); |
Visit(call->arguments()->at(1)); |
- current_function_builder_->EmitTeeLocal(tmp_y.index()); |
+ current_function_builder_->EmitSetLocal(tmp_y.index()); |
current_function_builder_->Emit(kExprI32LeS); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalI32); |
+ current_function_builder_->Emit(kExprIf); |
// then tmp_x |
current_function_builder_->EmitGetLocal(tmp_x.index()); |
@@ -1245,13 +1183,13 @@ |
// if set_local(tmp_x, x) < set_local(tmp_y, y) |
Visit(call->arguments()->at(0)); |
- current_function_builder_->EmitTeeLocal(tmp_x.index()); |
+ current_function_builder_->EmitSetLocal(tmp_x.index()); |
Visit(call->arguments()->at(1)); |
- current_function_builder_->EmitTeeLocal(tmp_y.index()); |
+ current_function_builder_->EmitSetLocal(tmp_y.index()); |
current_function_builder_->Emit(kExprI32LeS); |
- current_function_builder_->EmitWithU8(kExprIf, kLocalI32); |
+ current_function_builder_->Emit(kExprIf); |
// then tmp_y |
current_function_builder_->EmitGetLocal(tmp_y.index()); |
@@ -1337,20 +1275,18 @@ |
} |
} |
- void VisitCall(Call* expr) { VisitCallExpression(expr); } |
- |
- bool VisitCallExpression(Call* expr) { |
+ void VisitCall(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 true; |
+ return; |
} |
} |
+ uint32_t index; |
VariableProxy* vp = expr->expression()->AsVariableProxy(); |
DCHECK_NOT_NULL(vp); |
if (typer_->TypeOf(vp)->AsFFIType() != nullptr) { |
@@ -1360,23 +1296,22 @@ |
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))); |
} |
- uint32_t index = |
+ index = |
imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
VisitCallArgs(expr); |
- current_function_builder_->Emit(kExprCallFunction); |
+ current_function_builder_->Emit(kExprCallImport); |
+ current_function_builder_->EmitVarInt(expr->arguments()->length()); |
current_function_builder_->EmitVarInt(index); |
} else { |
- WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); |
+ index = LookupOrInsertFunction(vp->var()); |
VisitCallArgs(expr); |
current_function_builder_->Emit(kExprCallFunction); |
- current_function_builder_->EmitVarInt(function->func_index()); |
- returns_value = function->signature()->return_count() > 0; |
+ current_function_builder_->EmitVarInt(expr->arguments()->length()); |
+ current_function_builder_->EmitVarInt(index); |
} |
break; |
} |
@@ -1387,28 +1322,18 @@ |
VariableProxy* var = p->obj()->AsVariableProxy(); |
DCHECK_NOT_NULL(var); |
FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
- Visit(p->key()); // TODO(titzer): should use RECURSE() |
- |
- // We have to use a temporary for the correct order of evaluation. |
+ RECURSE(Visit(p->key())); |
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(); } |
@@ -1594,12 +1519,15 @@ |
RECURSE(Visit(GetLeft(expr))); |
} else { |
if (expr->op() == Token::COMMA) { |
- RECURSE(VisitForEffect(expr->left())); |
- RECURSE(Visit(expr->right())); |
- return; |
- } |
+ current_function_builder_->Emit(kExprBlock); |
+ } |
+ |
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); |
@@ -1800,33 +1728,18 @@ |
return (reinterpret_cast<IndexContainer*>(entry->value))->index; |
} |
- WasmFunctionBuilder* LookupOrInsertFunction(Variable* v) { |
+ uint32_t LookupOrInsertFunction(Variable* v) { |
DCHECK_NOT_NULL(builder_); |
ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v)); |
if (entry == nullptr) { |
- 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()); |
+ uint32_t index = builder_->AddFunction(); |
+ IndexContainer* container = new (zone()) IndexContainer(); |
+ container->index = index; |
entry = functions_.LookupOrInsert(v, ComputePointerHash(v), |
ZoneAllocationPolicy(zone())); |
- function->SetName( |
- reinterpret_cast<const char*>(v->raw_name()->raw_data()), |
- v->raw_name()->length()); |
- entry->value = function; |
- } |
- return (reinterpret_cast<WasmFunctionBuilder*>(entry->value)); |
+ entry->value = container; |
+ } |
+ return (reinterpret_cast<IndexContainer*>(entry->value))->index; |
} |
LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); } |
@@ -1861,8 +1774,8 @@ |
AsmTyper* typer_; |
ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
ZoneVector<ForeignVariable> foreign_variables_; |
- WasmFunctionBuilder* init_function_; |
- WasmFunctionBuilder* foreign_init_function_; |
+ uint32_t init_function_index_; |
+ uint32_t foreign_init_function_index_; |
uint32_t next_table_index_; |
ZoneHashMap function_tables_; |
ImportedFunctionTable imported_function_table_; |