Chromium Code Reviews| 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/wasm/switch-logic.h" | 15 #include "src/wasm/switch-logic.h" |
| 16 #include "src/wasm/wasm-macro-gen.h" | 16 #include "src/wasm/wasm-macro-gen.h" |
| 17 #include "src/wasm/wasm-opcodes.h" | 17 #include "src/wasm/wasm-opcodes.h" |
| 18 | 18 |
| 19 #include "src/ast/ast.h" | 19 #include "src/ast/ast.h" |
| 20 #include "src/ast/scopes.h" | 20 #include "src/ast/scopes.h" |
| 21 #include "src/codegen.h" | 21 #include "src/codegen.h" |
| 22 #include "src/compiler.h" | |
| 23 #include "src/isolate.h" | |
| 24 #include "src/parsing/parse-info.h" | |
| 22 | 25 |
| 23 namespace v8 { | 26 namespace v8 { |
| 24 namespace internal { | 27 namespace internal { |
| 25 namespace wasm { | 28 namespace wasm { |
| 26 | 29 |
| 27 #define RECURSE(call) \ | 30 #define RECURSE(call) \ |
| 28 do { \ | 31 do { \ |
| 29 DCHECK(!HasStackOverflow()); \ | 32 DCHECK(!HasStackOverflow()); \ |
| 30 call; \ | 33 call; \ |
| 31 if (HasStackOverflow()) return; \ | 34 if (HasStackOverflow()) return; \ |
| 32 } while (false) | 35 } while (false) |
| 33 | 36 |
| 34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | 37 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; |
| 35 enum ValueFate { kDrop, kLeaveOnStack }; | 38 enum ValueFate { kDrop, kLeaveOnStack }; |
| 36 | 39 |
| 37 struct ForeignVariable { | 40 struct ForeignVariable { |
| 38 Handle<Name> name; | 41 Handle<Name> name; |
| 39 Variable* var; | 42 Variable* var; |
| 40 LocalType type; | 43 LocalType type; |
| 41 }; | 44 }; |
| 42 | 45 |
| 43 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { | 46 class AsmWasmBuilderImpl final : public AstVisitor<AsmWasmBuilderImpl> { |
| 44 public: | 47 public: |
| 45 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 48 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, Script* script, |
| 46 AsmTyper* typer) | 49 FunctionLiteral* literal, AsmTyper* typer) |
| 47 : local_variables_(ZoneHashMap::kDefaultHashMapCapacity, | 50 : local_variables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 48 ZoneAllocationPolicy(zone)), | 51 ZoneAllocationPolicy(zone)), |
| 49 functions_(ZoneHashMap::kDefaultHashMapCapacity, | 52 functions_(ZoneHashMap::kDefaultHashMapCapacity, |
| 50 ZoneAllocationPolicy(zone)), | 53 ZoneAllocationPolicy(zone)), |
| 51 global_variables_(ZoneHashMap::kDefaultHashMapCapacity, | 54 global_variables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 52 ZoneAllocationPolicy(zone)), | 55 ZoneAllocationPolicy(zone)), |
| 53 scope_(kModuleScope), | 56 scope_(kModuleScope), |
| 54 builder_(new (zone) WasmModuleBuilder(zone)), | 57 builder_(new (zone) WasmModuleBuilder(zone)), |
| 55 current_function_builder_(nullptr), | 58 current_function_builder_(nullptr), |
| 56 literal_(literal), | 59 literal_(literal), |
| 57 isolate_(isolate), | 60 isolate_(isolate), |
| 58 zone_(zone), | 61 zone_(zone), |
| 62 script_(script), | |
| 59 typer_(typer), | 63 typer_(typer), |
| 64 typer_failed_(false), | |
| 60 breakable_blocks_(zone), | 65 breakable_blocks_(zone), |
| 61 foreign_variables_(zone), | 66 foreign_variables_(zone), |
| 62 init_function_(nullptr), | 67 init_function_(nullptr), |
| 63 foreign_init_function_(nullptr), | 68 foreign_init_function_(nullptr), |
| 64 next_table_index_(0), | |
| 65 function_tables_(ZoneHashMap::kDefaultHashMapCapacity, | 69 function_tables_(ZoneHashMap::kDefaultHashMapCapacity, |
| 66 ZoneAllocationPolicy(zone)), | 70 ZoneAllocationPolicy(zone)), |
| 67 imported_function_table_(this) { | 71 imported_function_table_(this) { |
| 68 InitializeAstVisitor(isolate); | 72 InitializeAstVisitor(isolate); |
| 69 } | 73 } |
| 70 | 74 |
| 71 void InitializeInitFunction() { | 75 void InitializeInitFunction() { |
| 72 FunctionSig::Builder b(zone(), 0, 0); | 76 FunctionSig::Builder b(zone(), 0, 0); |
| 73 init_function_ = builder_->AddFunction(b.Build()); | 77 init_function_ = builder_->AddFunction(b.Build()); |
| 74 builder_->MarkStartFunction(init_function_); | 78 builder_->MarkStartFunction(init_function_); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 101 i::Handle<i::FixedArray> GetForeignArgs() { | 105 i::Handle<i::FixedArray> GetForeignArgs() { |
| 102 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( | 106 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray( |
| 103 static_cast<int>(foreign_variables_.size())); | 107 static_cast<int>(foreign_variables_.size())); |
| 104 for (size_t i = 0; i < foreign_variables_.size(); ++i) { | 108 for (size_t i = 0; i < foreign_variables_.size(); ++i) { |
| 105 ForeignVariable* fv = &foreign_variables_[i]; | 109 ForeignVariable* fv = &foreign_variables_[i]; |
| 106 ret->set(static_cast<int>(i), *fv->name); | 110 ret->set(static_cast<int>(i), *fv->name); |
| 107 } | 111 } |
| 108 return ret; | 112 return ret; |
| 109 } | 113 } |
| 110 | 114 |
| 111 void Build() { | 115 bool Build() { |
| 112 InitializeInitFunction(); | 116 InitializeInitFunction(); |
| 113 RECURSE(VisitFunctionLiteral(literal_)); | 117 if (!typer_->ValidatePhase1of2()) { |
| 118 return false; | |
| 119 } | |
| 120 DCHECK(!HasStackOverflow()); | |
| 121 VisitFunctionLiteral(literal_); | |
| 122 if (HasStackOverflow()) { | |
| 123 return false; | |
| 124 } | |
| 125 if (typer_failed_) { | |
| 126 return false; | |
| 127 } | |
| 114 BuildForeignInitFunction(); | 128 BuildForeignInitFunction(); |
| 129 return true; | |
| 115 } | 130 } |
| 116 | 131 |
| 117 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 132 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
| 118 | 133 |
| 119 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 134 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 120 DCHECK_EQ(kModuleScope, scope_); | 135 DCHECK_EQ(kModuleScope, scope_); |
| 121 DCHECK_NULL(current_function_builder_); | 136 DCHECK_NULL(current_function_builder_); |
| 137 bool had_body; | |
| 138 i::Zone zone(isolate_->allocator()); | |
| 139 if (decl->fun()->body() == nullptr) { | |
| 140 Handle<SharedFunctionInfo> shared = | |
|
titzer
2016/10/07 12:56:59
Do we really need a shared function info here? See
bradn
2016/11/25 09:19:36
A large number of places in the parser assume a Sh
| |
| 141 i::Compiler::NewSharedFunctionInfoFromLiteral( | |
| 142 isolate_, 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_language_mode(decl->fun()->scope()->language_mode()); | |
| 147 info.set_lazy(true); | |
| 148 info.set_allow_lazy_parsing(false); | |
| 149 info.set_script_scope(decl->fun()->scope()); | |
| 150 if (!i::Compiler::ParseAndAnalyze(&info)) { | |
| 151 typer_failed_ = true; | |
| 152 return; | |
| 153 } | |
| 154 FunctionLiteral* func = info.literal(); | |
| 155 DCHECK_NOT_NULL(func); | |
| 156 decl->fun()->set_body(func->body()); | |
| 157 had_body = false; | |
| 158 } else { | |
| 159 had_body = true; | |
| 160 } | |
| 161 if (!typer_->ValidateInnerFunction(decl)) { | |
| 162 typer_failed_ = true; | |
| 163 return; | |
| 164 } | |
| 122 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); | 165 current_function_builder_ = LookupOrInsertFunction(decl->proxy()->var()); |
| 123 scope_ = kFuncScope; | 166 scope_ = kFuncScope; |
| 124 RECURSE(Visit(decl->fun())); | 167 RECURSE(Visit(decl->fun())); |
| 168 if (!had_body) { | |
| 169 decl->fun()->set_body(nullptr); | |
| 170 } | |
| 125 scope_ = kModuleScope; | 171 scope_ = kModuleScope; |
| 126 current_function_builder_ = nullptr; | 172 current_function_builder_ = nullptr; |
| 127 local_variables_.Clear(); | 173 local_variables_.Clear(); |
| 128 } | 174 } |
| 129 | 175 |
| 130 void VisitStatements(ZoneList<Statement*>* stmts) { | 176 void VisitStatements(ZoneList<Statement*>* stmts) { |
| 131 for (int i = 0; i < stmts->length(); ++i) { | 177 for (int i = 0; i < stmts->length(); ++i) { |
| 132 Statement* stmt = stmts->at(i); | 178 Statement* stmt = stmts->at(i); |
| 133 ExpressionStatement* e = stmt->AsExpressionStatement(); | 179 ExpressionStatement* e = stmt->AsExpressionStatement(); |
| 134 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | 180 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { |
| 135 continue; | 181 continue; |
| 136 } | 182 } |
| 137 RECURSE(Visit(stmt)); | 183 RECURSE(Visit(stmt)); |
| 184 if (typer_failed_) break; | |
| 138 if (stmt->IsJump()) break; | 185 if (stmt->IsJump()) break; |
| 139 } | 186 } |
| 140 } | 187 } |
| 141 | 188 |
| 142 void VisitBlock(Block* stmt) { | 189 void VisitBlock(Block* stmt) { |
| 143 if (stmt->statements()->length() == 1) { | 190 if (stmt->statements()->length() == 1) { |
| 144 ExpressionStatement* expr = | 191 ExpressionStatement* expr = |
| 145 stmt->statements()->at(0)->AsExpressionStatement(); | 192 stmt->statements()->at(0)->AsExpressionStatement(); |
| 146 if (expr != nullptr) { | 193 if (expr != nullptr) { |
| 147 if (expr->expression()->IsAssignment()) { | 194 if (expr->expression()->IsAssignment()) { |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 const auto& arguments = func_type->Arguments(); | 494 const auto& arguments = func_type->Arguments(); |
| 448 for (int i = 0; i < expr->parameter_count(); ++i) { | 495 for (int i = 0; i < expr->parameter_count(); ++i) { |
| 449 LocalType type = TypeFrom(arguments[i]); | 496 LocalType type = TypeFrom(arguments[i]); |
| 450 DCHECK_NE(kAstStmt, type); | 497 DCHECK_NE(kAstStmt, type); |
| 451 InsertParameter(scope->parameter(i), type, i); | 498 InsertParameter(scope->parameter(i), type, i); |
| 452 } | 499 } |
| 453 } else { | 500 } else { |
| 454 UNREACHABLE(); | 501 UNREACHABLE(); |
| 455 } | 502 } |
| 456 } | 503 } |
| 457 RECURSE(VisitStatements(expr->body())); | 504 if (scope_ == kFuncScope) { |
|
titzer
2016/10/07 12:56:59
Why do we need to do the declarations after for a
bradn
2016/11/25 09:19:36
No good reason.
Both should be declarations then s
| |
| 458 RECURSE(VisitDeclarations(scope->declarations())); | 505 RECURSE(VisitStatements(expr->body())); |
| 506 RECURSE(VisitDeclarations(scope->declarations())); | |
| 507 } else { | |
| 508 RECURSE(VisitDeclarations(scope->declarations())); | |
| 509 RECURSE(VisitStatements(expr->body())); | |
| 510 } | |
| 459 } | 511 } |
| 460 | 512 |
| 461 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 513 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 462 UNREACHABLE(); | 514 UNREACHABLE(); |
| 463 } | 515 } |
| 464 | 516 |
| 465 void VisitConditional(Conditional* expr) { | 517 void VisitConditional(Conditional* expr) { |
| 466 DCHECK_EQ(kFuncScope, scope_); | 518 DCHECK_EQ(kFuncScope, scope_); |
| 467 RECURSE(Visit(expr->condition())); | 519 RECURSE(Visit(expr->condition())); |
| 468 // WASM ifs come with implicit blocks for both arms. | 520 // WASM ifs come with implicit blocks for both arms. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 630 byte code[] = {WASM_F32(val)}; | 682 byte code[] = {WASM_F32(val)}; |
| 631 current_function_builder_->EmitCode(code, sizeof(code)); | 683 current_function_builder_->EmitCode(code, sizeof(code)); |
| 632 } else { | 684 } else { |
| 633 UNREACHABLE(); | 685 UNREACHABLE(); |
| 634 } | 686 } |
| 635 } | 687 } |
| 636 | 688 |
| 637 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } | 689 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
| 638 | 690 |
| 639 void VisitObjectLiteral(ObjectLiteral* expr) { | 691 void VisitObjectLiteral(ObjectLiteral* expr) { |
| 692 if (!typer_->ValidatePhase2of2()) { | |
| 693 typer_failed_ = true; | |
| 694 return; | |
| 695 } | |
| 696 | |
| 640 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 697 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
| 641 for (int i = 0; i < props->length(); ++i) { | 698 for (int i = 0; i < props->length(); ++i) { |
| 642 ObjectLiteralProperty* prop = props->at(i); | 699 ObjectLiteralProperty* prop = props->at(i); |
| 643 DCHECK_EQ(kExportScope, scope_); | 700 DCHECK_EQ(kExportScope, scope_); |
| 644 VariableProxy* expr = prop->value()->AsVariableProxy(); | 701 VariableProxy* expr = prop->value()->AsVariableProxy(); |
| 645 DCHECK_NOT_NULL(expr); | 702 DCHECK_NOT_NULL(expr); |
| 646 Variable* var = expr->var(); | 703 Variable* var = expr->var(); |
| 647 Literal* name = prop->key()->AsLiteral(); | 704 Literal* name = prop->key()->AsLiteral(); |
| 648 DCHECK_NOT_NULL(name); | 705 DCHECK_NOT_NULL(name); |
| 649 DCHECK(name->IsPropertyName()); | 706 DCHECK(name->IsPropertyName()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 662 void LoadInitFunction() { | 719 void LoadInitFunction() { |
| 663 current_function_builder_ = init_function_; | 720 current_function_builder_ = init_function_; |
| 664 scope_ = kInitScope; | 721 scope_ = kInitScope; |
| 665 } | 722 } |
| 666 | 723 |
| 667 void UnLoadInitFunction() { | 724 void UnLoadInitFunction() { |
| 668 scope_ = kModuleScope; | 725 scope_ = kModuleScope; |
| 669 current_function_builder_ = nullptr; | 726 current_function_builder_ = nullptr; |
| 670 } | 727 } |
| 671 | 728 |
| 672 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 729 struct FunctionTableIndices : public ZoneObject { |
| 673 auto* func_tbl_type = typer_->TypeOf(funcs)->AsFunctionTableType(); | 730 uint32_t start_index; |
| 674 DCHECK_NOT_NULL(func_tbl_type); | 731 uint32_t signature_index; |
| 675 auto* func_type = func_tbl_type->signature()->AsFunctionType(); | 732 }; |
| 733 | |
| 734 FunctionTableIndices* LookupOrAddFunctionTable(VariableProxy* table, | |
| 735 Property* p) { | |
| 736 FunctionTableIndices* indices = LookupFunctionTable(table->var()); | |
| 737 if (indices != nullptr) { | |
| 738 // Already setup. | |
| 739 return indices; | |
| 740 } | |
| 741 indices = new (zone()) FunctionTableIndices(); | |
| 742 auto* func_type = typer_->TypeOf(p)->AsFunctionType(); | |
| 743 auto* func_table_type = typer_->TypeOf(p->obj()->AsVariableProxy()->var()) | |
| 744 ->AsFunctionTableType(); | |
| 676 const auto& arguments = func_type->Arguments(); | 745 const auto& arguments = func_type->Arguments(); |
| 677 LocalType return_type = TypeFrom(func_type->ReturnType()); | 746 LocalType return_type = TypeFrom(func_type->ReturnType()); |
| 678 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 747 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 679 arguments.size()); | 748 arguments.size()); |
| 680 if (return_type != kAstStmt) { | 749 if (return_type != kAstStmt) { |
| 681 sig.AddReturn(return_type); | 750 sig.AddReturn(return_type); |
| 682 } | 751 } |
| 683 for (auto* arg : arguments) { | 752 for (auto* arg : arguments) { |
| 684 sig.AddParam(TypeFrom(arg)); | 753 sig.AddParam(TypeFrom(arg)); |
| 685 } | 754 } |
| 686 uint32_t signature_index = builder_->AddSignature(sig.Build()); | 755 uint32_t signature_index = builder_->AddSignature(sig.Build()); |
| 687 InsertFunctionTable(table->var(), next_table_index_, signature_index); | 756 indices->start_index = |
| 688 next_table_index_ += funcs->values()->length(); | 757 builder_->AllocateIndirectFunctions(func_table_type->length()); |
| 689 for (int i = 0; i < funcs->values()->length(); ++i) { | 758 indices->signature_index = signature_index; |
| 690 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | |
| 691 DCHECK_NOT_NULL(func); | |
| 692 builder_->AddIndirectFunction( | |
| 693 LookupOrInsertFunction(func->var())->func_index()); | |
| 694 } | |
| 695 } | |
| 696 | |
| 697 struct FunctionTableIndices : public ZoneObject { | |
| 698 uint32_t start_index; | |
| 699 uint32_t signature_index; | |
| 700 }; | |
| 701 | |
| 702 void InsertFunctionTable(Variable* v, uint32_t start_index, | |
| 703 uint32_t signature_index) { | |
| 704 FunctionTableIndices* container = new (zone()) FunctionTableIndices(); | |
| 705 container->start_index = start_index; | |
| 706 container->signature_index = signature_index; | |
| 707 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( | 759 ZoneHashMap::Entry* entry = function_tables_.LookupOrInsert( |
| 708 v, ComputePointerHash(v), ZoneAllocationPolicy(zone())); | 760 table->var(), ComputePointerHash(table->var()), |
| 709 entry->value = container; | 761 ZoneAllocationPolicy(zone())); |
| 762 entry->value = indices; | |
| 763 return indices; | |
| 710 } | 764 } |
| 711 | 765 |
| 712 FunctionTableIndices* LookupFunctionTable(Variable* v) { | 766 FunctionTableIndices* LookupFunctionTable(Variable* v) { |
| 713 ZoneHashMap::Entry* entry = | 767 ZoneHashMap::Entry* entry = |
| 714 function_tables_.Lookup(v, ComputePointerHash(v)); | 768 function_tables_.Lookup(v, ComputePointerHash(v)); |
| 715 DCHECK_NOT_NULL(entry); | 769 if (entry == nullptr) { |
| 770 return nullptr; | |
| 771 } | |
| 716 return reinterpret_cast<FunctionTableIndices*>(entry->value); | 772 return reinterpret_cast<FunctionTableIndices*>(entry->value); |
| 717 } | 773 } |
| 718 | 774 |
| 775 void PopulateFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | |
| 776 FunctionTableIndices* indices = LookupFunctionTable(table->var()); | |
| 777 DCHECK_NOT_NULL(indices); | |
| 778 for (int i = 0; i < funcs->values()->length(); ++i) { | |
| 779 VariableProxy* func = funcs->values()->at(i)->AsVariableProxy(); | |
| 780 DCHECK_NOT_NULL(func); | |
| 781 builder_->SetIndirectFunction( | |
| 782 indices->start_index + i, | |
| 783 LookupOrInsertFunction(func->var())->func_index()); | |
| 784 } | |
| 785 } | |
| 786 | |
| 719 class ImportedFunctionTable { | 787 class ImportedFunctionTable { |
| 720 private: | 788 private: |
| 721 class ImportedFunctionIndices : public ZoneObject { | 789 class ImportedFunctionIndices : public ZoneObject { |
| 722 public: | 790 public: |
| 723 const char* name_; | 791 const char* name_; |
| 724 int name_length_; | 792 int name_length_; |
| 725 WasmModuleBuilder::SignatureMap signature_to_index_; | 793 WasmModuleBuilder::SignatureMap signature_to_index_; |
| 726 | 794 |
| 727 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) | 795 ImportedFunctionIndices(const char* name, int name_length, Zone* zone) |
| 728 : name_(name), name_length_(name_length), signature_to_index_(zone) {} | 796 : name_(name), name_length_(name_length), signature_to_index_(zone) {} |
| 729 }; | 797 }; |
| 730 ZoneHashMap table_; | 798 ZoneHashMap table_; |
| 731 AsmWasmBuilderImpl* builder_; | 799 AsmWasmBuilderImpl* builder_; |
| 732 | 800 |
| 733 public: | 801 public: |
| 734 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) | 802 explicit ImportedFunctionTable(AsmWasmBuilderImpl* builder) |
| 735 : table_(ZoneHashMap::kDefaultHashMapCapacity, | 803 : table_(ZoneHashMap::kDefaultHashMapCapacity, |
| 736 ZoneAllocationPolicy(builder->zone())), | 804 ZoneAllocationPolicy(builder->zone())), |
| 737 builder_(builder) {} | 805 builder_(builder) {} |
| 738 | 806 |
| 739 void AddImport(Variable* v, const char* name, int name_length) { | 807 ImportedFunctionIndices* LookupOrInsertImport(Variable* v) { |
| 740 ImportedFunctionIndices* indices = new (builder_->zone()) | |
| 741 ImportedFunctionIndices(name, name_length, builder_->zone()); | |
| 742 auto* entry = table_.LookupOrInsert( | 808 auto* entry = table_.LookupOrInsert( |
| 743 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); | 809 v, ComputePointerHash(v), ZoneAllocationPolicy(builder_->zone())); |
| 744 entry->value = indices; | 810 ImportedFunctionIndices* indices; |
| 811 if (entry->value == nullptr) { | |
| 812 indices = new (builder_->zone()) | |
| 813 ImportedFunctionIndices(nullptr, 0, builder_->zone()); | |
| 814 entry->value = indices; | |
| 815 } else { | |
| 816 indices = reinterpret_cast<ImportedFunctionIndices*>(entry->value); | |
| 817 } | |
| 818 return indices; | |
| 819 } | |
| 820 | |
| 821 void SetImportName(Variable* v, const char* name, int name_length) { | |
| 822 auto* indices = LookupOrInsertImport(v); | |
| 823 indices->name_ = name; | |
| 824 indices->name_length_ = name_length; | |
| 825 for (auto i : indices->signature_to_index_) { | |
| 826 builder_->builder_->SetImportName(i.second, indices->name_, | |
| 827 indices->name_length_); | |
| 828 } | |
| 745 } | 829 } |
| 746 | 830 |
| 747 // Get a function's index (or allocate if new). | 831 // Get a function's index (or allocate if new). |
| 748 uint32_t LookupOrInsertImport(Variable* v, FunctionSig* sig) { | 832 uint32_t LookupOrInsertImportUse(Variable* v, FunctionSig* sig) { |
| 749 ZoneHashMap::Entry* entry = table_.Lookup(v, ComputePointerHash(v)); | 833 auto* indices = LookupOrInsertImport(v); |
| 750 DCHECK_NOT_NULL(entry); | |
| 751 ImportedFunctionIndices* indices = | |
| 752 reinterpret_cast<ImportedFunctionIndices*>(entry->value); | |
| 753 WasmModuleBuilder::SignatureMap::iterator pos = | 834 WasmModuleBuilder::SignatureMap::iterator pos = |
| 754 indices->signature_to_index_.find(sig); | 835 indices->signature_to_index_.find(sig); |
| 755 if (pos != indices->signature_to_index_.end()) { | 836 if (pos != indices->signature_to_index_.end()) { |
| 756 return pos->second; | 837 return pos->second; |
| 757 } else { | 838 } else { |
| 758 uint32_t index = builder_->builder_->AddImport( | 839 uint32_t index = builder_->builder_->AddImport( |
| 759 indices->name_, indices->name_length_, sig); | 840 indices->name_, indices->name_length_, sig); |
| 760 indices->signature_to_index_[sig] = index; | 841 indices->signature_to_index_[sig] = index; |
| 761 return index; | 842 return index; |
| 762 } | 843 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 } | 984 } |
| 904 Property* prop = expr->value()->AsProperty(); | 985 Property* prop = expr->value()->AsProperty(); |
| 905 if (prop != nullptr) { | 986 if (prop != nullptr) { |
| 906 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 987 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
| 907 if (vp != nullptr && vp->var()->IsParameter() && | 988 if (vp != nullptr && vp->var()->IsParameter() && |
| 908 vp->var()->index() == 1) { | 989 vp->var()->index() == 1) { |
| 909 VariableProxy* target = expr->target()->AsVariableProxy(); | 990 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 910 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { | 991 if (typer_->TypeOf(target)->AsFFIType() != nullptr) { |
| 911 const AstRawString* name = | 992 const AstRawString* name = |
| 912 prop->key()->AsLiteral()->AsRawPropertyName(); | 993 prop->key()->AsLiteral()->AsRawPropertyName(); |
| 913 imported_function_table_.AddImport( | 994 imported_function_table_.SetImportName( |
| 914 target->var(), reinterpret_cast<const char*>(name->raw_data()), | 995 target->var(), reinterpret_cast<const char*>(name->raw_data()), |
| 915 name->length()); | 996 name->length()); |
| 916 } | 997 } |
| 917 } | 998 } |
| 918 // Property values in module scope don't emit code, so return. | 999 // Property values in module scope don't emit code, so return. |
| 919 return; | 1000 return; |
| 920 } | 1001 } |
| 921 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 1002 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
| 922 if (funcs != nullptr && | 1003 if (funcs != nullptr) { |
| 923 typer_->TypeOf(funcs) | |
| 924 ->AsFunctionTableType() | |
| 925 ->signature() | |
| 926 ->AsFunctionType()) { | |
| 927 VariableProxy* target = expr->target()->AsVariableProxy(); | 1004 VariableProxy* target = expr->target()->AsVariableProxy(); |
| 928 DCHECK_NOT_NULL(target); | 1005 DCHECK_NOT_NULL(target); |
| 929 AddFunctionTable(target, funcs); | 1006 PopulateFunctionTable(target, funcs); |
| 930 // Only add to the function table. No init needed. | 1007 // Only add to the function table. No init needed. |
| 931 return; | 1008 return; |
| 932 } | 1009 } |
| 933 if (expr->value()->IsCallNew()) { | 1010 if (expr->value()->IsCallNew()) { |
| 934 // No init code to emit for CallNew nodes. | 1011 // No init code to emit for CallNew nodes. |
| 935 return; | 1012 return; |
| 936 } | 1013 } |
| 937 as_init = true; | 1014 as_init = true; |
| 938 } | 1015 } |
| 939 | 1016 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1354 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1431 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
| 1355 args->length()); | 1432 args->length()); |
| 1356 if (return_type != kAstStmt) { | 1433 if (return_type != kAstStmt) { |
| 1357 sig.AddReturn(return_type); | 1434 sig.AddReturn(return_type); |
| 1358 } else { | 1435 } else { |
| 1359 returns_value = false; | 1436 returns_value = false; |
| 1360 } | 1437 } |
| 1361 for (int i = 0; i < args->length(); ++i) { | 1438 for (int i = 0; i < args->length(); ++i) { |
| 1362 sig.AddParam(TypeOf(args->at(i))); | 1439 sig.AddParam(TypeOf(args->at(i))); |
| 1363 } | 1440 } |
| 1364 uint32_t index = imported_function_table_.LookupOrInsertImport( | 1441 uint32_t index = imported_function_table_.LookupOrInsertImportUse( |
| 1365 vp->var(), sig.Build()); | 1442 vp->var(), sig.Build()); |
| 1366 VisitCallArgs(expr); | 1443 VisitCallArgs(expr); |
| 1367 current_function_builder_->Emit(kExprCallFunction); | 1444 current_function_builder_->Emit(kExprCallFunction); |
| 1368 current_function_builder_->EmitVarInt(index); | 1445 current_function_builder_->EmitVarInt(index); |
| 1369 } else { | 1446 } else { |
| 1370 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); | 1447 WasmFunctionBuilder* function = LookupOrInsertFunction(vp->var()); |
| 1371 VisitCallArgs(expr); | 1448 VisitCallArgs(expr); |
| 1372 current_function_builder_->Emit(kExprCallFunction); | 1449 current_function_builder_->Emit(kExprCallFunction); |
| 1373 current_function_builder_->EmitDirectCallIndex( | 1450 current_function_builder_->EmitDirectCallIndex( |
| 1374 function->func_index()); | 1451 function->func_index()); |
| 1375 returns_value = function->signature()->return_count() > 0; | 1452 returns_value = function->signature()->return_count() > 0; |
| 1376 } | 1453 } |
| 1377 break; | 1454 break; |
| 1378 } | 1455 } |
| 1379 case Call::KEYED_PROPERTY_CALL: { | 1456 case Call::KEYED_PROPERTY_CALL: { |
| 1380 DCHECK_EQ(kFuncScope, scope_); | 1457 DCHECK_EQ(kFuncScope, scope_); |
| 1381 Property* p = expr->expression()->AsProperty(); | 1458 Property* p = expr->expression()->AsProperty(); |
| 1382 DCHECK_NOT_NULL(p); | 1459 DCHECK_NOT_NULL(p); |
| 1383 VariableProxy* var = p->obj()->AsVariableProxy(); | 1460 VariableProxy* var = p->obj()->AsVariableProxy(); |
| 1384 DCHECK_NOT_NULL(var); | 1461 DCHECK_NOT_NULL(var); |
| 1385 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1462 FunctionTableIndices* indices = LookupOrAddFunctionTable(var, p); |
| 1386 Visit(p->key()); // TODO(titzer): should use RECURSE() | 1463 Visit(p->key()); // TODO(titzer): should use RECURSE() |
| 1387 | 1464 |
| 1388 // We have to use a temporary for the correct order of evaluation. | 1465 // We have to use a temporary for the correct order of evaluation. |
| 1389 current_function_builder_->EmitI32Const(indices->start_index); | 1466 current_function_builder_->EmitI32Const(indices->start_index); |
| 1390 current_function_builder_->Emit(kExprI32Add); | 1467 current_function_builder_->Emit(kExprI32Add); |
| 1391 WasmTemporary tmp(current_function_builder_, kAstI32); | 1468 WasmTemporary tmp(current_function_builder_, kAstI32); |
| 1392 current_function_builder_->EmitSetLocal(tmp.index()); | 1469 current_function_builder_->EmitSetLocal(tmp.index()); |
| 1393 | 1470 |
| 1394 VisitCallArgs(expr); | 1471 VisitCallArgs(expr); |
| 1395 | 1472 |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1720 #undef NON_SIGNED_INT | 1797 #undef NON_SIGNED_INT |
| 1721 #undef SIGNED | 1798 #undef SIGNED |
| 1722 #undef NON_SIGNED | 1799 #undef NON_SIGNED |
| 1723 | 1800 |
| 1724 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } | 1801 void VisitThisFunction(ThisFunction* expr) { UNREACHABLE(); } |
| 1725 | 1802 |
| 1726 void VisitDeclarations(ZoneList<Declaration*>* decls) { | 1803 void VisitDeclarations(ZoneList<Declaration*>* decls) { |
| 1727 for (int i = 0; i < decls->length(); ++i) { | 1804 for (int i = 0; i < decls->length(); ++i) { |
| 1728 Declaration* decl = decls->at(i); | 1805 Declaration* decl = decls->at(i); |
| 1729 RECURSE(Visit(decl)); | 1806 RECURSE(Visit(decl)); |
| 1807 if (typer_failed_) { | |
| 1808 return; | |
| 1809 } | |
| 1730 } | 1810 } |
| 1731 } | 1811 } |
| 1732 | 1812 |
| 1733 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } | 1813 void VisitClassLiteral(ClassLiteral* expr) { UNREACHABLE(); } |
| 1734 | 1814 |
| 1735 void VisitSpread(Spread* expr) { UNREACHABLE(); } | 1815 void VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 1736 | 1816 |
| 1737 void VisitSuperPropertyReference(SuperPropertyReference* expr) { | 1817 void VisitSuperPropertyReference(SuperPropertyReference* expr) { |
| 1738 UNREACHABLE(); | 1818 UNREACHABLE(); |
| 1739 } | 1819 } |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1847 | 1927 |
| 1848 ZoneHashMap local_variables_; | 1928 ZoneHashMap local_variables_; |
| 1849 ZoneHashMap functions_; | 1929 ZoneHashMap functions_; |
| 1850 ZoneHashMap global_variables_; | 1930 ZoneHashMap global_variables_; |
| 1851 AsmScope scope_; | 1931 AsmScope scope_; |
| 1852 WasmModuleBuilder* builder_; | 1932 WasmModuleBuilder* builder_; |
| 1853 WasmFunctionBuilder* current_function_builder_; | 1933 WasmFunctionBuilder* current_function_builder_; |
| 1854 FunctionLiteral* literal_; | 1934 FunctionLiteral* literal_; |
| 1855 Isolate* isolate_; | 1935 Isolate* isolate_; |
| 1856 Zone* zone_; | 1936 Zone* zone_; |
| 1937 Script* script_; | |
| 1857 AsmTyper* typer_; | 1938 AsmTyper* typer_; |
| 1939 bool typer_failed_; | |
| 1858 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1940 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
| 1859 ZoneVector<ForeignVariable> foreign_variables_; | 1941 ZoneVector<ForeignVariable> foreign_variables_; |
| 1860 WasmFunctionBuilder* init_function_; | 1942 WasmFunctionBuilder* init_function_; |
| 1861 WasmFunctionBuilder* foreign_init_function_; | 1943 WasmFunctionBuilder* foreign_init_function_; |
| 1862 uint32_t next_table_index_; | 1944 uint32_t next_table_index_; |
| 1863 ZoneHashMap function_tables_; | 1945 ZoneHashMap function_tables_; |
| 1864 ImportedFunctionTable imported_function_table_; | 1946 ImportedFunctionTable imported_function_table_; |
| 1865 | 1947 |
| 1866 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1948 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
| 1867 | 1949 |
| 1868 private: | 1950 private: |
| 1869 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1951 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
| 1870 }; | 1952 }; |
| 1871 | 1953 |
| 1872 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, | 1954 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, Script* script, |
| 1873 FunctionLiteral* literal, AsmTyper* typer) | 1955 FunctionLiteral* literal) |
| 1874 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {} | 1956 : isolate_(isolate), |
| 1957 zone_(zone), | |
| 1958 script_(script), | |
| 1959 literal_(literal), | |
| 1960 typer_(isolate, zone, script, literal) {} | |
| 1875 | 1961 |
| 1876 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so | 1962 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so |
| 1877 // that zone in constructor may be thrown away once wasm module is written. | 1963 // that zone in constructor may be thrown away once wasm module is written. |
| 1878 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { | 1964 ZoneBuffer* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) { |
| 1879 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_); | 1965 AsmWasmBuilderImpl impl(isolate_, zone_, script_, literal_, &typer_); |
| 1880 impl.Build(); | 1966 if (!impl.Build()) { |
| 1967 return nullptr; | |
| 1968 } | |
| 1881 *foreign_args = impl.GetForeignArgs(); | 1969 *foreign_args = impl.GetForeignArgs(); |
| 1882 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); | 1970 ZoneBuffer* buffer = new (zone_) ZoneBuffer(zone_); |
| 1883 impl.builder_->WriteTo(*buffer); | 1971 impl.builder_->WriteTo(*buffer); |
| 1884 return buffer; | 1972 return buffer; |
| 1885 } | 1973 } |
| 1886 | 1974 |
| 1887 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; | 1975 const char* AsmWasmBuilder::foreign_init_name = "__foreign_init__"; |
| 1888 const char* AsmWasmBuilder::single_function_name = "__single_function__"; | 1976 const char* AsmWasmBuilder::single_function_name = "__single_function__"; |
| 1889 | 1977 |
| 1890 } // namespace wasm | 1978 } // namespace wasm |
| 1891 } // namespace internal | 1979 } // namespace internal |
| 1892 } // namespace v8 | 1980 } // namespace v8 |
| OLD | NEW |