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 DeclarationScope* new_func_scope = nullptr; | |
137 if (decl->fun()->body() == nullptr) { | |
138 // TODO(bradnelson): Refactor parser so we don't need a | |
139 // SharedFunctionInfo to parse a single function, | |
140 // or squirrel away the SharedFunctionInfo to use later. | |
141 Handle<SharedFunctionInfo> shared = | |
142 isolate_->factory()->NewSharedFunctionInfoForLiteral( | |
143 decl->fun(), handle(script_, isolate_)); | |
144 shared->set_is_toplevel(false); | |
145 i::ParseInfo info(&zone, handle(script_, isolate_)); | |
146 info.set_shared_info(shared); | |
147 info.set_toplevel(false); | |
148 info.set_language_mode(decl->fun()->scope()->language_mode()); | |
149 info.set_allow_lazy_parsing(false); | |
150 info.set_function_literal_id(shared->function_literal_id()); | |
151 info.set_ast_value_factory(ast_value_factory_); | |
152 info.set_ast_value_factory_owned(false); | |
153 // Create fresh function scope to use to parse the function in. | |
154 new_func_scope = new (info.zone()) DeclarationScope( | |
155 info.zone(), decl->fun()->scope()->outer_scope(), FUNCTION_SCOPE); | |
156 info.set_asm_function_scope(new_func_scope); | |
157 if (!i::Compiler::ParseAndAnalyze(&info)) { | |
158 typer_failed_ = true; | |
159 return; | |
160 } | |
161 FunctionLiteral* func = info.literal(); | |
162 DCHECK_NOT_NULL(func); | |
163 decl->set_fun(func); | |
164 } | |
165 if (!typer_->ValidateInnerFunction(decl)) { | |
166 typer_failed_ = true; | |
167 decl->set_fun(old_func); | |
168 if (new_func_scope != nullptr) { | |
169 DCHECK_EQ(new_func_scope, decl->scope()->inner_scope()); | |
170 DCHECK(decl->scope()->RemoveInnerScope(new_func_scope)); | |
marja
2016/11/29 10:48:50
This is not what you wanted :)
Now RemoveInnerSco
bradn
2016/11/29 11:00:46
Oops
Done.
| |
171 } | |
172 return; | |
173 } | |
116 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); | 174 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); |
117 scope_ = kFuncScope; | 175 scope_ = kFuncScope; |
118 RECURSE(Visit(decl->fun())); | 176 RECURSE(Visit(decl->fun())); |
177 decl->set_fun(old_func); | |
178 if (new_func_scope != nullptr) { | |
179 DCHECK_EQ(new_func_scope, decl->scope()->inner_scope()); | |
180 DCHECK(decl->scope()->RemoveInnerScope(new_func_scope)); | |
marja
2016/11/29 10:48:50
Ditto
bradn
2016/11/29 11:00:46
Done.
| |
181 } | |
119 scope_ = kModuleScope; | 182 scope_ = kModuleScope; |
120 current_function_builder_ = nullptr; | 183 current_function_builder_ = nullptr; |
121 local_variables_.Clear(); | 184 local_variables_.Clear(); |
185 typer_->ClearFunctionNodeTypes(); | |
122 } | 186 } |
123 | 187 |
124 void VisitStatements(ZoneList<Statement*>* stmts) { | 188 void VisitStatements(ZoneList<Statement*>* stmts) { |
125 for (int i = 0; i < stmts->length(); ++i) { | 189 for (int i = 0; i < stmts->length(); ++i) { |
126 Statement* stmt = stmts->at(i); | 190 Statement* stmt = stmts->at(i); |
127 ExpressionStatement* e = stmt->AsExpressionStatement(); | 191 ExpressionStatement* e = stmt->AsExpressionStatement(); |
128 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | 192 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { |
129 continue; | 193 continue; |
130 } | 194 } |
131 RECURSE(Visit(stmt)); | 195 RECURSE(Visit(stmt)); |
196 if (typer_failed_) break; | |
132 if (stmt->IsJump()) break; | 197 if (stmt->IsJump()) break; |
133 } | 198 } |
134 } | 199 } |
135 | 200 |
136 void VisitBlock(Block* stmt) { | 201 void VisitBlock(Block* stmt) { |
137 if (stmt->statements()->length() == 1) { | 202 if (stmt->statements()->length() == 1) { |
138 ExpressionStatement* expr = | 203 ExpressionStatement* expr = |
139 stmt->statements()->at(0)->AsExpressionStatement(); | 204 stmt->statements()->at(0)->AsExpressionStatement(); |
140 if (expr != nullptr) { | 205 if (expr != nullptr) { |
141 if (expr->expression()->IsAssignment()) { | 206 if (expr->expression()->IsAssignment()) { |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 void VisitContinueStatement(ContinueStatement* stmt) { | 303 void VisitContinueStatement(ContinueStatement* stmt) { |
239 DoBreakOrContinue(stmt->target(), true); | 304 DoBreakOrContinue(stmt->target(), true); |
240 } | 305 } |
241 | 306 |
242 void VisitBreakStatement(BreakStatement* stmt) { | 307 void VisitBreakStatement(BreakStatement* stmt) { |
243 DoBreakOrContinue(stmt->target(), false); | 308 DoBreakOrContinue(stmt->target(), false); |
244 } | 309 } |
245 | 310 |
246 void VisitReturnStatement(ReturnStatement* stmt) { | 311 void VisitReturnStatement(ReturnStatement* stmt) { |
247 if (scope_ == kModuleScope) { | 312 if (scope_ == kModuleScope) { |
313 if (!typer_->ValidateAfterFunctionsPhase()) { | |
314 typer_failed_ = true; | |
315 return; | |
316 } | |
248 scope_ = kExportScope; | 317 scope_ = kExportScope; |
249 RECURSE(Visit(stmt->expression())); | 318 RECURSE(Visit(stmt->expression())); |
250 scope_ = kModuleScope; | 319 scope_ = kModuleScope; |
251 } else if (scope_ == kFuncScope) { | 320 } else if (scope_ == kFuncScope) { |
252 RECURSE(Visit(stmt->expression())); | 321 RECURSE(Visit(stmt->expression())); |
253 current_function_builder_->Emit(kExprReturn); | 322 current_function_builder_->Emit(kExprReturn); |
254 } else { | 323 } else { |
255 UNREACHABLE(); | 324 UNREACHABLE(); |
256 } | 325 } |
257 } | 326 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
441 const auto& arguments = func_type->Arguments(); | 510 const auto& arguments = func_type->Arguments(); |
442 for (int i = 0; i < expr->parameter_count(); ++i) { | 511 for (int i = 0; i < expr->parameter_count(); ++i) { |
443 LocalType type = TypeFrom(arguments[i]); | 512 LocalType type = TypeFrom(arguments[i]); |
444 DCHECK_NE(kAstStmt, type); | 513 DCHECK_NE(kAstStmt, type); |
445 InsertParameter(scope->parameter(i), type, i); | 514 InsertParameter(scope->parameter(i), type, i); |
446 } | 515 } |
447 } else { | 516 } else { |
448 UNREACHABLE(); | 517 UNREACHABLE(); |
449 } | 518 } |
450 } | 519 } |
520 RECURSE(VisitDeclarations(scope->declarations())); | |
521 if (typer_failed_) return; | |
451 RECURSE(VisitStatements(expr->body())); | 522 RECURSE(VisitStatements(expr->body())); |
452 RECURSE(VisitDeclarations(scope->declarations())); | |
453 } | 523 } |
454 | 524 |
455 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 525 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
456 UNREACHABLE(); | 526 UNREACHABLE(); |
457 } | 527 } |
458 | 528 |
459 void VisitConditional(Conditional* expr) { | 529 void VisitConditional(Conditional* expr) { |
460 DCHECK_EQ(kFuncScope, scope_); | 530 DCHECK_EQ(kFuncScope, scope_); |
461 RECURSE(Visit(expr->condition())); | 531 RECURSE(Visit(expr->condition())); |
462 // WASM ifs come with implicit blocks for both arms. | 532 // 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() { | 723 void LoadInitFunction() { |
654 current_function_builder_ = init_function_; | 724 current_function_builder_ = init_function_; |
655 scope_ = kInitScope; | 725 scope_ = kInitScope; |
656 } | 726 } |
657 | 727 |
658 void UnLoadInitFunction() { | 728 void UnLoadInitFunction() { |
659 scope_ = kModuleScope; | 729 scope_ = kModuleScope; |
660 current_function_builder_ = nullptr; | 730 current_function_builder_ = nullptr; |
661 } | 731 } |
662 | 732 |
663 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 733 struct FunctionTableIndices : public ZoneObject { |
664 auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); | 734 uint32_t start_index; |
665 DCHECK_NOT_NULL(func_tbl_type); | 735 uint32_t signature_index; |
666 auto* func_type = func_tbl_type->signature()->AsFunctionType(); | 736 }; |
737 | |
738 FunctionTableIndices* LookupOrAddFunctionTable(VariableProxy* table, | |
739 Property* p) { | |
740 FunctionTableIndices* indices = LookupFunctionTable(table->var()); | |
741 if (indices != nullptr) { | |
742 // Already setup. | |
743 return indices; | |
744 } | |
745 indices = new (zone()) FunctionTableIndices(); | |
746 auto* func_type = typer_->TypeOf(p)->AsFunctionType(); | |
747 auto* func_table_type = typer_->TypeOf(p->obj()->AsVariableProxy()->var()) | |
748 ->AsFunctionTableType(); | |
667 const auto& arguments = func_type->Arguments(); | 749 const auto& arguments = func_type->Arguments(); |
668 LocalType return_type = TypeFrom(func_type->ReturnType()); | 750 LocalType return_type = TypeFrom(func_type->ReturnType()); |
669 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 751 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
670 arguments.size()); | 752 arguments.size()); |
671 if (return_type != kAstStmt) { | 753 if (return_type != kAstStmt) { |
672 sig.AddReturn(return_type); | 754 sig.AddReturn(return_type); |
673 } | 755 } |
674 for (auto* arg : arguments) { | 756 for (auto* arg : arguments) { |
675 sig.AddParam(TypeFrom(arg)); | 757 sig.AddParam(TypeFrom(arg)); |
676 } | 758 } |
677 uint32_t signature_index = builder_->AddSignature(sig.Build()); | 759 uint32_t signature_index = builder_->AddSignature(sig.Build()); |
678 InsertFunctionTable(table->var(), next_table_index_, signature_index); | 760 indices->start_index = builder_->AllocateIndirectFunctions( |
679 next_table_index_ += funcs->values()->length(); | 761 static_cast<uint32_t>(func_table_type->length())); |
680 for (int i = 0; i < funcs->values()->length(); ++i) { | 762 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( | 763 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
699 v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); | 764 table->var(), ComputePointerHash(table->var()), |
700 entry->value = container; | 765 ZoneAllocationPolicy(zone())); |
766 entry->value = indices; | |
767 return indices; | |
701 } | 768 } |
702 | 769 |
703 FunctionTableIndices* LookupFunctionTable(Variable* v) { | 770 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
704 ZoneHashMap::Entry* entry = | 771 ZoneHashMap::Entry* entry = |
705 function_tables_.Lookup(v, ComputePointerHash(v)); | 772 function_tables_.Lookup(v, ComputePointerHash(v)); |
706 DCHECK_NOT_NULL(entry); | 773 if (entry == nullptr) { |
774 return nullptr; | |
775 } | |
707 return reinterpret_cast<FunctionTableIndices*>(entry->value); | 776 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
708 } | 777 } |
709 | 778 |
779 void PopulateFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | |
780 FunctionTableIndices* indices = LookupFunctionTable(table->var()); | |
781 DCHECK_NOT_NULL(indices); | |
782 for (int i = 0; i < funcs->values()->length(); ++i) { | |
783 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | |
784 DCHECK_NOT_NULL(func); | |
785 builder_->SetIndirectFunction( | |
786 indices->start_index + i, | |
787 LookupOrInsertFunction(func->var())->func_index()); | |
788 } | |
789 } | |
790 | |
710 class ImportedFunctionTable { | 791 class ImportedFunctionTable { |
711 private: | 792 private: |
712 class ImportedFunctionIndices : public ZoneObject { | 793 class ImportedFunctionIndices : public ZoneObject { |
713 public: | 794 public: |
714 const char* name_; | 795 const char* name_; |
715 int name_length_; | 796 int name_length_; |
716 WasmModuleBuilder::SignatureMap signature_to_index_; | 797 WasmModuleBuilder::SignatureMap signature_to_index_; |
717 | 798 |
718 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) | 799 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) |
719 : name_(name), name_length_(name_length), signature_to_index_(zone) {} | 800 : name_(name), name_length_(name_length), signature_to_index_(zone) {} |
720 }; | 801 }; |
721 ZoneHashMap table_; | 802 ZoneHashMap table_; |
722 AsmWasmBuilderImpl* builder_; | 803 AsmWasmBuilderImpl* builder_; |
723 | 804 |
724 public: | 805 public: |
725 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) | 806 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) |
726 : table_(ZoneHashMap::kDefaultHashMapCapacity, | 807 : table_(ZoneHashMap::kDefaultHashMapCapacity, |
727 ZoneAllocationPolicy(builder->zone())), | 808 ZoneAllocationPolicy(builder->zone())), |
728 builder_(builder) {} | 809 builder_(builder) {} |
729 | 810 |
730 void AddImport(Variable* v, const char* name, int name_length) { | 811 ImportedFunctionIndices* LookupOrInsertImport(Variable* v) { |
731 ImportedFunctionIndices* indices = new (builder_->zone()) | |
732 ImportedFunctionIndices(name, name_length, builder_->zone()); | |
733 auto* entry = table_.LookupOrInsert( | 812 auto* entry = table_.LookupOrInsert( |
734 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); | 813 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |
735 entry->value = indices; | 814 ImportedFunctionIndices* indices; |
815 if (entry->value == nullptr) { | |
816 indices = new (builder_->zone()) | |
817 ImportedFunctionIndices(nullptr, 0, builder_->zone()); | |
818 entry->value = indices; | |
819 } else { | |
820 indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value); | |
821 } | |
822 return indices; | |
823 } | |
824 | |
825 void SetImportName(Variable* v, const char* name, int name_length) { | |
826 auto* indices = LookupOrInsertImport(v); | |
827 indices->name_ = name; | |
828 indices->name_length_ = name_length; | |
829 for (auto i : indices->signature_to_index_) { | |
830 builder_->builder_->SetImportName(i.second, indices->name_, | |
831 indices->name_length_); | |
832 } | |
736 } | 833 } |
737 | 834 |
738 // Get a function's index (or allocate if new). | 835 // Get a function's index (or allocate if new). |
739 uint32_t LookupOrInsertImport(Variable* v, FunctionSig* sig) { | 836 uint32_t LookupOrInsertImportUse(Variable* v, FunctionSig* sig) { |
740 ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); | 837 auto* indices = LookupOrInsertImport(v); |
741 DCHECK_NOT_NULL(entry); | |
742 ImportedFunctionIndices* indices = | |
743 reinterpret_cast<ImportedFunctionIndices*>(entry->value); | |
744 WasmModuleBuilder::SignatureMap::iterator pos = | 838 WasmModuleBuilder::SignatureMap::iterator pos = |
745 indices->signature_to_index_.find(sig); | 839 indices->signature_to_index_.find(sig); |
746 if (pos != indices->signature_to_index_.end()) { | 840 if (pos != indices->signature_to_index_.end()) { |
747 return pos->second; | 841 return pos->second; |
748 } else { | 842 } else { |
749 uint32_t index = builder_->builder_->AddImport( | 843 uint32_t index = builder_->builder_->AddImport( |
750 indices->name_, indices->name_length_, sig); | 844 indices->name_, indices->name_length_, sig); |
751 indices->signature_to_index_[sig] = index; | 845 indices->signature_to_index_[sig] = index; |
752 return index; | 846 return index; |
753 } | 847 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
894 } | 988 } |
895 Property* prop = expr->value()->AsProperty(); | 989 Property* prop = expr->value()->AsProperty(); |
896 if (prop != nullptr) { | 990 if (prop != nullptr) { |
897 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 991 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
898 if (vp != nullptr && vp->var()->IsParameter() && | 992 if (vp != nullptr && vp->var()->IsParameter() && |
899 vp->var()->index() == 1) { | 993 vp->var()->index() == 1) { |
900 VariableProxy* target = expr->target()->AsVariableProxy(); | 994 VariableProxy* target = expr->target()->AsVariableProxy(); |
901 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { | 995 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
902 const AstRawString* name = | 996 const AstRawString* name = |
903 prop->key()->AsLiteral()->AsRawPropertyName(); | 997 prop->key()->AsLiteral()->AsRawPropertyName(); |
904 imported_function_table_.AddImport( | 998 imported_function_table_.SetImportName( |
905 target->var(), reinterpret_cast<const char*>(name->raw_data()), | 999 target->var(), reinterpret_cast<const char*>(name->raw_data()), |
906 name->length()); | 1000 name->length()); |
907 } | 1001 } |
908 } | 1002 } |
909 // Property values in module scope don't emit code, so return. | 1003 // Property values in module scope don't emit code, so return. |
910 return; | 1004 return; |
911 } | 1005 } |
912 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 1006 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
913 if (funcs != nullptr && | 1007 if (funcs != nullptr) { |
914 typer_->TypeOf(funcs) | |
915 ->AsFunctionTableType() | |
916 ->signature() | |
917 ->AsFunctionType()) { | |
918 VariableProxy* target = expr->target()->AsVariableProxy(); | 1008 VariableProxy* target = expr->target()->AsVariableProxy(); |
919 DCHECK_NOT_NULL(target); | 1009 DCHECK_NOT_NULL(target); |
920 AddFunctionTable(target, funcs); | 1010 PopulateFunctionTable(target, funcs); |
921 // Only add to the function table. No init needed. | 1011 // Only add to the function table. No init needed. |
922 return; | 1012 return; |
923 } | 1013 } |
924 if (expr->value()->IsCallNew()) { | 1014 if (expr->value()->IsCallNew()) { |
925 // No init code to emit for CallNew nodes. | 1015 // No init code to emit for CallNew nodes. |
926 return; | 1016 return; |
927 } | 1017 } |
928 as_init = true; | 1018 as_init = true; |
929 } | 1019 } |
930 | 1020 |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1318 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1408 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
1319 args->length()); | 1409 args->length()); |
1320 if (return_type != kAstStmt) { | 1410 if (return_type != kAstStmt) { |
1321 sig.AddReturn(return_type); | 1411 sig.AddReturn(return_type); |
1322 } else { | 1412 } else { |
1323 returns_value = false; | 1413 returns_value = false; |
1324 } | 1414 } |
1325 for (int i = 0; i < args->length(); ++i) { | 1415 for (int i = 0; i < args->length(); ++i) { |
1326 sig.AddParam(TypeOf(args->at(i))); | 1416 sig.AddParam(TypeOf(args->at(i))); |
1327 } | 1417 } |
1328 uint32_t index = imported_function_table_.LookupOrInsertImport( | 1418 uint32_t index = imported_function_table_.LookupOrInsertImportUse( |
1329 vp->var(), sig.Build()); | 1419 vp->var(), sig.Build()); |
1330 VisitCallArgs(expr); | 1420 VisitCallArgs(expr); |
1331 current_function_builder_->AddAsmWasmOffset(expr->position()); | 1421 current_function_builder_->AddAsmWasmOffset(expr->position()); |
1332 current_function_builder_->Emit(kExprCallFunction); | 1422 current_function_builder_->Emit(kExprCallFunction); |
1333 current_function_builder_->EmitVarInt(index); | 1423 current_function_builder_->EmitVarInt(index); |
1334 } else { | 1424 } else { |
1335 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); | 1425 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); |
1336 VisitCallArgs(expr); | 1426 VisitCallArgs(expr); |
1337 current_function_builder_->AddAsmWasmOffset(expr->position()); | 1427 current_function_builder_->AddAsmWasmOffset(expr->position()); |
1338 current_function_builder_->Emit(kExprCallFunction); | 1428 current_function_builder_->Emit(kExprCallFunction); |
1339 current_function_builder_->EmitDirectCallIndex( | 1429 current_function_builder_->EmitDirectCallIndex( |
1340 function->func_index()); | 1430 function->func_index()); |
1341 returns_value = function->signature()->return_count() > 0; | 1431 returns_value = function->signature()->return_count() > 0; |
1342 } | 1432 } |
1343 break; | 1433 break; |
1344 } | 1434 } |
1345 case Call::KEYED_PROPERTY_CALL: { | 1435 case Call::KEYED_PROPERTY_CALL: { |
1346 DCHECK_EQ(kFuncScope, scope_); | 1436 DCHECK_EQ(kFuncScope, scope_); |
1347 Property* p = expr->expression()->AsProperty(); | 1437 Property* p = expr->expression()->AsProperty(); |
1348 DCHECK_NOT_NULL(p); | 1438 DCHECK_NOT_NULL(p); |
1349 VariableProxy* var = p->obj()->AsVariableProxy(); | 1439 VariableProxy* var = p->obj()->AsVariableProxy(); |
1350 DCHECK_NOT_NULL(var); | 1440 DCHECK_NOT_NULL(var); |
1351 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1441 FunctionTableIndices* indices = LookupOrAddFunctionTable(var, p); |
1352 Visit(p->key()); // TODO(titzer): should use RECURSE() | 1442 Visit(p->key()); // TODO(titzer): should use RECURSE() |
1353 | 1443 |
1354 // We have to use a temporary for the correct order of evaluation. | 1444 // We have to use a temporary for the correct order of evaluation. |
1355 current_function_builder_->EmitI32Const(indices->start_index); | 1445 current_function_builder_->EmitI32Const(indices->start_index); |
1356 current_function_builder_->Emit(kExprI32Add); | 1446 current_function_builder_->Emit(kExprI32Add); |
1357 WasmTemporary tmp(current_function_builder_, kAstI32); | 1447 WasmTemporary tmp(current_function_builder_, kAstI32); |
1358 current_function_builder_->EmitSetLocal(tmp.index()); | 1448 current_function_builder_->EmitSetLocal(tmp.index()); |
1359 | 1449 |
1360 VisitCallArgs(expr); | 1450 VisitCallArgs(expr); |
1361 | 1451 |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1687 #undef CASE | 1777 #undef CASE |
1688 #undef NON_SIGNED_INT | 1778 #undef NON_SIGNED_INT |
1689 #undef SIGNED | 1779 #undef SIGNED |
1690 #undef NON_SIGNED | 1780 #undef NON_SIGNED |
1691 | 1781 |
1692 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } | 1782 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } |
1693 | 1783 |
1694 void VisitDeclarations(Declaration::List* decls) { | 1784 void VisitDeclarations(Declaration::List* decls) { |
1695 for (Declaration* decl : *decls) { | 1785 for (Declaration* decl : *decls) { |
1696 RECURSE(Visit(decl)); | 1786 RECURSE(Visit(decl)); |
1787 if (typer_failed_) { | |
1788 return; | |
1789 } | |
1697 } | 1790 } |
1698 } | 1791 } |
1699 | 1792 |
1700 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } | 1793 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } |
1701 | 1794 |
1702 void VisitSpread(Spread* expr) { UNREACHABLE(); } | 1795 void VisitSpread(Spread* expr) { UNREACHABLE(); } |
1703 | 1796 |
1704 void VisitSuperPropertyReference(SuperPropertyReference* expr) { | 1797 void VisitSuperPropertyReference(SuperPropertyReference* expr) { |
1705 UNREACHABLE(); | 1798 UNREACHABLE(); |
1706 } | 1799 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1814 | 1907 |
1815 ZoneHashMap local_variables_; | 1908 ZoneHashMap local_variables_; |
1816 ZoneHashMap functions_; | 1909 ZoneHashMap functions_; |
1817 ZoneHashMap global_variables_; | 1910 ZoneHashMap global_variables_; |
1818 AsmScope scope_; | 1911 AsmScope scope_; |
1819 WasmModuleBuilder* builder_; | 1912 WasmModuleBuilder* builder_; |
1820 WasmFunctionBuilder* current_function_builder_; | 1913 WasmFunctionBuilder* current_function_builder_; |
1821 FunctionLiteral* literal_; | 1914 FunctionLiteral* literal_; |
1822 Isolate* isolate_; | 1915 Isolate* isolate_; |
1823 Zone* zone_; | 1916 Zone* zone_; |
1917 AstValueFactory* ast_value_factory_; | |
1918 Script* script_; | |
1824 AsmTyper* typer_; | 1919 AsmTyper* typer_; |
1920 bool typer_failed_; | |
1825 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1921 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1826 ZoneVector<ForeignVariable> foreign_variables_; | 1922 ZoneVector<ForeignVariable> foreign_variables_; |
1827 WasmFunctionBuilder* init_function_; | 1923 WasmFunctionBuilder* init_function_; |
1828 WasmFunctionBuilder* foreign_init_function_; | 1924 WasmFunctionBuilder* foreign_init_function_; |
1829 uint32_t next_table_index_; | 1925 uint32_t next_table_index_; |
1830 ZoneHashMap function_tables_; | 1926 ZoneHashMap function_tables_; |
1831 ImportedFunctionTable imported_function_table_; | 1927 ImportedFunctionTable imported_function_table_; |
1832 | 1928 |
1833 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1929 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1834 | 1930 |
1835 private: | 1931 private: |
1836 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1932 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1837 }; | 1933 }; |
1838 | 1934 |
1839 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1935 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, |
1840 FunctionLiteral* literal, AsmTyper* typer) | 1936 AstValueFactory* ast_value_factory, |
1841 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} | 1937 Script* script, FunctionLiteral* literal) |
1938 : isolate_(isolate), | |
1939 zone_(zone), | |
1940 ast_value_factory_(ast_value_factory), | |
1941 script_(script), | |
1942 literal_(literal), | |
1943 typer_(isolate, zone, script, literal) {} | |
1842 | 1944 |
1843 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1945 // 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. | 1946 // that zone in constructor may be thrown away once wasm module is written. |
1845 AsmWasmBuilder::Result AsmWasmBuilder::Run( | 1947 AsmWasmBuilder::Result AsmWasmBuilder::Run( |
1846 i::Handle<i::FixedArray>* foreign_args) { | 1948 i::Handle<i::FixedArray>* foreign_args) { |
1847 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); | 1949 AsmWasmBuilderImpl impl(isolate_, zone_, ast_value_factory_, script_, |
1848 impl.Build(); | 1950 literal_, &typer_); |
1951 bool success = impl.Build(); | |
1849 *foreign_args = impl.GetForeignArgs(); | 1952 *foreign_args = impl.GetForeignArgs(); |
1850 ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_); | 1953 ZoneBuffer* module_buffer = new (zone_) ZoneBuffer(zone_); |
1851 impl.builder_->WriteTo(*module_buffer); | 1954 impl.builder_->WriteTo(*module_buffer); |
1852 ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_); | 1955 ZoneBuffer* asm_offsets_buffer = new (zone_) ZoneBuffer(zone_); |
1853 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); | 1956 impl.builder_->WriteAsmJsOffsetTable(*asm_offsets_buffer); |
1854 return {module_buffer, asm_offsets_buffer}; | 1957 return {module_buffer, asm_offsets_buffer, success}; |
1855 } | 1958 } |
1856 | 1959 |
1857 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; | 1960 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; |
1858 const char* AsmWasmBuilder::single_function_name = "__single_function__"; | 1961 const char* AsmWasmBuilder::single_function_name = "__single_function__"; |
1859 | 1962 |
1860 } // namespace wasm | 1963 } // namespace wasm |
1861 } // namespace internal | 1964 } // namespace internal |
1862 } // namespace v8 | 1965 } // namespace v8 |
OLD | NEW |