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 12 matching lines...) Loading... | |
23 namespace internal { | 23 namespace internal { |
24 namespace wasm { | 24 namespace wasm { |
25 | 25 |
26 #define RECURSE(call) \ | 26 #define RECURSE(call) \ |
27 do { \ | 27 do { \ |
28 DCHECK(!HasStackOverflow()); \ | 28 DCHECK(!HasStackOverflow()); \ |
29 call; \ | 29 call; \ |
30 if (HasStackOverflow()) return; \ | 30 if (HasStackOverflow()) return; \ |
31 } while (false) | 31 } while (false) |
32 | 32 |
33 enum AsmScope { kModuleScope, kInitScope, kFuncScope, kExportScope }; | |
33 | 34 |
34 class AsmWasmBuilderImpl : public AstVisitor { | 35 class AsmWasmBuilderImpl : public AstVisitor { |
35 public: | 36 public: |
36 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 37 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
37 Handle<Object> foreign, AsmTyper* typer) | 38 Handle<Object> foreign, AsmTyper* typer) |
38 : local_variables_(HashMap::PointersMatch, | 39 : local_variables_(HashMap::PointersMatch, |
39 ZoneHashMap::kDefaultHashMapCapacity, | 40 ZoneHashMap::kDefaultHashMapCapacity, |
40 ZoneAllocationPolicy(zone)), | 41 ZoneAllocationPolicy(zone)), |
41 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 42 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
42 ZoneAllocationPolicy(zone)), | 43 ZoneAllocationPolicy(zone)), |
43 global_variables_(HashMap::PointersMatch, | 44 global_variables_(HashMap::PointersMatch, |
44 ZoneHashMap::kDefaultHashMapCapacity, | 45 ZoneHashMap::kDefaultHashMapCapacity, |
45 ZoneAllocationPolicy(zone)), | 46 ZoneAllocationPolicy(zone)), |
46 in_function_(false), | 47 scope_(kModuleScope), |
47 is_set_op_(false), | |
48 marking_exported(false), | |
49 builder_(new (zone) WasmModuleBuilder(zone)), | 48 builder_(new (zone) WasmModuleBuilder(zone)), |
50 current_function_builder_(nullptr), | 49 current_function_builder_(nullptr), |
51 literal_(literal), | 50 literal_(literal), |
52 isolate_(isolate), | 51 isolate_(isolate), |
53 zone_(zone), | 52 zone_(zone), |
54 foreign_(foreign), | 53 foreign_(foreign), |
55 typer_(typer), | 54 typer_(typer), |
56 cache_(TypeCache::Get()), | 55 cache_(TypeCache::Get()), |
57 breakable_blocks_(zone), | 56 breakable_blocks_(zone), |
58 block_size_(0), | |
59 init_function_index_(0), | 57 init_function_index_(0), |
60 next_table_index_(0), | 58 next_table_index_(0), |
61 function_tables_(HashMap::PointersMatch, | 59 function_tables_(HashMap::PointersMatch, |
62 ZoneHashMap::kDefaultHashMapCapacity, | 60 ZoneHashMap::kDefaultHashMapCapacity, |
63 ZoneAllocationPolicy(zone)), | 61 ZoneAllocationPolicy(zone)), |
64 imported_function_table_(this) { | 62 imported_function_table_(this) { |
65 InitializeAstVisitor(isolate); | 63 InitializeAstVisitor(isolate); |
66 } | 64 } |
67 | 65 |
68 void InitializeInitFunction() { | 66 void InitializeInitFunction() { |
69 init_function_index_ = builder_->AddFunction(); | 67 init_function_index_ = builder_->AddFunction(); |
70 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 68 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
71 current_function_builder_->ReturnType(kAstStmt); | 69 current_function_builder_->ReturnType(kAstStmt); |
72 builder_->MarkStartFunction(init_function_index_); | 70 builder_->MarkStartFunction(init_function_index_); |
73 current_function_builder_ = nullptr; | 71 current_function_builder_ = nullptr; |
74 } | 72 } |
75 | 73 |
76 void Compile() { | 74 void Compile() { |
77 InitializeInitFunction(); | 75 InitializeInitFunction(); |
78 RECURSE(VisitFunctionLiteral(literal_)); | 76 RECURSE(VisitFunctionLiteral(literal_)); |
79 } | 77 } |
80 | 78 |
81 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 79 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
82 | 80 |
83 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 81 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
84 DCHECK(!in_function_); | 82 DCHECK_EQ(kModuleScope, scope_); |
85 DCHECK_NULL(current_function_builder_); | 83 DCHECK_NULL(current_function_builder_); |
86 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); | 84 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); |
87 current_function_builder_ = builder_->FunctionAt(index); | 85 current_function_builder_ = builder_->FunctionAt(index); |
88 in_function_ = true; | 86 scope_ = kFuncScope; |
89 RECURSE(Visit(decl->fun())); | 87 RECURSE(Visit(decl->fun())); |
90 in_function_ = false; | 88 scope_ = kModuleScope; |
91 current_function_builder_ = nullptr; | 89 current_function_builder_ = nullptr; |
92 local_variables_.Clear(); | 90 local_variables_.Clear(); |
93 } | 91 } |
94 | 92 |
95 void VisitImportDeclaration(ImportDeclaration* decl) {} | 93 void VisitImportDeclaration(ImportDeclaration* decl) {} |
96 | 94 |
97 void VisitExportDeclaration(ExportDeclaration* decl) {} | 95 void VisitExportDeclaration(ExportDeclaration* decl) {} |
98 | 96 |
99 void VisitStatements(ZoneList<Statement*>* stmts) { | 97 void VisitStatements(ZoneList<Statement*>* stmts) { |
100 for (int i = 0; i < stmts->length(); ++i) { | 98 for (int i = 0; i < stmts->length(); ++i) { |
101 Statement* stmt = stmts->at(i); | 99 Statement* stmt = stmts->at(i); |
102 RECURSE(Visit(stmt)); | 100 RECURSE(Visit(stmt)); |
103 if (stmt->IsJump()) break; | 101 if (stmt->IsJump()) break; |
104 } | 102 } |
105 } | 103 } |
106 | 104 |
107 void VisitBlock(Block* stmt) { | 105 void VisitBlock(Block* stmt) { |
108 if (stmt->statements()->length() == 1) { | 106 if (stmt->statements()->length() == 1) { |
109 ExpressionStatement* expr = | 107 ExpressionStatement* expr = |
110 stmt->statements()->at(0)->AsExpressionStatement(); | 108 stmt->statements()->at(0)->AsExpressionStatement(); |
111 if (expr != nullptr) { | 109 if (expr != nullptr) { |
112 if (expr->expression()->IsAssignment()) { | 110 if (expr->expression()->IsAssignment()) { |
113 RECURSE(VisitExpressionStatement(expr)); | 111 RECURSE(VisitExpressionStatement(expr)); |
114 return; | 112 return; |
115 } | 113 } |
116 } | 114 } |
117 } | 115 } |
118 if (in_function_) { | 116 if (scope_ == kFuncScope) { |
119 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, | 117 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
120 false, | 118 false); |
121 static_cast<byte>(stmt->statements()->length())); | |
122 RECURSE(VisitStatements(stmt->statements())); | 119 RECURSE(VisitStatements(stmt->statements())); |
123 DCHECK(block_size_ >= 0); | |
124 } else { | 120 } else { |
125 RECURSE(VisitStatements(stmt->statements())); | 121 RECURSE(VisitStatements(stmt->statements())); |
126 } | 122 } |
127 } | 123 } |
128 | 124 |
129 class BlockVisitor { | 125 class BlockVisitor { |
130 private: | 126 private: |
131 int prev_block_size_; | |
132 uint32_t index_; | |
133 AsmWasmBuilderImpl* builder_; | 127 AsmWasmBuilderImpl* builder_; |
134 | 128 |
135 public: | 129 public: |
136 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, | 130 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
137 WasmOpcode opcode, bool is_loop, int initial_block_size) | 131 WasmOpcode opcode, bool is_loop) |
138 : builder_(builder) { | 132 : builder_(builder) { |
139 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); | 133 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |
140 builder_->current_function_builder_->Emit(opcode); | 134 builder_->current_function_builder_->Emit(opcode); |
141 index_ = | |
142 builder_->current_function_builder_->EmitEditableVarIntImmediate(); | |
143 prev_block_size_ = builder_->block_size_; | |
144 builder_->block_size_ = initial_block_size; | |
145 } | 135 } |
146 ~BlockVisitor() { | 136 ~BlockVisitor() { |
147 builder_->current_function_builder_->EditVarIntImmediate( | 137 builder_->current_function_builder_->Emit(kExprEnd); |
148 index_, builder_->block_size_); | |
149 builder_->block_size_ = prev_block_size_; | |
150 builder_->breakable_blocks_.pop_back(); | 138 builder_->breakable_blocks_.pop_back(); |
151 } | 139 } |
152 }; | 140 }; |
153 | 141 |
154 void VisitExpressionStatement(ExpressionStatement* stmt) { | 142 void VisitExpressionStatement(ExpressionStatement* stmt) { |
155 RECURSE(Visit(stmt->expression())); | 143 RECURSE(Visit(stmt->expression())); |
156 } | 144 } |
157 | 145 |
158 void VisitEmptyStatement(EmptyStatement* stmt) {} | 146 void VisitEmptyStatement(EmptyStatement* stmt) {} |
159 | 147 |
160 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } | 148 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } |
161 | 149 |
162 void VisitIfStatement(IfStatement* stmt) { | 150 void VisitIfStatement(IfStatement* stmt) { |
163 DCHECK(in_function_); | 151 DCHECK_EQ(kFuncScope, scope_); |
164 if (stmt->HasElseStatement()) { | |
165 current_function_builder_->Emit(kExprIfElse); | |
166 } else { | |
167 current_function_builder_->Emit(kExprIf); | |
168 } | |
169 RECURSE(Visit(stmt->condition())); | 152 RECURSE(Visit(stmt->condition())); |
153 current_function_builder_->Emit(kExprIf); | |
170 if (stmt->HasThenStatement()) { | 154 if (stmt->HasThenStatement()) { |
171 RECURSE(Visit(stmt->then_statement())); | 155 RECURSE(Visit(stmt->then_statement())); |
172 } else { | |
173 current_function_builder_->Emit(kExprNop); | |
174 } | 156 } |
175 if (stmt->HasElseStatement()) { | 157 if (stmt->HasElseStatement()) { |
158 current_function_builder_->Emit(kExprElse); | |
176 RECURSE(Visit(stmt->else_statement())); | 159 RECURSE(Visit(stmt->else_statement())); |
177 } | 160 } |
161 current_function_builder_->Emit(kExprEnd); | |
178 } | 162 } |
179 | 163 |
180 void VisitContinueStatement(ContinueStatement* stmt) { | 164 void VisitContinueStatement(ContinueStatement* stmt) { |
181 DCHECK(in_function_); | 165 DCHECK_EQ(kFuncScope, scope_); |
182 DCHECK_NOT_NULL(stmt->target()); | 166 DCHECK_NOT_NULL(stmt->target()); |
183 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 167 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
184 int block_distance = 0; | 168 int block_distance = 0; |
185 for (; i >= 0; i--) { | 169 for (; i >= 0; i--) { |
186 auto elem = breakable_blocks_.at(i); | 170 auto elem = breakable_blocks_.at(i); |
187 if (elem.first == stmt->target()) { | 171 if (elem.first == stmt->target()) { |
188 DCHECK(elem.second); | 172 DCHECK(elem.second); |
189 break; | 173 break; |
190 } else if (elem.second) { | 174 } else if (elem.second) { |
191 block_distance += 2; | 175 block_distance += 2; |
192 } else { | 176 } else { |
193 block_distance += 1; | 177 block_distance += 1; |
194 } | 178 } |
195 } | 179 } |
196 DCHECK(i >= 0); | 180 DCHECK(i >= 0); |
181 current_function_builder_->Emit(kExprNop); | |
197 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | 182 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); |
198 current_function_builder_->Emit(kExprNop); | |
199 } | 183 } |
200 | 184 |
201 void VisitBreakStatement(BreakStatement* stmt) { | 185 void VisitBreakStatement(BreakStatement* stmt) { |
202 DCHECK(in_function_); | 186 DCHECK_EQ(kFuncScope, scope_); |
203 DCHECK_NOT_NULL(stmt->target()); | 187 DCHECK_NOT_NULL(stmt->target()); |
204 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 188 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
205 int block_distance = 0; | 189 int block_distance = 0; |
206 for (; i >= 0; i--) { | 190 for (; i >= 0; i--) { |
207 auto elem = breakable_blocks_.at(i); | 191 auto elem = breakable_blocks_.at(i); |
208 if (elem.first == stmt->target()) { | 192 if (elem.first == stmt->target()) { |
209 if (elem.second) { | 193 if (elem.second) { |
210 block_distance++; | 194 block_distance++; |
211 } | 195 } |
212 break; | 196 break; |
213 } else if (elem.second) { | 197 } else if (elem.second) { |
214 block_distance += 2; | 198 block_distance += 2; |
215 } else { | 199 } else { |
216 block_distance += 1; | 200 block_distance += 1; |
217 } | 201 } |
218 } | 202 } |
219 DCHECK(i >= 0); | 203 DCHECK(i >= 0); |
204 current_function_builder_->Emit(kExprNop); | |
220 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | 205 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); |
221 current_function_builder_->Emit(kExprNop); | |
222 } | 206 } |
223 | 207 |
224 void VisitReturnStatement(ReturnStatement* stmt) { | 208 void VisitReturnStatement(ReturnStatement* stmt) { |
225 if (in_function_) { | 209 if (scope_ == kModuleScope) { |
210 scope_ = kExportScope; | |
211 RECURSE(Visit(stmt->expression())); | |
212 scope_ = kModuleScope; | |
213 } else if (scope_ == kFuncScope) { | |
214 RECURSE(Visit(stmt->expression())); | |
226 current_function_builder_->Emit(kExprReturn); | 215 current_function_builder_->Emit(kExprReturn); |
227 } else { | 216 } else { |
228 marking_exported = true; | 217 UNREACHABLE(); |
229 } | |
230 RECURSE(Visit(stmt->expression())); | |
231 if (!in_function_) { | |
232 marking_exported = false; | |
233 } | 218 } |
234 } | 219 } |
235 | 220 |
236 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 221 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |
237 | 222 |
238 void SetLocalTo(uint16_t index, int value) { | 223 void SetLocalTo(uint16_t index, int32_t value) { |
224 current_function_builder_->EmitI32Const(value); | |
239 current_function_builder_->Emit(kExprSetLocal); | 225 current_function_builder_->Emit(kExprSetLocal); |
240 AddLeb128(index, true); | 226 AddLeb128(index, true); |
241 // TODO(bradnelson): variable size | |
242 byte code[] = {WASM_I32V(value)}; | |
243 current_function_builder_->EmitCode(code, sizeof(code)); | |
244 block_size_++; | |
245 } | 227 } |
246 | 228 |
247 void CompileCase(CaseClause* clause, uint16_t fall_through, | 229 void CompileCase(CaseClause* clause, uint16_t fall_through, |
248 VariableProxy* tag) { | 230 VariableProxy* tag) { |
249 Literal* label = clause->label()->AsLiteral(); | 231 Literal* label = clause->label()->AsLiteral(); |
250 DCHECK_NOT_NULL(label); | 232 DCHECK_NOT_NULL(label); |
251 block_size_++; | |
252 current_function_builder_->Emit(kExprIf); | |
253 current_function_builder_->Emit(kExprI32Ior); | |
254 current_function_builder_->Emit(kExprI32Eq); | |
255 VisitVariableProxy(tag); | 233 VisitVariableProxy(tag); |
256 VisitLiteral(label); | 234 VisitLiteral(label); |
235 current_function_builder_->Emit(kExprI32Eq); | |
257 current_function_builder_->Emit(kExprGetLocal); | 236 current_function_builder_->Emit(kExprGetLocal); |
258 AddLeb128(fall_through, true); | 237 AddLeb128(fall_through, true); |
259 BlockVisitor visitor(this, nullptr, kExprBlock, false, 0); | 238 current_function_builder_->Emit(kExprI32Ior); |
239 current_function_builder_->Emit(kExprIf); | |
240 BlockVisitor visitor(this, nullptr, kExprBlock, false); | |
260 SetLocalTo(fall_through, 1); | 241 SetLocalTo(fall_through, 1); |
261 ZoneList<Statement*>* stmts = clause->statements(); | 242 ZoneList<Statement*>* stmts = clause->statements(); |
262 block_size_ += stmts->length(); | |
263 RECURSE(VisitStatements(stmts)); | 243 RECURSE(VisitStatements(stmts)); |
244 current_function_builder_->Emit(kExprEnd); | |
264 } | 245 } |
265 | 246 |
266 void VisitSwitchStatement(SwitchStatement* stmt) { | 247 void VisitSwitchStatement(SwitchStatement* stmt) { |
267 VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 248 VariableProxy* tag = stmt->tag()->AsVariableProxy(); |
268 DCHECK_NOT_NULL(tag); | 249 DCHECK_NOT_NULL(tag); |
269 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, | 250 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |
270 0); | |
271 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); | 251 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); |
272 SetLocalTo(fall_through, 0); | 252 SetLocalTo(fall_through, 0); |
273 | 253 |
274 ZoneList<CaseClause*>* clauses = stmt->cases(); | 254 ZoneList<CaseClause*>* clauses = stmt->cases(); |
275 for (int i = 0; i < clauses->length(); ++i) { | 255 for (int i = 0; i < clauses->length(); ++i) { |
276 CaseClause* clause = clauses->at(i); | 256 CaseClause* clause = clauses->at(i); |
277 if (!clause->is_default()) { | 257 if (!clause->is_default()) { |
278 CompileCase(clause, fall_through, tag); | 258 CompileCase(clause, fall_through, tag); |
279 } else { | 259 } else { |
280 ZoneList<Statement*>* stmts = clause->statements(); | 260 ZoneList<Statement*>* stmts = clause->statements(); |
281 block_size_ += stmts->length(); | |
282 RECURSE(VisitStatements(stmts)); | 261 RECURSE(VisitStatements(stmts)); |
283 } | 262 } |
284 } | 263 } |
285 } | 264 } |
286 | 265 |
287 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 266 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
288 | 267 |
289 void VisitDoWhileStatement(DoWhileStatement* stmt) { | 268 void VisitDoWhileStatement(DoWhileStatement* stmt) { |
290 DCHECK(in_function_); | 269 DCHECK_EQ(kFuncScope, scope_); |
291 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 270 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
292 2); | |
293 RECURSE(Visit(stmt->body())); | 271 RECURSE(Visit(stmt->body())); |
272 RECURSE(Visit(stmt->cond())); | |
294 current_function_builder_->Emit(kExprIf); | 273 current_function_builder_->Emit(kExprIf); |
295 RECURSE(Visit(stmt->cond())); | 274 current_function_builder_->EmitWithU8(kExprBr, 0); |
296 current_function_builder_->EmitWithVarInt(kExprBr, 0); | 275 current_function_builder_->Emit(kExprEnd); |
297 current_function_builder_->Emit(kExprNop); | |
298 } | 276 } |
299 | 277 |
300 void VisitWhileStatement(WhileStatement* stmt) { | 278 void VisitWhileStatement(WhileStatement* stmt) { |
301 DCHECK(in_function_); | 279 DCHECK_EQ(kFuncScope, scope_); |
302 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 280 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
303 1); | 281 RECURSE(Visit(stmt->cond())); |
304 current_function_builder_->Emit(kExprIf); | 282 current_function_builder_->Emit(kExprIf); |
305 RECURSE(Visit(stmt->cond())); | |
306 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
307 RECURSE(Visit(stmt->body())); | 283 RECURSE(Visit(stmt->body())); |
284 current_function_builder_->EmitWithU8(kExprBr, 0); | |
285 current_function_builder_->Emit(kExprEnd); | |
308 } | 286 } |
309 | 287 |
310 void VisitForStatement(ForStatement* stmt) { | 288 void VisitForStatement(ForStatement* stmt) { |
311 DCHECK(in_function_); | 289 DCHECK_EQ(kFuncScope, scope_); |
312 if (stmt->init() != nullptr) { | 290 if (stmt->init() != nullptr) { |
313 block_size_++; | |
314 RECURSE(Visit(stmt->init())); | 291 RECURSE(Visit(stmt->init())); |
315 } | 292 } |
316 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 293 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
317 0); | |
318 if (stmt->cond() != nullptr) { | 294 if (stmt->cond() != nullptr) { |
319 block_size_++; | 295 RECURSE(Visit(stmt->cond())); |
296 current_function_builder_->Emit(kExprI32Eqz); | |
320 current_function_builder_->Emit(kExprIf); | 297 current_function_builder_->Emit(kExprIf); |
321 current_function_builder_->Emit(kExprI32Eqz); | |
322 RECURSE(Visit(stmt->cond())); | |
323 current_function_builder_->EmitWithVarInt(kExprBr, 1); | |
324 current_function_builder_->Emit(kExprNop); | 298 current_function_builder_->Emit(kExprNop); |
299 current_function_builder_->EmitWithU8(kExprBr, 1); | |
300 current_function_builder_->Emit(kExprEnd); | |
325 } | 301 } |
326 if (stmt->body() != nullptr) { | 302 if (stmt->body() != nullptr) { |
327 block_size_++; | |
328 RECURSE(Visit(stmt->body())); | 303 RECURSE(Visit(stmt->body())); |
329 } | 304 } |
330 if (stmt->next() != nullptr) { | 305 if (stmt->next() != nullptr) { |
331 block_size_++; | |
332 RECURSE(Visit(stmt->next())); | 306 RECURSE(Visit(stmt->next())); |
333 } | 307 } |
334 block_size_++; | |
335 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
336 current_function_builder_->Emit(kExprNop); | 308 current_function_builder_->Emit(kExprNop); |
309 current_function_builder_->EmitWithU8(kExprBr, 0); | |
337 } | 310 } |
338 | 311 |
339 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } | 312 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |
340 | 313 |
341 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } | 314 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } |
342 | 315 |
343 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } | 316 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } |
344 | 317 |
345 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } | 318 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } |
346 | 319 |
347 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } | 320 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } |
348 | 321 |
349 void VisitFunctionLiteral(FunctionLiteral* expr) { | 322 void VisitFunctionLiteral(FunctionLiteral* expr) { |
350 Scope* scope = expr->scope(); | 323 Scope* scope = expr->scope(); |
351 if (in_function_) { | 324 if (scope_ == kFuncScope) { |
352 if (expr->bounds().lower->IsFunction()) { | 325 if (expr->bounds().lower->IsFunction()) { |
353 FunctionType* func_type = expr->bounds().lower->AsFunction(); | 326 FunctionType* func_type = expr->bounds().lower->AsFunction(); |
354 LocalType return_type = TypeFrom(func_type->Result()); | 327 LocalType return_type = TypeFrom(func_type->Result()); |
355 current_function_builder_->ReturnType(return_type); | 328 current_function_builder_->ReturnType(return_type); |
356 for (int i = 0; i < expr->parameter_count(); i++) { | 329 for (int i = 0; i < expr->parameter_count(); i++) { |
357 LocalType type = TypeFrom(func_type->Parameter(i)); | 330 LocalType type = TypeFrom(func_type->Parameter(i)); |
358 DCHECK_NE(kAstStmt, type); | 331 DCHECK_NE(kAstStmt, type); |
359 LookupOrInsertLocal(scope->parameter(i), type); | 332 LookupOrInsertLocal(scope->parameter(i), type); |
360 } | 333 } |
361 } else { | 334 } else { |
362 UNREACHABLE(); | 335 UNREACHABLE(); |
363 } | 336 } |
364 } | 337 } |
365 RECURSE(VisitStatements(expr->body())); | 338 RECURSE(VisitStatements(expr->body())); |
366 RECURSE(VisitDeclarations(scope->declarations())); | 339 RECURSE(VisitDeclarations(scope->declarations())); |
367 } | 340 } |
368 | 341 |
369 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 342 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
370 UNREACHABLE(); | 343 UNREACHABLE(); |
371 } | 344 } |
372 | 345 |
373 void VisitConditional(Conditional* expr) { | 346 void VisitConditional(Conditional* expr) { |
374 DCHECK(in_function_); | 347 DCHECK_EQ(kFuncScope, scope_); |
375 current_function_builder_->Emit(kExprIfElse); | |
376 RECURSE(Visit(expr->condition())); | 348 RECURSE(Visit(expr->condition())); |
349 current_function_builder_->Emit(kExprIf); | |
377 RECURSE(Visit(expr->then_expression())); | 350 RECURSE(Visit(expr->then_expression())); |
351 current_function_builder_->Emit(kExprElse); | |
378 RECURSE(Visit(expr->else_expression())); | 352 RECURSE(Visit(expr->else_expression())); |
353 current_function_builder_->Emit(kExprEnd); | |
379 } | 354 } |
380 | 355 |
381 bool VisitStdlibConstant(Variable* var) { | 356 bool VisitStdlibConstant(Variable* var) { |
382 AsmTyper::StandardMember standard_object = | 357 AsmTyper::StandardMember standard_object = |
383 typer_->VariableAsStandardMember(var); | 358 typer_->VariableAsStandardMember(var); |
384 double value; | 359 double value; |
385 switch (standard_object) { | 360 switch (standard_object) { |
386 case AsmTyper::kInfinity: { | 361 case AsmTyper::kInfinity: { |
387 value = std::numeric_limits<double>::infinity(); | 362 value = std::numeric_limits<double>::infinity(); |
388 break; | 363 break; |
(...skipping 35 matching lines...) Loading... | |
424 break; | 399 break; |
425 } | 400 } |
426 default: { return false; } | 401 default: { return false; } |
427 } | 402 } |
428 byte code[] = {WASM_F64(value)}; | 403 byte code[] = {WASM_F64(value)}; |
429 current_function_builder_->EmitCode(code, sizeof(code)); | 404 current_function_builder_->EmitCode(code, sizeof(code)); |
430 return true; | 405 return true; |
431 } | 406 } |
432 | 407 |
433 void VisitVariableProxy(VariableProxy* expr) { | 408 void VisitVariableProxy(VariableProxy* expr) { |
434 if (in_function_) { | 409 if (scope_ == kFuncScope || scope_ == kInitScope) { |
435 Variable* var = expr->var(); | 410 Variable* var = expr->var(); |
436 if (is_set_op_) { | 411 if (VisitStdlibConstant(var)) { |
437 if (var->IsContextSlot()) { | 412 return; |
438 current_function_builder_->Emit(kExprStoreGlobal); | |
439 } else { | |
440 current_function_builder_->Emit(kExprSetLocal); | |
441 } | |
442 is_set_op_ = false; | |
443 } else { | |
444 if (VisitStdlibConstant(var)) { | |
445 return; | |
446 } | |
447 if (var->IsContextSlot()) { | |
448 current_function_builder_->Emit(kExprLoadGlobal); | |
449 } else { | |
450 current_function_builder_->Emit(kExprGetLocal); | |
451 } | |
452 } | 413 } |
453 LocalType var_type = TypeOf(expr); | 414 LocalType var_type = TypeOf(expr); |
454 DCHECK_NE(kAstStmt, var_type); | 415 DCHECK_NE(kAstStmt, var_type); |
455 if (var->IsContextSlot()) { | 416 if (var->IsContextSlot()) { |
417 current_function_builder_->Emit(kExprLoadGlobal); | |
456 AddLeb128(LookupOrInsertGlobal(var, var_type), false); | 418 AddLeb128(LookupOrInsertGlobal(var, var_type), false); |
457 } else { | 419 } else { |
420 current_function_builder_->Emit(kExprGetLocal); | |
458 AddLeb128(LookupOrInsertLocal(var, var_type), true); | 421 AddLeb128(LookupOrInsertLocal(var, var_type), true); |
459 } | 422 } |
460 } | 423 } |
461 } | 424 } |
462 | 425 |
463 void VisitLiteral(Literal* expr) { | 426 void VisitLiteral(Literal* expr) { |
464 if (in_function_) { | 427 if (scope_ == kFuncScope || scope_ == kInitScope) { |
465 if (expr->raw_value()->IsNumber()) { | 428 if (expr->raw_value()->IsNumber()) { |
466 LocalType type = TypeOf(expr); | 429 LocalType type = TypeOf(expr); |
467 switch (type) { | 430 switch (type) { |
468 case kAstI32: { | 431 case kAstI32: { |
469 int val = static_cast<int>(expr->raw_value()->AsNumber()); | 432 int32_t val = static_cast<int32_t>(expr->raw_value()->AsNumber()); |
470 // TODO(bradnelson): variable size | 433 current_function_builder_->EmitI32Const(val); |
471 byte code[] = {WASM_I32V(val)}; | |
472 current_function_builder_->EmitCode(code, sizeof(code)); | |
473 break; | 434 break; |
474 } | 435 } |
475 case kAstF32: { | 436 case kAstF32: { |
476 float val = static_cast<float>(expr->raw_value()->AsNumber()); | 437 float val = static_cast<float>(expr->raw_value()->AsNumber()); |
477 byte code[] = {WASM_F32(val)}; | 438 byte code[] = {WASM_F32(val)}; |
478 current_function_builder_->EmitCode(code, sizeof(code)); | 439 current_function_builder_->EmitCode(code, sizeof(code)); |
479 break; | 440 break; |
480 } | 441 } |
481 case kAstF64: { | 442 case kAstF64: { |
482 double val = static_cast<double>(expr->raw_value()->AsNumber()); | 443 double val = static_cast<double>(expr->raw_value()->AsNumber()); |
483 byte code[] = {WASM_F64(val)}; | 444 byte code[] = {WASM_F64(val)}; |
484 current_function_builder_->EmitCode(code, sizeof(code)); | 445 current_function_builder_->EmitCode(code, sizeof(code)); |
485 break; | 446 break; |
486 } | 447 } |
487 default: | 448 default: |
488 UNREACHABLE(); | 449 UNREACHABLE(); |
489 } | 450 } |
490 } | 451 } |
491 } | 452 } |
492 } | 453 } |
493 | 454 |
494 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } | 455 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
495 | 456 |
496 void VisitObjectLiteral(ObjectLiteral* expr) { | 457 void VisitObjectLiteral(ObjectLiteral* expr) { |
497 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 458 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
498 for (int i = 0; i < props->length(); ++i) { | 459 for (int i = 0; i < props->length(); ++i) { |
499 ObjectLiteralProperty* prop = props->at(i); | 460 ObjectLiteralProperty* prop = props->at(i); |
500 DCHECK(marking_exported); | 461 DCHECK_EQ(kExportScope, scope_); |
501 VariableProxy* expr = prop->value()->AsVariableProxy(); | 462 VariableProxy* expr = prop->value()->AsVariableProxy(); |
502 DCHECK_NOT_NULL(expr); | 463 DCHECK_NOT_NULL(expr); |
503 Variable* var = expr->var(); | 464 Variable* var = expr->var(); |
504 Literal* name = prop->key()->AsLiteral(); | 465 Literal* name = prop->key()->AsLiteral(); |
505 DCHECK_NOT_NULL(name); | 466 DCHECK_NOT_NULL(name); |
506 DCHECK(name->IsPropertyName()); | 467 DCHECK(name->IsPropertyName()); |
507 const AstRawString* raw_name = name->AsRawPropertyName(); | 468 const AstRawString* raw_name = name->AsRawPropertyName(); |
508 if (var->is_function()) { | 469 if (var->is_function()) { |
509 uint16_t index = LookupOrInsertFunction(var); | 470 uint16_t index = LookupOrInsertFunction(var); |
510 builder_->FunctionAt(index)->Exported(1); | 471 builder_->FunctionAt(index)->Exported(1); |
511 builder_->FunctionAt(index) | 472 builder_->FunctionAt(index) |
512 ->SetName(raw_name->raw_data(), raw_name->length()); | 473 ->SetName(raw_name->raw_data(), raw_name->length()); |
513 } | 474 } |
514 } | 475 } |
515 } | 476 } |
516 | 477 |
517 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 478 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
518 | 479 |
519 void LoadInitFunction() { | 480 void LoadInitFunction() { |
520 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 481 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
521 in_function_ = true; | 482 scope_ = kInitScope; |
522 } | 483 } |
523 | 484 |
524 void UnLoadInitFunction() { | 485 void UnLoadInitFunction() { |
525 in_function_ = false; | 486 scope_ = kModuleScope; |
526 current_function_builder_ = nullptr; | 487 current_function_builder_ = nullptr; |
527 } | 488 } |
528 | 489 |
529 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 490 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
530 FunctionType* func_type = | 491 FunctionType* func_type = |
531 funcs->bounds().lower->AsArray()->Element()->AsFunction(); | 492 funcs->bounds().lower->AsArray()->Element()->AsFunction(); |
532 LocalType return_type = TypeFrom(func_type->Result()); | 493 LocalType return_type = TypeFrom(func_type->Result()); |
533 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 494 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
534 func_type->Arity()); | 495 func_type->Arity()); |
535 if (return_type != kAstStmt) { | 496 if (return_type != kAstStmt) { |
(...skipping 82 matching lines...) Loading... | |
618 function->ReturnType(sig->GetReturn()); | 579 function->ReturnType(sig->GetReturn()); |
619 } | 580 } |
620 for (size_t i = 0; i < sig->parameter_count(); i++) { | 581 for (size_t i = 0; i < sig->parameter_count(); i++) { |
621 function->AddParam(sig->GetParam(i)); | 582 function->AddParam(sig->GetParam(i)); |
622 } | 583 } |
623 return index; | 584 return index; |
624 } | 585 } |
625 } | 586 } |
626 }; | 587 }; |
627 | 588 |
628 void VisitAssignment(Assignment* expr) { | 589 void EmitAssignmentLhs(Expression* target, MachineType* mtype) { |
629 bool in_init = false; | 590 // Match the left hand side of the assignment. |
630 if (!in_function_) { | 591 VariableProxy* target_var = target->AsVariableProxy(); |
631 BinaryOperation* binop = expr->value()->AsBinaryOperation(); | 592 if (target_var != nullptr) { |
632 if (binop != nullptr) { | 593 // Left hand side is a local or a global variable, no code on LHS. |
594 return; | |
595 } | |
596 | |
597 Property* target_prop = target->AsProperty(); | |
598 if (target_prop != nullptr) { | |
599 // Left hand side is a property access, i.e. the asm.js heap. | |
600 VisitPropertyAndEmitIndex(target_prop, mtype); | |
601 return; | |
602 } | |
603 | |
604 if (target_var == nullptr && target_prop == nullptr) { | |
bradnelson
2016/03/23 19:14:25
You return above, why guard this, as you return in
titzer
2016/03/23 19:53:05
Because paranoia :-)
bradn
2016/03/23 19:58:50
Seems like leaving the UNREACHABLE unguarded would
| |
605 UNREACHABLE(); // invalid assignment. | |
606 } | |
607 } | |
608 | |
609 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { | |
610 BinaryOperation* binop = value->AsBinaryOperation(); | |
611 if (binop != nullptr) { | |
612 if (scope_ == kInitScope) { | |
613 // Handle foreign variables in the initialization scope. | |
633 Property* prop = binop->left()->AsProperty(); | 614 Property* prop = binop->left()->AsProperty(); |
634 DCHECK_NOT_NULL(prop); | |
635 LoadInitFunction(); | |
636 is_set_op_ = true; | |
637 RECURSE(Visit(expr->target())); | |
638 DCHECK(!is_set_op_); | |
639 if (binop->op() == Token::MUL) { | 615 if (binop->op() == Token::MUL) { |
640 DCHECK(binop->right()->IsLiteral()); | 616 DCHECK(binop->right()->IsLiteral()); |
641 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 617 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
642 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 618 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
643 VisitForeignVariable(true, prop); | 619 VisitForeignVariable(true, prop); |
620 return; | |
644 } else if (binop->op() == Token::BIT_OR) { | 621 } else if (binop->op() == Token::BIT_OR) { |
645 DCHECK(binop->right()->IsLiteral()); | 622 DCHECK(binop->right()->IsLiteral()); |
646 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 623 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
647 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 624 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
648 VisitForeignVariable(false, prop); | 625 VisitForeignVariable(false, prop); |
626 return; | |
649 } else { | 627 } else { |
650 UNREACHABLE(); | 628 UNREACHABLE(); |
651 } | 629 } |
652 UnLoadInitFunction(); | |
653 return; | |
654 } | 630 } |
631 if (MatchBinaryOperation(binop) == kAsIs) { | |
632 VariableProxy* target_var = target->AsVariableProxy(); | |
633 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); | |
634 if (target_var != nullptr && effective_value_var != nullptr && | |
635 target_var->var() == effective_value_var->var()) { | |
636 *is_nop = true; | |
637 return; | |
638 } | |
639 } | |
640 } | |
641 RECURSE(Visit(value)); | |
642 } | |
643 | |
644 void EmitAssignment(Assignment* expr, MachineType mtype) { | |
645 // Match the left hand side of the assignment. | |
646 VariableProxy* target_var = expr->target()->AsVariableProxy(); | |
647 if (target_var != nullptr) { | |
648 // Left hand side is a local or a global variable. | |
649 Variable* var = target_var->var(); | |
650 LocalType var_type = TypeOf(expr); | |
651 DCHECK_NE(kAstStmt, var_type); | |
652 if (var->IsContextSlot()) { | |
653 current_function_builder_->Emit(kExprStoreGlobal); | |
654 AddLeb128(LookupOrInsertGlobal(var, var_type), false); | |
655 } else { | |
656 current_function_builder_->Emit(kExprSetLocal); | |
657 AddLeb128(LookupOrInsertLocal(var, var_type), true); | |
658 } | |
659 } | |
660 | |
661 Property* target_prop = expr->target()->AsProperty(); | |
662 if (target_prop != nullptr) { | |
663 // Left hand side is a property access, i.e. the asm.js heap. | |
664 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
665 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
666 cache_.kFloat32Array)) { | |
667 current_function_builder_->Emit(kExprF32ConvertF64); | |
668 } | |
669 current_function_builder_->EmitWithU8U8( | |
670 WasmOpcodes::LoadStoreOpcodeOf(mtype, true), 0, 0); | |
671 } | |
672 | |
673 if (target_var == nullptr && target_prop == nullptr) { | |
bradnelson
2016/03/23 19:14:25
Add returns instead of guard here?
titzer
2016/03/23 19:53:05
Don't want to silently forget to generate code.
| |
674 UNREACHABLE(); // invalid assignment. | |
675 } | |
676 } | |
677 | |
678 void VisitAssignment(Assignment* expr) { | |
679 bool as_init = false; | |
680 if (scope_ == kModuleScope) { | |
655 Property* prop = expr->value()->AsProperty(); | 681 Property* prop = expr->value()->AsProperty(); |
656 if (prop != nullptr) { | 682 if (prop != nullptr) { |
657 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 683 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
658 if (vp != nullptr && vp->var()->IsParameter() && | 684 if (vp != nullptr && vp->var()->IsParameter() && |
659 vp->var()->index() == 1) { | 685 vp->var()->index() == 1) { |
660 VariableProxy* target = expr->target()->AsVariableProxy(); | 686 VariableProxy* target = expr->target()->AsVariableProxy(); |
661 if (target->bounds().lower->Is(Type::Function())) { | 687 if (target->bounds().lower->Is(Type::Function())) { |
662 const AstRawString* name = | 688 const AstRawString* name = |
663 prop->key()->AsLiteral()->AsRawPropertyName(); | 689 prop->key()->AsLiteral()->AsRawPropertyName(); |
664 imported_function_table_.AddImport(target->var(), name->raw_data(), | 690 imported_function_table_.AddImport(target->var(), name->raw_data(), |
665 name->length()); | 691 name->length()); |
666 } | 692 } |
667 } | 693 } |
668 // Property values in module scope don't emit code, so return. | 694 // Property values in module scope don't emit code, so return. |
669 return; | 695 return; |
670 } | 696 } |
671 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 697 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
672 if (funcs != nullptr && | 698 if (funcs != nullptr && |
673 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 699 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
674 VariableProxy* target = expr->target()->AsVariableProxy(); | 700 VariableProxy* target = expr->target()->AsVariableProxy(); |
675 DCHECK_NOT_NULL(target); | 701 DCHECK_NOT_NULL(target); |
676 AddFunctionTable(target, funcs); | 702 AddFunctionTable(target, funcs); |
677 // Only add to the function table. No init needed. | 703 // Only add to the function table. No init needed. |
678 return; | 704 return; |
679 } | 705 } |
680 if (expr->value()->IsCallNew()) { | 706 if (expr->value()->IsCallNew()) { |
681 // No init code to emit for CallNew nodes. | 707 // No init code to emit for CallNew nodes. |
682 return; | 708 return; |
683 } | 709 } |
684 in_init = true; | 710 as_init = true; |
685 LoadInitFunction(); | |
686 } | 711 } |
687 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 712 |
688 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 713 if (as_init) LoadInitFunction(); |
689 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 714 MachineType mtype; |
690 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 715 bool is_nop = false; |
691 if (target_var != nullptr && effective_value_var != nullptr && | 716 EmitAssignmentLhs(expr->target(), &mtype); |
692 target_var->var() == effective_value_var->var()) { | 717 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
693 block_size_--; | 718 if (!is_nop) { |
694 return; | 719 EmitAssignment(expr, mtype); |
695 } | |
696 } | 720 } |
697 is_set_op_ = true; | 721 if (as_init) UnLoadInitFunction(); |
698 RECURSE(Visit(expr->target())); | |
699 DCHECK(!is_set_op_); | |
700 // Assignment to heapf32 from float64 converts. | |
701 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
702 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
703 cache_.kFloat32Array)) { | |
704 current_function_builder_->Emit(kExprF32ConvertF64); | |
705 } | |
706 RECURSE(Visit(expr->value())); | |
707 if (in_init) { | |
708 UnLoadInitFunction(); | |
709 } | |
710 } | 722 } |
711 | 723 |
712 void VisitYield(Yield* expr) { UNREACHABLE(); } | 724 void VisitYield(Yield* expr) { UNREACHABLE(); } |
713 | 725 |
714 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 726 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
715 | 727 |
716 void VisitForeignVariable(bool is_float, Property* expr) { | 728 void VisitForeignVariable(bool is_float, Property* expr) { |
717 DCHECK(expr->obj()->AsVariableProxy()); | 729 DCHECK(expr->obj()->AsVariableProxy()); |
718 DCHECK(VariableLocation::PARAMETER == | 730 DCHECK(VariableLocation::PARAMETER == |
719 expr->obj()->AsVariableProxy()->var()->location()); | 731 expr->obj()->AsVariableProxy()->var()->location()); |
(...skipping 18 matching lines...) Loading... | |
738 return; | 750 return; |
739 } | 751 } |
740 } | 752 } |
741 } else { | 753 } else { |
742 MaybeHandle<Object> maybe_nvalue = | 754 MaybeHandle<Object> maybe_nvalue = |
743 i::Object::ToInt32(isolate_, value); | 755 i::Object::ToInt32(isolate_, value); |
744 if (!maybe_nvalue.is_null()) { | 756 if (!maybe_nvalue.is_null()) { |
745 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | 757 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
746 if (nvalue->IsNumber()) { | 758 if (nvalue->IsNumber()) { |
747 int32_t val = static_cast<int32_t>(nvalue->Number()); | 759 int32_t val = static_cast<int32_t>(nvalue->Number()); |
748 // TODO(bradnelson): variable size | 760 current_function_builder_->EmitI32Const(val); |
749 byte code[] = {WASM_I32V(val)}; | |
750 current_function_builder_->EmitCode(code, sizeof(code)); | |
751 return; | 761 return; |
752 } | 762 } |
753 } | 763 } |
754 } | 764 } |
755 } | 765 } |
756 } | 766 } |
757 if (is_float) { | 767 if (is_float) { |
758 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; | 768 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; |
759 current_function_builder_->EmitCode(code, sizeof(code)); | 769 current_function_builder_->EmitCode(code, sizeof(code)); |
760 } else { | 770 } else { |
761 byte code[] = {WASM_I32V_1(0)}; | 771 byte code[] = {WASM_I32V_1(0)}; |
762 current_function_builder_->EmitCode(code, sizeof(code)); | 772 current_function_builder_->EmitCode(code, sizeof(code)); |
763 } | 773 } |
764 } | 774 } |
765 | 775 |
766 void VisitProperty(Property* expr) { | 776 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
767 Expression* obj = expr->obj(); | 777 Expression* obj = expr->obj(); |
768 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); | 778 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); |
769 Type* type = obj->bounds().lower; | 779 Type* type = obj->bounds().lower; |
770 MachineType mtype; | |
771 int size; | 780 int size; |
772 if (type->Is(cache_.kUint8Array)) { | 781 if (type->Is(cache_.kUint8Array)) { |
773 mtype = MachineType::Uint8(); | 782 *mtype = MachineType::Uint8(); |
774 size = 1; | 783 size = 1; |
775 } else if (type->Is(cache_.kInt8Array)) { | 784 } else if (type->Is(cache_.kInt8Array)) { |
776 mtype = MachineType::Int8(); | 785 *mtype = MachineType::Int8(); |
777 size = 1; | 786 size = 1; |
778 } else if (type->Is(cache_.kUint16Array)) { | 787 } else if (type->Is(cache_.kUint16Array)) { |
779 mtype = MachineType::Uint16(); | 788 *mtype = MachineType::Uint16(); |
780 size = 2; | 789 size = 2; |
781 } else if (type->Is(cache_.kInt16Array)) { | 790 } else if (type->Is(cache_.kInt16Array)) { |
782 mtype = MachineType::Int16(); | 791 *mtype = MachineType::Int16(); |
783 size = 2; | 792 size = 2; |
784 } else if (type->Is(cache_.kUint32Array)) { | 793 } else if (type->Is(cache_.kUint32Array)) { |
785 mtype = MachineType::Uint32(); | 794 *mtype = MachineType::Uint32(); |
786 size = 4; | 795 size = 4; |
787 } else if (type->Is(cache_.kInt32Array)) { | 796 } else if (type->Is(cache_.kInt32Array)) { |
788 mtype = MachineType::Int32(); | 797 *mtype = MachineType::Int32(); |
789 size = 4; | 798 size = 4; |
790 } else if (type->Is(cache_.kUint32Array)) { | 799 } else if (type->Is(cache_.kUint32Array)) { |
791 mtype = MachineType::Uint32(); | 800 *mtype = MachineType::Uint32(); |
792 size = 4; | 801 size = 4; |
793 } else if (type->Is(cache_.kFloat32Array)) { | 802 } else if (type->Is(cache_.kFloat32Array)) { |
794 mtype = MachineType::Float32(); | 803 *mtype = MachineType::Float32(); |
795 size = 4; | 804 size = 4; |
796 } else if (type->Is(cache_.kFloat64Array)) { | 805 } else if (type->Is(cache_.kFloat64Array)) { |
797 mtype = MachineType::Float64(); | 806 *mtype = MachineType::Float64(); |
798 size = 8; | 807 size = 8; |
799 } else { | 808 } else { |
800 UNREACHABLE(); | 809 UNREACHABLE(); |
801 } | 810 } |
802 // TODO(titzer): use special asm-compatibility opcodes? | |
803 current_function_builder_->EmitWithU8U8( | |
804 WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_), 0, 0); | |
805 is_set_op_ = false; | |
806 if (size == 1) { | 811 if (size == 1) { |
807 // Allow more general expression in byte arrays than the spec | 812 // Allow more general expression in byte arrays than the spec |
808 // strictly permits. | 813 // strictly permits. |
809 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 814 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
810 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 815 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
811 RECURSE(Visit(expr->key())); | 816 RECURSE(Visit(expr->key())); |
812 return; | 817 return; |
813 } else { | 818 } |
814 Literal* value = expr->key()->AsLiteral(); | 819 |
815 if (value) { | 820 Literal* value = expr->key()->AsLiteral(); |
816 DCHECK(value->raw_value()->IsNumber()); | 821 if (value) { |
817 DCHECK_EQ(kAstI32, TypeOf(value)); | 822 DCHECK(value->raw_value()->IsNumber()); |
818 int val = static_cast<int>(value->raw_value()->AsNumber()); | 823 DCHECK_EQ(kAstI32, TypeOf(value)); |
819 // TODO(bradnelson): variable size | 824 int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber()); |
820 byte code[] = {WASM_I32V(val * size)}; | 825 // TODO(titzer): handle overflow here. |
bradnelson
2016/03/23 19:14:25
Spec allows 0 - 2^32 -1 here. What did you mean?
titzer
2016/03/23 19:53:05
Right. If it is 2^31, e.g., and then we multiply b
bradn
2016/03/23 19:58:50
Ah, yes.
| |
821 current_function_builder_->EmitCode(code, sizeof(code)); | 826 current_function_builder_->EmitI32Const(val * size); |
822 return; | 827 return; |
823 } | 828 } |
824 BinaryOperation* binop = expr->key()->AsBinaryOperation(); | 829 BinaryOperation* binop = expr->key()->AsBinaryOperation(); |
825 if (binop) { | 830 if (binop) { |
826 DCHECK_EQ(Token::SAR, binop->op()); | 831 DCHECK_EQ(Token::SAR, binop->op()); |
827 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); | 832 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); |
828 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); | 833 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); |
829 DCHECK_EQ(size, | 834 DCHECK_EQ(size, |
830 1 << static_cast<int>( | 835 1 << static_cast<int>( |
831 binop->right()->AsLiteral()->raw_value()->AsNumber())); | 836 binop->right()->AsLiteral()->raw_value()->AsNumber())); |
832 // Mask bottom bits to match asm.js behavior. | 837 // Mask bottom bits to match asm.js behavior. |
833 current_function_builder_->Emit(kExprI32And); | 838 byte mask = static_cast<byte>(~(size - 1)); |
834 byte code[] = {WASM_I8(~(size - 1))}; | 839 RECURSE(Visit(binop->left())); |
835 current_function_builder_->EmitCode(code, sizeof(code)); | 840 current_function_builder_->EmitWithU8(kExprI8Const, mask); |
836 RECURSE(Visit(binop->left())); | 841 current_function_builder_->Emit(kExprI32And); |
837 return; | 842 return; |
838 } | |
839 } | 843 } |
840 UNREACHABLE(); | 844 UNREACHABLE(); |
841 } | 845 } |
842 | 846 |
847 void VisitProperty(Property* expr) { | |
848 MachineType mtype; | |
849 VisitPropertyAndEmitIndex(expr, &mtype); | |
850 current_function_builder_->EmitWithU8U8( | |
851 WasmOpcodes::LoadStoreOpcodeOf(mtype, false), 0, 0); | |
852 } | |
853 | |
843 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { | 854 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
844 Variable* var = expr->var(); | 855 Variable* var = expr->var(); |
845 AsmTyper::StandardMember standard_object = | 856 AsmTyper::StandardMember standard_object = |
846 typer_->VariableAsStandardMember(var); | 857 typer_->VariableAsStandardMember(var); |
847 ZoneList<Expression*>* args = call->arguments(); | 858 ZoneList<Expression*>* args = call->arguments(); |
848 LocalType call_type = TypeOf(call); | 859 LocalType call_type = TypeOf(call); |
860 | |
849 switch (standard_object) { | 861 switch (standard_object) { |
850 case AsmTyper::kNone: { | 862 case AsmTyper::kNone: { |
851 return false; | 863 return false; |
852 } | 864 } |
853 case AsmTyper::kMathAcos: { | 865 case AsmTyper::kMathAcos: { |
866 VisitCallArgs(call); | |
854 DCHECK_EQ(kAstF64, call_type); | 867 DCHECK_EQ(kAstF64, call_type); |
855 current_function_builder_->Emit(kExprF64Acos); | 868 current_function_builder_->Emit(kExprF64Acos); |
856 break; | 869 break; |
857 } | 870 } |
858 case AsmTyper::kMathAsin: { | 871 case AsmTyper::kMathAsin: { |
872 VisitCallArgs(call); | |
859 DCHECK_EQ(kAstF64, call_type); | 873 DCHECK_EQ(kAstF64, call_type); |
860 current_function_builder_->Emit(kExprF64Asin); | 874 current_function_builder_->Emit(kExprF64Asin); |
861 break; | 875 break; |
862 } | 876 } |
863 case AsmTyper::kMathAtan: { | 877 case AsmTyper::kMathAtan: { |
878 VisitCallArgs(call); | |
864 DCHECK_EQ(kAstF64, call_type); | 879 DCHECK_EQ(kAstF64, call_type); |
865 current_function_builder_->Emit(kExprF64Atan); | 880 current_function_builder_->Emit(kExprF64Atan); |
866 break; | 881 break; |
867 } | 882 } |
868 case AsmTyper::kMathCos: { | 883 case AsmTyper::kMathCos: { |
884 VisitCallArgs(call); | |
869 DCHECK_EQ(kAstF64, call_type); | 885 DCHECK_EQ(kAstF64, call_type); |
870 current_function_builder_->Emit(kExprF64Cos); | 886 current_function_builder_->Emit(kExprF64Cos); |
871 break; | 887 break; |
872 } | 888 } |
873 case AsmTyper::kMathSin: { | 889 case AsmTyper::kMathSin: { |
890 VisitCallArgs(call); | |
874 DCHECK_EQ(kAstF64, call_type); | 891 DCHECK_EQ(kAstF64, call_type); |
875 current_function_builder_->Emit(kExprF64Sin); | 892 current_function_builder_->Emit(kExprF64Sin); |
876 break; | 893 break; |
877 } | 894 } |
878 case AsmTyper::kMathTan: { | 895 case AsmTyper::kMathTan: { |
896 VisitCallArgs(call); | |
879 DCHECK_EQ(kAstF64, call_type); | 897 DCHECK_EQ(kAstF64, call_type); |
880 current_function_builder_->Emit(kExprF64Tan); | 898 current_function_builder_->Emit(kExprF64Tan); |
881 break; | 899 break; |
882 } | 900 } |
883 case AsmTyper::kMathExp: { | 901 case AsmTyper::kMathExp: { |
902 VisitCallArgs(call); | |
884 DCHECK_EQ(kAstF64, call_type); | 903 DCHECK_EQ(kAstF64, call_type); |
885 current_function_builder_->Emit(kExprF64Exp); | 904 current_function_builder_->Emit(kExprF64Exp); |
886 break; | 905 break; |
887 } | 906 } |
888 case AsmTyper::kMathLog: { | 907 case AsmTyper::kMathLog: { |
908 VisitCallArgs(call); | |
889 DCHECK_EQ(kAstF64, call_type); | 909 DCHECK_EQ(kAstF64, call_type); |
890 current_function_builder_->Emit(kExprF64Log); | 910 current_function_builder_->Emit(kExprF64Log); |
891 break; | 911 break; |
892 } | 912 } |
893 case AsmTyper::kMathCeil: { | 913 case AsmTyper::kMathCeil: { |
914 VisitCallArgs(call); | |
894 if (call_type == kAstF32) { | 915 if (call_type == kAstF32) { |
895 current_function_builder_->Emit(kExprF32Ceil); | 916 current_function_builder_->Emit(kExprF32Ceil); |
896 } else if (call_type == kAstF64) { | 917 } else if (call_type == kAstF64) { |
897 current_function_builder_->Emit(kExprF64Ceil); | 918 current_function_builder_->Emit(kExprF64Ceil); |
898 } else { | 919 } else { |
899 UNREACHABLE(); | 920 UNREACHABLE(); |
900 } | 921 } |
901 break; | 922 break; |
902 } | 923 } |
903 case AsmTyper::kMathFloor: { | 924 case AsmTyper::kMathFloor: { |
925 VisitCallArgs(call); | |
904 if (call_type == kAstF32) { | 926 if (call_type == kAstF32) { |
905 current_function_builder_->Emit(kExprF32Floor); | 927 current_function_builder_->Emit(kExprF32Floor); |
906 } else if (call_type == kAstF64) { | 928 } else if (call_type == kAstF64) { |
907 current_function_builder_->Emit(kExprF64Floor); | 929 current_function_builder_->Emit(kExprF64Floor); |
908 } else { | 930 } else { |
909 UNREACHABLE(); | 931 UNREACHABLE(); |
910 } | 932 } |
911 break; | 933 break; |
912 } | 934 } |
913 case AsmTyper::kMathSqrt: { | 935 case AsmTyper::kMathSqrt: { |
936 VisitCallArgs(call); | |
914 if (call_type == kAstF32) { | 937 if (call_type == kAstF32) { |
915 current_function_builder_->Emit(kExprF32Sqrt); | 938 current_function_builder_->Emit(kExprF32Sqrt); |
916 } else if (call_type == kAstF64) { | 939 } else if (call_type == kAstF64) { |
917 current_function_builder_->Emit(kExprF64Sqrt); | 940 current_function_builder_->Emit(kExprF64Sqrt); |
918 } else { | 941 } else { |
919 UNREACHABLE(); | 942 UNREACHABLE(); |
920 } | 943 } |
921 break; | 944 break; |
922 } | 945 } |
923 case AsmTyper::kMathAbs: { | 946 case AsmTyper::kMathAbs: { |
924 // TODO(bradnelson): Should this be cast to float? | |
925 if (call_type == kAstI32) { | 947 if (call_type == kAstI32) { |
926 current_function_builder_->Emit(kExprIfElse); | 948 uint16_t tmp = current_function_builder_->AddLocal(kAstI32); |
927 current_function_builder_->Emit(kExprI32LtS); | 949 |
928 Visit(args->at(0)); | 950 // if set_local(tmp, x) < 0 |
951 Visit(call->arguments()->at(0)); | |
952 current_function_builder_->Emit(kExprSetLocal); | |
953 AddLeb128(tmp, true); | |
929 byte code[] = {WASM_I8(0)}; | 954 byte code[] = {WASM_I8(0)}; |
930 current_function_builder_->EmitCode(code, sizeof(code)); | 955 current_function_builder_->EmitCode(code, sizeof(code)); |
956 current_function_builder_->Emit(kExprI32LtS); | |
957 current_function_builder_->Emit(kExprIf); | |
958 | |
959 // then (0 - tmp) | |
960 current_function_builder_->EmitCode(code, sizeof(code)); | |
961 current_function_builder_->Emit(kExprGetLocal); | |
962 AddLeb128(tmp, true); | |
931 current_function_builder_->Emit(kExprI32Sub); | 963 current_function_builder_->Emit(kExprI32Sub); |
932 current_function_builder_->EmitCode(code, sizeof(code)); | 964 |
933 Visit(args->at(0)); | 965 // else tmp |
966 current_function_builder_->Emit(kExprElse); | |
967 current_function_builder_->Emit(kExprGetLocal); | |
968 AddLeb128(tmp, true); | |
969 // end | |
970 current_function_builder_->Emit(kExprEnd); | |
971 | |
934 } else if (call_type == kAstF32) { | 972 } else if (call_type == kAstF32) { |
973 VisitCallArgs(call); | |
935 current_function_builder_->Emit(kExprF32Abs); | 974 current_function_builder_->Emit(kExprF32Abs); |
936 } else if (call_type == kAstF64) { | 975 } else if (call_type == kAstF64) { |
976 VisitCallArgs(call); | |
937 current_function_builder_->Emit(kExprF64Abs); | 977 current_function_builder_->Emit(kExprF64Abs); |
938 } else { | 978 } else { |
939 UNREACHABLE(); | 979 UNREACHABLE(); |
940 } | 980 } |
941 break; | 981 break; |
942 } | 982 } |
943 case AsmTyper::kMathMin: { | 983 case AsmTyper::kMathMin: { |
944 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. | 984 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |
945 if (call_type == kAstI32) { | 985 if (call_type == kAstI32) { |
946 current_function_builder_->Emit(kExprIfElse); | 986 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
987 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); | |
bradnelson
2016/03/23 19:14:25
Did we want to turn these into asm specific opcode
titzer
2016/03/23 19:53:05
It's probably about the same amount of work either
bradn
2016/03/23 19:58:50
K, although I still want to understand why tf call
| |
988 | |
989 // if set_local(tmp_x, x) < set_local(tmp_y, y) | |
990 Visit(call->arguments()->at(0)); | |
991 current_function_builder_->Emit(kExprSetLocal); | |
992 AddLeb128(tmp_x, true); | |
993 | |
994 Visit(call->arguments()->at(1)); | |
995 current_function_builder_->Emit(kExprSetLocal); | |
996 AddLeb128(tmp_y, true); | |
997 | |
947 current_function_builder_->Emit(kExprI32LeS); | 998 current_function_builder_->Emit(kExprI32LeS); |
948 Visit(args->at(0)); | 999 current_function_builder_->Emit(kExprIf); |
949 Visit(args->at(1)); | 1000 |
1001 // then tmp_x | |
1002 current_function_builder_->Emit(kExprGetLocal); | |
1003 AddLeb128(tmp_x, true); | |
1004 | |
1005 // else tmp_y | |
1006 current_function_builder_->Emit(kExprElse); | |
1007 current_function_builder_->Emit(kExprGetLocal); | |
1008 AddLeb128(tmp_y, true); | |
1009 current_function_builder_->Emit(kExprEnd); | |
1010 | |
950 } else if (call_type == kAstF32) { | 1011 } else if (call_type == kAstF32) { |
1012 VisitCallArgs(call); | |
951 current_function_builder_->Emit(kExprF32Min); | 1013 current_function_builder_->Emit(kExprF32Min); |
952 } else if (call_type == kAstF64) { | 1014 } else if (call_type == kAstF64) { |
1015 VisitCallArgs(call); | |
953 current_function_builder_->Emit(kExprF64Min); | 1016 current_function_builder_->Emit(kExprF64Min); |
954 } else { | 1017 } else { |
955 UNREACHABLE(); | 1018 UNREACHABLE(); |
956 } | 1019 } |
957 break; | 1020 break; |
958 } | 1021 } |
959 case AsmTyper::kMathMax: { | 1022 case AsmTyper::kMathMax: { |
960 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. | 1023 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |
961 if (call_type == kAstI32) { | 1024 if (call_type == kAstI32) { |
962 current_function_builder_->Emit(kExprIfElse); | 1025 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
963 current_function_builder_->Emit(kExprI32GtS); | 1026 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
964 Visit(args->at(0)); | 1027 |
965 Visit(args->at(1)); | 1028 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
1029 Visit(call->arguments()->at(0)); | |
1030 current_function_builder_->Emit(kExprSetLocal); | |
1031 AddLeb128(tmp_x, true); | |
1032 | |
1033 Visit(call->arguments()->at(1)); | |
1034 current_function_builder_->Emit(kExprSetLocal); | |
1035 AddLeb128(tmp_y, true); | |
1036 | |
1037 current_function_builder_->Emit(kExprI32LeS); | |
1038 current_function_builder_->Emit(kExprIf); | |
1039 | |
1040 // then tmp_y | |
1041 current_function_builder_->Emit(kExprGetLocal); | |
1042 AddLeb128(tmp_y, true); | |
1043 | |
1044 // else tmp_x | |
1045 current_function_builder_->Emit(kExprElse); | |
1046 current_function_builder_->Emit(kExprGetLocal); | |
1047 AddLeb128(tmp_x, true); | |
1048 current_function_builder_->Emit(kExprEnd); | |
1049 | |
966 } else if (call_type == kAstF32) { | 1050 } else if (call_type == kAstF32) { |
1051 VisitCallArgs(call); | |
967 current_function_builder_->Emit(kExprF32Max); | 1052 current_function_builder_->Emit(kExprF32Max); |
968 } else if (call_type == kAstF64) { | 1053 } else if (call_type == kAstF64) { |
1054 VisitCallArgs(call); | |
969 current_function_builder_->Emit(kExprF64Max); | 1055 current_function_builder_->Emit(kExprF64Max); |
970 } else { | 1056 } else { |
971 UNREACHABLE(); | 1057 UNREACHABLE(); |
972 } | 1058 } |
973 break; | 1059 break; |
974 } | 1060 } |
975 case AsmTyper::kMathAtan2: { | 1061 case AsmTyper::kMathAtan2: { |
1062 VisitCallArgs(call); | |
976 DCHECK_EQ(kAstF64, call_type); | 1063 DCHECK_EQ(kAstF64, call_type); |
977 current_function_builder_->Emit(kExprF64Atan2); | 1064 current_function_builder_->Emit(kExprF64Atan2); |
978 break; | 1065 break; |
979 } | 1066 } |
980 case AsmTyper::kMathPow: { | 1067 case AsmTyper::kMathPow: { |
1068 VisitCallArgs(call); | |
981 DCHECK_EQ(kAstF64, call_type); | 1069 DCHECK_EQ(kAstF64, call_type); |
982 current_function_builder_->Emit(kExprF64Pow); | 1070 current_function_builder_->Emit(kExprF64Pow); |
983 break; | 1071 break; |
984 } | 1072 } |
985 case AsmTyper::kMathImul: { | 1073 case AsmTyper::kMathImul: { |
1074 VisitCallArgs(call); | |
986 current_function_builder_->Emit(kExprI32Mul); | 1075 current_function_builder_->Emit(kExprI32Mul); |
987 break; | 1076 break; |
988 } | 1077 } |
989 case AsmTyper::kMathFround: { | 1078 case AsmTyper::kMathFround: { |
990 DCHECK(args->length() == 1); | 1079 DCHECK(args->length() == 1); |
991 Literal* literal = args->at(0)->AsLiteral(); | 1080 Literal* literal = args->at(0)->AsLiteral(); |
992 if (literal != nullptr) { | 1081 if (literal != nullptr) { |
1082 // constant fold Math.fround(#const); | |
993 if (literal->raw_value()->IsNumber()) { | 1083 if (literal->raw_value()->IsNumber()) { |
994 float val = static_cast<float>(literal->raw_value()->AsNumber()); | 1084 float val = static_cast<float>(literal->raw_value()->AsNumber()); |
995 byte code[] = {WASM_F32(val)}; | 1085 byte code[] = {WASM_F32(val)}; |
996 current_function_builder_->EmitCode(code, sizeof(code)); | 1086 current_function_builder_->EmitCode(code, sizeof(code)); |
997 return true; | 1087 return true; |
998 } | 1088 } |
999 } | 1089 } |
1090 VisitCallArgs(call); | |
1000 switch (TypeIndexOf(args->at(0))) { | 1091 switch (TypeIndexOf(args->at(0))) { |
1001 case kInt32: | 1092 case kInt32: |
1002 case kFixnum: | 1093 case kFixnum: |
1003 current_function_builder_->Emit(kExprF32SConvertI32); | 1094 current_function_builder_->Emit(kExprF32SConvertI32); |
1004 break; | 1095 break; |
1005 case kUint32: | 1096 case kUint32: |
1006 current_function_builder_->Emit(kExprF32UConvertI32); | 1097 current_function_builder_->Emit(kExprF32UConvertI32); |
1007 break; | 1098 break; |
1008 case kFloat32: | 1099 case kFloat32: |
1009 break; | 1100 break; |
1010 case kFloat64: | 1101 case kFloat64: |
1011 current_function_builder_->Emit(kExprF32ConvertF64); | 1102 current_function_builder_->Emit(kExprF32ConvertF64); |
1012 break; | 1103 break; |
1013 default: | 1104 default: |
1014 UNREACHABLE(); | 1105 UNREACHABLE(); |
1015 } | 1106 } |
1016 break; | 1107 break; |
1017 } | 1108 } |
1018 default: { | 1109 default: { |
1019 UNREACHABLE(); | 1110 UNREACHABLE(); |
1020 break; | 1111 break; |
1021 } | 1112 } |
1022 } | 1113 } |
1023 VisitCallArgs(call); | |
1024 return true; | 1114 return true; |
1025 } | 1115 } |
1026 | 1116 |
1027 void VisitCallArgs(Call* expr) { | 1117 void VisitCallArgs(Call* expr) { |
1028 ZoneList<Expression*>* args = expr->arguments(); | 1118 ZoneList<Expression*>* args = expr->arguments(); |
1029 for (int i = 0; i < args->length(); ++i) { | 1119 for (int i = 0; i < args->length(); ++i) { |
1030 Expression* arg = args->at(i); | 1120 Expression* arg = args->at(i); |
1031 RECURSE(Visit(arg)); | 1121 RECURSE(Visit(arg)); |
1032 } | 1122 } |
1033 } | 1123 } |
1034 | 1124 |
1035 void VisitCall(Call* expr) { | 1125 void VisitCall(Call* expr) { |
1036 Call::CallType call_type = expr->GetCallType(isolate_); | 1126 Call::CallType call_type = expr->GetCallType(isolate_); |
1127 std::vector<byte> call_code; | |
1037 switch (call_type) { | 1128 switch (call_type) { |
1038 case Call::OTHER_CALL: { | 1129 case Call::OTHER_CALL: { |
1039 DCHECK(in_function_); | 1130 DCHECK_EQ(kFuncScope, scope_); |
1040 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1131 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
1041 if (proxy != nullptr) { | 1132 if (proxy != nullptr) { |
1042 if (VisitStdlibFunction(expr, proxy)) { | 1133 if (VisitStdlibFunction(expr, proxy)) { |
1043 return; | 1134 return; |
1044 } | 1135 } |
1045 } | 1136 } |
1046 uint16_t index; | 1137 uint16_t index; |
1047 VariableProxy* vp = expr->expression()->AsVariableProxy(); | 1138 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
1048 if (vp != nullptr && | 1139 if (vp != nullptr && |
1049 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { | 1140 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { |
1050 LocalType return_type = TypeOf(expr); | 1141 LocalType return_type = TypeOf(expr); |
1051 ZoneList<Expression*>* args = expr->arguments(); | 1142 ZoneList<Expression*>* args = expr->arguments(); |
1052 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1143 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
1053 args->length()); | 1144 args->length()); |
1054 if (return_type != kAstStmt) { | 1145 if (return_type != kAstStmt) { |
1055 sig.AddReturn(return_type); | 1146 sig.AddReturn(return_type); |
1056 } | 1147 } |
1057 for (int i = 0; i < args->length(); i++) { | 1148 for (int i = 0; i < args->length(); i++) { |
1058 sig.AddParam(TypeOf(args->at(i))); | 1149 sig.AddParam(TypeOf(args->at(i))); |
1059 } | 1150 } |
1060 index = | 1151 index = |
1061 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 1152 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
1062 } else { | 1153 } else { |
1063 index = LookupOrInsertFunction(vp->var()); | 1154 index = LookupOrInsertFunction(vp->var()); |
1064 } | 1155 } |
1065 current_function_builder_->Emit(kExprCallFunction); | 1156 call_code.push_back(kExprCallFunction); |
1066 std::vector<uint8_t> index_arr = UnsignedLEB128From(index); | 1157 // TODO(titzer): inefficient and clunky |
1067 current_function_builder_->EmitCode( | 1158 std::vector<byte> leb = UnsignedLEB128From(index); |
1068 &index_arr[0], static_cast<uint32_t>(index_arr.size())); | 1159 call_code.insert(call_code.end(), leb.begin(), leb.end()); |
1069 break; | 1160 break; |
1070 } | 1161 } |
1071 case Call::KEYED_PROPERTY_CALL: { | 1162 case Call::KEYED_PROPERTY_CALL: { |
1072 DCHECK(in_function_); | 1163 DCHECK_EQ(kFuncScope, scope_); |
1073 Property* p = expr->expression()->AsProperty(); | 1164 Property* p = expr->expression()->AsProperty(); |
1074 DCHECK_NOT_NULL(p); | 1165 DCHECK_NOT_NULL(p); |
1075 VariableProxy* var = p->obj()->AsVariableProxy(); | 1166 VariableProxy* var = p->obj()->AsVariableProxy(); |
1076 DCHECK_NOT_NULL(var); | 1167 DCHECK_NOT_NULL(var); |
1077 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1168 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
1078 current_function_builder_->EmitWithVarInt(kExprCallIndirect, | 1169 RECURSE(Visit(p->key())); |
1079 indices->signature_index); | 1170 current_function_builder_->EmitI32Const(indices->start_index); |
1080 current_function_builder_->Emit(kExprI32Add); | 1171 current_function_builder_->Emit(kExprI32Add); |
1081 // TODO(bradnelson): variable size | 1172 call_code.push_back(kExprCallIndirect); |
1082 byte code[] = {WASM_I32V(indices->start_index)}; | 1173 // TODO(titzer): inefficient and clunky |
1083 current_function_builder_->EmitCode(code, sizeof(code)); | 1174 std::vector<byte> leb = UnsignedLEB128From(indices->signature_index); |
1084 RECURSE(Visit(p->key())); | 1175 call_code.insert(call_code.end(), leb.begin(), leb.end()); |
1085 break; | 1176 break; |
1086 } | 1177 } |
1087 default: | 1178 default: |
1088 UNREACHABLE(); | 1179 UNREACHABLE(); |
1089 } | 1180 } |
1090 VisitCallArgs(expr); | 1181 VisitCallArgs(expr); |
1182 | |
1183 current_function_builder_->EmitCode( | |
1184 &call_code[0], static_cast<uint32_t>(call_code.size())); | |
1091 } | 1185 } |
1092 | 1186 |
1093 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 1187 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
1094 | 1188 |
1095 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 1189 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
1096 | 1190 |
1097 void VisitUnaryOperation(UnaryOperation* expr) { | 1191 void VisitUnaryOperation(UnaryOperation* expr) { |
1192 RECURSE(Visit(expr->expression())); | |
1098 switch (expr->op()) { | 1193 switch (expr->op()) { |
1099 case Token::NOT: { | 1194 case Token::NOT: { |
1100 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); | 1195 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); |
1101 current_function_builder_->Emit(kExprI32Eqz); | 1196 current_function_builder_->Emit(kExprI32Eqz); |
1102 break; | 1197 break; |
1103 } | 1198 } |
1104 default: | 1199 default: |
1105 UNREACHABLE(); | 1200 UNREACHABLE(); |
1106 } | 1201 } |
1107 RECURSE(Visit(expr->expression())); | |
1108 } | 1202 } |
1109 | 1203 |
1110 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } | 1204 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } |
1111 | 1205 |
1112 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, | 1206 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, |
1113 int32_t val) { | 1207 int32_t val) { |
1114 DCHECK_NOT_NULL(expr->right()); | 1208 DCHECK_NOT_NULL(expr->right()); |
1115 if (expr->op() == op && expr->right()->IsLiteral() && | 1209 if (expr->op() == op && expr->right()->IsLiteral() && |
1116 TypeOf(expr) == kAstI32) { | 1210 TypeOf(expr) == kAstI32) { |
1117 Literal* right = expr->right()->AsLiteral(); | 1211 Literal* right = expr->right()->AsLiteral(); |
(...skipping 125 matching lines...) Loading... | |
1243 if (expr->op() == Token::BIT_XOR) { | 1337 if (expr->op() == Token::BIT_XOR) { |
1244 return expr->left()->AsBinaryOperation()->left(); | 1338 return expr->left()->AsBinaryOperation()->left(); |
1245 } else { | 1339 } else { |
1246 return expr->left(); | 1340 return expr->left(); |
1247 } | 1341 } |
1248 } | 1342 } |
1249 | 1343 |
1250 void VisitBinaryOperation(BinaryOperation* expr) { | 1344 void VisitBinaryOperation(BinaryOperation* expr) { |
1251 ConvertOperation convertOperation = MatchBinaryOperation(expr); | 1345 ConvertOperation convertOperation = MatchBinaryOperation(expr); |
1252 if (convertOperation == kToDouble) { | 1346 if (convertOperation == kToDouble) { |
1347 RECURSE(Visit(expr->left())); | |
1253 TypeIndex type = TypeIndexOf(expr->left()); | 1348 TypeIndex type = TypeIndexOf(expr->left()); |
1254 if (type == kInt32 || type == kFixnum) { | 1349 if (type == kInt32 || type == kFixnum) { |
1255 current_function_builder_->Emit(kExprF64SConvertI32); | 1350 current_function_builder_->Emit(kExprF64SConvertI32); |
1256 } else if (type == kUint32) { | 1351 } else if (type == kUint32) { |
1257 current_function_builder_->Emit(kExprF64UConvertI32); | 1352 current_function_builder_->Emit(kExprF64UConvertI32); |
1258 } else if (type == kFloat32) { | 1353 } else if (type == kFloat32) { |
1259 current_function_builder_->Emit(kExprF64ConvertF32); | 1354 current_function_builder_->Emit(kExprF64ConvertF32); |
1260 } else { | 1355 } else { |
1261 UNREACHABLE(); | 1356 UNREACHABLE(); |
1262 } | 1357 } |
1263 RECURSE(Visit(expr->left())); | |
1264 } else if (convertOperation == kToInt) { | 1358 } else if (convertOperation == kToInt) { |
1359 RECURSE(Visit(GetLeft(expr))); | |
1265 TypeIndex type = TypeIndexOf(GetLeft(expr)); | 1360 TypeIndex type = TypeIndexOf(GetLeft(expr)); |
1266 if (type == kFloat32) { | 1361 if (type == kFloat32) { |
1267 current_function_builder_->Emit(kExprI32SConvertF32); | 1362 current_function_builder_->Emit(kExprI32SConvertF32); |
1268 } else if (type == kFloat64) { | 1363 } else if (type == kFloat64) { |
1269 current_function_builder_->Emit(kExprI32SConvertF64); | 1364 current_function_builder_->Emit(kExprI32SConvertF64); |
1270 } else { | 1365 } else { |
1271 UNREACHABLE(); | 1366 UNREACHABLE(); |
1272 } | 1367 } |
1273 RECURSE(Visit(GetLeft(expr))); | |
1274 } else if (convertOperation == kAsIs) { | 1368 } else if (convertOperation == kAsIs) { |
1275 RECURSE(Visit(GetLeft(expr))); | 1369 RECURSE(Visit(GetLeft(expr))); |
1276 } else { | 1370 } else { |
1371 if (expr->op() == Token::COMMA) { | |
1372 current_function_builder_->Emit(kExprBlock); | |
1373 } | |
1374 | |
1375 RECURSE(Visit(expr->left())); | |
1376 RECURSE(Visit(expr->right())); | |
1377 | |
1378 if (expr->op() == Token::COMMA) { | |
1379 current_function_builder_->Emit(kExprEnd); | |
bradnelson
2016/03/23 19:14:25
return here vs the break down below, might be more
| |
1380 } | |
1381 | |
1277 switch (expr->op()) { | 1382 switch (expr->op()) { |
1278 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 1383 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
1279 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 1384 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
1280 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 1385 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
1281 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 1386 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
1282 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 1387 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
1283 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); | 1388 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
1284 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 1389 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
1285 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 1390 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
1286 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 1391 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
1287 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 1392 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
1288 case Token::MOD: { | 1393 case Token::MOD: { |
1289 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 1394 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
1290 if (type == kInt32) { | 1395 if (type == kInt32) { |
1291 current_function_builder_->Emit(kExprI32RemS); | 1396 current_function_builder_->Emit(kExprI32RemS); |
1292 } else if (type == kUint32) { | 1397 } else if (type == kUint32) { |
1293 current_function_builder_->Emit(kExprI32RemU); | 1398 current_function_builder_->Emit(kExprI32RemU); |
1294 } else if (type == kFloat64) { | 1399 } else if (type == kFloat64) { |
1295 current_function_builder_->Emit(kExprF64Mod); | 1400 current_function_builder_->Emit(kExprF64Mod); |
1296 return; | 1401 return; |
1297 } else { | 1402 } else { |
1298 UNREACHABLE(); | 1403 UNREACHABLE(); |
1299 } | 1404 } |
1300 break; | 1405 break; |
1301 } | 1406 } |
1302 case Token::COMMA: { | 1407 case Token::COMMA: { |
1303 current_function_builder_->EmitWithVarInt(kExprBlock, 2); | |
1304 break; | 1408 break; |
1305 } | 1409 } |
1306 default: | 1410 default: |
1307 UNREACHABLE(); | 1411 UNREACHABLE(); |
1308 } | 1412 } |
1309 RECURSE(Visit(expr->left())); | |
1310 RECURSE(Visit(expr->right())); | |
1311 } | 1413 } |
1312 } | 1414 } |
1313 | 1415 |
1314 void AddLeb128(uint32_t index, bool is_local) { | 1416 void AddLeb128(uint32_t index, bool is_local) { |
1315 std::vector<uint8_t> index_vec = UnsignedLEB128From(index); | 1417 std::vector<uint8_t> index_vec = UnsignedLEB128From(index); |
1316 if (is_local) { | 1418 if (is_local) { |
1317 uint32_t pos_of_index[1] = {0}; | 1419 uint32_t pos_of_index[1] = {0}; |
1318 current_function_builder_->EmitCode( | 1420 current_function_builder_->EmitCode( |
1319 &index_vec[0], static_cast<uint32_t>(index_vec.size()), pos_of_index, | 1421 &index_vec[0], static_cast<uint32_t>(index_vec.size()), pos_of_index, |
1320 1); | 1422 1); |
1321 } else { | 1423 } else { |
1322 current_function_builder_->EmitCode( | 1424 current_function_builder_->EmitCode( |
1323 &index_vec[0], static_cast<uint32_t>(index_vec.size())); | 1425 &index_vec[0], static_cast<uint32_t>(index_vec.size())); |
1324 } | 1426 } |
1325 } | 1427 } |
1326 | 1428 |
1327 void VisitCompareOperation(CompareOperation* expr) { | 1429 void VisitCompareOperation(CompareOperation* expr) { |
1430 RECURSE(Visit(expr->left())); | |
1431 RECURSE(Visit(expr->right())); | |
1328 switch (expr->op()) { | 1432 switch (expr->op()) { |
1329 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); | 1433 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); |
1330 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); | 1434 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); |
1331 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); | 1435 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); |
1332 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); | 1436 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); |
1333 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); | 1437 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); |
1334 default: | 1438 default: |
1335 UNREACHABLE(); | 1439 UNREACHABLE(); |
1336 } | 1440 } |
1337 RECURSE(Visit(expr->left())); | |
1338 RECURSE(Visit(expr->right())); | |
1339 } | 1441 } |
1340 | 1442 |
1341 #undef BINOP_CASE | 1443 #undef BINOP_CASE |
1342 #undef NON_SIGNED_INT_BINOP | 1444 #undef NON_SIGNED_INT_BINOP |
1343 #undef SIGNED_BINOP | 1445 #undef SIGNED_BINOP |
1344 #undef NON_SIGNED_BINOP | 1446 #undef NON_SIGNED_BINOP |
1345 | 1447 |
1346 enum TypeIndex { | 1448 enum TypeIndex { |
1347 kInt32 = 0, | 1449 kInt32 = 0, |
1348 kUint32 = 1, | 1450 kUint32 = 1, |
(...skipping 141 matching lines...) Loading... | |
1490 } else { | 1592 } else { |
1491 return kAstStmt; | 1593 return kAstStmt; |
1492 } | 1594 } |
1493 } | 1595 } |
1494 | 1596 |
1495 Zone* zone() { return zone_; } | 1597 Zone* zone() { return zone_; } |
1496 | 1598 |
1497 ZoneHashMap local_variables_; | 1599 ZoneHashMap local_variables_; |
1498 ZoneHashMap functions_; | 1600 ZoneHashMap functions_; |
1499 ZoneHashMap global_variables_; | 1601 ZoneHashMap global_variables_; |
1500 bool in_function_; | 1602 AsmScope scope_; |
1501 bool is_set_op_; | |
1502 bool marking_exported; | |
1503 WasmModuleBuilder* builder_; | 1603 WasmModuleBuilder* builder_; |
1504 WasmFunctionBuilder* current_function_builder_; | 1604 WasmFunctionBuilder* current_function_builder_; |
1505 FunctionLiteral* literal_; | 1605 FunctionLiteral* literal_; |
1506 Isolate* isolate_; | 1606 Isolate* isolate_; |
1507 Zone* zone_; | 1607 Zone* zone_; |
1508 Handle<Object> foreign_; | 1608 Handle<Object> foreign_; |
1509 AsmTyper* typer_; | 1609 AsmTyper* typer_; |
1510 TypeCache const& cache_; | 1610 TypeCache const& cache_; |
1511 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1611 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1512 int block_size_; | |
1513 uint16_t init_function_index_; | 1612 uint16_t init_function_index_; |
1514 uint32_t next_table_index_; | 1613 uint32_t next_table_index_; |
1515 ZoneHashMap function_tables_; | 1614 ZoneHashMap function_tables_; |
1516 ImportedFunctionTable imported_function_table_; | 1615 ImportedFunctionTable imported_function_table_; |
1517 | 1616 |
1518 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1617 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1519 | 1618 |
1520 private: | 1619 private: |
1521 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1620 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1522 }; | 1621 }; |
(...skipping 11 matching lines...) Loading... | |
1534 // that zone in constructor may be thrown away once wasm module is written. | 1633 // that zone in constructor may be thrown away once wasm module is written. |
1535 WasmModuleIndex* AsmWasmBuilder::Run() { | 1634 WasmModuleIndex* AsmWasmBuilder::Run() { |
1536 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1635 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
1537 impl.Compile(); | 1636 impl.Compile(); |
1538 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1637 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1539 return writer->WriteTo(zone_); | 1638 return writer->WriteTo(zone_); |
1540 } | 1639 } |
1541 } // namespace wasm | 1640 } // namespace wasm |
1542 } // namespace internal | 1641 } // namespace internal |
1543 } // namespace v8 | 1642 } // namespace v8 |
OLD | NEW |