| OLD | NEW | 
|     1 // Copyright 2015 the V8 project authors. All rights reserved. |     1 // Copyright 2015 the V8 project authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include "src/v8.h" |     5 #include "src/v8.h" | 
|     6  |     6  | 
|     7 // Required to get M_E etc. in MSVC. |     7 // Required to get M_E etc. in MSVC. | 
|     8 #if defined(_WIN32) |     8 #if defined(_WIN32) | 
|     9 #define _USE_MATH_DEFINES |     9 #define _USE_MATH_DEFINES | 
|    10 #endif |    10 #endif | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|    25 namespace wasm { |    25 namespace wasm { | 
|    26  |    26  | 
|    27 #define RECURSE(call)               \ |    27 #define RECURSE(call)               \ | 
|    28   do {                              \ |    28   do {                              \ | 
|    29     DCHECK(!HasStackOverflow());    \ |    29     DCHECK(!HasStackOverflow());    \ | 
|    30     call;                           \ |    30     call;                           \ | 
|    31     if (HasStackOverflow()) return; \ |    31     if (HasStackOverflow()) return; \ | 
|    32   } while (false) |    32   } while (false) | 
|    33  |    33  | 
|    34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |    34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | 
 |    35 enum ValueFate { kDrop, kLeaveOnStack }; | 
|    35  |    36  | 
|    36 struct ForeignVariable { |    37 struct ForeignVariable { | 
|    37   Handle<Name> name; |    38   Handle<Name> name; | 
|    38   Variable* var; |    39   Variable* var; | 
|    39   LocalType type; |    40   LocalType type; | 
|    40 }; |    41 }; | 
|    41  |    42  | 
|    42 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |    43 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { | 
|    43  public: |    44  public: | 
|    44   AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |    45   AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 
|    45                      AsmTyper* typer) |    46                      AsmTyper* typer) | 
|    46       : local_variables_(base::HashMap::PointersMatch, |    47       : local_variables_(base::HashMap::PointersMatch, | 
|    47                          ZoneHashMap::kDefaultHashMapCapacity, |    48                          ZoneHashMap::kDefaultHashMapCapacity, | 
|    48                          ZoneAllocationPolicy(zone)), |    49                          ZoneAllocationPolicy(zone)), | 
|    49         functions_(base::HashMap::PointersMatch, |    50         functions_(base::HashMap::PointersMatch, | 
|    50                    ZoneHashMap::kDefaultHashMapCapacity, |    51                    ZoneHashMap::kDefaultHashMapCapacity, | 
|    51                    ZoneAllocationPolicy(zone)), |    52                    ZoneAllocationPolicy(zone)), | 
|    52         global_variables_(base::HashMap::PointersMatch, |    53         global_variables_(base::HashMap::PointersMatch, | 
|    53                           ZoneHashMap::kDefaultHashMapCapacity, |    54                           ZoneHashMap::kDefaultHashMapCapacity, | 
|    54                           ZoneAllocationPolicy(zone)), |    55                           ZoneAllocationPolicy(zone)), | 
|    55         scope_(kModuleScope), |    56         scope_(kModuleScope), | 
|    56         builder_(new (zone) WasmModuleBuilder(zone)), |    57         builder_(new (zone) WasmModuleBuilder(zone)), | 
|    57         current_function_builder_(nullptr), |    58         current_function_builder_(nullptr), | 
|    58         literal_(literal), |    59         literal_(literal), | 
|    59         isolate_(isolate), |    60         isolate_(isolate), | 
|    60         zone_(zone), |    61         zone_(zone), | 
|    61         typer_(typer), |    62         typer_(typer), | 
|    62         breakable_blocks_(zone), |    63         breakable_blocks_(zone), | 
|    63         foreign_variables_(zone), |    64         foreign_variables_(zone), | 
|    64         init_function_index_(0), |    65         init_function_(nullptr), | 
|    65         foreign_init_function_index_(0), |    66         foreign_init_function_(nullptr), | 
|    66         next_table_index_(0), |    67         next_table_index_(0), | 
|    67         function_tables_(base::HashMap::PointersMatch, |    68         function_tables_(base::HashMap::PointersMatch, | 
|    68                          ZoneHashMap::kDefaultHashMapCapacity, |    69                          ZoneHashMap::kDefaultHashMapCapacity, | 
|    69                          ZoneAllocationPolicy(zone)), |    70                          ZoneAllocationPolicy(zone)), | 
|    70         imported_function_table_(this) { |    71         imported_function_table_(this) { | 
|    71     InitializeAstVisitor(isolate); |    72     InitializeAstVisitor(isolate); | 
|    72   } |    73   } | 
|    73  |    74  | 
|    74   void InitializeInitFunction() { |    75   void InitializeInitFunction() { | 
|    75     init_function_index_ = builder_->AddFunction(); |  | 
|    76     FunctionSig::Builder b(zone(), 0, 0); |    76     FunctionSig::Builder b(zone(), 0, 0); | 
|    77     current_function_builder_ = builder_->FunctionAt(init_function_index_); |    77     init_function_ = builder_->AddFunction(b.Build()); | 
|    78     current_function_builder_->SetSignature(b.Build()); |    78     builder_->MarkStartFunction(init_function_); | 
|    79     builder_->MarkStartFunction(init_function_index_); |  | 
|    80     current_function_builder_ = nullptr; |  | 
|    81   } |    79   } | 
|    82  |    80  | 
|    83   void BuildForeignInitFunction() { |    81   void BuildForeignInitFunction() { | 
|    84     foreign_init_function_index_ = builder_->AddFunction(); |    82     foreign_init_function_ = builder_->AddFunction(); | 
|    85     FunctionSig::Builder b(zone(), 0, foreign_variables_.size()); |    83     FunctionSig::Builder b(zone(), 0, foreign_variables_.size()); | 
|    86     for (auto i = foreign_variables_.begin(); i != foreign_variables_.end(); |    84     for (auto i = foreign_variables_.begin(); i != foreign_variables_.end(); | 
|    87          ++i) { |    85          ++i) { | 
|    88       b.AddParam(i->type); |    86       b.AddParam(i->type); | 
|    89     } |    87     } | 
|    90     current_function_builder_ = |    88     foreign_init_function_->SetExported(); | 
|    91         builder_->FunctionAt(foreign_init_function_index_); |  | 
|    92     current_function_builder_->SetExported(); |  | 
|    93     std::string raw_name = "__foreign_init__"; |    89     std::string raw_name = "__foreign_init__"; | 
|    94     current_function_builder_->SetName(raw_name.data(), |    90     foreign_init_function_->SetName(raw_name.data(), | 
|    95                                        static_cast<int>(raw_name.size())); |    91                                     static_cast<int>(raw_name.size())); | 
|    96     current_function_builder_->SetSignature(b.Build()); |    92     foreign_init_function_->SetSignature(b.Build()); | 
|    97     for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) { |    93     for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) { | 
|    98       current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos)); |    94       foreign_init_function_->EmitGetLocal(static_cast<uint32_t>(pos)); | 
|    99       ForeignVariable* fv = &foreign_variables_[pos]; |    95       ForeignVariable* fv = &foreign_variables_[pos]; | 
|   100       uint32_t index = LookupOrInsertGlobal(fv->var, fv->type); |    96       uint32_t index = LookupOrInsertGlobal(fv->var, fv->type); | 
|   101       current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); |    97       foreign_init_function_->EmitWithVarInt(kExprSetGlobal, index); | 
|   102     } |    98     } | 
|   103     current_function_builder_ = nullptr; |  | 
|   104   } |    99   } | 
|   105  |   100  | 
|   106   i::Handle<i::FixedArray> GetForeignArgs() { |   101   i::Handle<i::FixedArray> GetForeignArgs() { | 
|   107     i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( |   102     i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( | 
|   108         static_cast<int>(foreign_variables_.size())); |   103         static_cast<int>(foreign_variables_.size())); | 
|   109     for (size_t i = 0; i < foreign_variables_.size(); ++i) { |   104     for (size_t i = 0; i < foreign_variables_.size(); ++i) { | 
|   110       ForeignVariable* fv = &foreign_variables_[i]; |   105       ForeignVariable* fv = &foreign_variables_[i]; | 
|   111       ret->set(static_cast<int>(i), *fv->name); |   106       ret->set(static_cast<int>(i), *fv->name); | 
|   112     } |   107     } | 
|   113     return ret; |   108     return ret; | 
|   114   } |   109   } | 
|   115  |   110  | 
 |   111   void BuildImports() { | 
 |   112     for (const AsmTyper::FFIUseSignature& ffi : *typer_->FFIUseSignatures()) { | 
 |   113       size_t ret_count = ffi.return_type_ == AsmType::Void() ? 0 : 1; | 
 |   114       FunctionSig::Builder b(zone_, ret_count, ffi.arg_types_.size()); | 
 |   115       for (AsmType* arg : ffi.arg_types_) b.AddParam(TypeFrom(arg)); | 
 |   116       if (ffi.return_type_ != AsmType::Void()) { | 
 |   117         b.AddReturn(TypeFrom(ffi.return_type_)); | 
 |   118       } | 
 |   119       imported_function_table_.AddFunction(ffi.var, b.Build()); | 
 |   120     } | 
 |   121   } | 
 |   122  | 
