Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Side by Side Diff: src/wasm/asm-wasm-builder.cc

Issue 1999523002: Delay asm->wasm foreign globals init until later. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 // Required to get M_E etc. in MSVC. 7 // Required to get M_E etc. in MSVC.
8 #if defined(_WIN32) 8 #if defined(_WIN32)
9 #define _USE_MATH_DEFINES 9 #define _USE_MATH_DEFINES
10 #endif 10 #endif
(...skipping 18 matching lines...) Expand all
29 DCHECK(!HasStackOverflow()); \ 29 DCHECK(!HasStackOverflow()); \
30 call; \ 30 call; \
31 if (HasStackOverflow()) return; \ 31 if (HasStackOverflow()) return; \
32 } while (false) 32 } while (false)
33 33
34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; 34 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope };
35 35
36 class AsmWasmBuilderImpl : public AstVisitor { 36 class AsmWasmBuilderImpl : public AstVisitor {
37 public: 37 public:
38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, 38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal,
39 Handle<Object> foreign, AsmTyper* typer) 39 AsmTyper* typer)
40 : local_variables_(HashMap::PointersMatch, 40 : local_variables_(HashMap::PointersMatch,
41 ZoneHashMap::kDefaultHashMapCapacity, 41 ZoneHashMap::kDefaultHashMapCapacity,
42 ZoneAllocationPolicy(zone)), 42 ZoneAllocationPolicy(zone)),
43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, 43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity,
44 ZoneAllocationPolicy(zone)), 44 ZoneAllocationPolicy(zone)),
45 global_variables_(HashMap::PointersMatch, 45 global_variables_(HashMap::PointersMatch,
46 ZoneHashMap::kDefaultHashMapCapacity, 46 ZoneHashMap::kDefaultHashMapCapacity,
47 ZoneAllocationPolicy(zone)), 47 ZoneAllocationPolicy(zone)),
48 scope_(kModuleScope), 48 scope_(kModuleScope),
49 builder_(new (zone) WasmModuleBuilder(zone)), 49 builder_(new (zone) WasmModuleBuilder(zone)),
50 current_function_builder_(nullptr), 50 current_function_builder_(nullptr),
51 literal_(literal), 51 literal_(literal),
52 isolate_(isolate), 52 isolate_(isolate),
53 zone_(zone), 53 zone_(zone),
54 foreign_(foreign),
55 typer_(typer), 54 typer_(typer),
56 cache_(TypeCache::Get()), 55 cache_(TypeCache::Get()),
57 breakable_blocks_(zone), 56 breakable_blocks_(zone),
57 foreign_variables_(zone),
58 init_function_index_(0), 58 init_function_index_(0),
59 foreign_init_function_index_(0),
59 next_table_index_(0), 60 next_table_index_(0),
60 function_tables_(HashMap::PointersMatch, 61 function_tables_(HashMap::PointersMatch,
61 ZoneHashMap::kDefaultHashMapCapacity, 62 ZoneHashMap::kDefaultHashMapCapacity,
62 ZoneAllocationPolicy(zone)), 63 ZoneAllocationPolicy(zone)),
63 imported_function_table_(this), 64 imported_function_table_(this),
64 bounds_(typer->bounds()) { 65 bounds_(typer->bounds()) {
65 InitializeAstVisitor(isolate); 66 InitializeAstVisitor(isolate);
66 } 67 }
67 68
68 void InitializeInitFunction() { 69 void InitializeInitFunction() {
69 init_function_index_ = builder_->AddFunction(); 70 init_function_index_ = builder_->AddFunction();
70 FunctionSig::Builder b(zone(), 0, 0); 71 FunctionSig::Builder b(zone(), 0, 0);
71 current_function_builder_ = builder_->FunctionAt(init_function_index_); 72 current_function_builder_ = builder_->FunctionAt(init_function_index_);
72 current_function_builder_->SetSignature(b.Build()); 73 current_function_builder_->SetSignature(b.Build());
73 builder_->MarkStartFunction(init_function_index_); 74 builder_->MarkStartFunction(init_function_index_);
74 current_function_builder_ = nullptr; 75 current_function_builder_ = nullptr;
75 } 76 }
76 77
78 void BuildForeignInitFunction() {
79 foreign_init_function_index_ = builder_->AddFunction();
80 FunctionSig::Builder b(zone(), 0, foreign_variables_.size());
81 for (auto i = foreign_variables_.begin(); i != foreign_variables_.end();
82 ++i) {
83 if (i->is_float) {
84 b.AddParam(kAstF64);
85 } else {
86 b.AddParam(kAstI32);
87 }
88 }
89 current_function_builder_ =
90 builder_->FunctionAt(foreign_init_function_index_);
91 current_function_builder_->Exported(1);
92 std::string raw_name = "__foreign_init__";
93 current_function_builder_->SetName(raw_name.data(),
94 static_cast<int>(raw_name.size()));
95 current_function_builder_->SetSignature(b.Build());
96 for (size_t pos = 0; pos < foreign_variables_.size(); ++pos) {
97 current_function_builder_->EmitGetLocal(static_cast<uint32_t>(pos));
98 ForeignVariable* fv = &foreign_variables_[pos];
99 LocalType var_type = fv->is_float ? kAstF64 : kAstI32;
100 uint32_t index = LookupOrInsertGlobal(fv->var, var_type);
101 current_function_builder_->EmitWithVarInt(kExprStoreGlobal, index);
102 }
103 current_function_builder_ = nullptr;
104 }
105
106 i::Handle<i::FixedArray> GetForeignArgs() {
107 i::Handle<FixedArray> ret = isolate_->factory()->NewFixedArray(
108 static_cast<int>(foreign_variables_.size()));
109 for (size_t i = 0; i < foreign_variables_.size(); ++i) {
110 ForeignVariable* fv = &foreign_variables_[i];
111 ret->set(static_cast<int>(i), *fv->name);
112 }
113 return ret;
114 }
115
77 void Compile() { 116 void Compile() {
78 InitializeInitFunction(); 117 InitializeInitFunction();
79 RECURSE(VisitFunctionLiteral(literal_)); 118 RECURSE(VisitFunctionLiteral(literal_));
119 BuildForeignInitFunction();
80 } 120 }
81 121
82 void VisitVariableDeclaration(VariableDeclaration* decl) {} 122 void VisitVariableDeclaration(VariableDeclaration* decl) {}
83 123
84 void VisitFunctionDeclaration(FunctionDeclaration* decl) { 124 void VisitFunctionDeclaration(FunctionDeclaration* decl) {
85 DCHECK_EQ(kModuleScope, scope_); 125 DCHECK_EQ(kModuleScope, scope_);
86 DCHECK_NULL(current_function_builder_); 126 DCHECK_NULL(current_function_builder_);
87 uint32_t index = LookupOrInsertFunction(decl->proxy()->var()); 127 uint32_t index = LookupOrInsertFunction(decl->proxy()->var());
88 current_function_builder_ = builder_->FunctionAt(index); 128 current_function_builder_ = builder_->FunctionAt(index);
89 scope_ = kFuncScope; 129 scope_ = kFuncScope;
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { 739 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) {
700 BinaryOperation* binop = value->AsBinaryOperation(); 740 BinaryOperation* binop = value->AsBinaryOperation();
701 if (binop != nullptr) { 741 if (binop != nullptr) {
702 if (scope_ == kInitScope) { 742 if (scope_ == kInitScope) {
703 // Handle foreign variables in the initialization scope. 743 // Handle foreign variables in the initialization scope.
704 Property* prop = binop->left()->AsProperty(); 744 Property* prop = binop->left()->AsProperty();
705 if (binop->op() == Token::MUL) { 745 if (binop->op() == Token::MUL) {
706 DCHECK(binop->right()->IsLiteral()); 746 DCHECK(binop->right()->IsLiteral());
707 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); 747 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
708 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); 748 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot());
709 VisitForeignVariable(true, prop); 749 DCHECK(target->IsVariableProxy());
750 VisitForeignVariable(true, target->AsVariableProxy()->var(), prop);
751 *is_nop = true;
710 return; 752 return;
711 } else if (binop->op() == Token::BIT_OR) { 753 } else if (binop->op() == Token::BIT_OR) {
712 DCHECK(binop->right()->IsLiteral()); 754 DCHECK(binop->right()->IsLiteral());
713 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); 755 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber());
714 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); 756 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot());
715 VisitForeignVariable(false, prop); 757 DCHECK(target->IsVariableProxy());
758 VisitForeignVariable(false, target->AsVariableProxy()->var(), prop);
759 *is_nop = true;
716 return; 760 return;
717 } else { 761 } else {
718 UNREACHABLE(); 762 UNREACHABLE();
719 } 763 }
720 } 764 }
721 if (MatchBinaryOperation(binop) == kAsIs) { 765 if (MatchBinaryOperation(binop) == kAsIs) {
722 VariableProxy* target_var = target->AsVariableProxy(); 766 VariableProxy* target_var = target->AsVariableProxy();
723 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); 767 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy();
724 if (target_var != nullptr && effective_value_var != nullptr && 768 if (target_var != nullptr && effective_value_var != nullptr &&
725 target_var->var() == effective_value_var->var()) { 769 target_var->var() == effective_value_var->var()) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 if (!is_nop) { 872 if (!is_nop) {
829 EmitAssignment(expr, mtype); 873 EmitAssignment(expr, mtype);
830 } 874 }
831 if (as_init) UnLoadInitFunction(); 875 if (as_init) UnLoadInitFunction();
832 } 876 }
833 877
834 void VisitYield(Yield* expr) { UNREACHABLE(); } 878 void VisitYield(Yield* expr) { UNREACHABLE(); }
835 879
836 void VisitThrow(Throw* expr) { UNREACHABLE(); } 880 void VisitThrow(Throw* expr) { UNREACHABLE(); }
837 881
838 void VisitForeignVariable(bool is_float, Property* expr) { 882 void VisitForeignVariable(bool is_float, Variable* var, Property* expr) {
839 DCHECK(expr->obj()->AsVariableProxy()); 883 DCHECK(expr->obj()->AsVariableProxy());
840 DCHECK(VariableLocation::PARAMETER == 884 DCHECK(VariableLocation::PARAMETER ==
841 expr->obj()->AsVariableProxy()->var()->location()); 885 expr->obj()->AsVariableProxy()->var()->location());
842 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index()); 886 DCHECK_EQ(1, expr->obj()->AsVariableProxy()->var()->index());
843 Literal* key_literal = expr->key()->AsLiteral(); 887 Literal* key_literal = expr->key()->AsLiteral();
844 DCHECK_NOT_NULL(key_literal); 888 DCHECK_NOT_NULL(key_literal);
845 if (!key_literal->value().is_null() && !foreign_.is_null() && 889 if (!key_literal->value().is_null()) {
846 foreign_->IsObject()) {
847 Handle<Name> name = 890 Handle<Name> name =
848 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked(); 891 i::Object::ToName(isolate_, key_literal->value()).ToHandleChecked();
849 MaybeHandle<Object> maybe_value = i::Object::GetProperty(foreign_, name); 892 ForeignVariable foreign;
850 if (!maybe_value.is_null()) { 893 foreign.name = name;
851 Handle<Object> value = maybe_value.ToHandleChecked(); 894 foreign.var = var;
852 if (is_float) { 895 foreign.is_float = is_float;
853 MaybeHandle<Object> maybe_nvalue = i::Object::ToNumber(value); 896 foreign_variables_.push_back(foreign);
titzer 2016/05/20 11:39:59 Could you just do push_back({...})?
bradn 2016/05/20 14:37:32 Done.
854 if (!maybe_nvalue.is_null()) {
855 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
856 if (nvalue->IsNumber()) {
857 double val = nvalue->Number();
858 byte code[] = {WASM_F64(val)};
859 current_function_builder_->EmitCode(code, sizeof(code));
860 return;
861 }
862 }
863 } else {
864 MaybeHandle<Object> maybe_nvalue =
865 i::Object::ToInt32(isolate_, value);
866 if (!maybe_nvalue.is_null()) {
867 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked();
868 if (nvalue->IsNumber()) {
869 int32_t val = static_cast<int32_t>(nvalue->Number());
870 current_function_builder_->EmitI32Const(val);
871 return;
872 }
873 }
874 }
875 }
876 }
877 if (is_float) {
878 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())};
879 current_function_builder_->EmitCode(code, sizeof(code));
880 } else {
881 byte code[] = {WASM_I32V_1(0)};
882 current_function_builder_->EmitCode(code, sizeof(code));
883 } 897 }
884 } 898 }
885 899
886 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { 900 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) {
887 Expression* obj = expr->obj(); 901 Expression* obj = expr->obj();
888 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper); 902 DCHECK_EQ(bounds_->get(obj).lower, bounds_->get(obj).upper);
889 Type* type = bounds_->get(obj).lower; 903 Type* type = bounds_->get(obj).lower;
890 int size; 904 int size;
891 if (type->Is(cache_.kUint8Array)) { 905 if (type->Is(cache_.kUint8Array)) {
892 *mtype = MachineType::Uint8(); 906 *mtype = MachineType::Uint8();
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after
1706 return kAstI32; 1720 return kAstI32;
1707 } else if (type->Is(cache_.kAsmFloat)) { 1721 } else if (type->Is(cache_.kAsmFloat)) {
1708 return kAstF32; 1722 return kAstF32;
1709 } else if (type->Is(cache_.kAsmDouble)) { 1723 } else if (type->Is(cache_.kAsmDouble)) {
1710 return kAstF64; 1724 return kAstF64;
1711 } else { 1725 } else {
1712 return kAstStmt; 1726 return kAstStmt;
1713 } 1727 }
1714 } 1728 }
1715 1729
1730 struct ForeignVariable {
titzer 2016/05/20 11:39:59 Can you move this to the top?
bradn 2016/05/20 14:37:32 Done.
1731 Variable* var;
1732 Handle<Name> name;
1733 bool is_float;
titzer 2016/05/20 11:39:59 Should we store the AST type here instead of a boo
bradn 2016/05/20 14:37:32 Done.
1734 };
1735
1716 Zone* zone() { return zone_; } 1736 Zone* zone() { return zone_; }
1717 1737
1718 ZoneHashMap local_variables_; 1738 ZoneHashMap local_variables_;
1719 ZoneHashMap functions_; 1739 ZoneHashMap functions_;
1720 ZoneHashMap global_variables_; 1740 ZoneHashMap global_variables_;
1721 AsmScope scope_; 1741 AsmScope scope_;
1722 WasmModuleBuilder* builder_; 1742 WasmModuleBuilder* builder_;
1723 WasmFunctionBuilder* current_function_builder_; 1743 WasmFunctionBuilder* current_function_builder_;
1724 FunctionLiteral* literal_; 1744 FunctionLiteral* literal_;
1725 Isolate* isolate_; 1745 Isolate* isolate_;
1726 Zone* zone_; 1746 Zone* zone_;
1727 Handle<Object> foreign_;
1728 AsmTyper* typer_; 1747 AsmTyper* typer_;
1729 TypeCache const& cache_; 1748 TypeCache const& cache_;
1730 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; 1749 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_;
1750 ZoneVector<ForeignVariable> foreign_variables_;
1731 uint32_t init_function_index_; 1751 uint32_t init_function_index_;
1752 uint32_t foreign_init_function_index_;
1732 uint32_t next_table_index_; 1753 uint32_t next_table_index_;
1733 ZoneHashMap function_tables_; 1754 ZoneHashMap function_tables_;
1734 ImportedFunctionTable imported_function_table_; 1755 ImportedFunctionTable imported_function_table_;
1735 const AstTypeBounds* bounds_; 1756 const AstTypeBounds* bounds_;
1736 1757
1737 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); 1758 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
1738 1759
1739 private: 1760 private:
1740 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); 1761 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl);
1741 }; 1762 };
1742 1763
1743 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone, 1764 AsmWasmBuilder::AsmWasmBuilder(Isolate* isolate, Zone* zone,
1744 FunctionLiteral* literal, Handle<Object> foreign, 1765 FunctionLiteral* literal, AsmTyper* typer)
1745 AsmTyper* typer) 1766 : isolate_(isolate), zone_(zone), literal_(literal), typer_(typer) {}
1746 : isolate_(isolate),
1747 zone_(zone),
1748 literal_(literal),
1749 foreign_(foreign),
1750 typer_(typer) {}
1751 1767
1752 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so 1768 // TODO(aseemgarg): probably should take zone (to write wasm to) as input so
1753 // that zone in constructor may be thrown away once wasm module is written. 1769 // that zone in constructor may be thrown away once wasm module is written.
1754 WasmModuleIndex* AsmWasmBuilder::Run() { 1770 WasmModuleIndex* AsmWasmBuilder::Run(i::Handle<i::FixedArray>* foreign_args) {
1755 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); 1771 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, typer_);
1756 impl.Compile(); 1772 impl.Compile();
1773 *foreign_args = impl.GetForeignArgs();
1757 WasmModuleWriter* writer = impl.builder_->Build(zone_); 1774 WasmModuleWriter* writer = impl.builder_->Build(zone_);
1758 return writer->WriteTo(zone_); 1775 return writer->WriteTo(zone_);
1759 } 1776 }
1760 } // namespace wasm 1777 } // namespace wasm
1761 } // namespace internal 1778 } // namespace internal
1762 } // namespace v8 1779 } // namespace v8
OLDNEW
« no previous file with comments | « src/wasm/asm-wasm-builder.h ('k') | src/wasm/wasm-js.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698