| 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 |
| 11 #include <math.h> | 11 #include <math.h> |
| 12 | 12 |
| 13 #include "src/asmjs/asm-types.h" | 13 #include "src/asmjs/asm-types.h" |
| 14 #include "src/asmjs/asm-wasm-builder.h" | 14 #include "src/asmjs/asm-wasm-builder.h" |
| 15 #include "src/asmjs/switch-logic.h" | 15 #include "src/asmjs/switch-logic.h" |
| 16 | 16 |
| 17 #include "src/wasm/wasm-macro-gen.h" | 17 #include "src/wasm/wasm-macro-gen.h" |
| 18 #include "src/wasm/wasm-opcodes.h" | 18 #include "src/wasm/wasm-opcodes.h" |
| 19 | 19 |
| 20 #include "src/ast/ast.h" | 20 #include "src/ast/ast.h" |
| 21 #include "src/ast/scopes.h" | 21 #include "src/ast/scopes.h" |
| 22 #include "src/codegen.h" |
| 23 #include "src/compiler.h" |
| 24 #include "src/isolate.h" |
| 25 #include "src/parsing/parse-info.h" |
| 22 | 26 |
| 23 namespace v8 { | 27 namespace v8 { |
| 24 namespace internal { | 28 namespace internal { |
| 25 namespace wasm { | 29 namespace wasm { |
| 26 | 30 |
| 27 #define RECURSE(call) \ | 31 #define RECURSE(call) \ |
| 28 do { \ | 32 do { \ |
| 29 DCHECK(!HasStackOverflow()); \ | 33 DCHECK(!HasStackOverflow()); \ |
| 30 call; \ | 34 call; \ |
| 31 if (HasStackOverflow()) return; \ | 35 if (HasStackOverflow()) return; \ |
| 32 } while (false) | 36 } while (false) |
| 33 | 37 |
| 34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | 38 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
| 35 enum ValueFate { kDrop, kLeaveOnStack }; | 39 enum ValueFate { kDrop, kLeaveOnStack }; |
| 36 | 40 |
| 37 struct ForeignVariable { | 41 struct ForeignVariable { |
| 38 Handle<Name> name; | 42 Handle<Name> name; |
| 39 Variable* var; | 43 Variable* var; |
| 40 LocalType type; | 44 LocalType type; |
| 41 }; | 45 }; |
| 42 | 46 |
| 43 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { | 47 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| 44 public: | 48 public: |
| 45 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 49 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, |
| 46 AsmTyper* typer) | 50 AstValueFactory* ast_value_factory, Script* script, |
| 51 FunctionLiteral* literal, AsmTyper* typer) |
| 47 : local_variables_(ZoneHashMap::kDefaultHashMapCapacity, | 52 : local_variables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 48 ZoneAllocationPolicy(zone)), | 53 ZoneAllocationPolicy(zone)), |
| 49 functions_(ZoneHashMap::kDefaultHashMapCapacity, | 54 functions_(ZoneHashMap::kDefaultHashMapCapacity, |
| 50 ZoneAllocationPolicy(zone)), | 55 ZoneAllocationPolicy(zone)), |
| 51 global_variables_(ZoneHashMap::kDefaultHashMapCapacity, | 56 global_variables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 52 ZoneAllocationPolicy(zone)), | 57 ZoneAllocationPolicy(zone)), |
| 53 scope_(kModuleScope), | 58 scope_(kModuleScope), |
| 54 builder_(new (zone) WasmModuleBuilder(zone)), | 59 builder_(new (zone) WasmModuleBuilder(zone)), |
| 55 current_function_builder_(nullptr), | 60 current_function_builder_(nullptr), |
| 56 literal_(literal), | 61 literal_(literal), |
| 57 isolate_(isolate), | 62 isolate_(isolate), |
| 58 zone_(zone), | 63 zone_(zone), |
| 64 ast_value_factory_(ast_value_factory), |
| 65 script_(script), |
| 59 typer_(typer), | 66 typer_(typer), |
| 67 typer_failed_(false), |
| 60 breakable_blocks_(zone), | 68 breakable_blocks_(zone), |
| 61 foreign_variables_(zone), | 69 foreign_variables_(zone), |
| 62 init_function_(nullptr), | 70 init_function_(nullptr), |
| 63 foreign_init_function_(nullptr), | 71 foreign_init_function_(nullptr), |
| 64 next_table_index_(0), | |
| 65 function_tables_(ZoneHashMap::kDefaultHashMapCapacity, | 72 function_tables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 66 ZoneAllocationPolicy(zone)), | 73 ZoneAllocationPolicy(zone)), |
| 67 imported_function_table_(this) { | 74 imported_function_table_(this) { |
| 68 InitializeAstVisitor(isolate); | 75 InitializeAstVisitor(isolate); |
| 69 } | 76 } |
| 70 | 77 |
| 71 void InitializeInitFunction() { | 78 void InitializeInitFunction() { |
| 72 FunctionSig::Builder b(zone(), 0, 0); | 79 FunctionSig::Builder b(zone(), 0, 0); |
| 73 init_function_ = builder_->AddFunction(b.Build()); | 80 init_function_ = builder_->AddFunction(b.Build()); |
| 74 builder_->MarkStartFunction(init_function_); | 81 builder_->MarkStartFunction(init_function_); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 95 i::Handle<i::FixedArray> GetForeignArgs() { | 102 i::Handle<i::FixedArray> GetForeignArgs() { |
| 96 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( | 103 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( |
| 97 static_cast<int>(foreign_variables_.size())); | 104 static_cast<int>(foreign_variables_.size())); |
| 98 for (size_t i = 0; i < foreign_variables_.size(); ++i) { | 105 for (size_t i = 0; i < foreign_variables_.size(); ++i) { |
| 99 ForeignVariable* fv = &foreign_variables_[i]; | 106 ForeignVariable* fv = &foreign_variables_[i]; |
| 100 ret->set(static_cast<int>(i), *fv->name); | 107 ret->set(static_cast<int>(i), *fv->name); |
| 101 } | 108 } |
| 102 return ret; | 109 return ret; |
| 103 } | 110 } |
| 104 | 111 |
| 105 void Build() { | 112 bool Build() { |
| 106 InitializeInitFunction(); | 113 InitializeInitFunction(); |
| 107 RECURSE(VisitFunctionLiteral(literal_)); | 114 if (!typer_->ValidateBeforeFunctionsPhase()) { |
| 115 return false; |
| 116 } |
| 117 DCHECK(!HasStackOverflow()); |
| 118 VisitFunctionLiteral(literal_); |
| 119 if (HasStackOverflow()) { |
| 120 return false; |
| 121 } |
| 122 if (typer_failed_) { |
| 123 return false; |
| 124 } |
| 108 BuildForeignInitFunction(); | 125 BuildForeignInitFunction(); |
| 126 return true; |
| 109 } | 127 } |
| 110 | 128 |
| 111 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 129 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
| 112 | 130 |
| 113 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 131 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 114 DCHECK_EQ(kModuleScope, scope_); | 132 DCHECK_EQ(kModuleScope, scope_); |
| 115 DCHECK_NULL(current_function_builder_); | 133 DCHECK_NULL(current_function_builder_); |
| 134 FunctionLiteral* old_func = decl->fun(); |
| 135 i::Zone zone(isolate_->allocator(), ZONE_NAME); |
| 136 if (decl->fun()->body() == nullptr) { |
| 137 // TODO(bradnelson): Refactor parser so we don't need a |
| 138 // SharedFunctionInfo to parse a single function, |
| 139 // or squirrel away the SharedFunctionInfo to use later. |
| 140 Handle<SharedFunctionInfo> shared = |
| 141 isolate_->factory()->NewSharedFunctionInfoForLiteral( |
| 142 decl->fun(), handle(script_, isolate_)); |
| 143 shared->set_is_toplevel(false); |
| 144 i::ParseInfo info(&zone, handle(script_, isolate_)); |
| 145 info.set_shared_info(shared); |
| 146 info.set_toplevel(false); |
| 147 info.set_language_mode(decl->fun()->scope()->language_mode()); |
| 148 info.set_allow_lazy_parsing(false); |
| 149 info.set_ast_value_factory(ast_value_factory_); |
| 150 info.set_ast_value_factory_owned(false); |
| 151 // Create fresh function scope to use to parse the function in. |
| 152 DeclarationScope* new_func_scope = new (info.zone()) DeclarationScope( |
| 153 info.zone(), decl->fun()->scope()->outer_scope(), FUNCTION_SCOPE); |
| 154 info.set_asm_function_scope(new_func_scope); |
| 155 if (!i::Compiler::ParseAndAnalyze(&info)) { |
| 156 typer_failed_ = true; |
| 157 return; |
| 158 } |
| 159 FunctionLiteral* func = info.literal(); |
| 160 DCHECK_NOT_NULL(func); |
| 161 decl->set_fun(func); |
| 162 } |
| 163 if (!typer_->ValidateInnerFunction(decl)) { |
| 164 typer_failed_ = true; |
| 165 decl->set_fun(old_func); |
| 166 decl->scope()->RemoveInnerScope(decl->scope()->inner_scope()); |
| 167 return; |
| 168 } |
| 116 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); | 169 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); |
| 117 scope_ = kFuncScope; | 170 scope_ = kFuncScope; |
| 118 RECURSE(Visit(decl->fun())); | 171 RECURSE(Visit(decl->fun())); |
| 172 decl->set_fun(old_func); |
| 173 decl->scope()->RemoveInnerScope(decl->scope()->inner_scope()); |
| 119 scope_ = kModuleScope; | 174 scope_ = kModuleScope; |
| 120 current_function_builder_ = nullptr; | 175 current_function_builder_ = nullptr; |
| 121 local_variables_.Clear(); | 176 local_variables_.Clear(); |
| 122 } | 177 } |
| 123 | 178 |
| 124 void VisitStatements(ZoneList<Statement*>* stmts) { | 179 void VisitStatements(ZoneList<Statement*>* stmts) { |
| 125 for (int i = 0; i < stmts->length(); ++i) { | 180 for (int i = 0; i < stmts->length(); ++i) { |
| 126 Statement* stmt = stmts->at(i); | 181 Statement* stmt = stmts->at(i); |
| 127 ExpressionStatement* e = stmt->AsExpressionStatement(); | 182 ExpressionStatement* e = stmt->AsExpressionStatement(); |
| 128 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | 183 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { |
| 129 continue; | 184 continue; |
| 130 } | 185 } |
| 131 RECURSE(Visit(stmt)); | 186 RECURSE(Visit(stmt)); |
| 187 if (typer_failed_) break; |
| 132 if (stmt->IsJump()) break; | 188 if (stmt->IsJump()) break; |
| 133 } | 189 } |
| 134 } | 190 } |
| 135 | 191 |
| 136 void VisitBlock(Block* stmt) { | 192 void VisitBlock(Block* stmt) { |
| 137 if (stmt->statements()->length() == 1) { | 193 if (stmt->statements()->length() == 1) { |
| 138 ExpressionStatement* expr = | 194 ExpressionStatement* expr = |
| 139 stmt->statements()->at(0)->AsExpressionStatement(); | 195 stmt->statements()->at(0)->AsExpressionStatement(); |
| 140 if (expr != nullptr) { | 196 if (expr != nullptr) { |
| 141 if (expr->expression()->IsAssignment()) { | 197 if (expr->expression()->IsAssignment()) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 void VisitContinueStatement(ContinueStatement* stmt) { | 294 void VisitContinueStatement(ContinueStatement* stmt) { |
| 239 DoBreakOrContinue(stmt->target(), true); | 295 DoBreakOrContinue(stmt->target(), true); |
| 240 } | 296 } |
| 241 | 297 |
| 242 void VisitBreakStatement(BreakStatement* stmt) { | 298 void VisitBreakStatement(BreakStatement* stmt) { |
| 243 DoBreakOrContinue(stmt->target(), false); | 299 DoBreakOrContinue(stmt->target(), false); |
| 244 } | 300 } |
| 245 | 301 |
| 246 void VisitReturnStatement(ReturnStatement* stmt) { | 302 void VisitReturnStatement(ReturnStatement* stmt) { |
| 247 if (scope_ == kModuleScope) { | 303 if (scope_ == kModuleScope) { |
| 304 if (!typer_->ValidateAfterFunctionsPhase()) { |
| 305 typer_failed_ = true; |
| 306 return; |
| 307 } |
| 248 scope_ = kExportScope; | 308 scope_ = kExportScope; |
| 249 RECURSE(Visit(stmt->expression())); | 309 RECURSE(Visit(stmt->expression())); |
| 250 scope_ = kModuleScope; | 310 scope_ = kModuleScope; |
| 251 } else if (scope_ == kFuncScope) { | 311 } else if (scope_ == kFuncScope) { |
| 252 RECURSE(Visit(stmt->expression())); | 312 RECURSE(Visit(stmt->expression())); |
| 253 current_function_builder_->Emit(kExprReturn); | 313 current_function_builder_->Emit(kExprReturn); |
| 254 } else { | 314 } else { |
| 255 UNREACHABLE(); | 315 UNREACHABLE(); |
| 256 } | 316 } |
| 257 } | 317 } |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 const auto& arguments = func_type->Arguments(); | 501 const auto& arguments = func_type->Arguments(); |
| 442 for (int i = 0; i < expr->parameter_count(); ++i) { | 502 for (int i = 0; i < expr->parameter_count(); ++i) { |
| 443 LocalType type = TypeFrom(arguments[i]); | 503 LocalType type = TypeFrom(arguments[i]); |
| 444 DCHECK_NE(kAstStmt, type); | 504 DCHECK_NE(kAstStmt, type); |
| 445 InsertParameter(scope->parameter(i), type, i); | 505 InsertParameter(scope->parameter(i), type, i); |
| 446 } | 506 } |
| 447 } else { | 507 } else { |
| 448 UNREACHABLE(); | 508 UNREACHABLE(); |
| 449 } | 509 } |
| 450 } | 510 } |
| 511 RECURSE(VisitDeclarations(scope->declarations())); |
| 512 if (typer_failed_) return; |
| 451 RECURSE(VisitStatements(expr->body())); | 513 RECURSE(VisitStatements(expr->body())); |
| 452 RECURSE(VisitDeclarations(scope->declarations())); | |
| 453 } | 514 } |
| 454 | 515 |
| 455 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 516 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 456 UNREACHABLE(); | 517 UNREACHABLE(); |
| 457 } | 518 } |
| 458 | 519 |
| 459 void VisitConditional(Conditional* expr) { | 520 void VisitConditional(Conditional* expr) { |
| 460 DCHECK_EQ(kFuncScope, scope_); | 521 DCHECK_EQ(kFuncScope, scope_); |
| 461 RECURSE(Visit(expr->condition())); | 522 RECURSE(Visit(expr->condition())); |
| 462 // WASM ifs come with implicit blocks for both arms. | 523 // WASM ifs come with implicit blocks for both arms. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 653 void LoadInitFunction() { | 714 void LoadInitFunction() { |
| 654 current_function_builder_ = init_function_; | 715 current_function_builder_ = init_function_; |
| 655 scope_ = kInitScope; | 716 scope_ = kInitScope; |
| 656 } | 717 } |
| 657 | 718 |
| 658 void UnLoadInitFunction() { | 719 void UnLoadInitFunction() { |
| 659 scope_ = kModuleScope; | 720 scope_ = kModuleScope; |
| 660 current_function_builder_ = nullptr; | 721 current_function_builder_ = nullptr; |
| 661 } | 722 } |
| 662 | 723 |
| 663 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 724 struct FunctionTableIndices : public ZoneObject { |
| 664 auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); | 725 uint32_t start_index; |
| 665 DCHECK_NOT_NULL(func_tbl_type); | 726 uint32_t signature_index; |
| 666 auto* func_type = func_tbl_type->signature()->AsFunctionType(); | 727 }; |
| 728 |
| 729 FunctionTableIndices* LookupOrAddFunctionTable(VariableProxy* table, |
| 730 Property* p) { |
| 731 FunctionTableIndices* indices = LookupFunctionTable(table->var()); |
| 732 if (indices != nullptr) { |
| 733 // Already setup. |
| 734 return indices; |
| 735 } |
| 736 indices = new (zone()) FunctionTableIndices(); |
| 737 auto* func_type = typer_->TypeOf(p)->AsFunctionType(); |
| 738 auto* func_table_type = typer_->TypeOf(p->obj()->AsVariableProxy()->var()) |
| 739 ->AsFunctionTableType(); |
| 667 const auto& arguments = func_type->Arguments(); | 740 const auto& arguments = func_type->Arguments(); |
| 668 LocalType return_type = TypeFrom(func_type->ReturnType()); | 741 LocalType return_type = TypeFrom(func_type->ReturnType()); |
| 669 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 742 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 670 arguments.size()); | 743 arguments.size()); |
| 671 if (return_type != kAstStmt) { | 744 if (return_type != kAstStmt) { |
| 672 sig.AddReturn(return_type); | 745 sig.AddReturn(return_type); |
| 673 } | 746 } |
| 674 for (auto* arg : arguments) { | 747 for (auto* arg : arguments) { |
| 675 sig.AddParam(TypeFrom(arg)); | 748 sig.AddParam(TypeFrom(arg)); |
| 676 } | 749 } |
| 677 uint32_t signature_index = builder_->AddSignature(sig.Build()); | 750 uint32_t signature_index = builder_->AddSignature(sig.Build()); |
| 678 InsertFunctionTable(table->var(), next_table_index_, signature_index); | 751 indices->start_index = builder_->AllocateIndirectFunctions( |
| 679 next_table_index_ += funcs->values()->length(); | 752 static_cast<uint32_t>(func_table_type->length())); |
| 680 for (int i = 0; i < funcs->values()->length(); ++i) { | 753 indices->signature_index = signature_index; |
| 681 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | |
| 682 DCHECK_NOT_NULL(func); | |
| 683 builder_->AddIndirectFunction( | |
| 684 LookupOrInsertFunction(func->var())->func_index()); | |
| 685 } | |
| 686 } | |
| 687 | |
| 688 struct FunctionTableIndices : public ZoneObject { | |
| 689 uint32_t start_index; | |
| 690 uint32_t signature_index; | |
| 691 }; | |
| 692 | |
| 693 void InsertFunctionTable(Variable* v, uint32_t start_index, | |
| 694 uint32_t signature_index) { | |
| 695 FunctionTableIndices* container = new (zone()) FunctionTableIndices(); | |
| 696 container->start_index = start_index; | |
| 697 container->signature_index = signature_index; | |
| 698 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( | 754 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
| 699 v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); | 755 table->var(), ComputePointerHash(table->var()), |
| 700 entry->value = container; | 756 ZoneAllocationPolicy(zone())); |
| 757 entry->value = indices; |
| 758 return indices; |
| 701 } | 759 } |
| 702 | 760 |
| 703 FunctionTableIndices* LookupFunctionTable(Variable* v) { | 761 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
| 704 ZoneHashMap::Entry* entry = | 762 ZoneHashMap::Entry* entry = |
| 705 function_tables_.Lookup(v, ComputePointerHash(v)); | 763 function_tables_.Lookup(v, ComputePointerHash(v)); |
| 706 DCHECK_NOT_NULL(entry); | 764 if (entry == nullptr) { |
| 765 return nullptr; |
| 766 } |
| 707 return reinterpret_cast<FunctionTableIndices*>(entry->value); | 767 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
| 708 } | 768 } |
| 709 | 769 |
| 770 void PopulateFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
| 771 FunctionTableIndices* indices = LookupFunctionTable(table->var()); |
| 772 DCHECK_NOT_NULL(indices); |
| 773 for (int i = 0; i < funcs->values()->length(); ++i) { |
| 774 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); |
| 775 DCHECK_NOT_NULL(func); |
| 776 builder_->SetIndirectFunction( |
| 777 indices->start_index + i, |
| 778 LookupOrInsertFunction(func->var())->func_index()); |
| 779 } |
| 780 } |
| 781 |
| 710 class ImportedFunctionTable { | 782 class ImportedFunctionTable { |
| 711 private: | 783 private: |
| 712 class ImportedFunctionIndices : public ZoneObject { | 784 class ImportedFunctionIndices : public ZoneObject { |
| 713 public: | 785 public: |
| 714 const char* name_; | 786 const char* name_; |
| 715 int name_length_; | 787 int name_length_; |
| 716 WasmModuleBuilder::SignatureMap signature_to_index_; | 788 WasmModuleBuilder::SignatureMap signature_to_index_; |
| 717 | 789 |
| 718 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) | 790 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) |
| 719 : name_(name), name_length_(name_length), signature_to_index_(zone) {} | 791 : name_(name), name_length_(name_length), signature_to_index_(zone) {} |
| 720 }; | 792 }; |
| 721 ZoneHashMap table_; | 793 ZoneHashMap table_; |
| 722 AsmWasmBuilderImpl* builder_; | 794 AsmWasmBuilderImpl* builder_; |
| 723 | 795 |
| 724 public: | 796 public: |
| 725 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) | 797 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) |
| 726 : table_(ZoneHashMap::kDefaultHashMapCapacity, | 798 : table_(ZoneHashMap::kDefaultHashMapCapacity, |
| 727 ZoneAllocationPolicy(builder->zone())), | 799 ZoneAllocationPolicy(builder->zone())), |
| 728 builder_(builder) {} | 800 builder_(builder) {} |
| 729 | 801 |
| 730 void AddImport(Variable* v, const char* name, int name_length) { | 802 ImportedFunctionIndices* LookupOrInsertImport(Variable* v) { |
| 731 ImportedFunctionIndices* indices = new (builder_->zone()) | |
| 732 ImportedFunctionIndices(name, name_length, builder_->zone()); | |
| 733 auto* entry = table_.LookupOrInsert( | 803 auto* entry = table_.LookupOrInsert( |
| 734 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); | 804 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |
| 735 entry->value = indices; | 805 ImportedFunctionIndices* indices; |
| 806 if (entry->value == nullptr) { |
| 807 indices = new (builder_->zone()) |
| 808 ImportedFunctionIndices(nullptr, 0, builder_->zone()); |
| 809 entry->value = indices; |
| 810 } else { |
| 811 indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value); |
| 812 } |
| 813 return indices; |
| 814 } |
| 815 |
| 816 void SetImportName(Variable* v, const char* name, int name_length) { |
| 817 auto* indices = LookupOrInsertImport(v); |
| 818 indices->name_ = name; |
| 819 indices->name_length_ = name_length; |
| 820 for (auto i : indices->signature_to_index_) { |
| 821 builder_->builder_->SetImportName(i.second, indices->name_, |
| 822 indices->name_length_); |
| 823 } |
| 736 } | 824 } |
| 737 | 825 |
| 738 // Get a function's index (or allocate if new). | 826 // Get a function's index (or allocate if new). |
| 739 uint32_t LookupOrInsertImport(Variable* v, FunctionSig* sig) { | 827 uint32_t LookupOrInsertImportUse(Variable* v, FunctionSig* sig) { |
| 740 ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); | 828 auto* indices = LookupOrInsertImport(v); |
| 741 DCHECK_NOT_NULL(entry); | |
| 742 ImportedFunctionIndices* indices = | |
| 743 reinterpret_cast<ImportedFunctionIndices*>(entry->value); | |
| 744 WasmModuleBuilder::SignatureMap::iterator pos = | 829 WasmModuleBuilder::SignatureMap::iterator pos = |
| 745 indices->signature_to_index_.find(sig); | 830 indices->signature_to_index_.find(sig); |
| 746 if (pos != indices->signature_to_index_.end()) { | 831 if (pos != indices->signature_to_index_.end()) { |
| 747 return pos->second; | 832 return pos->second; |
| 748 } else { | 833 } else { |
| 749 uint32_t index = builder_->builder_->AddImport( | 834 uint32_t index = builder_->builder_->AddImport( |
| 750 indices->name_, indices->name_length_, sig); | 835 indices->name_, indices->name_length_, sig); |
| 751 indices->signature_to_index_[sig] = index; | 836 indices->signature_to_index_[sig] = index; |
| 752 return index; | 837 return index; |
| 753 } | 838 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 894 } | 979 } |
| 895 Property* prop = expr->value()->AsProperty(); | 980 Property* prop = expr->value()->AsProperty(); |
| 896 if (prop != nullptr) { | 981 if (prop != nullptr) { |
| 897 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 982 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 898 if (vp != nullptr && vp->var()->IsParameter() && | 983 if (vp != nullptr && vp->var()->IsParameter() && |
| 899 vp->var()->index() == 1) { | 984 vp->var()->index() == 1) { |
| 900 VariableProxy* target = expr->target()->AsVariableProxy(); | 985 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 901 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { | 986 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
| 902 const AstRawString* name = | 987 const AstRawString* name = |
| 903 prop->key()->AsLiteral()->AsRawPropertyName(); | 988 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 904 imported_function_table_.AddImport( | 989 imported_function_table_.SetImportName( |
| 905 target->var(), reinterpret_cast<const char*>(name->raw_data()), | 990 target->var(), reinterpret_cast<const char*>(name->raw_data()), |
| 906 name->length()); | 991 name->length()); |
| 907 } | 992 } |
| 908 } | 993 } |
| 909 // Property values in module scope don't emit code, so return. | 994 // Property values in module scope don't emit code, so return. |
| 910 return; | 995 return; |
| 911 } | 996 } |
| 912 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 997 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 913 if (funcs != nullptr && | 998 if (funcs != nullptr) { |
| 914 typer_->TypeOf(funcs) | |
| 915 ->AsFunctionTableType() | |
| 916 ->signature() | |
| 917 ->AsFunctionType()) { | |
| 918 VariableProxy* target = expr->target()->AsVariableProxy(); | 999 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 919 DCHECK_NOT_NULL(target); | 1000 DCHECK_NOT_NULL(target); |
| 920 AddFunctionTable(target, funcs); | 1001 PopulateFunctionTable(target, funcs); |
| 921 // Only add to the function table. No init needed. | 1002 // Only add to the function table. No init needed. |
| 922 return; | 1003 return; |
| 923 } | 1004 } |
| 924 if (expr->value()->IsCallNew()) { | 1005 if (expr->value()->IsCallNew()) { |
| 925 // No init code to emit for CallNew nodes. | 1006 // No init code to emit for CallNew nodes. |
| 926 return; | 1007 return; |
| 927 } | 1008 } |
| 928 as_init = true; | 1009 as_init = true; |
| 929 } | 1010 } |
| 930 | 1011 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1399 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 1319 args->length()); | 1400 args->length()); |
| 1320 if (return_type != kAstStmt) { | 1401 if (return_type != kAstStmt) { |
| 1321 sig.AddReturn(return_type); | 1402 sig.AddReturn(return_type); |
| 1322 } else { | 1403 } else { |
| 1323 returns_value = false; | 1404 returns_value = false; |
| 1324 } | 1405 } |
| 1325 for (int i = 0; i < args->length(); ++i) { | 1406 for (int i = 0; i < args->length(); ++i) { |
| 1326 sig.AddParam(TypeOf(args->at(i))); | 1407 sig.AddParam(TypeOf(args->at(i))); |
| 1327 } | 1408 } |
| 1328 uint32_t index = imported_function_table_.LookupOrInsertImport( | 1409 uint32_t index = imported_function_table_.LookupOrInsertImportUse( |
| 1329 vp->var(), sig.Build()); | 1410 vp->var(), sig.Build()); |
| 1330 VisitCallArgs(expr); | 1411 VisitCallArgs(expr); |
| 1331 current_function_builder_->AddAsmWasmOffset(expr->position()); | 1412 current_function_builder_->AddAsmWasmOffset(expr->position()); |
| 1332 current_function_builder_->Emit(kExprCallFunction); | 1413 current_function_builder_->Emit(kExprCallFunction); |
| 1333 current_function_builder_->EmitVarInt(index); | 1414 current_function_builder_->EmitVarInt(index); |
| 1334 } else { | 1415 } else { |
| 1335 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); | 1416 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); |
| 1336 VisitCallArgs(expr); | 1417 VisitCallArgs(expr); |
| 1337 current_function_builder_->AddAsmWasmOffset(expr->position()); | 1418 current_function_builder_->AddAsmWasmOffset(expr->position()); |
| 1338 current_function_builder_->Emit(kExprCallFunction); | 1419 current_function_builder_->Emit(kExprCallFunction); |
| 1339 current_function_builder_->EmitDirectCallIndex( | 1420 current_function_builder_->EmitDirectCallIndex( |
| 1340 function->func_index()); | 1421 function->func_index()); |
| 1341 returns_value = function->signature()->return_count() > 0; | 1422 returns_value = function->signature()->return_count() > 0; |
| 1342 } | 1423 } |
| 1343 break; | 1424 break; |
| 1344 } | 1425 } |
| 1345 case Call::KEYED_PROPERTY_CALL: { | 1426 case Call::KEYED_PROPERTY_CALL: { |
| 1346 DCHECK_EQ(kFuncScope, scope_); | 1427 DCHECK_EQ(kFuncScope, scope_); |
| 1347 Property* p = expr->expression()->AsProperty(); | 1428 Property* p = expr->expression()->AsProperty(); |
| 1348 DCHECK_NOT_NULL(p); | 1429 DCHECK_NOT_NULL(p); |
| 1349 VariableProxy* var = p->obj()->AsVariableProxy(); | 1430 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 1350 DCHECK_NOT_NULL(var); | 1431 DCHECK_NOT_NULL(var); |
| 1351 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1432 FunctionTableIndices* indices = LookupOrAddFunctionTable(var, p); |
| 1352 Visit(p->key()); // TODO(titzer): should use RECURSE() | 1433 Visit(p->key()); // TODO(titzer): should use RECURSE() |
| 1353 | 1434 |
| 1354 // We have to use a temporary for the correct order of evaluation. | 1435 // We have to use a temporary for the correct order of evaluation. |
| 1355 current_function_builder_->EmitI32Const(indices->start_index); | 1436 current_function_builder_->EmitI32Const(indices->start_index); |
| 1356 current_function_builder_->Emit(kExprI32Add); | 1437 current_function_builder_->Emit(kExprI32Add); |
| 1357 WasmTemporary tmp(current_function_builder_, kAstI32); | 1438 WasmTemporary tmp(current_function_builder_, kAstI32); |
| 1358 current_function_builder_->EmitSetLocal(tmp.index()); | 1439 current_function_builder_->EmitSetLocal(tmp.index()); |
| 1359 | 1440 |
| 1360 VisitCallArgs(expr); | 1441 VisitCallArgs(expr); |
| 1361 | 1442 |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 #undef CASE | 1768 #undef CASE |
| 1688 #undef NON_SIGNED_INT | 1769 #undef NON_SIGNED_INT |
| 1689 #undef SIGNED | 1770 #undef SIGNED |
| 1690 #undef NON_SIGNED | 1771 #undef NON_SIGNED |
| 1691 | 1772 |
| 1692 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } | 1773 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } |
| 1693 | 1774 |
| 1694 void VisitDeclarations(Declaration::List* decls) { | 1775 void VisitDeclarations(Declaration::List* decls) { |
| 1695 for (Declaration* decl : *decls) { | 1776 for (Declaration* decl : *decls) { |
| 1696 RECURSE(Visit(decl)); | 1777 RECURSE(Visit(decl)); |
| 1778 if (typer_failed_) { |
| 1779 return; |
| 1780 } |
| 1697 } | 1781 } |
| 1698 } | 1782 } |
| 1699 | 1783 |
| 1700 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } | 1784 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } |
| 1701 | 1785 |
| 1702 void VisitSpread(Spread* expr) { UNREACHABLE(); } | 1786 void VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 1703 | 1787 |
| 1704 void VisitSuperPropertyReference(SuperPropertyReference* expr) { | 1788 void VisitSuperPropertyReference(SuperPropertyReference* expr) { |
| 1705 UNREACHABLE(); | 1789 UNREACHABLE(); |
| 1706 } | 1790 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 | 1898 |
| 1815 ZoneHashMap local_variables_; | 1899 ZoneHashMap local_variables_; |
| 1816 ZoneHashMap functions_; | 1900 ZoneHashMap functions_; |
| 1817 ZoneHashMap global_variables_; | 1901 ZoneHashMap global_variables_; |
| 1818 AsmScope scope_; | 1902 AsmScope scope_; |
| 1819 WasmModuleBuilder* builder_; | 1903 WasmModuleBuilder* builder_; |
| 1820 WasmFunctionBuilder* current_function_builder_; | 1904 WasmFunctionBuilder* current_function_builder_; |
| 1821 FunctionLiteral* literal_; | 1905 FunctionLiteral* literal_; |
| 1822 Isolate* isolate_; | 1906 Isolate* isolate_; |
| 1823 Zone* zone_; | 1907 Zone* zone_; |
| 1908 AstValueFactory* ast_value_factory_; |
| 1909 Script* script_; |
| 1824 AsmTyper* typer_; | 1910 AsmTyper* typer_; |
| 1911 bool typer_failed_; |
| 1825 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1912 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1826 ZoneVector<ForeignVariable> foreign_variables_; | 1913 ZoneVector<ForeignVariable> foreign_variables_; |
| 1827 WasmFunctionBuilder* init_function_; | 1914 WasmFunctionBuilder* init_function_; |
| 1828 WasmFunctionBuilder* foreign_init_function_; | 1915 WasmFunctionBuilder* foreign_init_function_; |
| 1829 uint32_t next_table_index_; | 1916 uint32_t next_table_index_; |
| 1830 ZoneHashMap function_tables_; | 1917 ZoneHashMap function_tables_; |
| 1831 ImportedFunctionTable imported_function_table_; | 1918 ImportedFunctionTable imported_function_table_; |
| 1832 | 1919 |
| 1833 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1920 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1834 | 1921 |
| 1835 private: | 1922 private: |
| 1836 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1923 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1837 }; | 1924 }; |
| 1838 | 1925 |
| 1839 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1926 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
| 1840 FunctionLiteral* literal, AsmTyper* typer) | 1927 AstValueFactory* ast_value_factory, |
| 1841 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} | 1928 Script* script, FunctionLiteral* literal) |
| 1929 : isolate_(isolate), |
| 1930 zone_(zone), |
| 1931 ast_value_factory_(ast_value_factory), |
| 1932 script_(script), |
| 1933 literal_(literal), |
| 1934 typer_(isolate, zone, script, literal) {} |
| 1842 | 1935 |
| 1843 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1936 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
| 1844 // that zone in constructor may be thrown away once wasm module is written. | 1937 // that zone in constructor may be thrown away once wasm module is written. |
| 1845 AsmWasmBuilder::Result AsmWasmBuilder::Run( | 1938 AsmWasmBuilder::Result AsmWasmBuilder::Run( |
| 1846 i::Handle<i::FixedArray>* foreign_args) { | 1939 i::Handle<i::FixedArray>* foreign_args) { |
| 1847 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); | 1940 AsmWasmBuilderImpl impl(isolate_, zone_, ast_value_factory_, script_, |
| 1848 impl.Build(); | 1941 literal_, &typer_); |
| 1942 bool success = impl.Build(); |
| 1849 *foreign_args = impl.GetForeignArgs(); | 1943 *foreign_args = impl.GetForeignArgs(); |
| 1850 ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_); | 1944 ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_); |
| 1851 impl.builder_->WriteTo(*module_buffer); | 1945 impl.builder_->WriteTo(*module_buffer); |
| 1852 ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_); | 1946 ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_); |
| 1853 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); | 1947 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); |
| 1854 return {module_buffer, asm_offsets_buffer}; | 1948 return {module_buffer, asm_offsets_buffer, success}; |
| 1855 } | 1949 } |
| 1856 | 1950 |
| 1857 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; | 1951 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; |
| 1858 const char* AsmWasmBuilder::single_function_name = "__single_function__"; | 1952 const char* AsmWasmBuilder::single_function_name = "__single_function__"; |
| 1859 | 1953 |
| 1860 } // namespace wasm | 1954 } // namespace wasm |
| 1861 } // namespace internal | 1955 } // namespace internal |
| 1862 } // namespace v8 | 1956 } // namespace v8 |
| OLD | NEW |