|   116   void Build() { |   123   void Build() { | 
 |   124     BuildImports(); | 
|   117     InitializeInitFunction(); |   125     InitializeInitFunction(); | 
|   118     RECURSE(VisitFunctionLiteral(literal_)); |   126     RECURSE(VisitFunctionLiteral(literal_)); | 
|   119     BuildForeignInitFunction(); |   127     BuildForeignInitFunction(); | 
|   120   } |   128   } | 
|   121  |   129  | 
|   122   void VisitVariableDeclaration(VariableDeclaration* decl) {} |   130   void VisitVariableDeclaration(VariableDeclaration* decl) {} | 
|   123  |   131  | 
|   124   void VisitFunctionDeclaration(FunctionDeclaration* decl) { |   132   void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 
|   125     DCHECK_EQ(kModuleScope, scope_); |   133     DCHECK_EQ(kModuleScope, scope_); | 
|   126     DCHECK_NULL(current_function_builder_); |   134     DCHECK_NULL(current_function_builder_); | 
|   127     uint32_t index = LookupOrInsertFunction(decl->proxy()->var()); |   135     current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); | 
|   128     current_function_builder_ = builder_->FunctionAt(index); |  | 
|   129     scope_ = kFuncScope; |   136     scope_ = kFuncScope; | 
|   130     RECURSE(Visit(decl->fun())); |   137     RECURSE(Visit(decl->fun())); | 
|   131     scope_ = kModuleScope; |   138     scope_ = kModuleScope; | 
|   132     current_function_builder_ = nullptr; |   139     current_function_builder_ = nullptr; | 
|   133     local_variables_.Clear(); |   140     local_variables_.Clear(); | 
|   134   } |   141   } | 
|   135  |   142  | 
|   136   void VisitStatements(ZoneList<Statement*>* stmts) { |   143   void VisitStatements(ZoneList<Statement*>* stmts) { | 
|   137     for (int i = 0; i < stmts->length(); ++i) { |   144     for (int i = 0; i < stmts->length(); ++i) { | 
|   138       Statement* stmt = stmts->at(i); |   145       Statement* stmt = stmts->at(i); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   150       ExpressionStatement* expr = |   157       ExpressionStatement* expr = | 
|   151           stmt->statements()->at(0)->AsExpressionStatement(); |   158           stmt->statements()->at(0)->AsExpressionStatement(); | 
|   152       if (expr != nullptr) { |   159       if (expr != nullptr) { | 
|   153         if (expr->expression()->IsAssignment()) { |   160         if (expr->expression()->IsAssignment()) { | 
|   154           RECURSE(VisitExpressionStatement(expr)); |   161           RECURSE(VisitExpressionStatement(expr)); | 
|   155           return; |   162           return; | 
|   156         } |   163         } | 
|   157       } |   164       } | 
|   158     } |   165     } | 
|   159     if (scope_ == kFuncScope) { |   166     if (scope_ == kFuncScope) { | 
|   160       BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |   167       BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); | 
|   161                            false); |  | 
|   162       RECURSE(VisitStatements(stmt->statements())); |   168       RECURSE(VisitStatements(stmt->statements())); | 
|   163     } else { |   169     } else { | 
|   164       RECURSE(VisitStatements(stmt->statements())); |   170       RECURSE(VisitStatements(stmt->statements())); | 
|   165     } |   171     } | 
|   166   } |   172   } | 
|   167  |   173  | 
|   168   class BlockVisitor { |   174   class BlockVisitor { | 
|   169    private: |   175    private: | 
|   170     AsmWasmBuilderImpl* builder_; |   176     AsmWasmBuilderImpl* builder_; | 
|   171  |   177  | 
|   172    public: |   178    public: | 
|   173     BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |   179     BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, | 
|   174                  WasmOpcode opcode, bool is_loop) |   180                  WasmOpcode opcode) | 
|   175         : builder_(builder) { |   181         : builder_(builder) { | 
|   176       builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |   182       builder_->breakable_blocks_.push_back( | 
|   177       builder_->current_function_builder_->Emit(opcode); |   183           std::make_pair(stmt, opcode == kExprLoop)); | 
 |   184       // block and loops have a type immediate. | 
 |   185       builder_->current_function_builder_->EmitWithU8(opcode, kLocalVoid); | 
|   178     } |   186     } | 
|   179     ~BlockVisitor() { |   187     ~BlockVisitor() { | 
|   180       builder_->current_function_builder_->Emit(kExprEnd); |   188       builder_->current_function_builder_->Emit(kExprEnd); | 
|   181       builder_->breakable_blocks_.pop_back(); |   189       builder_->breakable_blocks_.pop_back(); | 
|   182     } |   190     } | 
|   183   }; |   191   }; | 
|   184  |   192  | 
|   185   void VisitExpressionStatement(ExpressionStatement* stmt) { |   193   void VisitExpressionStatement(ExpressionStatement* stmt) { | 
|   186     RECURSE(Visit(stmt->expression())); |   194     VisitForEffect(stmt->expression()); | 
 |   195   } | 
 |   196  | 
 |   197   void VisitForEffect(Expression* expr) { | 
 |   198     if (expr->IsAssignment()) { | 
 |   199       // Don't emit drops for assignments. Instead use SetLocal/GetLocal. | 
 |   200       VisitAssignment(expr->AsAssignment(), kDrop); | 
 |   201       return; | 
 |   202     } | 
 |   203     if (expr->IsCall()) { | 
 |   204       // Only emit a drop if the call has a non-void return value. | 
 |   205       if (VisitCallExpression(expr->AsCall()) && scope_ == kFuncScope) { | 
 |   206         current_function_builder_->Emit(kExprDrop); | 
 |   207       } | 
 |   208       return; | 
 |   209     } | 
 |   210     if (expr->IsBinaryOperation()) { | 
 |   211       BinaryOperation* binop = expr->AsBinaryOperation(); | 
 |   212       if (binop->op() == Token::COMMA) { | 
 |   213         VisitForEffect(binop->left()); | 
 |   214         VisitForEffect(binop->right()); | 
 |   215         return; | 
 |   216       } | 
 |   217     } | 
 |   218     RECURSE(Visit(expr)); | 
 |   219     if (scope_ == kFuncScope) current_function_builder_->Emit(kExprDrop); | 
|   187   } |   220   } | 
|   188  |   221  | 
|   189   void VisitEmptyStatement(EmptyStatement* stmt) {} |   222   void VisitEmptyStatement(EmptyStatement* stmt) {} | 
|   190  |   223  | 
|   191   void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } |   224   void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } | 
|   192  |   225  | 
|   193   void VisitIfStatement(IfStatement* stmt) { |   226   void VisitIfStatement(IfStatement* stmt) { | 
|   194     DCHECK_EQ(kFuncScope, scope_); |   227     DCHECK_EQ(kFuncScope, scope_); | 
|   195     RECURSE(Visit(stmt->condition())); |   228     RECURSE(Visit(stmt->condition())); | 
|   196     current_function_builder_->Emit(kExprIf); |   229     current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   197     // WASM ifs come with implement blocks for both arms. |   230     // WASM ifs come with implement blocks for both arms. | 
|   198     breakable_blocks_.push_back(std::make_pair(nullptr, false)); |   231     breakable_blocks_.push_back(std::make_pair(nullptr, false)); | 
|   199     if (stmt->HasThenStatement()) { |   232     if (stmt->HasThenStatement()) { | 
|   200       RECURSE(Visit(stmt->then_statement())); |   233       RECURSE(Visit(stmt->then_statement())); | 
|   201     } |   234     } | 
|   202     if (stmt->HasElseStatement()) { |   235     if (stmt->HasElseStatement()) { | 
|   203       current_function_builder_->Emit(kExprElse); |   236       current_function_builder_->Emit(kExprElse); | 
|   204       RECURSE(Visit(stmt->else_statement())); |   237       RECURSE(Visit(stmt->else_statement())); | 
|   205     } |   238     } | 
|   206     current_function_builder_->Emit(kExprEnd); |   239     current_function_builder_->Emit(kExprEnd); | 
|   207     breakable_blocks_.pop_back(); |   240     breakable_blocks_.pop_back(); | 
|   208   } |   241   } | 
|   209  |   242  | 
|   210   void VisitContinueStatement(ContinueStatement* stmt) { |   243   void DoBreakOrContinue(BreakableStatement* target, bool is_continue) { | 
|   211     DCHECK_EQ(kFuncScope, scope_); |   244     DCHECK_EQ(kFuncScope, scope_); | 
|   212     DCHECK_NOT_NULL(stmt->target()); |   245     for (int i = static_cast<int>(breakable_blocks_.size()) - 1; i >= 0; i--) { | 
|   213     int i = static_cast<int>(breakable_blocks_.size()) - 1; |  | 
|   214     int block_distance = 0; |  | 
|   215     for (; i >= 0; i--) { |  | 
|   216       auto elem = breakable_blocks_.at(i); |   246       auto elem = breakable_blocks_.at(i); | 
|   217       if (elem.first == stmt->target()) { |   247       if (elem.first == target && elem.second == is_continue) { | 
|   218         DCHECK(elem.second); |   248         int block_distance = static_cast<int>(breakable_blocks_.size() - i - 1); | 
|   219         break; |   249         current_function_builder_->Emit(kExprBr); | 
|   220       } else if (elem.second) { |   250         current_function_builder_->EmitVarInt(block_distance); | 
|   221         block_distance += 2; |   251         return; | 
|   222       } else { |  | 
|   223         block_distance += 1; |  | 
|   224       } |   252       } | 
|   225     } |   253     } | 
|   226     DCHECK(i >= 0); |   254     UNREACHABLE();  // statement not found | 
|   227     current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |   255   } | 
|   228     current_function_builder_->EmitVarInt(block_distance); |   256  | 
 |   257   void VisitContinueStatement(ContinueStatement* stmt) { | 
 |   258     DoBreakOrContinue(stmt->target(), true); | 
|   229   } |   259   } | 
|   230  |   260  | 
|   231   void VisitBreakStatement(BreakStatement* stmt) { |   261   void VisitBreakStatement(BreakStatement* stmt) { | 
|   232     DCHECK_EQ(kFuncScope, scope_); |   262     DoBreakOrContinue(stmt->target(), false); | 
|   233     DCHECK_NOT_NULL(stmt->target()); |  | 
|   234     int i = static_cast<int>(breakable_blocks_.size()) - 1; |  | 
|   235     int block_distance = 0; |  | 
|   236     for (; i >= 0; i--) { |  | 
|   237       auto elem = breakable_blocks_.at(i); |  | 
|   238       if (elem.first == stmt->target()) { |  | 
|   239         if (elem.second) { |  | 
|   240           block_distance++; |  | 
|   241         } |  | 
|   242         break; |  | 
|   243       } else if (elem.second) { |  | 
|   244         block_distance += 2; |  | 
|   245       } else { |  | 
|   246         block_distance += 1; |  | 
|   247       } |  | 
|   248     } |  | 
|   249     DCHECK(i >= 0); |  | 
|   250     current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |  | 
|   251     current_function_builder_->EmitVarInt(block_distance); |  | 
|   252   } |   263   } | 
|   253  |   264  | 
|   254   void VisitReturnStatement(ReturnStatement* stmt) { |   265   void VisitReturnStatement(ReturnStatement* stmt) { | 
|   255     if (scope_ == kModuleScope) { |   266     if (scope_ == kModuleScope) { | 
|   256       scope_ = kExportScope; |   267       scope_ = kExportScope; | 
|   257       RECURSE(Visit(stmt->expression())); |   268       RECURSE(Visit(stmt->expression())); | 
|   258       scope_ = kModuleScope; |   269       scope_ = kModuleScope; | 
|   259     } else if (scope_ == kFuncScope) { |   270     } else if (scope_ == kFuncScope) { | 
|   260       RECURSE(Visit(stmt->expression())); |   271       RECURSE(Visit(stmt->expression())); | 
|   261       uint8_t arity = |   272       current_function_builder_->Emit(kExprReturn); | 
|   262           TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1; |  | 
|   263       current_function_builder_->EmitWithU8(kExprReturn, arity); |  | 
|   264     } else { |   273     } else { | 
|   265       UNREACHABLE(); |   274       UNREACHABLE(); | 
|   266     } |   275     } | 
|   267   } |   276   } | 
|   268  |   277  | 
|   269   void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |   278   void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 
|   270  |   279  | 
|   271   void HandleCase(CaseNode* node, |   280   void HandleCase(CaseNode* node, | 
|   272                   ZoneMap<int, unsigned int>& case_to_block, |   281                   ZoneMap<int, unsigned int>& case_to_block, | 
|   273                   VariableProxy* tag, int default_block, int if_depth) { |   282                   VariableProxy* tag, int default_block, int if_depth) { | 
|   274     int prev_if_depth = if_depth; |   283     int prev_if_depth = if_depth; | 
|   275     if (node->left != nullptr) { |   284     if (node->left != nullptr) { | 
|   276       VisitVariableProxy(tag); |   285       VisitVariableProxy(tag); | 
|   277       current_function_builder_->EmitI32Const(node->begin); |   286       current_function_builder_->EmitI32Const(node->begin); | 
|   278       current_function_builder_->Emit(kExprI32LtS); |   287       current_function_builder_->Emit(kExprI32LtS); | 
|   279       current_function_builder_->Emit(kExprIf); |   288       current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   280       if_depth++; |   289       if_depth++; | 
|   281       breakable_blocks_.push_back(std::make_pair(nullptr, false)); |   290       breakable_blocks_.push_back(std::make_pair(nullptr, false)); | 
|   282       HandleCase(node->left, case_to_block, tag, default_block, if_depth); |   291       HandleCase(node->left, case_to_block, tag, default_block, if_depth); | 
|   283       current_function_builder_->Emit(kExprElse); |   292       current_function_builder_->Emit(kExprElse); | 
|   284     } |   293     } | 
|   285     if (node->right != nullptr) { |   294     if (node->right != nullptr) { | 
|   286       VisitVariableProxy(tag); |   295       VisitVariableProxy(tag); | 
|   287       current_function_builder_->EmitI32Const(node->end); |   296       current_function_builder_->EmitI32Const(node->end); | 
|   288       current_function_builder_->Emit(kExprI32GtS); |   297       current_function_builder_->Emit(kExprI32GtS); | 
|   289       current_function_builder_->Emit(kExprIf); |   298       current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   290       if_depth++; |   299       if_depth++; | 
|   291       breakable_blocks_.push_back(std::make_pair(nullptr, false)); |   300       breakable_blocks_.push_back(std::make_pair(nullptr, false)); | 
|   292       HandleCase(node->right, case_to_block, tag, default_block, if_depth); |   301       HandleCase(node->right, case_to_block, tag, default_block, if_depth); | 
|   293       current_function_builder_->Emit(kExprElse); |   302       current_function_builder_->Emit(kExprElse); | 
|   294     } |   303     } | 
|   295     if (node->begin == node->end) { |   304     if (node->begin == node->end) { | 
|   296       VisitVariableProxy(tag); |   305       VisitVariableProxy(tag); | 
|   297       current_function_builder_->EmitI32Const(node->begin); |   306       current_function_builder_->EmitI32Const(node->begin); | 
|   298       current_function_builder_->Emit(kExprI32Eq); |   307       current_function_builder_->Emit(kExprI32Eq); | 
|   299       current_function_builder_->Emit(kExprIf); |   308       current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   300       DCHECK(case_to_block.find(node->begin) != case_to_block.end()); |   309       DCHECK(case_to_block.find(node->begin) != case_to_block.end()); | 
|   301       current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |   310       current_function_builder_->Emit(kExprBr); | 
|   302       current_function_builder_->EmitVarInt(1 + if_depth + |   311       current_function_builder_->EmitVarInt(1 + if_depth + | 
|   303                                             case_to_block[node->begin]); |   312                                             case_to_block[node->begin]); | 
|   304       current_function_builder_->Emit(kExprEnd); |   313       current_function_builder_->Emit(kExprEnd); | 
|   305     } else { |   314     } else { | 
|   306       if (node->begin != 0) { |   315       if (node->begin != 0) { | 
|   307         VisitVariableProxy(tag); |   316         VisitVariableProxy(tag); | 
|   308         current_function_builder_->EmitI32Const(node->begin); |   317         current_function_builder_->EmitI32Const(node->begin); | 
|   309         current_function_builder_->Emit(kExprI32Sub); |   318         current_function_builder_->Emit(kExprI32Sub); | 
|   310       } else { |   319       } else { | 
|   311         VisitVariableProxy(tag); |   320         VisitVariableProxy(tag); | 
|   312       } |   321       } | 
|   313       current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0); |   322       current_function_builder_->Emit(kExprBrTable); | 
|   314       current_function_builder_->EmitVarInt(node->end - node->begin + 1); |   323       current_function_builder_->EmitVarInt(node->end - node->begin + 1); | 
|   315       for (int v = node->begin; v <= node->end; v++) { |   324       for (int v = node->begin; v <= node->end; v++) { | 
|   316         if (case_to_block.find(v) != case_to_block.end()) { |   325         if (case_to_block.find(v) != case_to_block.end()) { | 
|   317           byte break_code[] = {BR_TARGET(if_depth + case_to_block[v])}; |   326           byte break_code[] = {BR_TARGET(if_depth + case_to_block[v])}; | 
|   318           current_function_builder_->EmitCode(break_code, sizeof(break_code)); |   327           current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 
|   319         } else { |   328         } else { | 
|   320           byte break_code[] = {BR_TARGET(if_depth + default_block)}; |   329           byte break_code[] = {BR_TARGET(if_depth + default_block)}; | 
|   321           current_function_builder_->EmitCode(break_code, sizeof(break_code)); |   330           current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 
|   322         } |   331         } | 
|   323         if (v == kMaxInt) { |   332         if (v == kMaxInt) { | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|   335   } |   344   } | 
|   336  |   345  | 
|   337   void VisitSwitchStatement(SwitchStatement* stmt) { |   346   void VisitSwitchStatement(SwitchStatement* stmt) { | 
|   338     VariableProxy* tag = stmt->tag()->AsVariableProxy(); |   347     VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 
|   339     DCHECK_NOT_NULL(tag); |   348     DCHECK_NOT_NULL(tag); | 
|   340     ZoneList<CaseClause*>* clauses = stmt->cases(); |   349     ZoneList<CaseClause*>* clauses = stmt->cases(); | 
|   341     int case_count = clauses->length(); |   350     int case_count = clauses->length(); | 
|   342     if (case_count == 0) { |   351     if (case_count == 0) { | 
|   343       return; |   352       return; | 
|   344     } |   353     } | 
|   345     BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |   354     BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock); | 
|   346     ZoneVector<BlockVisitor*> blocks(zone_); |   355     ZoneVector<BlockVisitor*> blocks(zone_); | 
|   347     ZoneVector<int32_t> cases(zone_); |   356     ZoneVector<int32_t> cases(zone_); | 
|   348     ZoneMap<int, unsigned int> case_to_block(zone_); |   357     ZoneMap<int, unsigned int> case_to_block(zone_); | 
|   349     bool has_default = false; |   358     bool has_default = false; | 
|   350     for (int i = case_count - 1; i >= 0; i--) { |   359     for (int i = case_count - 1; i >= 0; i--) { | 
|   351       CaseClause* clause = clauses->at(i); |   360       CaseClause* clause = clauses->at(i); | 
|   352       blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); |   361       blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock)); | 
|   353       if (!clause->is_default()) { |   362       if (!clause->is_default()) { | 
|   354         Literal* label = clause->label()->AsLiteral(); |   363         Literal* label = clause->label()->AsLiteral(); | 
|   355         Handle<Object> value = label->value(); |   364         Handle<Object> value = label->value(); | 
|   356         int32_t label_value; |   365         int32_t label_value; | 
|   357         bool label_is_i32 = value->ToInt32(&label_value); |   366         bool label_is_i32 = value->ToInt32(&label_value); | 
|   358         DCHECK(value->IsNumber() && label_is_i32); |   367         DCHECK(value->IsNumber() && label_is_i32); | 
|   359         (void)label_is_i32; |   368         (void)label_is_i32; | 
|   360         case_to_block[label_value] = i; |   369         case_to_block[label_value] = i; | 
|   361         cases.push_back(label_value); |   370         cases.push_back(label_value); | 
|   362       } else { |   371       } else { | 
|   363         DCHECK_EQ(i, case_count - 1); |   372         DCHECK_EQ(i, case_count - 1); | 
|   364         has_default = true; |   373         has_default = true; | 
|   365       } |   374       } | 
|   366     } |   375     } | 
|   367     if (!has_default || case_count > 1) { |   376     if (!has_default || case_count > 1) { | 
|   368       int default_block = has_default ? case_count - 1 : case_count; |   377       int default_block = has_default ? case_count - 1 : case_count; | 
|   369       BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); |   378       BlockVisitor switch_logic_block(this, nullptr, kExprBlock); | 
|   370       CaseNode* root = OrderCases(&cases, zone_); |   379       CaseNode* root = OrderCases(&cases, zone_); | 
|   371       HandleCase(root, case_to_block, tag, default_block, 0); |   380       HandleCase(root, case_to_block, tag, default_block, 0); | 
|   372       if (root->left != nullptr || root->right != nullptr || |   381       if (root->left != nullptr || root->right != nullptr || | 
|   373           root->begin == root->end) { |   382           root->begin == root->end) { | 
|   374         current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |   383         current_function_builder_->Emit(kExprBr); | 
|   375         current_function_builder_->EmitVarInt(default_block); |   384         current_function_builder_->EmitVarInt(default_block); | 
|   376       } |   385       } | 
|   377     } |   386     } | 
|   378     for (int i = 0; i < case_count; ++i) { |   387     for (int i = 0; i < case_count; ++i) { | 
|   379       CaseClause* clause = clauses->at(i); |   388       CaseClause* clause = clauses->at(i); | 
|   380       RECURSE(VisitStatements(clause->statements())); |   389       RECURSE(VisitStatements(clause->statements())); | 
|   381       BlockVisitor* v = blocks.at(case_count - i - 1); |   390       BlockVisitor* v = blocks.at(case_count - i - 1); | 
|   382       blocks.pop_back(); |   391       blocks.pop_back(); | 
|   383       delete v; |   392       delete v; | 
|   384     } |   393     } | 
|   385   } |   394   } | 
|   386  |   395  | 
|   387   void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |   396   void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 
|   388  |   397  | 
|   389   void VisitDoWhileStatement(DoWhileStatement* stmt) { |   398   void VisitDoWhileStatement(DoWhileStatement* stmt) { | 
|   390     DCHECK_EQ(kFuncScope, scope_); |   399     DCHECK_EQ(kFuncScope, scope_); | 
|   391     BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |   400     BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); | 
 |   401     BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); | 
