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