|   392     RECURSE(Visit(stmt->body())); |   402     RECURSE(Visit(stmt->body())); | 
|   393     RECURSE(Visit(stmt->cond())); |   403     RECURSE(Visit(stmt->cond())); | 
|   394     current_function_builder_->Emit(kExprIf); |   404     current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   395     current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |   405     current_function_builder_->EmitWithU8(kExprBr, 1); | 
|   396     current_function_builder_->Emit(kExprEnd); |   406     current_function_builder_->Emit(kExprEnd); | 
|   397   } |   407   } | 
|   398  |   408  | 
|   399   void VisitWhileStatement(WhileStatement* stmt) { |   409   void VisitWhileStatement(WhileStatement* stmt) { | 
|   400     DCHECK_EQ(kFuncScope, scope_); |   410     DCHECK_EQ(kFuncScope, scope_); | 
|   401     BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |   411     BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); | 
 |   412     BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); | 
|   402     RECURSE(Visit(stmt->cond())); |   413     RECURSE(Visit(stmt->cond())); | 
|   403     breakable_blocks_.push_back(std::make_pair(nullptr, false)); |   414     breakable_blocks_.push_back(std::make_pair(nullptr, false)); | 
|   404     current_function_builder_->Emit(kExprIf); |   415     current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   405     RECURSE(Visit(stmt->body())); |   416     RECURSE(Visit(stmt->body())); | 
|   406     current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |   417     current_function_builder_->EmitWithU8(kExprBr, 1); | 
|   407     current_function_builder_->Emit(kExprEnd); |   418     current_function_builder_->Emit(kExprEnd); | 
|   408     breakable_blocks_.pop_back(); |   419     breakable_blocks_.pop_back(); | 
|   409   } |   420   } | 
|   410  |   421  | 
|   411   void VisitForStatement(ForStatement* stmt) { |   422   void VisitForStatement(ForStatement* stmt) { | 
|   412     DCHECK_EQ(kFuncScope, scope_); |   423     DCHECK_EQ(kFuncScope, scope_); | 
|   413     if (stmt->init() != nullptr) { |   424     if (stmt->init() != nullptr) { | 
|   414       RECURSE(Visit(stmt->init())); |   425       RECURSE(Visit(stmt->init())); | 
|   415     } |   426     } | 
|   416     BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |   427     BlockVisitor block(this, stmt->AsBreakableStatement(), kExprBlock); | 
 |   428     BlockVisitor loop(this, stmt->AsBreakableStatement(), kExprLoop); | 
|   417     if (stmt->cond() != nullptr) { |   429     if (stmt->cond() != nullptr) { | 
|   418       RECURSE(Visit(stmt->cond())); |   430       RECURSE(Visit(stmt->cond())); | 
|   419       current_function_builder_->Emit(kExprI32Eqz); |   431       current_function_builder_->Emit(kExprI32Eqz); | 
|   420       current_function_builder_->Emit(kExprIf); |   432       current_function_builder_->EmitWithU8(kExprIf, kLocalVoid); | 
|   421       current_function_builder_->Emit(kExprNop); |   433       current_function_builder_->EmitWithU8(kExprBr, 2); | 
|   422       current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2); |  | 
|   423       current_function_builder_->Emit(kExprEnd); |   434       current_function_builder_->Emit(kExprEnd); | 
|   424     } |   435     } | 
|   425     if (stmt->body() != nullptr) { |   436     if (stmt->body() != nullptr) { | 
|   426       RECURSE(Visit(stmt->body())); |   437       RECURSE(Visit(stmt->body())); | 
|   427     } |   438     } | 
|   428     if (stmt->next() != nullptr) { |   439     if (stmt->next() != nullptr) { | 
|   429       RECURSE(Visit(stmt->next())); |   440       RECURSE(Visit(stmt->next())); | 
|   430     } |   441     } | 
|   431     current_function_builder_->Emit(kExprNop); |   442     current_function_builder_->EmitWithU8(kExprBr, 0); | 
|   432     current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0); |  | 
|   433   } |   443   } | 
|   434  |   444  | 
|   435   void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |   445   void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } | 
|   436  |   446  | 
|   437   void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } |   447   void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } | 
|   438  |   448  | 
|   439   void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } |   449   void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } | 
|   440  |   450  | 
|   441   void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } |   451   void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } | 
|   442  |   452  | 
|   443   void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } |   453   void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } | 
|   444  |   454  | 
|   445   void VisitFunctionLiteral(FunctionLiteral* expr) { |   455   void VisitFunctionLiteral(FunctionLiteral* expr) { | 
|   446     DeclarationScope* scope = expr->scope(); |   456     DeclarationScope* scope = expr->scope(); | 
|   447     if (scope_ == kFuncScope) { |   457     if (scope_ == kFuncScope) { | 
|   448       if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) { |   458       if (auto* func_type = typer_->TypeOf(expr)->AsFunctionType()) { | 
|   449         // Build the signature for the function. |   459         // Add the parameters for the function. | 
|   450         LocalType return_type = TypeFrom(func_type->ReturnType()); |  | 
|   451         const auto& arguments = func_type->Arguments(); |   460         const auto& arguments = func_type->Arguments(); | 
|   452         FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1, |  | 
|   453                                arguments.size()); |  | 
|   454         if (return_type != kAstStmt) b.AddReturn(return_type); |  | 
|   455         for (int i = 0; i < expr->parameter_count(); ++i) { |   461         for (int i = 0; i < expr->parameter_count(); ++i) { | 
|   456           LocalType type = TypeFrom(arguments[i]); |   462           LocalType type = TypeFrom(arguments[i]); | 
|   457           DCHECK_NE(kAstStmt, type); |   463           DCHECK_NE(kAstStmt, type); | 
|   458           b.AddParam(type); |  | 
|   459           InsertParameter(scope->parameter(i), type, i); |   464           InsertParameter(scope->parameter(i), type, i); | 
|   460         } |   465         } | 
|   461         current_function_builder_->SetSignature(b.Build()); |  | 
|   462       } else { |   466       } else { | 
|   463         UNREACHABLE(); |   467         UNREACHABLE(); | 
|   464       } |   468       } | 
|   465     } |   469     } | 
|   466     RECURSE(VisitStatements(expr->body())); |   470     RECURSE(VisitStatements(expr->body())); | 
|   467     RECURSE(VisitDeclarations(scope->declarations())); |   471     RECURSE(VisitDeclarations(scope->declarations())); | 
|   468   } |   472   } | 
|   469  |   473  | 
|   470   void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |   474   void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 
|   471     UNREACHABLE(); |   475     UNREACHABLE(); | 
|   472   } |   476   } | 
|   473  |   477  | 
|   474   void VisitConditional(Conditional* expr) { |   478   void VisitConditional(Conditional* expr) { | 
|   475     DCHECK_EQ(kFuncScope, scope_); |   479     DCHECK_EQ(kFuncScope, scope_); | 
|   476     RECURSE(Visit(expr->condition())); |   480     RECURSE(Visit(expr->condition())); | 
|   477     // WASM ifs come with implicit blocks for both arms. |   481     // WASM ifs come with implicit blocks for both arms. | 
|   478     breakable_blocks_.push_back(std::make_pair(nullptr, false)); |   482     breakable_blocks_.push_back(std::make_pair(nullptr, false)); | 
|   479     current_function_builder_->Emit(kExprIf); |   483     LocalTypeCode type; | 
 |   484     switch (TypeOf(expr)) { | 
 |   485       case kAstI32: | 
 |   486         type = kLocalI32; | 
 |   487         break; | 
 |   488       case kAstI64: | 
 |   489         type = kLocalI64; | 
 |   490         break; | 
 |   491       case kAstF32: | 
 |   492         type = kLocalF32; | 
 |   493         break; | 
 |   494       case kAstF64: | 
 |   495         type = kLocalF64; | 
 |   496         break; | 
 |   497       default: | 
 |   498         UNREACHABLE(); | 
 |   499     } | 
 |   500     current_function_builder_->EmitWithU8(kExprIf, type); | 
|   480     RECURSE(Visit(expr->then_expression())); |   501     RECURSE(Visit(expr->then_expression())); | 
|   481     current_function_builder_->Emit(kExprElse); |   502     current_function_builder_->Emit(kExprElse); | 
|   482     RECURSE(Visit(expr->else_expression())); |   503     RECURSE(Visit(expr->else_expression())); | 
|   483     current_function_builder_->Emit(kExprEnd); |   504     current_function_builder_->Emit(kExprEnd); | 
|   484     breakable_blocks_.pop_back(); |   505     breakable_blocks_.pop_back(); | 
|   485   } |   506   } | 
|   486  |   507  | 
|   487   bool VisitStdlibConstant(Variable* var) { |   508   bool VisitStdlibConstant(Variable* var) { | 
|   488     AsmTyper::StandardMember standard_object = |   509     AsmTyper::StandardMember standard_object = | 
|   489         typer_->VariableAsStandardMember(var); |   510         typer_->VariableAsStandardMember(var); | 
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   594       ObjectLiteralProperty* prop = props->at(i); |   615       ObjectLiteralProperty* prop = props->at(i); | 
|   595       DCHECK_EQ(kExportScope, scope_); |   616       DCHECK_EQ(kExportScope, scope_); | 
|   596       VariableProxy* expr = prop->value()->AsVariableProxy(); |   617       VariableProxy* expr = prop->value()->AsVariableProxy(); | 
|   597       DCHECK_NOT_NULL(expr); |   618       DCHECK_NOT_NULL(expr); | 
|   598       Variable* var = expr->var(); |   619       Variable* var = expr->var(); | 
|   599       Literal* name = prop->key()->AsLiteral(); |   620       Literal* name = prop->key()->AsLiteral(); | 
|   600       DCHECK_NOT_NULL(name); |   621       DCHECK_NOT_NULL(name); | 
|   601       DCHECK(name->IsPropertyName()); |   622       DCHECK(name->IsPropertyName()); | 
|   602       const AstRawString* raw_name = name->AsRawPropertyName(); |   623       const AstRawString* raw_name = name->AsRawPropertyName(); | 
|   603       if (var->is_function()) { |   624       if (var->is_function()) { | 
|   604         uint32_t index = LookupOrInsertFunction(var); |   625         WasmFunctionBuilder* function = LookupOrInsertFunction(var); | 
|   605         builder_->FunctionAt(index)->SetExported(); |   626         function->SetExported(); | 
|   606         builder_->FunctionAt(index)->SetName( |   627         function->SetName(reinterpret_cast<const char*>(raw_name->raw_data()), | 
|   607             reinterpret_cast<const char*>(raw_name->raw_data()), |   628                           raw_name->length()); | 
|   608             raw_name->length()); |  | 
|   609       } |   629       } | 
|   610     } |   630     } | 
|   611   } |   631   } | 
|   612  |   632  | 
|   613   void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |   633   void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 
|   614  |   634  | 
|   615   void LoadInitFunction() { |   635   void LoadInitFunction() { | 
|   616     current_function_builder_ = builder_->FunctionAt(init_function_index_); |   636     current_function_builder_ = init_function_; | 
|   617     scope_ = kInitScope; |   637     scope_ = kInitScope; | 
|   618   } |   638   } | 
|   619  |   639  | 
|   620   void UnLoadInitFunction() { |   640   void UnLoadInitFunction() { | 
|   621     scope_ = kModuleScope; |   641     scope_ = kModuleScope; | 
|   622     current_function_builder_ = nullptr; |   642     current_function_builder_ = nullptr; | 
|   623   } |   643   } | 
|   624  |   644  | 
|   625   void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |   645   void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 
|   626     auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); |   646     auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); | 
|   627     DCHECK_NOT_NULL(func_tbl_type); |   647     DCHECK_NOT_NULL(func_tbl_type); | 
|   628     auto* func_type = func_tbl_type->signature()->AsFunctionType(); |   648     auto* func_type = func_tbl_type->signature()->AsFunctionType(); | 
|   629     const auto& arguments = func_type->Arguments(); |   649     const auto& arguments = func_type->Arguments(); | 
|   630     LocalType return_type = TypeFrom(func_type->ReturnType()); |   650     LocalType return_type = TypeFrom(func_type->ReturnType()); | 
|   631     FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |   651     FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 
|   632                              arguments.size()); |   652                              arguments.size()); | 
|   633     if (return_type != kAstStmt) { |   653     if (return_type != kAstStmt) { | 
|   634       sig.AddReturn(return_type); |   654       sig.AddReturn(return_type); | 
|   635     } |   655     } | 
|   636     for (auto* arg : arguments) { |   656     for (auto* arg : arguments) { | 
|   637       sig.AddParam(TypeFrom(arg)); |   657       sig.AddParam(TypeFrom(arg)); | 
|   638     } |   658     } | 
|   639     uint32_t signature_index = builder_->AddSignature(sig.Build()); |   659     uint32_t signature_index = builder_->AddSignature(sig.Build()); | 
|   640     InsertFunctionTable(table->var(), next_table_index_, signature_index); |   660     InsertFunctionTable(table->var(), next_table_index_, signature_index); | 
|   641     next_table_index_ += funcs->values()->length(); |   661     next_table_index_ += funcs->values()->length(); | 
|   642     for (int i = 0; i < funcs->values()->length(); ++i) { |   662     for (int i = 0; i < funcs->values()->length(); ++i) { | 
|   643       VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |   663       VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | 
|   644       DCHECK_NOT_NULL(func); |   664       DCHECK_NOT_NULL(func); | 
|   645       builder_->AddIndirectFunction(LookupOrInsertFunction(func->var())); |   665       builder_->AddIndirectFunction( | 
 |   666           LookupOrInsertFunction(func->var())->func_index()); | 
|   646     } |   667     } | 
|   647   } |   668   } | 
|   648  |   669  | 
|   649   struct FunctionTableIndices : public ZoneObject { |   670   struct FunctionTableIndices : public ZoneObject { | 
|   650     uint32_t start_index; |   671     uint32_t start_index; | 
|   651     uint32_t signature_index; |   672     uint32_t signature_index; | 
|   652   }; |   673   }; | 
|   653  |   674  | 
|   654   void InsertFunctionTable(Variable* v, uint32_t start_index, |   675   void InsertFunctionTable(Variable* v, uint32_t start_index, | 
|   655                            uint32_t signature_index) { |   676                            uint32_t signature_index) { | 
|   656     FunctionTableIndices* container = new (zone()) FunctionTableIndices(); |   677     FunctionTableIndices* container = new (zone()) FunctionTableIndices(); | 
|   657     container->start_index = start_index; |   678     container->start_index = start_index; | 
|   658     container->signature_index = signature_index; |   679     container->signature_index = signature_index; | 
|   659     ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |   680     ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( | 
|   660         v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); |   681         v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); | 
|   661     entry->value = container; |   682     entry->value = container; | 
|   662   } |   683   } | 
|   663  |   684  | 
|   664   FunctionTableIndices* LookupFunctionTable(Variable* v) { |   685   FunctionTableIndices* LookupFunctionTable(Variable* v) { | 
|   665     ZoneHashMap::Entry* entry = |   686     ZoneHashMap::Entry* entry = | 
|   666         function_tables_.Lookup(v, ComputePointerHash(v)); |   687         function_tables_.Lookup(v, ComputePointerHash(v)); | 
|   667     DCHECK_NOT_NULL(entry); |   688     DCHECK_NOT_NULL(entry); | 
|   668     return reinterpret_cast<FunctionTableIndices*>(entry->value); |   689     return reinterpret_cast<FunctionTableIndices*>(entry->value); | 
|   669   } |   690   } | 
|   670  |   691  | 
|   671   class ImportedFunctionTable { |   692   class ImportedFunctionTable { | 
|   672    private: |   693    private: | 
|   673     class ImportedFunctionIndices : public ZoneObject { |   694     class ImportedFunctionIndices : public ZoneObject { | 
|   674      public: |   695      public: | 
|   675       const char* name_; |   696       bool has_name_; | 
|   676       int name_length_; |  | 
|   677       WasmModuleBuilder::SignatureMap signature_to_index_; |   697       WasmModuleBuilder::SignatureMap signature_to_index_; | 
|   678  |   698  | 
|   679       ImportedFunctionIndices(const char* name, int name_length, Zone* zone) |   699       explicit ImportedFunctionIndices(Zone* zone) | 
|   680           : name_(name), name_length_(name_length), signature_to_index_(zone) {} |   700           : has_name_(false), signature_to_index_(zone) {} | 
|   681     }; |   701     }; | 
|   682     ZoneHashMap table_; |   702     ZoneHashMap table_; | 
|   683     AsmWasmBuilderImpl* builder_; |   703     AsmWasmBuilderImpl* builder_; | 
|   684  |   704  | 
|   685    public: |   705    public: | 
|   686     explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) |   706     explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) | 
|   687         : table_(base::HashMap::PointersMatch, |   707         : table_(base::HashMap::PointersMatch, | 
|   688                  ZoneHashMap::kDefaultHashMapCapacity, |   708                  ZoneHashMap::kDefaultHashMapCapacity, | 
|   689                  ZoneAllocationPolicy(builder->zone())), |   709                  ZoneAllocationPolicy(builder->zone())), | 
|   690           builder_(builder) {} |   710           builder_(builder) {} | 
|   691  |   711  | 
|   692     void AddImport(Variable* v, const char* name, int name_length) { |   712     // Set the imported name of a variable. Must happen after all signatures | 
|   693       ImportedFunctionIndices* indices = new (builder_->zone()) |   713     // (and thus import indices) are added for a given variable. | 
|   694           ImportedFunctionIndices(name, name_length, builder_->zone()); |   714     void SetImportName(Variable* v, const char* name, int name_length) { | 
|   695       ZoneHashMap::Entry* entry = table_.LookupOrInsert( |   715       auto indices = GetEntry(v); | 
|   696           v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |   716       if (indices) { | 
|   697       entry->value = indices; |   717         for (auto entry : indices->signature_to_index_) { | 
 |   718           uint32_t index = entry.second; | 
 |   719           builder_->builder_->SetImportName(index, name, name_length); | 
 |   720         } | 
 |   721         indices->has_name_ = true; | 
 |   722       } | 
|   698     } |   723     } | 
|   699  |   724  | 
 |   725     // Get a function's index. Does not insert new entries. | 
|   700     uint32_t GetFunctionIndex(Variable* v, FunctionSig* sig) { |   726     uint32_t GetFunctionIndex(Variable* v, FunctionSig* sig) { | 
|   701       ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); |   727       auto indices = GetEntry(v); | 
|   702       DCHECK_NOT_NULL(entry); |   728       DCHECK_NOT_NULL(indices); | 
|   703       ImportedFunctionIndices* indices = |   729       auto pos = indices->signature_to_index_.find(sig); | 
|   704           reinterpret_cast<ImportedFunctionIndices*>(entry->value); |   730       DCHECK(pos != indices->signature_to_index_.end()); | 
|   705       WasmModuleBuilder::SignatureMap::iterator pos = |   731       return pos->second; | 
|   706           indices->signature_to_index_.find(sig); |   732     } | 
|   707       if (pos != indices->signature_to_index_.end()) { |   733  | 
|   708         return pos->second; |   734     // Add a function and register it as an import with the builder. | 
|   709       } else { |   735     void AddFunction(Variable* v, FunctionSig* sig) { | 
|   710         uint32_t index = builder_->builder_->AddImport( |   736       auto entry = table_.LookupOrInsert( | 
|   711             indices->name_, indices->name_length_, sig); |   737           v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); | 
 |   738       if (entry->value == nullptr) { | 
 |   739         entry->value = | 
 |   740             new (builder_->zone()) ImportedFunctionIndices(builder_->zone()); | 
 |   741       } | 
 |   742       auto indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value); | 
 |   743       DCHECK(!indices->has_name_); | 
 |   744       auto pos = indices->signature_to_index_.find(sig); | 
 |   745       if (pos == indices->signature_to_index_.end()) { | 
 |   746         // A new import. Name is not known up front. | 
 |   747         uint32_t index = builder_->builder_->AddImport(nullptr, 0, sig); | 
|   712         indices->signature_to_index_[sig] = index; |   748         indices->signature_to_index_[sig] = index; | 
|   713         return index; |  | 
|   714       } |   749       } | 
|   715     } |   750     } | 
 |   751  | 
 |   752     ImportedFunctionIndices* GetEntry(Variable* v) { | 
 |   753       auto entry = table_.Lookup(v, ComputePointerHash(v)); | 
 |   754       if (entry == nullptr) return nullptr; | 
 |   755       return reinterpret_cast<ImportedFunctionIndices*>(entry->value); | 
 |   756     } | 
|   716   }; |   757   }; | 
|   717  |   758  | 
|   718   void EmitAssignmentLhs(Expression* target, MachineType* mtype) { |   759   void EmitAssignmentLhs(Expression* target, MachineType* mtype) { | 
|   719     // Match the left hand side of the assignment. |   760     // Match the left hand side of the assignment. | 
|   720     VariableProxy* target_var = target->AsVariableProxy(); |   761     VariableProxy* target_var = target->AsVariableProxy(); | 
|   721     if (target_var != nullptr) { |   762     if (target_var != nullptr) { | 
|   722       // Left hand side is a local or a global variable, no code on LHS. |   763       // Left hand side is a local or a global variable, no code on LHS. | 
|   723       return; |   764       return; | 
|   724     } |   765     } | 
|   725  |   766  | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   767         if (target_var != nullptr && effective_value_var != nullptr && |   808         if (target_var != nullptr && effective_value_var != nullptr && | 
|   768             target_var->var() == effective_value_var->var()) { |   809             target_var->var() == effective_value_var->var()) { | 
|   769           *is_nop = true; |   810           *is_nop = true; | 
|   770           return; |   811           return; | 
|   771         } |   812         } | 
|   772       } |   813       } | 
|   773     } |   814     } | 
|   774     RECURSE(Visit(value)); |   815     RECURSE(Visit(value)); | 
|   775   } |   816   } | 
|   776  |   817  | 
|   777   void EmitAssignment(Assignment* expr, MachineType type) { |   818   void EmitAssignment(Assignment* expr, MachineType type, ValueFate fate) { | 
|   778     // Match the left hand side of the assignment. |   819     // Match the left hand side of the assignment. | 
|   779     VariableProxy* target_var = expr->target()->AsVariableProxy(); |   820     VariableProxy* target_var = expr->target()->AsVariableProxy(); | 
|   780     if (target_var != nullptr) { |   821     if (target_var != nullptr) { | 
|   781       // Left hand side is a local or a global variable. |   822       // Left hand side is a local or a global variable. | 
|   782       Variable* var = target_var->var(); |   823       Variable* var = target_var->var(); | 
|   783       LocalType var_type = TypeOf(expr); |   824       LocalType var_type = TypeOf(expr); | 
|   784       DCHECK_NE(kAstStmt, var_type); |   825       DCHECK_NE(kAstStmt, var_type); | 
|   785       if (var->IsContextSlot()) { |   826       if (var->IsContextSlot()) { | 
|   786         current_function_builder_->EmitWithVarInt( |   827         uint32_t index = LookupOrInsertGlobal(var, var_type); | 
|   787             kExprSetGlobal, LookupOrInsertGlobal(var, var_type)); |   828         current_function_builder_->EmitWithVarInt(kExprSetGlobal, index); | 
 |   829         if (fate == kLeaveOnStack) { | 
 |   830           current_function_builder_->EmitWithVarInt(kExprGetGlobal, index); | 
 |   831         } | 
|   788       } else { |   832       } else { | 
|   789         current_function_builder_->EmitSetLocal( |   833         if (fate == kDrop) { | 
|   790             LookupOrInsertLocal(var, var_type)); |   834           current_function_builder_->EmitSetLocal( | 
 |   835               LookupOrInsertLocal(var, var_type)); | 
 |   836         } else { | 
 |   837           current_function_builder_->EmitTeeLocal( | 
 |   838               LookupOrInsertLocal(var, var_type)); | 
 |   839         } | 
|   791       } |   840       } | 
|   792     } |   841     } | 
|   793  |   842  | 
|   794     Property* target_prop = expr->target()->AsProperty(); |   843     Property* target_prop = expr->target()->AsProperty(); | 
|   795     if (target_prop != nullptr) { |   844     if (target_prop != nullptr) { | 
|   796       // Left hand side is a property access, i.e. the asm.js heap. |   845       // Left hand side is a property access, i.e. the asm.js heap. | 
|   797       if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && |   846       if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | 
|   798           typer_->TypeOf(expr->target()->AsProperty()->obj()) |   847           typer_->TypeOf(expr->target()->AsProperty()->obj()) | 
|   799               ->IsA(AsmType::Float32Array())) { |   848               ->IsA(AsmType::Float32Array())) { | 
|   800         current_function_builder_->Emit(kExprF32ConvertF64); |   849         current_function_builder_->Emit(kExprF32ConvertF64); | 
|   801       } |   850       } | 
 |   851       // Note that unlike StoreMem, AsmjsStoreMem ignores out-of-bounds writes. | 
|   802       WasmOpcode opcode; |   852       WasmOpcode opcode; | 
|   803       if (type == MachineType::Int8()) { |   853       if (type == MachineType::Int8()) { | 
|   804         opcode = kExprI32AsmjsStoreMem8; |   854         opcode = kExprI32AsmjsStoreMem8; | 
|   805       } else if (type == MachineType::Uint8()) { |   855       } else if (type == MachineType::Uint8()) { | 
|   806         opcode = kExprI32AsmjsStoreMem8; |   856         opcode = kExprI32AsmjsStoreMem8; | 
|   807       } else if (type == MachineType::Int16()) { |   857       } else if (type == MachineType::Int16()) { | 
|   808         opcode = kExprI32AsmjsStoreMem16; |   858         opcode = kExprI32AsmjsStoreMem16; | 
|   809       } else if (type == MachineType::Uint16()) { |   859       } else if (type == MachineType::Uint16()) { | 
|   810         opcode = kExprI32AsmjsStoreMem16; |   860         opcode = kExprI32AsmjsStoreMem16; | 
|   811       } else if (type == MachineType::Int32()) { |   861       } else if (type == MachineType::Int32()) { | 
|   812         opcode = kExprI32AsmjsStoreMem; |   862         opcode = kExprI32AsmjsStoreMem; | 
|   813       } else if (type == MachineType::Uint32()) { |   863       } else if (type == MachineType::Uint32()) { | 
|   814         opcode = kExprI32AsmjsStoreMem; |   864         opcode = kExprI32AsmjsStoreMem; | 
|   815       } else if (type == MachineType::Float32()) { |   865       } else if (type == MachineType::Float32()) { | 
|   816         opcode = kExprF32AsmjsStoreMem; |   866         opcode = kExprF32AsmjsStoreMem; | 
|   817       } else if (type == MachineType::Float64()) { |   867       } else if (type == MachineType::Float64()) { | 
|   818         opcode = kExprF64AsmjsStoreMem; |   868         opcode = kExprF64AsmjsStoreMem; | 
|   819       } else { |   869       } else { | 
|   820         UNREACHABLE(); |   870         UNREACHABLE(); | 
|   821       } |   871       } | 
|   822       current_function_builder_->Emit(opcode); |   872       current_function_builder_->Emit(opcode); | 
 |   873       if (fate == kDrop) { | 
 |   874         // Asm.js stores to memory leave their result on the stack. | 
 |   875         current_function_builder_->Emit(kExprDrop); | 
 |   876       } | 
|   823     } |   877     } | 
|   824  |   878  | 
|   825     if (target_var == nullptr && target_prop == nullptr) { |   879     if (target_var == nullptr && target_prop == nullptr) { | 
|   826       UNREACHABLE();  // invalid assignment. |   880       UNREACHABLE();  // invalid assignment. | 
|   827     } |   881     } | 
|   828   } |   882   } | 
|   829  |   883  | 
|   830   void VisitAssignment(Assignment* expr) { |   884   void VisitAssignment(Assignment* expr) { | 
 |   885     VisitAssignment(expr, kLeaveOnStack); | 
 |   886   } | 
 |   887  | 
 |   888   void VisitAssignment(Assignment* expr, ValueFate fate) { | 
|   831     bool as_init = false; |   889     bool as_init = false; | 
|   832     if (scope_ == kModuleScope) { |   890     if (scope_ == kModuleScope) { | 
|   833       // Skip extra assignment inserted by the parser when in this form: |   891       // Skip extra assignment inserted by the parser when in this form: | 
|   834       // (function Module(a, b, c) {... }) |   892       // (function Module(a, b, c) {... }) | 
|   835       if (expr->target()->IsVariableProxy() && |   893       if (expr->target()->IsVariableProxy() && | 
|   836           expr->target()->AsVariableProxy()->var()->is_sloppy_function_name()) { |   894           expr->target()->AsVariableProxy()->var()->is_sloppy_function_name()) { | 
|   837         return; |   895         return; | 
|   838       } |   896       } | 
|   839       Property* prop = expr->value()->AsProperty(); |   897       Property* prop = expr->value()->AsProperty(); | 
|   840       if (prop != nullptr) { |   898       if (prop != nullptr) { | 
|   841         VariableProxy* vp = prop->obj()->AsVariableProxy(); |   899         VariableProxy* vp = prop->obj()->AsVariableProxy(); | 
|   842         if (vp != nullptr && vp->var()->IsParameter() && |   900         if (vp != nullptr && vp->var()->IsParameter() && | 
|   843             vp->var()->index() == 1) { |   901             vp->var()->index() == 1) { | 
|   844           VariableProxy* target = expr->target()->AsVariableProxy(); |   902           VariableProxy* target = expr->target()->AsVariableProxy(); | 
|   845           if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |   903           if (typer_->TypeOf(target)->AsFFIType() != nullptr) { | 
|   846             const AstRawString* name = |   904             const AstRawString* name = | 
|   847                 prop->key()->AsLiteral()->AsRawPropertyName(); |   905                 prop->key()->AsLiteral()->AsRawPropertyName(); | 
|   848             imported_function_table_.AddImport( |   906             imported_function_table_.SetImportName( | 
|   849                 target->var(), reinterpret_cast<const char*>(name->raw_data()), |   907                 target->var(), reinterpret_cast<const char*>(name->raw_data()), | 
|   850                 name->length()); |   908                 name->length()); | 
|   851           } |   909           } | 
|   852         } |   910         } | 
|   853         // Property values in module scope don't emit code, so return. |   911         // Property values in module scope don't emit code, so return. | 
|   854         return; |   912         return; | 
|   855       } |   913       } | 
|   856       ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |   914       ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 
|   857       if (funcs != nullptr && |   915       if (funcs != nullptr && | 
|   858           typer_->TypeOf(funcs) |   916           typer_->TypeOf(funcs) | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|   871       } |   929       } | 
|   872       as_init = true; |   930       as_init = true; | 
|   873     } |   931     } | 
|   874  |   932  | 
|   875     if (as_init) LoadInitFunction(); |   933     if (as_init) LoadInitFunction(); | 
|   876     MachineType mtype; |   934     MachineType mtype; | 
|   877     bool is_nop = false; |   935     bool is_nop = false; | 
|   878     EmitAssignmentLhs(expr->target(), &mtype); |   936     EmitAssignmentLhs(expr->target(), &mtype); | 
|   879     EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |   937     EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); | 
|   880     if (!is_nop) { |   938     if (!is_nop) { | 
|   881       EmitAssignment(expr, mtype); |   939       EmitAssignment(expr, mtype, fate); | 
|   882     } |   940     } | 
|   883     if (as_init) UnLoadInitFunction(); |   941     if (as_init) UnLoadInitFunction(); | 
|   884   } |   942   } | 
|   885  |   943  | 
|   886   void VisitYield(Yield* expr) { UNREACHABLE(); } |   944   void VisitYield(Yield* expr) { UNREACHABLE(); } | 
|   887  |   945  | 
|   888   void VisitThrow(Throw* expr) { UNREACHABLE(); } |   946   void VisitThrow(Throw* expr) { UNREACHABLE(); } | 
|   889  |   947  | 
|   890   void VisitForeignVariable(bool is_float, Variable* var, Property* expr) { |   948   void VisitForeignVariable(bool is_float, Variable* var, Property* expr) { | 
|   891     DCHECK(expr->obj()->AsVariableProxy()); |   949     DCHECK(expr->obj()->AsVariableProxy()); | 
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1096         DCHECK(call_type == kAstI32); |  1154         DCHECK(call_type == kAstI32); | 
|  1097         current_function_builder_->Emit(kExprI32Clz); |  1155         current_function_builder_->Emit(kExprI32Clz); | 
|  1098         break; |  1156         break; | 
|  1099       } |  1157       } | 
|  1100       case AsmTyper::kMathAbs: { |  1158       case AsmTyper::kMathAbs: { | 
|  1101         if (call_type == kAstI32) { |  1159         if (call_type == kAstI32) { | 
|  1102           WasmTemporary tmp(current_function_builder_, kAstI32); |  1160           WasmTemporary tmp(current_function_builder_, kAstI32); | 
|  1103  |  1161  | 
|  1104           // if set_local(tmp, x) < 0 |  1162           // if set_local(tmp, x) < 0 | 
|  1105           Visit(call->arguments()->at(0)); |  1163           Visit(call->arguments()->at(0)); | 
|  1106           current_function_builder_->EmitSetLocal(tmp.index()); |  1164           current_function_builder_->EmitTeeLocal(tmp.index()); | 
|  1107           byte code[] = {WASM_I8(0)}; |  1165           byte code[] = {WASM_I8(0)}; | 
|  1108           current_function_builder_->EmitCode(code, sizeof(code)); |  1166           current_function_builder_->EmitCode(code, sizeof(code)); | 
|  1109           current_function_builder_->Emit(kExprI32LtS); |  1167           current_function_builder_->Emit(kExprI32LtS); | 
|  1110           current_function_builder_->Emit(kExprIf); |  1168           current_function_builder_->EmitWithU8(kExprIf, kLocalI32); | 
|  1111  |  1169  | 
|  1112           // then (0 - tmp) |  1170           // then (0 - tmp) | 
|  1113           current_function_builder_->EmitCode(code, sizeof(code)); |  1171           current_function_builder_->EmitCode(code, sizeof(code)); | 
|  1114           current_function_builder_->EmitGetLocal(tmp.index()); |  1172           current_function_builder_->EmitGetLocal(tmp.index()); | 
|  1115           current_function_builder_->Emit(kExprI32Sub); |  1173           current_function_builder_->Emit(kExprI32Sub); | 
|  1116  |  1174  | 
|  1117           // else tmp |  1175           // else tmp | 
|  1118           current_function_builder_->Emit(kExprElse); |  1176           current_function_builder_->Emit(kExprElse); | 
|  1119           current_function_builder_->EmitGetLocal(tmp.index()); |  1177           current_function_builder_->EmitGetLocal(tmp.index()); | 
|  1120           // end |  1178           // end | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  1132         break; |  1190         break; | 
|  1133       } |  1191       } | 
|  1134       case AsmTyper::kMathMin: { |  1192       case AsmTyper::kMathMin: { | 
|  1135         // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |  1193         // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. | 
|  1136         if (call_type == kAstI32) { |  1194         if (call_type == kAstI32) { | 
|  1137           WasmTemporary tmp_x(current_function_builder_, kAstI32); |  1195           WasmTemporary tmp_x(current_function_builder_, kAstI32); | 
|  1138           WasmTemporary tmp_y(current_function_builder_, kAstI32); |  1196           WasmTemporary tmp_y(current_function_builder_, kAstI32); | 
|  1139  |  1197  | 
|  1140           // if set_local(tmp_x, x) < set_local(tmp_y, y) |  1198           // if set_local(tmp_x, x) < set_local(tmp_y, y) | 
|  1141           Visit(call->arguments()->at(0)); |  1199           Visit(call->arguments()->at(0)); | 
|  1142           current_function_builder_->EmitSetLocal(tmp_x.index()); |  1200           current_function_builder_->EmitTeeLocal(tmp_x.index()); | 
|  1143  |  1201  | 
|  1144           Visit(call->arguments()->at(1)); |  1202           Visit(call->arguments()->at(1)); | 
|  1145           current_function_builder_->EmitSetLocal(tmp_y.index()); |  1203           current_function_builder_->EmitTeeLocal(tmp_y.index()); | 
|  1146  |  1204  | 
|  1147           current_function_builder_->Emit(kExprI32LeS); |  1205           current_function_builder_->Emit(kExprI32LeS); | 
|  1148           current_function_builder_->Emit(kExprIf); |  1206           current_function_builder_->EmitWithU8(kExprIf, kLocalI32); | 
|  1149  |  1207  | 
|  1150           // then tmp_x |  1208           // then tmp_x | 
|  1151           current_function_builder_->EmitGetLocal(tmp_x.index()); |  1209           current_function_builder_->EmitGetLocal(tmp_x.index()); | 
|  1152  |  1210  | 
|  1153           // else tmp_y |  1211           // else tmp_y | 
|  1154           current_function_builder_->Emit(kExprElse); |  1212           current_function_builder_->Emit(kExprElse); | 
|  1155           current_function_builder_->EmitGetLocal(tmp_y.index()); |  1213           current_function_builder_->EmitGetLocal(tmp_y.index()); | 
|  1156           current_function_builder_->Emit(kExprEnd); |  1214           current_function_builder_->Emit(kExprEnd); | 
|  1157  |  1215  | 
|  1158         } else if (call_type == kAstF32) { |  1216         } else if (call_type == kAstF32) { | 
|  1159           VisitCallArgs(call); |  1217           VisitCallArgs(call); | 
|  1160           current_function_builder_->Emit(kExprF32Min); |  1218           current_function_builder_->Emit(kExprF32Min); | 
|  1161         } else if (call_type == kAstF64) { |  1219         } else if (call_type == kAstF64) { | 
|  1162           VisitCallArgs(call); |  1220           VisitCallArgs(call); | 
|  1163           current_function_builder_->Emit(kExprF64Min); |  1221           current_function_builder_->Emit(kExprF64Min); | 
|  1164         } else { |  1222         } else { | 
|  1165           UNREACHABLE(); |  1223           UNREACHABLE(); | 
|  1166         } |  1224         } | 
|  1167         break; |  1225         break; | 
|  1168       } |  1226       } | 
|  1169       case AsmTyper::kMathMax: { |  1227       case AsmTyper::kMathMax: { | 
|  1170         // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |  1228         // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. | 
|  1171         if (call_type == kAstI32) { |  1229         if (call_type == kAstI32) { | 
|  1172           WasmTemporary tmp_x(current_function_builder_, kAstI32); |  1230           WasmTemporary tmp_x(current_function_builder_, kAstI32); | 
|  1173           WasmTemporary tmp_y(current_function_builder_, kAstI32); |  1231           WasmTemporary tmp_y(current_function_builder_, kAstI32); | 
|  1174  |  1232  | 
|  1175           // if set_local(tmp_x, x) < set_local(tmp_y, y) |  1233           // if set_local(tmp_x, x) < set_local(tmp_y, y) | 
|  1176           Visit(call->arguments()->at(0)); |  1234           Visit(call->arguments()->at(0)); | 
|  1177  |  1235  | 
|  1178           current_function_builder_->EmitSetLocal(tmp_x.index()); |  1236           current_function_builder_->EmitTeeLocal(tmp_x.index()); | 
|  1179  |  1237  | 
|  1180           Visit(call->arguments()->at(1)); |  1238           Visit(call->arguments()->at(1)); | 
|  1181           current_function_builder_->EmitSetLocal(tmp_y.index()); |  1239           current_function_builder_->EmitTeeLocal(tmp_y.index()); | 
|  1182  |  1240  | 
|  1183           current_function_builder_->Emit(kExprI32LeS); |  1241           current_function_builder_->Emit(kExprI32LeS); | 
|  1184           current_function_builder_->Emit(kExprIf); |  1242           current_function_builder_->EmitWithU8(kExprIf, kLocalI32); | 
|  1185  |  1243  | 
|  1186           // then tmp_y |  1244           // then tmp_y | 
|  1187           current_function_builder_->EmitGetLocal(tmp_y.index()); |  1245           current_function_builder_->EmitGetLocal(tmp_y.index()); | 
|  1188  |  1246  | 
|  1189           // else tmp_x |  1247           // else tmp_x | 
|  1190           current_function_builder_->Emit(kExprElse); |  1248           current_function_builder_->Emit(kExprElse); | 
|  1191           current_function_builder_->EmitGetLocal(tmp_x.index()); |  1249           current_function_builder_->EmitGetLocal(tmp_x.index()); | 
|  1192           current_function_builder_->Emit(kExprEnd); |  1250           current_function_builder_->Emit(kExprEnd); | 
|  1193  |  1251  | 
|  1194         } else if (call_type == kAstF32) { |  1252         } else if (call_type == kAstF32) { | 
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1260   } |  1318   } | 
|  1261  |  1319  | 
|  1262   void VisitCallArgs(Call* expr) { |  1320   void VisitCallArgs(Call* expr) { | 
|  1263     ZoneList<Expression*>* args = expr->arguments(); |  1321     ZoneList<Expression*>* args = expr->arguments(); | 
|  1264     for (int i = 0; i < args->length(); ++i) { |  1322     for (int i = 0; i < args->length(); ++i) { | 
|  1265       Expression* arg = args->at(i); |  1323       Expression* arg = args->at(i); | 
|  1266       RECURSE(Visit(arg)); |  1324       RECURSE(Visit(arg)); | 
|  1267     } |  1325     } | 
|  1268   } |  1326   } | 
|  1269  |  1327  | 
|  1270   void VisitCall(Call* expr) { |  1328   void VisitCall(Call* expr) { VisitCallExpression(expr); } | 
 |  1329  | 
 |  1330   bool VisitCallExpression(Call* expr) { | 
|  1271     Call::CallType call_type = expr->GetCallType(); |  1331     Call::CallType call_type = expr->GetCallType(); | 
 |  1332     bool returns_value = true; | 
|  1272     switch (call_type) { |  1333     switch (call_type) { | 
|  1273       case Call::OTHER_CALL: { |  1334       case Call::OTHER_CALL: { | 
|  1274         DCHECK_EQ(kFuncScope, scope_); |  1335         DCHECK_EQ(kFuncScope, scope_); | 
|  1275         VariableProxy* proxy = expr->expression()->AsVariableProxy(); |  1336         VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 
|  1276         if (proxy != nullptr) { |  1337         if (proxy != nullptr) { | 
|  1277           if (VisitStdlibFunction(expr, proxy)) { |  1338           if (VisitStdlibFunction(expr, proxy)) { | 
|  1278             return; |  1339             return true; | 
|  1279           } |  1340           } | 
|  1280         } |  1341         } | 
|  1281         uint32_t index; |  | 
|  1282         VariableProxy* vp = expr->expression()->AsVariableProxy(); |  1342         VariableProxy* vp = expr->expression()->AsVariableProxy(); | 
|  1283         DCHECK_NOT_NULL(vp); |  1343         DCHECK_NOT_NULL(vp); | 
|  1284         if (typer_->TypeOf(vp)->AsFFIType() != nullptr) { |  1344         if (typer_->TypeOf(vp)->AsFFIType() != nullptr) { | 
|  1285           LocalType return_type = TypeOf(expr); |  1345           LocalType return_type = TypeOf(expr); | 
|  1286           ZoneList<Expression*>* args = expr->arguments(); |  1346           ZoneList<Expression*>* args = expr->arguments(); | 
|  1287           FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |  1347           FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 
|  1288                                    args->length()); |  1348                                    args->length()); | 
|  1289           if (return_type != kAstStmt) { |  1349           if (return_type != kAstStmt) { | 
|  1290             sig.AddReturn(return_type); |  1350             sig.AddReturn(return_type); | 
 |  1351           } else { | 
 |  1352             returns_value = false; | 
|  1291           } |  1353           } | 
|  1292           for (int i = 0; i < args->length(); ++i) { |  1354           for (int i = 0; i < args->length(); ++i) { | 
|  1293             sig.AddParam(TypeOf(args->at(i))); |  1355             sig.AddParam(TypeOf(args->at(i))); | 
|  1294           } |  1356           } | 
|  1295           index = |  1357           uint32_t index = | 
|  1296               imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |  1358               imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 
|  1297           VisitCallArgs(expr); |  1359           VisitCallArgs(expr); | 
|  1298           current_function_builder_->Emit(kExprCallImport); |  1360           current_function_builder_->Emit(kExprCallFunction); | 
|  1299           current_function_builder_->EmitVarInt(expr->arguments()->length()); |  | 
|  1300           current_function_builder_->EmitVarInt(index); |  1361           current_function_builder_->EmitVarInt(index); | 
|  1301         } else { |  1362         } else { | 
|  1302           index = LookupOrInsertFunction(vp->var()); |  1363           WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); | 
|  1303           VisitCallArgs(expr); |  1364           VisitCallArgs(expr); | 
|  1304           current_function_builder_->Emit(kExprCallFunction); |  1365           current_function_builder_->Emit(kExprCallFunction); | 
|  1305           current_function_builder_->EmitVarInt(expr->arguments()->length()); |  1366           current_function_builder_->EmitVarInt(function->func_index()); | 
|  1306           current_function_builder_->EmitVarInt(index); |  1367           returns_value = function->signature()->return_count() > 0; | 
|  1307         } |  1368         } | 
|  1308         break; |  1369         break; | 
|  1309       } |  1370       } | 
|  1310       case Call::KEYED_PROPERTY_CALL: { |  1371       case Call::KEYED_PROPERTY_CALL: { | 
|  1311         DCHECK_EQ(kFuncScope, scope_); |  1372         DCHECK_EQ(kFuncScope, scope_); | 
|  1312         Property* p = expr->expression()->AsProperty(); |  1373         Property* p = expr->expression()->AsProperty(); | 
|  1313         DCHECK_NOT_NULL(p); |  1374         DCHECK_NOT_NULL(p); | 
|  1314         VariableProxy* var = p->obj()->AsVariableProxy(); |  1375         VariableProxy* var = p->obj()->AsVariableProxy(); | 
|  1315         DCHECK_NOT_NULL(var); |  1376         DCHECK_NOT_NULL(var); | 
|  1316         FunctionTableIndices* indices = LookupFunctionTable(var->var()); |  1377         FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 
|  1317         RECURSE(Visit(p->key())); |  1378         Visit(p->key());  // TODO(titzer): should use RECURSE() | 
 |  1379  | 
 |  1380         // We have to use a temporary for the correct order of evaluation. | 
|  1318         current_function_builder_->EmitI32Const(indices->start_index); |  1381         current_function_builder_->EmitI32Const(indices->start_index); | 
|  1319         current_function_builder_->Emit(kExprI32Add); |  1382         current_function_builder_->Emit(kExprI32Add); | 
 |  1383         WasmTemporary tmp(current_function_builder_, kAstI32); | 
 |  1384         current_function_builder_->EmitSetLocal(tmp.index()); | 
 |  1385  | 
|  1320         VisitCallArgs(expr); |  1386         VisitCallArgs(expr); | 
 |  1387  | 
 |  1388         current_function_builder_->EmitGetLocal(tmp.index()); | 
|  1321         current_function_builder_->Emit(kExprCallIndirect); |  1389         current_function_builder_->Emit(kExprCallIndirect); | 
|  1322         current_function_builder_->EmitVarInt(expr->arguments()->length()); |  | 
|  1323         current_function_builder_->EmitVarInt(indices->signature_index); |  1390         current_function_builder_->EmitVarInt(indices->signature_index); | 
 |  1391         returns_value = | 
 |  1392             builder_->GetSignature(indices->signature_index)->return_count() > | 
 |  1393             0; | 
|  1324         break; |  1394         break; | 
|  1325       } |  1395       } | 
|  1326       default: |  1396       default: | 
|  1327         UNREACHABLE(); |  1397         UNREACHABLE(); | 
|  1328     } |  1398     } | 
 |  1399     return returns_value; | 
|  1329   } |  1400   } | 
|  1330  |  1401  | 
|  1331   void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |  1402   void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 
|  1332  |  1403  | 
|  1333   void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |  1404   void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 
|  1334  |  1405  | 
|  1335   void VisitUnaryOperation(UnaryOperation* expr) { |  1406   void VisitUnaryOperation(UnaryOperation* expr) { | 
|  1336     RECURSE(Visit(expr->expression())); |  1407     RECURSE(Visit(expr->expression())); | 
|  1337     switch (expr->op()) { |  1408     switch (expr->op()) { | 
|  1338       case Token::NOT: { |  1409       case Token::NOT: { | 
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1504         current_function_builder_->Emit(kExprI32AsmjsSConvertF32); |  1575         current_function_builder_->Emit(kExprI32AsmjsSConvertF32); | 
|  1505       } else if (type == kFloat64) { |  1576       } else if (type == kFloat64) { | 
|  1506         current_function_builder_->Emit(kExprI32AsmjsSConvertF64); |  1577         current_function_builder_->Emit(kExprI32AsmjsSConvertF64); | 
|  1507       } else { |  1578       } else { | 
|  1508         UNREACHABLE(); |  1579         UNREACHABLE(); | 
|  1509       } |  1580       } | 
|  1510     } else if (convertOperation == kAsIs) { |  1581     } else if (convertOperation == kAsIs) { | 
|  1511       RECURSE(Visit(GetLeft(expr))); |  1582       RECURSE(Visit(GetLeft(expr))); | 
|  1512     } else { |  1583     } else { | 
|  1513       if (expr->op() == Token::COMMA) { |  1584       if (expr->op() == Token::COMMA) { | 
|  1514         current_function_builder_->Emit(kExprBlock); |  1585         RECURSE(VisitForEffect(expr->left())); | 
 |  1586         RECURSE(Visit(expr->right())); | 
 |  1587         return; | 
|  1515       } |  1588       } | 
|  1516  |  | 
|  1517       RECURSE(Visit(expr->left())); |  1589       RECURSE(Visit(expr->left())); | 
|  1518       RECURSE(Visit(expr->right())); |  1590       RECURSE(Visit(expr->right())); | 
|  1519  |  1591  | 
|  1520       if (expr->op() == Token::COMMA) { |  | 
|  1521         current_function_builder_->Emit(kExprEnd); |  | 
|  1522       } |  | 
|  1523  |  | 
|  1524       switch (expr->op()) { |  1592       switch (expr->op()) { | 
|  1525         BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |  1593         BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 
|  1526         BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |  1594         BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 
|  1527         BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |  1595         BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 
|  1528         BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |  1596         BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 
|  1529         BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |  1597         BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); | 
|  1530         BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |  1598         BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 
|  1531         BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |  1599         BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 
|  1532         BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |  1600         BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 
|  1533         BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |  1601         BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1713       uint32_t index = builder_->AddGlobal(type, 0); |  1781       uint32_t index = builder_->AddGlobal(type, 0); | 
|  1714       IndexContainer* container = new (zone()) IndexContainer(); |  1782       IndexContainer* container = new (zone()) IndexContainer(); | 
|  1715       container->index = index; |  1783       container->index = index; | 
|  1716       entry = global_variables_.LookupOrInsert(v, ComputePointerHash(v), |  1784       entry = global_variables_.LookupOrInsert(v, ComputePointerHash(v), | 
|  1717                                                ZoneAllocationPolicy(zone())); |  1785                                                ZoneAllocationPolicy(zone())); | 
|  1718       entry->value = container; |  1786       entry->value = container; | 
|  1719     } |  1787     } | 
|  1720     return (reinterpret_cast<IndexContainer*>(entry->value))->index; |  1788     return (reinterpret_cast<IndexContainer*>(entry->value))->index; | 
|  1721   } |  1789   } | 
|  1722  |  1790  | 
|  1723   uint32_t LookupOrInsertFunction(Variable* v) { |  1791   WasmFunctionBuilder* LookupOrInsertFunction(Variable* v) { | 
|  1724     DCHECK_NOT_NULL(builder_); |  1792     DCHECK_NOT_NULL(builder_); | 
|  1725     ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v)); |  1793     ZoneHashMap::Entry* entry = functions_.Lookup(v, ComputePointerHash(v)); | 
|  1726     if (entry == nullptr) { |  1794     if (entry == nullptr) { | 
|  1727       uint32_t index = builder_->AddFunction(); |  1795       auto* func_type = typer_->TypeOf(v)->AsFunctionType(); | 
|  1728       IndexContainer* container = new (zone()) IndexContainer(); |  1796       DCHECK_NOT_NULL(func_type); | 
|  1729       container->index = index; |  1797       // Build the signature for the function. | 
 |  1798       LocalType return_type = TypeFrom(func_type->ReturnType()); | 
 |  1799       const auto& arguments = func_type->Arguments(); | 
 |  1800       FunctionSig::Builder b(zone(), return_type == kAstStmt ? 0 : 1, | 
 |  1801                              arguments.size()); | 
 |  1802       if (return_type != kAstStmt) b.AddReturn(return_type); | 
 |  1803       for (int i = 0; i < static_cast<int>(arguments.size()); ++i) { | 
 |  1804         LocalType type = TypeFrom(arguments[i]); | 
 |  1805         DCHECK_NE(kAstStmt, type); | 
 |  1806         b.AddParam(type); | 
 |  1807       } | 
 |  1808  | 
 |  1809       WasmFunctionBuilder* function = builder_->AddFunction(b.Build()); | 
|  1730       entry = functions_.LookupOrInsert(v, ComputePointerHash(v), |  1810       entry = functions_.LookupOrInsert(v, ComputePointerHash(v), | 
|  1731                                         ZoneAllocationPolicy(zone())); |  1811                                         ZoneAllocationPolicy(zone())); | 
|  1732       entry->value = container; |  1812       function->SetName( | 
 |  1813           reinterpret_cast<const char*>(v->raw_name()->raw_data()), | 
 |  1814           v->raw_name()->length()); | 
 |  1815       entry->value = function; | 
|  1733     } |  1816     } | 
|  1734     return (reinterpret_cast<IndexContainer*>(entry->value))->index; |  1817     return (reinterpret_cast<WasmFunctionBuilder*>(entry->value)); | 
|  1735   } |  1818   } | 
|  1736  |  1819  | 
|  1737   LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); } |  1820   LocalType TypeOf(Expression* expr) { return TypeFrom(typer_->TypeOf(expr)); } | 
|  1738  |  1821  | 
|  1739   LocalType TypeFrom(AsmType* type) { |  1822   LocalType TypeFrom(AsmType* type) { | 
|  1740     if (type->IsA(AsmType::Intish())) { |  1823     if (type->IsA(AsmType::Intish())) { | 
|  1741       return kAstI32; |  1824       return kAstI32; | 
|  1742     } |  1825     } | 
|  1743  |  1826  | 
|  1744     if (type->IsA(AsmType::Floatish())) { |  1827     if (type->IsA(AsmType::Floatish())) { | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  1759   ZoneHashMap global_variables_; |  1842   ZoneHashMap global_variables_; | 
|  1760   AsmScope scope_; |  1843   AsmScope scope_; | 
|  1761   WasmModuleBuilder* builder_; |  1844   WasmModuleBuilder* builder_; | 
|  1762   WasmFunctionBuilder* current_function_builder_; |  1845   WasmFunctionBuilder* current_function_builder_; | 
|  1763   FunctionLiteral* literal_; |  1846   FunctionLiteral* literal_; | 
|  1764   Isolate* isolate_; |  1847   Isolate* isolate_; | 
|  1765   Zone* zone_; |  1848   Zone* zone_; | 
|  1766   AsmTyper* typer_; |  1849   AsmTyper* typer_; | 
|  1767   ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |  1850   ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 
|  1768   ZoneVector<ForeignVariable> foreign_variables_; |  1851   ZoneVector<ForeignVariable> foreign_variables_; | 
|  1769   uint32_t init_function_index_; |  1852   WasmFunctionBuilder* init_function_; | 
|  1770   uint32_t foreign_init_function_index_; |  1853   WasmFunctionBuilder* foreign_init_function_; | 
|  1771   uint32_t next_table_index_; |  1854   uint32_t next_table_index_; | 
|  1772   ZoneHashMap function_tables_; |  1855   ZoneHashMap function_tables_; | 
|  1773   ImportedFunctionTable imported_function_table_; |  1856   ImportedFunctionTable imported_function_table_; | 
|  1774  |  1857  | 
|  1775   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |  1858   DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 
|  1776  |  1859  | 
|  1777  private: |  1860  private: | 
|  1778   DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |  1861   DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 
|  1779 }; |  1862 }; | 
|  1780  |  1863  | 
|  1781 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |  1864 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 
|  1782                                FunctionLiteral* literal, AsmTyper* typer) |  1865                                FunctionLiteral* literal, AsmTyper* typer) | 
|  1783     : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} |  1866     : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} | 
|  1784  |  1867  | 
|  1785 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |  1868 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 
|  1786 // that zone in constructor may be thrown away once wasm module is written. |  1869 // that zone in constructor may be thrown away once wasm module is written. | 
|  1787 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { |  1870 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { | 
|  1788   AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); |  1871   AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); | 
|  1789   impl.Build(); |  1872   impl.Build(); | 
|  1790   *foreign_args = impl.GetForeignArgs(); |  1873   *foreign_args = impl.GetForeignArgs(); | 
|  1791   ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); |  1874   ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); | 
|  1792   impl.builder_->WriteTo(*buffer); |  1875   impl.builder_->WriteTo(*buffer); | 
|  1793   return buffer; |  1876   return buffer; | 
|  1794 } |  1877 } | 
|  1795 }  // namespace wasm |  1878 }  // namespace wasm | 
|  1796 }  // namespace internal |  1879 }  // namespace internal | 
|  1797 }  // namespace v8 |  1880 }  // namespace v8 | 
| OLD | NEW |