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 13 matching lines...) Expand all Loading... |
24 namespace internal { | 24 namespace internal { |
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 | 35 |
35 class AsmWasmBuilderImpl : public AstVisitor { | 36 class AsmWasmBuilderImpl : public AstVisitor { |
36 public: | 37 public: |
37 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, | 38 AsmWasmBuilderImpl(Isolate* isolate, Zone* zone, FunctionLiteral* literal, |
38 Handle<Object> foreign, AsmTyper* typer) | 39 Handle<Object> foreign, AsmTyper* typer) |
39 : local_variables_(HashMap::PointersMatch, | 40 : local_variables_(HashMap::PointersMatch, |
40 ZoneHashMap::kDefaultHashMapCapacity, | 41 ZoneHashMap::kDefaultHashMapCapacity, |
41 ZoneAllocationPolicy(zone)), | 42 ZoneAllocationPolicy(zone)), |
42 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, | 43 functions_(HashMap::PointersMatch, ZoneHashMap::kDefaultHashMapCapacity, |
43 ZoneAllocationPolicy(zone)), | 44 ZoneAllocationPolicy(zone)), |
44 global_variables_(HashMap::PointersMatch, | 45 global_variables_(HashMap::PointersMatch, |
45 ZoneHashMap::kDefaultHashMapCapacity, | 46 ZoneHashMap::kDefaultHashMapCapacity, |
46 ZoneAllocationPolicy(zone)), | 47 ZoneAllocationPolicy(zone)), |
47 in_function_(false), | 48 scope_(kModuleScope), |
48 is_set_op_(false), | |
49 marking_exported(false), | |
50 builder_(new (zone) WasmModuleBuilder(zone)), | 49 builder_(new (zone) WasmModuleBuilder(zone)), |
51 current_function_builder_(nullptr), | 50 current_function_builder_(nullptr), |
52 literal_(literal), | 51 literal_(literal), |
53 isolate_(isolate), | 52 isolate_(isolate), |
54 zone_(zone), | 53 zone_(zone), |
55 foreign_(foreign), | 54 foreign_(foreign), |
56 typer_(typer), | 55 typer_(typer), |
57 cache_(TypeCache::Get()), | 56 cache_(TypeCache::Get()), |
58 breakable_blocks_(zone), | 57 breakable_blocks_(zone), |
59 block_size_(0), | |
60 init_function_index_(0), | 58 init_function_index_(0), |
61 next_table_index_(0), | 59 next_table_index_(0), |
62 function_tables_(HashMap::PointersMatch, | 60 function_tables_(HashMap::PointersMatch, |
63 ZoneHashMap::kDefaultHashMapCapacity, | 61 ZoneHashMap::kDefaultHashMapCapacity, |
64 ZoneAllocationPolicy(zone)), | 62 ZoneAllocationPolicy(zone)), |
65 imported_function_table_(this) { | 63 imported_function_table_(this) { |
66 InitializeAstVisitor(isolate); | 64 InitializeAstVisitor(isolate); |
67 } | 65 } |
68 | 66 |
69 void InitializeInitFunction() { | 67 void InitializeInitFunction() { |
70 init_function_index_ = builder_->AddFunction(); | 68 init_function_index_ = builder_->AddFunction(); |
71 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 69 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
72 current_function_builder_->ReturnType(kAstStmt); | 70 current_function_builder_->ReturnType(kAstStmt); |
73 builder_->MarkStartFunction(init_function_index_); | 71 builder_->MarkStartFunction(init_function_index_); |
74 current_function_builder_ = nullptr; | 72 current_function_builder_ = nullptr; |
75 } | 73 } |
76 | 74 |
77 void Compile() { | 75 void Compile() { |
78 InitializeInitFunction(); | 76 InitializeInitFunction(); |
79 RECURSE(VisitFunctionLiteral(literal_)); | 77 RECURSE(VisitFunctionLiteral(literal_)); |
80 } | 78 } |
81 | 79 |
82 void VisitVariableDeclaration(VariableDeclaration* decl) {} | 80 void VisitVariableDeclaration(VariableDeclaration* decl) {} |
83 | 81 |
84 void VisitFunctionDeclaration(FunctionDeclaration* decl) { | 82 void VisitFunctionDeclaration(FunctionDeclaration* decl) { |
85 DCHECK(!in_function_); | 83 DCHECK_EQ(kModuleScope, scope_); |
86 DCHECK_NULL(current_function_builder_); | 84 DCHECK_NULL(current_function_builder_); |
87 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); | 85 uint16_t index = LookupOrInsertFunction(decl->proxy()->var()); |
88 current_function_builder_ = builder_->FunctionAt(index); | 86 current_function_builder_ = builder_->FunctionAt(index); |
89 in_function_ = true; | 87 scope_ = kFuncScope; |
90 RECURSE(Visit(decl->fun())); | 88 RECURSE(Visit(decl->fun())); |
91 in_function_ = false; | 89 scope_ = kModuleScope; |
92 current_function_builder_ = nullptr; | 90 current_function_builder_ = nullptr; |
93 local_variables_.Clear(); | 91 local_variables_.Clear(); |
94 } | 92 } |
95 | 93 |
96 void VisitImportDeclaration(ImportDeclaration* decl) {} | 94 void VisitImportDeclaration(ImportDeclaration* decl) {} |
97 | 95 |
98 void VisitExportDeclaration(ExportDeclaration* decl) {} | 96 void VisitExportDeclaration(ExportDeclaration* decl) {} |
99 | 97 |
100 void VisitStatements(ZoneList<Statement*>* stmts) { | 98 void VisitStatements(ZoneList<Statement*>* stmts) { |
101 for (int i = 0; i < stmts->length(); ++i) { | 99 for (int i = 0; i < stmts->length(); ++i) { |
102 Statement* stmt = stmts->at(i); | 100 Statement* stmt = stmts->at(i); |
103 ExpressionStatement* e = stmt->AsExpressionStatement(); | 101 ExpressionStatement* e = stmt->AsExpressionStatement(); |
104 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { | 102 if (e != nullptr && e->expression()->IsUndefinedLiteral()) { |
105 block_size_--; | |
106 continue; | 103 continue; |
107 } | 104 } |
108 RECURSE(Visit(stmt)); | 105 RECURSE(Visit(stmt)); |
109 if (stmt->IsJump()) break; | 106 if (stmt->IsJump()) break; |
110 } | 107 } |
111 } | 108 } |
112 | 109 |
113 void VisitBlock(Block* stmt) { | 110 void VisitBlock(Block* stmt) { |
114 if (stmt->statements()->length() == 1) { | 111 if (stmt->statements()->length() == 1) { |
115 ExpressionStatement* expr = | 112 ExpressionStatement* expr = |
116 stmt->statements()->at(0)->AsExpressionStatement(); | 113 stmt->statements()->at(0)->AsExpressionStatement(); |
117 if (expr != nullptr) { | 114 if (expr != nullptr) { |
118 if (expr->expression()->IsAssignment()) { | 115 if (expr->expression()->IsAssignment()) { |
119 RECURSE(VisitExpressionStatement(expr)); | 116 RECURSE(VisitExpressionStatement(expr)); |
120 return; | 117 return; |
121 } | 118 } |
122 } | 119 } |
123 } | 120 } |
124 if (in_function_) { | 121 if (scope_ == kFuncScope) { |
125 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, | 122 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, |
126 false, | 123 false); |
127 static_cast<byte>(stmt->statements()->length())); | |
128 RECURSE(VisitStatements(stmt->statements())); | 124 RECURSE(VisitStatements(stmt->statements())); |
129 DCHECK(block_size_ >= 0); | |
130 } else { | 125 } else { |
131 RECURSE(VisitStatements(stmt->statements())); | 126 RECURSE(VisitStatements(stmt->statements())); |
132 } | 127 } |
133 } | 128 } |
134 | 129 |
135 class BlockVisitor { | 130 class BlockVisitor { |
136 private: | 131 private: |
137 int prev_block_size_; | |
138 uint32_t index_; | |
139 AsmWasmBuilderImpl* builder_; | 132 AsmWasmBuilderImpl* builder_; |
140 | 133 |
141 public: | 134 public: |
142 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, | 135 BlockVisitor(AsmWasmBuilderImpl* builder, BreakableStatement* stmt, |
143 WasmOpcode opcode, bool is_loop, int initial_block_size) | 136 WasmOpcode opcode, bool is_loop) |
144 : builder_(builder) { | 137 : builder_(builder) { |
145 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); | 138 builder_->breakable_blocks_.push_back(std::make_pair(stmt, is_loop)); |
146 builder_->current_function_builder_->Emit(opcode); | 139 builder_->current_function_builder_->Emit(opcode); |
147 index_ = | |
148 builder_->current_function_builder_->EmitEditableVarIntImmediate(); | |
149 prev_block_size_ = builder_->block_size_; | |
150 builder_->block_size_ = initial_block_size; | |
151 } | 140 } |
152 ~BlockVisitor() { | 141 ~BlockVisitor() { |
153 builder_->current_function_builder_->EditVarIntImmediate( | 142 builder_->current_function_builder_->Emit(kExprEnd); |
154 index_, builder_->block_size_); | |
155 builder_->block_size_ = prev_block_size_; | |
156 builder_->breakable_blocks_.pop_back(); | 143 builder_->breakable_blocks_.pop_back(); |
157 } | 144 } |
158 }; | 145 }; |
159 | 146 |
160 void VisitExpressionStatement(ExpressionStatement* stmt) { | 147 void VisitExpressionStatement(ExpressionStatement* stmt) { |
161 RECURSE(Visit(stmt->expression())); | 148 RECURSE(Visit(stmt->expression())); |
162 } | 149 } |
163 | 150 |
164 void VisitEmptyStatement(EmptyStatement* stmt) {} | 151 void VisitEmptyStatement(EmptyStatement* stmt) {} |
165 | 152 |
166 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } | 153 void VisitEmptyParentheses(EmptyParentheses* paren) { UNREACHABLE(); } |
167 | 154 |
168 void VisitIfStatement(IfStatement* stmt) { | 155 void VisitIfStatement(IfStatement* stmt) { |
169 DCHECK(in_function_); | 156 DCHECK_EQ(kFuncScope, scope_); |
170 if (stmt->HasElseStatement()) { | |
171 current_function_builder_->Emit(kExprIfElse); | |
172 } else { | |
173 current_function_builder_->Emit(kExprIf); | |
174 } | |
175 RECURSE(Visit(stmt->condition())); | 157 RECURSE(Visit(stmt->condition())); |
| 158 current_function_builder_->Emit(kExprIf); |
| 159 // WASM ifs come with implement blocks for both arms. |
| 160 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
176 if (stmt->HasThenStatement()) { | 161 if (stmt->HasThenStatement()) { |
177 RECURSE(Visit(stmt->then_statement())); | 162 RECURSE(Visit(stmt->then_statement())); |
178 } else { | |
179 current_function_builder_->Emit(kExprNop); | |
180 } | 163 } |
181 if (stmt->HasElseStatement()) { | 164 if (stmt->HasElseStatement()) { |
| 165 current_function_builder_->Emit(kExprElse); |
182 RECURSE(Visit(stmt->else_statement())); | 166 RECURSE(Visit(stmt->else_statement())); |
183 } | 167 } |
| 168 current_function_builder_->Emit(kExprEnd); |
| 169 breakable_blocks_.pop_back(); |
184 } | 170 } |
185 | 171 |
186 void VisitContinueStatement(ContinueStatement* stmt) { | 172 void VisitContinueStatement(ContinueStatement* stmt) { |
187 DCHECK(in_function_); | 173 DCHECK_EQ(kFuncScope, scope_); |
188 DCHECK_NOT_NULL(stmt->target()); | 174 DCHECK_NOT_NULL(stmt->target()); |
189 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 175 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
190 int block_distance = 0; | 176 int block_distance = 0; |
191 for (; i >= 0; i--) { | 177 for (; i >= 0; i--) { |
192 auto elem = breakable_blocks_.at(i); | 178 auto elem = breakable_blocks_.at(i); |
193 if (elem.first == stmt->target()) { | 179 if (elem.first == stmt->target()) { |
194 DCHECK(elem.second); | 180 DCHECK(elem.second); |
195 break; | 181 break; |
196 } else if (elem.second) { | 182 } else if (elem.second) { |
197 block_distance += 2; | 183 block_distance += 2; |
198 } else { | 184 } else { |
199 block_distance += 1; | 185 block_distance += 1; |
200 } | 186 } |
201 } | 187 } |
202 DCHECK(i >= 0); | 188 DCHECK(i >= 0); |
203 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | |
204 current_function_builder_->Emit(kExprNop); | 189 current_function_builder_->Emit(kExprNop); |
| 190 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 191 current_function_builder_->EmitVarInt(block_distance); |
205 } | 192 } |
206 | 193 |
207 void VisitBreakStatement(BreakStatement* stmt) { | 194 void VisitBreakStatement(BreakStatement* stmt) { |
208 DCHECK(in_function_); | 195 DCHECK_EQ(kFuncScope, scope_); |
209 DCHECK_NOT_NULL(stmt->target()); | 196 DCHECK_NOT_NULL(stmt->target()); |
210 int i = static_cast<int>(breakable_blocks_.size()) - 1; | 197 int i = static_cast<int>(breakable_blocks_.size()) - 1; |
211 int block_distance = 0; | 198 int block_distance = 0; |
212 for (; i >= 0; i--) { | 199 for (; i >= 0; i--) { |
213 auto elem = breakable_blocks_.at(i); | 200 auto elem = breakable_blocks_.at(i); |
214 if (elem.first == stmt->target()) { | 201 if (elem.first == stmt->target()) { |
215 if (elem.second) { | 202 if (elem.second) { |
216 block_distance++; | 203 block_distance++; |
217 } | 204 } |
218 break; | 205 break; |
219 } else if (elem.second) { | 206 } else if (elem.second) { |
220 block_distance += 2; | 207 block_distance += 2; |
221 } else { | 208 } else { |
222 block_distance += 1; | 209 block_distance += 1; |
223 } | 210 } |
224 } | 211 } |
225 DCHECK(i >= 0); | 212 DCHECK(i >= 0); |
226 current_function_builder_->EmitWithVarInt(kExprBr, block_distance); | |
227 current_function_builder_->Emit(kExprNop); | 213 current_function_builder_->Emit(kExprNop); |
| 214 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 215 current_function_builder_->EmitVarInt(block_distance); |
228 } | 216 } |
229 | 217 |
230 void VisitReturnStatement(ReturnStatement* stmt) { | 218 void VisitReturnStatement(ReturnStatement* stmt) { |
231 if (in_function_) { | 219 if (scope_ == kModuleScope) { |
232 current_function_builder_->Emit(kExprReturn); | 220 scope_ = kExportScope; |
| 221 RECURSE(Visit(stmt->expression())); |
| 222 scope_ = kModuleScope; |
| 223 } else if (scope_ == kFuncScope) { |
| 224 RECURSE(Visit(stmt->expression())); |
| 225 uint8_t arity = |
| 226 TypeOf(stmt->expression()) == kAstStmt ? ARITY_0 : ARITY_1; |
| 227 current_function_builder_->EmitWithU8(kExprReturn, arity); |
233 } else { | 228 } else { |
234 marking_exported = true; | 229 UNREACHABLE(); |
235 } | |
236 RECURSE(Visit(stmt->expression())); | |
237 if (!in_function_) { | |
238 marking_exported = false; | |
239 } | 230 } |
240 } | 231 } |
241 | 232 |
242 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } | 233 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } |
243 | 234 |
244 void GenerateCaseComparisonCode(int value, WasmOpcode op, | |
245 VariableProxy* tag) { | |
246 current_function_builder_->Emit(kExprIfElse); | |
247 current_function_builder_->Emit(op); | |
248 VisitVariableProxy(tag); | |
249 byte code[] = {WASM_I32V(value)}; | |
250 current_function_builder_->EmitCode(code, sizeof(code)); | |
251 } | |
252 | |
253 void HandleCase(CaseNode* node, | 235 void HandleCase(CaseNode* node, |
254 const ZoneMap<int, unsigned int>& case_to_block, | 236 const ZoneMap<int, unsigned int>& case_to_block, |
255 VariableProxy* tag, int default_block) { | 237 VariableProxy* tag, int default_block, int if_depth) { |
| 238 int prev_if_depth = if_depth; |
256 if (node->left != nullptr) { | 239 if (node->left != nullptr) { |
257 GenerateCaseComparisonCode(node->begin, kExprI32LtS, tag); | 240 VisitVariableProxy(tag); |
258 HandleCase(node->left, case_to_block, tag, default_block); | 241 current_function_builder_->EmitI32Const(node->begin); |
| 242 current_function_builder_->Emit(kExprI32LtS); |
| 243 current_function_builder_->Emit(kExprIf); |
| 244 if_depth++; |
| 245 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 246 HandleCase(node->left, case_to_block, tag, default_block, if_depth); |
| 247 current_function_builder_->Emit(kExprElse); |
259 } | 248 } |
260 if (node->right != nullptr) { | 249 if (node->right != nullptr) { |
261 GenerateCaseComparisonCode(node->end, kExprI32GtS, tag); | 250 VisitVariableProxy(tag); |
262 HandleCase(node->right, case_to_block, tag, default_block); | 251 current_function_builder_->EmitI32Const(node->end); |
| 252 current_function_builder_->Emit(kExprI32GtS); |
| 253 current_function_builder_->Emit(kExprIf); |
| 254 if_depth++; |
| 255 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 256 HandleCase(node->right, case_to_block, tag, default_block, if_depth); |
| 257 current_function_builder_->Emit(kExprElse); |
263 } | 258 } |
264 if (node->begin == node->end) { | 259 if (node->begin == node->end) { |
| 260 VisitVariableProxy(tag); |
| 261 current_function_builder_->EmitI32Const(node->begin); |
| 262 current_function_builder_->Emit(kExprI32Eq); |
265 current_function_builder_->Emit(kExprIf); | 263 current_function_builder_->Emit(kExprIf); |
266 current_function_builder_->Emit(kExprI32Eq); | |
267 VisitVariableProxy(tag); | |
268 byte code[] = {WASM_I32V(node->begin)}; | |
269 current_function_builder_->EmitCode(code, sizeof(code)); | |
270 DCHECK(case_to_block.find(node->begin) != case_to_block.end()); | 264 DCHECK(case_to_block.find(node->begin) != case_to_block.end()); |
271 current_function_builder_->EmitWithVarInt(kExprBr, | |
272 case_to_block.at(node->begin)); | |
273 current_function_builder_->Emit(kExprNop); | 265 current_function_builder_->Emit(kExprNop); |
| 266 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
| 267 current_function_builder_->EmitVarInt(1 + if_depth + |
| 268 case_to_block.at(node->begin)); |
| 269 current_function_builder_->Emit(kExprEnd); |
274 } else { | 270 } else { |
275 current_function_builder_->Emit(kExprBrTable); | 271 current_function_builder_->Emit(kExprNop); |
| 272 if (node->begin != 0) { |
| 273 VisitVariableProxy(tag); |
| 274 current_function_builder_->EmitI32Const(node->begin); |
| 275 current_function_builder_->Emit(kExprI32Sub); |
| 276 } else { |
| 277 VisitVariableProxy(tag); |
| 278 } |
| 279 current_function_builder_->EmitWithU8(kExprBrTable, ARITY_0); |
276 current_function_builder_->EmitVarInt(node->end - node->begin + 1); | 280 current_function_builder_->EmitVarInt(node->end - node->begin + 1); |
277 for (int v = node->begin; v <= node->end; v++) { | 281 for (int v = node->begin; v <= node->end; v++) { |
278 if (case_to_block.find(v) != case_to_block.end()) { | 282 if (case_to_block.find(v) != case_to_block.end()) { |
279 byte break_code[] = {BR_TARGET(case_to_block.at(v))}; | 283 byte break_code[] = {BR_TARGET(if_depth + case_to_block.at(v))}; |
280 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 284 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
281 } else { | 285 } else { |
282 byte break_code[] = {BR_TARGET(default_block)}; | 286 byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
283 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 287 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
284 } | 288 } |
285 if (v == kMaxInt) { | 289 if (v == kMaxInt) { |
286 break; | 290 break; |
287 } | 291 } |
288 } | 292 } |
289 byte break_code[] = {BR_TARGET(default_block)}; | 293 byte break_code[] = {BR_TARGET(if_depth + default_block)}; |
290 current_function_builder_->EmitCode(break_code, sizeof(break_code)); | 294 current_function_builder_->EmitCode(break_code, sizeof(break_code)); |
291 // TODO(aseemgarg): remove the if once sub 0 is fixed | 295 } |
292 if (node->begin != 0) { | 296 |
293 current_function_builder_->Emit(kExprI32Sub); | 297 while (if_depth-- != prev_if_depth) { |
294 VisitVariableProxy(tag); | 298 breakable_blocks_.pop_back(); |
295 byte code[] = {WASM_I32V(node->begin)}; | 299 current_function_builder_->Emit(kExprEnd); |
296 current_function_builder_->EmitCode(code, sizeof(code)); | |
297 } else { | |
298 VisitVariableProxy(tag); | |
299 } | |
300 } | 300 } |
301 } | 301 } |
302 | 302 |
303 void VisitSwitchStatement(SwitchStatement* stmt) { | 303 void VisitSwitchStatement(SwitchStatement* stmt) { |
304 VariableProxy* tag = stmt->tag()->AsVariableProxy(); | 304 VariableProxy* tag = stmt->tag()->AsVariableProxy(); |
305 DCHECK_NOT_NULL(tag); | 305 DCHECK_NOT_NULL(tag); |
306 ZoneList<CaseClause*>* clauses = stmt->cases(); | 306 ZoneList<CaseClause*>* clauses = stmt->cases(); |
307 int case_count = clauses->length(); | 307 int case_count = clauses->length(); |
308 if (case_count == 0) { | 308 if (case_count == 0) { |
309 block_size_--; | |
310 return; | 309 return; |
311 } | 310 } |
312 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, | 311 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false); |
313 1); | |
314 ZoneVector<BlockVisitor*> blocks(zone_); | 312 ZoneVector<BlockVisitor*> blocks(zone_); |
315 ZoneVector<int32_t> cases(zone_); | 313 ZoneVector<int32_t> cases(zone_); |
316 ZoneMap<int, unsigned int> case_to_block(zone_); | 314 ZoneMap<int, unsigned int> case_to_block(zone_); |
317 bool has_default = false; | 315 bool has_default = false; |
318 for (int i = case_count - 1; i >= 0; i--) { | 316 for (int i = case_count - 1; i >= 0; i--) { |
319 CaseClause* clause = clauses->at(i); | 317 CaseClause* clause = clauses->at(i); |
320 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false, | 318 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false)); |
321 clause->statements()->length() + 1)); | |
322 if (!clause->is_default()) { | 319 if (!clause->is_default()) { |
323 Literal* label = clause->label()->AsLiteral(); | 320 Literal* label = clause->label()->AsLiteral(); |
324 Handle<Object> value = label->value(); | 321 Handle<Object> value = label->value(); |
325 DCHECK(value->IsNumber() && | 322 DCHECK(value->IsNumber() && |
326 label->bounds().upper->Is(cache_.kAsmSigned)); | 323 label->bounds().upper->Is(cache_.kAsmSigned)); |
327 int32_t label_value; | 324 int32_t label_value; |
328 if (!value->ToInt32(&label_value)) { | 325 if (!value->ToInt32(&label_value)) { |
329 UNREACHABLE(); | 326 UNREACHABLE(); |
330 } | 327 } |
331 case_to_block[label_value] = i; | 328 case_to_block[label_value] = i; |
332 cases.push_back(label_value); | 329 cases.push_back(label_value); |
333 } else { | 330 } else { |
334 DCHECK_EQ(i, case_count - 1); | 331 DCHECK_EQ(i, case_count - 1); |
335 has_default = true; | 332 has_default = true; |
336 } | 333 } |
337 } | 334 } |
338 if (!has_default || case_count > 1) { | 335 if (!has_default || case_count > 1) { |
339 int default_block = has_default ? case_count - 1 : case_count; | 336 int default_block = has_default ? case_count - 1 : case_count; |
340 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false, 1); | 337 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false); |
341 CaseNode* root = OrderCases(&cases, zone_); | 338 CaseNode* root = OrderCases(&cases, zone_); |
342 HandleCase(root, case_to_block, tag, default_block); | 339 HandleCase(root, case_to_block, tag, default_block, 0); |
343 if (root->left != nullptr || root->right != nullptr || | 340 if (root->left != nullptr || root->right != nullptr || |
344 root->begin == root->end) { | 341 root->begin == root->end) { |
345 block_size_++; | 342 current_function_builder_->EmitWithU8(kExprBr, ARITY_0); |
346 current_function_builder_->EmitWithVarInt(kExprBr, default_block); | 343 current_function_builder_->EmitVarInt(default_block); |
347 current_function_builder_->Emit(kExprNop); | 344 current_function_builder_->Emit(kExprNop); |
348 } | 345 } |
349 } else { | |
350 block_size_ = clauses->at(0)->statements()->length(); | |
351 } | 346 } |
352 for (int i = 0; i < case_count; i++) { | 347 for (int i = 0; i < case_count; i++) { |
353 CaseClause* clause = clauses->at(i); | 348 CaseClause* clause = clauses->at(i); |
354 RECURSE(VisitStatements(clause->statements())); | 349 RECURSE(VisitStatements(clause->statements())); |
355 BlockVisitor* v = blocks.at(case_count - i - 1); | 350 BlockVisitor* v = blocks.at(case_count - i - 1); |
356 blocks.pop_back(); | 351 blocks.pop_back(); |
357 delete v; | 352 delete v; |
358 } | 353 } |
359 } | 354 } |
360 | 355 |
361 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } | 356 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } |
362 | 357 |
363 void VisitDoWhileStatement(DoWhileStatement* stmt) { | 358 void VisitDoWhileStatement(DoWhileStatement* stmt) { |
364 DCHECK(in_function_); | 359 DCHECK_EQ(kFuncScope, scope_); |
365 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 360 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
366 2); | |
367 RECURSE(Visit(stmt->body())); | 361 RECURSE(Visit(stmt->body())); |
| 362 RECURSE(Visit(stmt->cond())); |
368 current_function_builder_->Emit(kExprIf); | 363 current_function_builder_->Emit(kExprIf); |
369 RECURSE(Visit(stmt->cond())); | 364 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
370 current_function_builder_->EmitWithVarInt(kExprBr, 0); | 365 current_function_builder_->Emit(kExprEnd); |
371 current_function_builder_->Emit(kExprNop); | |
372 } | 366 } |
373 | 367 |
374 void VisitWhileStatement(WhileStatement* stmt) { | 368 void VisitWhileStatement(WhileStatement* stmt) { |
375 DCHECK(in_function_); | 369 DCHECK_EQ(kFuncScope, scope_); |
376 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 370 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
377 1); | 371 RECURSE(Visit(stmt->cond())); |
| 372 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
378 current_function_builder_->Emit(kExprIf); | 373 current_function_builder_->Emit(kExprIf); |
379 RECURSE(Visit(stmt->cond())); | |
380 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
381 RECURSE(Visit(stmt->body())); | 374 RECURSE(Visit(stmt->body())); |
| 375 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 1); |
| 376 current_function_builder_->Emit(kExprEnd); |
| 377 breakable_blocks_.pop_back(); |
382 } | 378 } |
383 | 379 |
384 void VisitForStatement(ForStatement* stmt) { | 380 void VisitForStatement(ForStatement* stmt) { |
385 DCHECK(in_function_); | 381 DCHECK_EQ(kFuncScope, scope_); |
386 if (stmt->init() != nullptr) { | 382 if (stmt->init() != nullptr) { |
387 block_size_++; | |
388 RECURSE(Visit(stmt->init())); | 383 RECURSE(Visit(stmt->init())); |
389 } | 384 } |
390 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, | 385 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true); |
391 0); | |
392 if (stmt->cond() != nullptr) { | 386 if (stmt->cond() != nullptr) { |
393 block_size_++; | 387 RECURSE(Visit(stmt->cond())); |
| 388 current_function_builder_->Emit(kExprI32Eqz); |
394 current_function_builder_->Emit(kExprIf); | 389 current_function_builder_->Emit(kExprIf); |
395 current_function_builder_->Emit(kExprI32Eqz); | |
396 RECURSE(Visit(stmt->cond())); | |
397 current_function_builder_->EmitWithVarInt(kExprBr, 1); | |
398 current_function_builder_->Emit(kExprNop); | 390 current_function_builder_->Emit(kExprNop); |
| 391 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 2); |
| 392 current_function_builder_->Emit(kExprEnd); |
399 } | 393 } |
400 if (stmt->body() != nullptr) { | 394 if (stmt->body() != nullptr) { |
401 block_size_++; | |
402 RECURSE(Visit(stmt->body())); | 395 RECURSE(Visit(stmt->body())); |
403 } | 396 } |
404 if (stmt->next() != nullptr) { | 397 if (stmt->next() != nullptr) { |
405 block_size_++; | |
406 RECURSE(Visit(stmt->next())); | 398 RECURSE(Visit(stmt->next())); |
407 } | 399 } |
408 block_size_++; | |
409 current_function_builder_->EmitWithVarInt(kExprBr, 0); | |
410 current_function_builder_->Emit(kExprNop); | 400 current_function_builder_->Emit(kExprNop); |
| 401 current_function_builder_->EmitWithU8U8(kExprBr, ARITY_0, 0); |
411 } | 402 } |
412 | 403 |
413 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } | 404 void VisitForInStatement(ForInStatement* stmt) { UNREACHABLE(); } |
414 | 405 |
415 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } | 406 void VisitForOfStatement(ForOfStatement* stmt) { UNREACHABLE(); } |
416 | 407 |
417 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } | 408 void VisitTryCatchStatement(TryCatchStatement* stmt) { UNREACHABLE(); } |
418 | 409 |
419 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } | 410 void VisitTryFinallyStatement(TryFinallyStatement* stmt) { UNREACHABLE(); } |
420 | 411 |
421 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } | 412 void VisitDebuggerStatement(DebuggerStatement* stmt) { UNREACHABLE(); } |
422 | 413 |
423 void VisitFunctionLiteral(FunctionLiteral* expr) { | 414 void VisitFunctionLiteral(FunctionLiteral* expr) { |
424 Scope* scope = expr->scope(); | 415 Scope* scope = expr->scope(); |
425 if (in_function_) { | 416 if (scope_ == kFuncScope) { |
426 if (expr->bounds().lower->IsFunction()) { | 417 if (expr->bounds().lower->IsFunction()) { |
427 FunctionType* func_type = expr->bounds().lower->AsFunction(); | 418 FunctionType* func_type = expr->bounds().lower->AsFunction(); |
428 LocalType return_type = TypeFrom(func_type->Result()); | 419 LocalType return_type = TypeFrom(func_type->Result()); |
429 current_function_builder_->ReturnType(return_type); | 420 current_function_builder_->ReturnType(return_type); |
430 for (int i = 0; i < expr->parameter_count(); i++) { | 421 for (int i = 0; i < expr->parameter_count(); i++) { |
431 LocalType type = TypeFrom(func_type->Parameter(i)); | 422 LocalType type = TypeFrom(func_type->Parameter(i)); |
432 DCHECK_NE(kAstStmt, type); | 423 DCHECK_NE(kAstStmt, type); |
433 LookupOrInsertLocal(scope->parameter(i), type); | 424 LookupOrInsertLocal(scope->parameter(i), type); |
434 } | 425 } |
435 } else { | 426 } else { |
436 UNREACHABLE(); | 427 UNREACHABLE(); |
437 } | 428 } |
438 } | 429 } |
439 RECURSE(VisitStatements(expr->body())); | 430 RECURSE(VisitStatements(expr->body())); |
440 RECURSE(VisitDeclarations(scope->declarations())); | 431 RECURSE(VisitDeclarations(scope->declarations())); |
441 } | 432 } |
442 | 433 |
443 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 434 void VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
444 UNREACHABLE(); | 435 UNREACHABLE(); |
445 } | 436 } |
446 | 437 |
447 void VisitConditional(Conditional* expr) { | 438 void VisitConditional(Conditional* expr) { |
448 DCHECK(in_function_); | 439 DCHECK_EQ(kFuncScope, scope_); |
449 current_function_builder_->Emit(kExprIfElse); | |
450 RECURSE(Visit(expr->condition())); | 440 RECURSE(Visit(expr->condition())); |
| 441 // WASM ifs come with implicit blocks for both arms. |
| 442 breakable_blocks_.push_back(std::make_pair(nullptr, false)); |
| 443 current_function_builder_->Emit(kExprIf); |
451 RECURSE(Visit(expr->then_expression())); | 444 RECURSE(Visit(expr->then_expression())); |
| 445 current_function_builder_->Emit(kExprElse); |
452 RECURSE(Visit(expr->else_expression())); | 446 RECURSE(Visit(expr->else_expression())); |
| 447 current_function_builder_->Emit(kExprEnd); |
| 448 breakable_blocks_.pop_back(); |
453 } | 449 } |
454 | 450 |
455 bool VisitStdlibConstant(Variable* var) { | 451 bool VisitStdlibConstant(Variable* var) { |
456 AsmTyper::StandardMember standard_object = | 452 AsmTyper::StandardMember standard_object = |
457 typer_->VariableAsStandardMember(var); | 453 typer_->VariableAsStandardMember(var); |
458 double value; | 454 double value; |
459 switch (standard_object) { | 455 switch (standard_object) { |
460 case AsmTyper::kInfinity: { | 456 case AsmTyper::kInfinity: { |
461 value = std::numeric_limits<double>::infinity(); | 457 value = std::numeric_limits<double>::infinity(); |
462 break; | 458 break; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 break; | 494 break; |
499 } | 495 } |
500 default: { return false; } | 496 default: { return false; } |
501 } | 497 } |
502 byte code[] = {WASM_F64(value)}; | 498 byte code[] = {WASM_F64(value)}; |
503 current_function_builder_->EmitCode(code, sizeof(code)); | 499 current_function_builder_->EmitCode(code, sizeof(code)); |
504 return true; | 500 return true; |
505 } | 501 } |
506 | 502 |
507 void VisitVariableProxy(VariableProxy* expr) { | 503 void VisitVariableProxy(VariableProxy* expr) { |
508 if (in_function_) { | 504 if (scope_ == kFuncScope || scope_ == kInitScope) { |
509 Variable* var = expr->var(); | 505 Variable* var = expr->var(); |
| 506 if (VisitStdlibConstant(var)) { |
| 507 return; |
| 508 } |
510 LocalType var_type = TypeOf(expr); | 509 LocalType var_type = TypeOf(expr); |
511 if (is_set_op_) { | 510 DCHECK_NE(kAstStmt, var_type); |
512 is_set_op_ = false; | 511 if (var->IsContextSlot()) { |
513 if (var->IsContextSlot()) { | 512 current_function_builder_->EmitWithVarInt( |
514 return current_function_builder_->EmitWithVarInt( | 513 kExprLoadGlobal, LookupOrInsertGlobal(var, var_type)); |
515 kExprStoreGlobal, LookupOrInsertGlobal(var, var_type)); | |
516 } else { | |
517 return current_function_builder_->EmitSetLocal( | |
518 LookupOrInsertLocal(var, var_type)); | |
519 } | |
520 } else { | 514 } else { |
521 if (VisitStdlibConstant(var)) { | 515 current_function_builder_->EmitGetLocal( |
522 return; | 516 LookupOrInsertLocal(var, var_type)); |
523 } | |
524 if (var->IsContextSlot()) { | |
525 return current_function_builder_->EmitWithVarInt( | |
526 kExprLoadGlobal, LookupOrInsertGlobal(var, var_type)); | |
527 } else { | |
528 return current_function_builder_->EmitGetLocal( | |
529 LookupOrInsertLocal(var, var_type)); | |
530 } | |
531 } | 517 } |
532 } | 518 } |
533 } | 519 } |
534 | 520 |
535 void VisitLiteral(Literal* expr) { | 521 void VisitLiteral(Literal* expr) { |
536 Handle<Object> value = expr->value(); | 522 Handle<Object> value = expr->value(); |
537 if (!in_function_ || !value->IsNumber()) { | 523 if (!value->IsNumber() || (scope_ != kFuncScope && scope_ != kInitScope)) { |
538 return; | 524 return; |
539 } | 525 } |
540 Type* type = expr->bounds().upper; | 526 Type* type = expr->bounds().upper; |
541 if (type->Is(cache_.kAsmSigned)) { | 527 if (type->Is(cache_.kAsmSigned)) { |
542 int32_t i = 0; | 528 int32_t i = 0; |
543 if (!value->ToInt32(&i)) { | 529 if (!value->ToInt32(&i)) { |
544 UNREACHABLE(); | 530 UNREACHABLE(); |
545 } | 531 } |
546 byte code[] = {WASM_I32V(i)}; | 532 byte code[] = {WASM_I32V(i)}; |
547 current_function_builder_->EmitCode(code, sizeof(code)); | 533 current_function_builder_->EmitCode(code, sizeof(code)); |
(...skipping 13 matching lines...) Expand all Loading... |
561 UNREACHABLE(); | 547 UNREACHABLE(); |
562 } | 548 } |
563 } | 549 } |
564 | 550 |
565 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } | 551 void VisitRegExpLiteral(RegExpLiteral* expr) { UNREACHABLE(); } |
566 | 552 |
567 void VisitObjectLiteral(ObjectLiteral* expr) { | 553 void VisitObjectLiteral(ObjectLiteral* expr) { |
568 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); | 554 ZoneList<ObjectLiteralProperty*>* props = expr->properties(); |
569 for (int i = 0; i < props->length(); ++i) { | 555 for (int i = 0; i < props->length(); ++i) { |
570 ObjectLiteralProperty* prop = props->at(i); | 556 ObjectLiteralProperty* prop = props->at(i); |
571 DCHECK(marking_exported); | 557 DCHECK_EQ(kExportScope, scope_); |
572 VariableProxy* expr = prop->value()->AsVariableProxy(); | 558 VariableProxy* expr = prop->value()->AsVariableProxy(); |
573 DCHECK_NOT_NULL(expr); | 559 DCHECK_NOT_NULL(expr); |
574 Variable* var = expr->var(); | 560 Variable* var = expr->var(); |
575 Literal* name = prop->key()->AsLiteral(); | 561 Literal* name = prop->key()->AsLiteral(); |
576 DCHECK_NOT_NULL(name); | 562 DCHECK_NOT_NULL(name); |
577 DCHECK(name->IsPropertyName()); | 563 DCHECK(name->IsPropertyName()); |
578 const AstRawString* raw_name = name->AsRawPropertyName(); | 564 const AstRawString* raw_name = name->AsRawPropertyName(); |
579 if (var->is_function()) { | 565 if (var->is_function()) { |
580 uint16_t index = LookupOrInsertFunction(var); | 566 uint16_t index = LookupOrInsertFunction(var); |
581 builder_->FunctionAt(index)->Exported(1); | 567 builder_->FunctionAt(index)->Exported(1); |
582 builder_->FunctionAt(index) | 568 builder_->FunctionAt(index) |
583 ->SetName(raw_name->raw_data(), raw_name->length()); | 569 ->SetName(raw_name->raw_data(), raw_name->length()); |
584 } | 570 } |
585 } | 571 } |
586 } | 572 } |
587 | 573 |
588 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } | 574 void VisitArrayLiteral(ArrayLiteral* expr) { UNREACHABLE(); } |
589 | 575 |
590 void LoadInitFunction() { | 576 void LoadInitFunction() { |
591 current_function_builder_ = builder_->FunctionAt(init_function_index_); | 577 current_function_builder_ = builder_->FunctionAt(init_function_index_); |
592 in_function_ = true; | 578 scope_ = kInitScope; |
593 } | 579 } |
594 | 580 |
595 void UnLoadInitFunction() { | 581 void UnLoadInitFunction() { |
596 in_function_ = false; | 582 scope_ = kModuleScope; |
597 current_function_builder_ = nullptr; | 583 current_function_builder_ = nullptr; |
598 } | 584 } |
599 | 585 |
600 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { | 586 void AddFunctionTable(VariableProxy* table, ArrayLiteral* funcs) { |
601 FunctionType* func_type = | 587 FunctionType* func_type = |
602 funcs->bounds().lower->AsArray()->Element()->AsFunction(); | 588 funcs->bounds().lower->AsArray()->Element()->AsFunction(); |
603 LocalType return_type = TypeFrom(func_type->Result()); | 589 LocalType return_type = TypeFrom(func_type->Result()); |
604 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 590 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
605 func_type->Arity()); | 591 func_type->Arity()); |
606 if (return_type != kAstStmt) { | 592 if (return_type != kAstStmt) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 function->ReturnType(sig->GetReturn()); | 675 function->ReturnType(sig->GetReturn()); |
690 } | 676 } |
691 for (size_t i = 0; i < sig->parameter_count(); i++) { | 677 for (size_t i = 0; i < sig->parameter_count(); i++) { |
692 function->AddParam(sig->GetParam(i)); | 678 function->AddParam(sig->GetParam(i)); |
693 } | 679 } |
694 return index; | 680 return index; |
695 } | 681 } |
696 } | 682 } |
697 }; | 683 }; |
698 | 684 |
699 void VisitAssignment(Assignment* expr) { | 685 void EmitAssignmentLhs(Expression* target, MachineType* mtype) { |
700 bool in_init = false; | 686 // Match the left hand side of the assignment. |
701 if (!in_function_) { | 687 VariableProxy* target_var = target->AsVariableProxy(); |
702 BinaryOperation* binop = expr->value()->AsBinaryOperation(); | 688 if (target_var != nullptr) { |
703 if (binop != nullptr) { | 689 // Left hand side is a local or a global variable, no code on LHS. |
| 690 return; |
| 691 } |
| 692 |
| 693 Property* target_prop = target->AsProperty(); |
| 694 if (target_prop != nullptr) { |
| 695 // Left hand side is a property access, i.e. the asm.js heap. |
| 696 VisitPropertyAndEmitIndex(target_prop, mtype); |
| 697 return; |
| 698 } |
| 699 |
| 700 if (target_var == nullptr && target_prop == nullptr) { |
| 701 UNREACHABLE(); // invalid assignment. |
| 702 } |
| 703 } |
| 704 |
| 705 void EmitAssignmentRhs(Expression* target, Expression* value, bool* is_nop) { |
| 706 BinaryOperation* binop = value->AsBinaryOperation(); |
| 707 if (binop != nullptr) { |
| 708 if (scope_ == kInitScope) { |
| 709 // Handle foreign variables in the initialization scope. |
704 Property* prop = binop->left()->AsProperty(); | 710 Property* prop = binop->left()->AsProperty(); |
705 DCHECK_NOT_NULL(prop); | |
706 LoadInitFunction(); | |
707 is_set_op_ = true; | |
708 RECURSE(Visit(expr->target())); | |
709 DCHECK(!is_set_op_); | |
710 if (binop->op() == Token::MUL) { | 711 if (binop->op() == Token::MUL) { |
711 DCHECK(binop->right()->IsLiteral()); | 712 DCHECK(binop->right()->IsLiteral()); |
712 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 713 DCHECK_EQ(1.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
713 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 714 DCHECK(binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
714 VisitForeignVariable(true, prop); | 715 VisitForeignVariable(true, prop); |
| 716 return; |
715 } else if (binop->op() == Token::BIT_OR) { | 717 } else if (binop->op() == Token::BIT_OR) { |
716 DCHECK(binop->right()->IsLiteral()); | 718 DCHECK(binop->right()->IsLiteral()); |
717 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); | 719 DCHECK_EQ(0.0, binop->right()->AsLiteral()->raw_value()->AsNumber()); |
718 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); | 720 DCHECK(!binop->right()->AsLiteral()->raw_value()->ContainsDot()); |
719 VisitForeignVariable(false, prop); | 721 VisitForeignVariable(false, prop); |
| 722 return; |
720 } else { | 723 } else { |
721 UNREACHABLE(); | 724 UNREACHABLE(); |
722 } | 725 } |
723 UnLoadInitFunction(); | |
724 return; | |
725 } | 726 } |
| 727 if (MatchBinaryOperation(binop) == kAsIs) { |
| 728 VariableProxy* target_var = target->AsVariableProxy(); |
| 729 VariableProxy* effective_value_var = GetLeft(binop)->AsVariableProxy(); |
| 730 if (target_var != nullptr && effective_value_var != nullptr && |
| 731 target_var->var() == effective_value_var->var()) { |
| 732 *is_nop = true; |
| 733 return; |
| 734 } |
| 735 } |
| 736 } |
| 737 RECURSE(Visit(value)); |
| 738 } |
| 739 |
| 740 void EmitAssignment(Assignment* expr, MachineType mtype) { |
| 741 // Match the left hand side of the assignment. |
| 742 VariableProxy* target_var = expr->target()->AsVariableProxy(); |
| 743 if (target_var != nullptr) { |
| 744 // Left hand side is a local or a global variable. |
| 745 Variable* var = target_var->var(); |
| 746 LocalType var_type = TypeOf(expr); |
| 747 DCHECK_NE(kAstStmt, var_type); |
| 748 if (var->IsContextSlot()) { |
| 749 current_function_builder_->EmitWithVarInt( |
| 750 kExprStoreGlobal, LookupOrInsertGlobal(var, var_type)); |
| 751 } else { |
| 752 current_function_builder_->EmitSetLocal( |
| 753 LookupOrInsertLocal(var, var_type)); |
| 754 } |
| 755 } |
| 756 |
| 757 Property* target_prop = expr->target()->AsProperty(); |
| 758 if (target_prop != nullptr) { |
| 759 // Left hand side is a property access, i.e. the asm.js heap. |
| 760 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && |
| 761 expr->target()->AsProperty()->obj()->bounds().lower->Is( |
| 762 cache_.kFloat32Array)) { |
| 763 current_function_builder_->Emit(kExprF32ConvertF64); |
| 764 } |
| 765 current_function_builder_->EmitWithU8U8( |
| 766 WasmOpcodes::LoadStoreOpcodeOf(mtype, true), 0, 0); |
| 767 } |
| 768 |
| 769 if (target_var == nullptr && target_prop == nullptr) { |
| 770 UNREACHABLE(); // invalid assignment. |
| 771 } |
| 772 } |
| 773 |
| 774 void VisitAssignment(Assignment* expr) { |
| 775 bool as_init = false; |
| 776 if (scope_ == kModuleScope) { |
726 Property* prop = expr->value()->AsProperty(); | 777 Property* prop = expr->value()->AsProperty(); |
727 if (prop != nullptr) { | 778 if (prop != nullptr) { |
728 VariableProxy* vp = prop->obj()->AsVariableProxy(); | 779 VariableProxy* vp = prop->obj()->AsVariableProxy(); |
729 if (vp != nullptr && vp->var()->IsParameter() && | 780 if (vp != nullptr && vp->var()->IsParameter() && |
730 vp->var()->index() == 1) { | 781 vp->var()->index() == 1) { |
731 VariableProxy* target = expr->target()->AsVariableProxy(); | 782 VariableProxy* target = expr->target()->AsVariableProxy(); |
732 if (target->bounds().lower->Is(Type::Function())) { | 783 if (target->bounds().lower->Is(Type::Function())) { |
733 const AstRawString* name = | 784 const AstRawString* name = |
734 prop->key()->AsLiteral()->AsRawPropertyName(); | 785 prop->key()->AsLiteral()->AsRawPropertyName(); |
735 imported_function_table_.AddImport(target->var(), name->raw_data(), | 786 imported_function_table_.AddImport(target->var(), name->raw_data(), |
736 name->length()); | 787 name->length()); |
737 } | 788 } |
738 } | 789 } |
739 // Property values in module scope don't emit code, so return. | 790 // Property values in module scope don't emit code, so return. |
740 return; | 791 return; |
741 } | 792 } |
742 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); | 793 ArrayLiteral* funcs = expr->value()->AsArrayLiteral(); |
743 if (funcs != nullptr && | 794 if (funcs != nullptr && |
744 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { | 795 funcs->bounds().lower->AsArray()->Element()->IsFunction()) { |
745 VariableProxy* target = expr->target()->AsVariableProxy(); | 796 VariableProxy* target = expr->target()->AsVariableProxy(); |
746 DCHECK_NOT_NULL(target); | 797 DCHECK_NOT_NULL(target); |
747 AddFunctionTable(target, funcs); | 798 AddFunctionTable(target, funcs); |
748 // Only add to the function table. No init needed. | 799 // Only add to the function table. No init needed. |
749 return; | 800 return; |
750 } | 801 } |
751 if (expr->value()->IsCallNew()) { | 802 if (expr->value()->IsCallNew()) { |
752 // No init code to emit for CallNew nodes. | 803 // No init code to emit for CallNew nodes. |
753 return; | 804 return; |
754 } | 805 } |
755 in_init = true; | 806 as_init = true; |
756 LoadInitFunction(); | |
757 } | 807 } |
758 BinaryOperation* value_op = expr->value()->AsBinaryOperation(); | 808 |
759 if (value_op != nullptr && MatchBinaryOperation(value_op) == kAsIs) { | 809 if (as_init) LoadInitFunction(); |
760 VariableProxy* target_var = expr->target()->AsVariableProxy(); | 810 MachineType mtype; |
761 VariableProxy* effective_value_var = GetLeft(value_op)->AsVariableProxy(); | 811 bool is_nop = false; |
762 if (target_var != nullptr && effective_value_var != nullptr && | 812 EmitAssignmentLhs(expr->target(), &mtype); |
763 target_var->var() == effective_value_var->var()) { | 813 EmitAssignmentRhs(expr->target(), expr->value(), &is_nop); |
764 block_size_--; | 814 if (!is_nop) { |
765 return; | 815 EmitAssignment(expr, mtype); |
766 } | |
767 } | 816 } |
768 is_set_op_ = true; | 817 if (as_init) UnLoadInitFunction(); |
769 RECURSE(Visit(expr->target())); | |
770 DCHECK(!is_set_op_); | |
771 // Assignment to heapf32 from float64 converts. | |
772 if (TypeOf(expr->value()) == kAstF64 && expr->target()->IsProperty() && | |
773 expr->target()->AsProperty()->obj()->bounds().lower->Is( | |
774 cache_.kFloat32Array)) { | |
775 current_function_builder_->Emit(kExprF32ConvertF64); | |
776 } | |
777 RECURSE(Visit(expr->value())); | |
778 if (in_init) { | |
779 UnLoadInitFunction(); | |
780 } | |
781 } | 818 } |
782 | 819 |
783 void VisitYield(Yield* expr) { UNREACHABLE(); } | 820 void VisitYield(Yield* expr) { UNREACHABLE(); } |
784 | 821 |
785 void VisitThrow(Throw* expr) { UNREACHABLE(); } | 822 void VisitThrow(Throw* expr) { UNREACHABLE(); } |
786 | 823 |
787 void VisitForeignVariable(bool is_float, Property* expr) { | 824 void VisitForeignVariable(bool is_float, Property* expr) { |
788 DCHECK(expr->obj()->AsVariableProxy()); | 825 DCHECK(expr->obj()->AsVariableProxy()); |
789 DCHECK(VariableLocation::PARAMETER == | 826 DCHECK(VariableLocation::PARAMETER == |
790 expr->obj()->AsVariableProxy()->var()->location()); | 827 expr->obj()->AsVariableProxy()->var()->location()); |
(...skipping 18 matching lines...) Expand all Loading... |
809 return; | 846 return; |
810 } | 847 } |
811 } | 848 } |
812 } else { | 849 } else { |
813 MaybeHandle<Object> maybe_nvalue = | 850 MaybeHandle<Object> maybe_nvalue = |
814 i::Object::ToInt32(isolate_, value); | 851 i::Object::ToInt32(isolate_, value); |
815 if (!maybe_nvalue.is_null()) { | 852 if (!maybe_nvalue.is_null()) { |
816 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); | 853 Handle<Object> nvalue = maybe_nvalue.ToHandleChecked(); |
817 if (nvalue->IsNumber()) { | 854 if (nvalue->IsNumber()) { |
818 int32_t val = static_cast<int32_t>(nvalue->Number()); | 855 int32_t val = static_cast<int32_t>(nvalue->Number()); |
819 // TODO(bradnelson): variable size | 856 current_function_builder_->EmitI32Const(val); |
820 byte code[] = {WASM_I32V(val)}; | |
821 current_function_builder_->EmitCode(code, sizeof(code)); | |
822 return; | 857 return; |
823 } | 858 } |
824 } | 859 } |
825 } | 860 } |
826 } | 861 } |
827 } | 862 } |
828 if (is_float) { | 863 if (is_float) { |
829 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; | 864 byte code[] = {WASM_F64(std::numeric_limits<double>::quiet_NaN())}; |
830 current_function_builder_->EmitCode(code, sizeof(code)); | 865 current_function_builder_->EmitCode(code, sizeof(code)); |
831 } else { | 866 } else { |
832 byte code[] = {WASM_I32V_1(0)}; | 867 byte code[] = {WASM_I32V_1(0)}; |
833 current_function_builder_->EmitCode(code, sizeof(code)); | 868 current_function_builder_->EmitCode(code, sizeof(code)); |
834 } | 869 } |
835 } | 870 } |
836 | 871 |
837 void VisitProperty(Property* expr) { | 872 void VisitPropertyAndEmitIndex(Property* expr, MachineType* mtype) { |
838 Expression* obj = expr->obj(); | 873 Expression* obj = expr->obj(); |
839 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); | 874 DCHECK_EQ(obj->bounds().lower, obj->bounds().upper); |
840 Type* type = obj->bounds().lower; | 875 Type* type = obj->bounds().lower; |
841 MachineType mtype; | |
842 int size; | 876 int size; |
843 if (type->Is(cache_.kUint8Array)) { | 877 if (type->Is(cache_.kUint8Array)) { |
844 mtype = MachineType::Uint8(); | 878 *mtype = MachineType::Uint8(); |
845 size = 1; | 879 size = 1; |
846 } else if (type->Is(cache_.kInt8Array)) { | 880 } else if (type->Is(cache_.kInt8Array)) { |
847 mtype = MachineType::Int8(); | 881 *mtype = MachineType::Int8(); |
848 size = 1; | 882 size = 1; |
849 } else if (type->Is(cache_.kUint16Array)) { | 883 } else if (type->Is(cache_.kUint16Array)) { |
850 mtype = MachineType::Uint16(); | 884 *mtype = MachineType::Uint16(); |
851 size = 2; | 885 size = 2; |
852 } else if (type->Is(cache_.kInt16Array)) { | 886 } else if (type->Is(cache_.kInt16Array)) { |
853 mtype = MachineType::Int16(); | 887 *mtype = MachineType::Int16(); |
854 size = 2; | 888 size = 2; |
855 } else if (type->Is(cache_.kUint32Array)) { | 889 } else if (type->Is(cache_.kUint32Array)) { |
856 mtype = MachineType::Uint32(); | 890 *mtype = MachineType::Uint32(); |
857 size = 4; | 891 size = 4; |
858 } else if (type->Is(cache_.kInt32Array)) { | 892 } else if (type->Is(cache_.kInt32Array)) { |
859 mtype = MachineType::Int32(); | 893 *mtype = MachineType::Int32(); |
860 size = 4; | 894 size = 4; |
861 } else if (type->Is(cache_.kUint32Array)) { | 895 } else if (type->Is(cache_.kUint32Array)) { |
862 mtype = MachineType::Uint32(); | 896 *mtype = MachineType::Uint32(); |
863 size = 4; | 897 size = 4; |
864 } else if (type->Is(cache_.kFloat32Array)) { | 898 } else if (type->Is(cache_.kFloat32Array)) { |
865 mtype = MachineType::Float32(); | 899 *mtype = MachineType::Float32(); |
866 size = 4; | 900 size = 4; |
867 } else if (type->Is(cache_.kFloat64Array)) { | 901 } else if (type->Is(cache_.kFloat64Array)) { |
868 mtype = MachineType::Float64(); | 902 *mtype = MachineType::Float64(); |
869 size = 8; | 903 size = 8; |
870 } else { | 904 } else { |
871 UNREACHABLE(); | 905 UNREACHABLE(); |
872 } | 906 } |
873 // TODO(titzer): use special asm-compatibility opcodes? | |
874 current_function_builder_->EmitWithU8U8( | |
875 WasmOpcodes::LoadStoreOpcodeOf(mtype, is_set_op_), 0, 0); | |
876 is_set_op_ = false; | |
877 if (size == 1) { | 907 if (size == 1) { |
878 // Allow more general expression in byte arrays than the spec | 908 // Allow more general expression in byte arrays than the spec |
879 // strictly permits. | 909 // strictly permits. |
880 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in | 910 // Early versions of Emscripten emit HEAP8[HEAP32[..]|0] in |
881 // places that strictly should be HEAP8[HEAP32[..]>>0]. | 911 // places that strictly should be HEAP8[HEAP32[..]>>0]. |
882 RECURSE(Visit(expr->key())); | 912 RECURSE(Visit(expr->key())); |
883 return; | 913 return; |
884 } else { | 914 } |
885 Literal* value = expr->key()->AsLiteral(); | 915 |
886 if (value) { | 916 Literal* value = expr->key()->AsLiteral(); |
887 DCHECK(value->raw_value()->IsNumber()); | 917 if (value) { |
888 DCHECK_EQ(kAstI32, TypeOf(value)); | 918 DCHECK(value->raw_value()->IsNumber()); |
889 int val = static_cast<int>(value->raw_value()->AsNumber()); | 919 DCHECK_EQ(kAstI32, TypeOf(value)); |
890 // TODO(bradnelson): variable size | 920 int32_t val = static_cast<int32_t>(value->raw_value()->AsNumber()); |
891 byte code[] = {WASM_I32V(val * size)}; | 921 // TODO(titzer): handle overflow here. |
892 current_function_builder_->EmitCode(code, sizeof(code)); | 922 current_function_builder_->EmitI32Const(val * size); |
893 return; | 923 return; |
894 } | 924 } |
895 BinaryOperation* binop = expr->key()->AsBinaryOperation(); | 925 BinaryOperation* binop = expr->key()->AsBinaryOperation(); |
896 if (binop) { | 926 if (binop) { |
897 DCHECK_EQ(Token::SAR, binop->op()); | 927 DCHECK_EQ(Token::SAR, binop->op()); |
898 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); | 928 DCHECK(binop->right()->AsLiteral()->raw_value()->IsNumber()); |
899 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); | 929 DCHECK(kAstI32 == TypeOf(binop->right()->AsLiteral())); |
900 DCHECK_EQ(size, | 930 DCHECK_EQ(size, |
901 1 << static_cast<int>( | 931 1 << static_cast<int>( |
902 binop->right()->AsLiteral()->raw_value()->AsNumber())); | 932 binop->right()->AsLiteral()->raw_value()->AsNumber())); |
903 // Mask bottom bits to match asm.js behavior. | 933 // Mask bottom bits to match asm.js behavior. |
904 current_function_builder_->Emit(kExprI32And); | 934 byte mask = static_cast<byte>(~(size - 1)); |
905 byte code[] = {WASM_I8(~(size - 1))}; | 935 RECURSE(Visit(binop->left())); |
906 current_function_builder_->EmitCode(code, sizeof(code)); | 936 current_function_builder_->EmitWithU8(kExprI8Const, mask); |
907 RECURSE(Visit(binop->left())); | 937 current_function_builder_->Emit(kExprI32And); |
908 return; | 938 return; |
909 } | |
910 } | 939 } |
911 UNREACHABLE(); | 940 UNREACHABLE(); |
912 } | 941 } |
913 | 942 |
| 943 void VisitProperty(Property* expr) { |
| 944 MachineType mtype; |
| 945 VisitPropertyAndEmitIndex(expr, &mtype); |
| 946 current_function_builder_->EmitWithU8U8( |
| 947 WasmOpcodes::LoadStoreOpcodeOf(mtype, false), 0, 0); |
| 948 } |
| 949 |
914 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { | 950 bool VisitStdlibFunction(Call* call, VariableProxy* expr) { |
915 Variable* var = expr->var(); | 951 Variable* var = expr->var(); |
916 AsmTyper::StandardMember standard_object = | 952 AsmTyper::StandardMember standard_object = |
917 typer_->VariableAsStandardMember(var); | 953 typer_->VariableAsStandardMember(var); |
918 ZoneList<Expression*>* args = call->arguments(); | 954 ZoneList<Expression*>* args = call->arguments(); |
919 LocalType call_type = TypeOf(call); | 955 LocalType call_type = TypeOf(call); |
| 956 |
920 switch (standard_object) { | 957 switch (standard_object) { |
921 case AsmTyper::kNone: { | 958 case AsmTyper::kNone: { |
922 return false; | 959 return false; |
923 } | 960 } |
924 case AsmTyper::kMathAcos: { | 961 case AsmTyper::kMathAcos: { |
| 962 VisitCallArgs(call); |
925 DCHECK_EQ(kAstF64, call_type); | 963 DCHECK_EQ(kAstF64, call_type); |
926 current_function_builder_->Emit(kExprF64Acos); | 964 current_function_builder_->Emit(kExprF64Acos); |
927 break; | 965 break; |
928 } | 966 } |
929 case AsmTyper::kMathAsin: { | 967 case AsmTyper::kMathAsin: { |
| 968 VisitCallArgs(call); |
930 DCHECK_EQ(kAstF64, call_type); | 969 DCHECK_EQ(kAstF64, call_type); |
931 current_function_builder_->Emit(kExprF64Asin); | 970 current_function_builder_->Emit(kExprF64Asin); |
932 break; | 971 break; |
933 } | 972 } |
934 case AsmTyper::kMathAtan: { | 973 case AsmTyper::kMathAtan: { |
| 974 VisitCallArgs(call); |
935 DCHECK_EQ(kAstF64, call_type); | 975 DCHECK_EQ(kAstF64, call_type); |
936 current_function_builder_->Emit(kExprF64Atan); | 976 current_function_builder_->Emit(kExprF64Atan); |
937 break; | 977 break; |
938 } | 978 } |
939 case AsmTyper::kMathCos: { | 979 case AsmTyper::kMathCos: { |
| 980 VisitCallArgs(call); |
940 DCHECK_EQ(kAstF64, call_type); | 981 DCHECK_EQ(kAstF64, call_type); |
941 current_function_builder_->Emit(kExprF64Cos); | 982 current_function_builder_->Emit(kExprF64Cos); |
942 break; | 983 break; |
943 } | 984 } |
944 case AsmTyper::kMathSin: { | 985 case AsmTyper::kMathSin: { |
| 986 VisitCallArgs(call); |
945 DCHECK_EQ(kAstF64, call_type); | 987 DCHECK_EQ(kAstF64, call_type); |
946 current_function_builder_->Emit(kExprF64Sin); | 988 current_function_builder_->Emit(kExprF64Sin); |
947 break; | 989 break; |
948 } | 990 } |
949 case AsmTyper::kMathTan: { | 991 case AsmTyper::kMathTan: { |
| 992 VisitCallArgs(call); |
950 DCHECK_EQ(kAstF64, call_type); | 993 DCHECK_EQ(kAstF64, call_type); |
951 current_function_builder_->Emit(kExprF64Tan); | 994 current_function_builder_->Emit(kExprF64Tan); |
952 break; | 995 break; |
953 } | 996 } |
954 case AsmTyper::kMathExp: { | 997 case AsmTyper::kMathExp: { |
| 998 VisitCallArgs(call); |
955 DCHECK_EQ(kAstF64, call_type); | 999 DCHECK_EQ(kAstF64, call_type); |
956 current_function_builder_->Emit(kExprF64Exp); | 1000 current_function_builder_->Emit(kExprF64Exp); |
957 break; | 1001 break; |
958 } | 1002 } |
959 case AsmTyper::kMathLog: { | 1003 case AsmTyper::kMathLog: { |
| 1004 VisitCallArgs(call); |
960 DCHECK_EQ(kAstF64, call_type); | 1005 DCHECK_EQ(kAstF64, call_type); |
961 current_function_builder_->Emit(kExprF64Log); | 1006 current_function_builder_->Emit(kExprF64Log); |
962 break; | 1007 break; |
963 } | 1008 } |
964 case AsmTyper::kMathCeil: { | 1009 case AsmTyper::kMathCeil: { |
| 1010 VisitCallArgs(call); |
965 if (call_type == kAstF32) { | 1011 if (call_type == kAstF32) { |
966 current_function_builder_->Emit(kExprF32Ceil); | 1012 current_function_builder_->Emit(kExprF32Ceil); |
967 } else if (call_type == kAstF64) { | 1013 } else if (call_type == kAstF64) { |
968 current_function_builder_->Emit(kExprF64Ceil); | 1014 current_function_builder_->Emit(kExprF64Ceil); |
969 } else { | 1015 } else { |
970 UNREACHABLE(); | 1016 UNREACHABLE(); |
971 } | 1017 } |
972 break; | 1018 break; |
973 } | 1019 } |
974 case AsmTyper::kMathFloor: { | 1020 case AsmTyper::kMathFloor: { |
| 1021 VisitCallArgs(call); |
975 if (call_type == kAstF32) { | 1022 if (call_type == kAstF32) { |
976 current_function_builder_->Emit(kExprF32Floor); | 1023 current_function_builder_->Emit(kExprF32Floor); |
977 } else if (call_type == kAstF64) { | 1024 } else if (call_type == kAstF64) { |
978 current_function_builder_->Emit(kExprF64Floor); | 1025 current_function_builder_->Emit(kExprF64Floor); |
979 } else { | 1026 } else { |
980 UNREACHABLE(); | 1027 UNREACHABLE(); |
981 } | 1028 } |
982 break; | 1029 break; |
983 } | 1030 } |
984 case AsmTyper::kMathSqrt: { | 1031 case AsmTyper::kMathSqrt: { |
| 1032 VisitCallArgs(call); |
985 if (call_type == kAstF32) { | 1033 if (call_type == kAstF32) { |
986 current_function_builder_->Emit(kExprF32Sqrt); | 1034 current_function_builder_->Emit(kExprF32Sqrt); |
987 } else if (call_type == kAstF64) { | 1035 } else if (call_type == kAstF64) { |
988 current_function_builder_->Emit(kExprF64Sqrt); | 1036 current_function_builder_->Emit(kExprF64Sqrt); |
989 } else { | 1037 } else { |
990 UNREACHABLE(); | 1038 UNREACHABLE(); |
991 } | 1039 } |
992 break; | 1040 break; |
993 } | 1041 } |
994 case AsmTyper::kMathAbs: { | 1042 case AsmTyper::kMathAbs: { |
995 // TODO(bradnelson): Should this be cast to float? | |
996 if (call_type == kAstI32) { | 1043 if (call_type == kAstI32) { |
997 current_function_builder_->Emit(kExprIfElse); | 1044 uint16_t tmp = current_function_builder_->AddLocal(kAstI32); |
998 current_function_builder_->Emit(kExprI32LtS); | 1045 |
999 Visit(args->at(0)); | 1046 // if set_local(tmp, x) < 0 |
| 1047 Visit(call->arguments()->at(0)); |
| 1048 current_function_builder_->EmitSetLocal(tmp); |
1000 byte code[] = {WASM_I8(0)}; | 1049 byte code[] = {WASM_I8(0)}; |
1001 current_function_builder_->EmitCode(code, sizeof(code)); | 1050 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1051 current_function_builder_->Emit(kExprI32LtS); |
| 1052 current_function_builder_->Emit(kExprIf); |
| 1053 |
| 1054 // then (0 - tmp) |
| 1055 current_function_builder_->EmitCode(code, sizeof(code)); |
| 1056 current_function_builder_->EmitGetLocal(tmp); |
1002 current_function_builder_->Emit(kExprI32Sub); | 1057 current_function_builder_->Emit(kExprI32Sub); |
1003 current_function_builder_->EmitCode(code, sizeof(code)); | 1058 |
1004 Visit(args->at(0)); | 1059 // else tmp |
| 1060 current_function_builder_->Emit(kExprElse); |
| 1061 current_function_builder_->EmitGetLocal(tmp); |
| 1062 // end |
| 1063 current_function_builder_->Emit(kExprEnd); |
| 1064 |
1005 } else if (call_type == kAstF32) { | 1065 } else if (call_type == kAstF32) { |
| 1066 VisitCallArgs(call); |
1006 current_function_builder_->Emit(kExprF32Abs); | 1067 current_function_builder_->Emit(kExprF32Abs); |
1007 } else if (call_type == kAstF64) { | 1068 } else if (call_type == kAstF64) { |
| 1069 VisitCallArgs(call); |
1008 current_function_builder_->Emit(kExprF64Abs); | 1070 current_function_builder_->Emit(kExprF64Abs); |
1009 } else { | 1071 } else { |
1010 UNREACHABLE(); | 1072 UNREACHABLE(); |
1011 } | 1073 } |
1012 break; | 1074 break; |
1013 } | 1075 } |
1014 case AsmTyper::kMathMin: { | 1076 case AsmTyper::kMathMin: { |
1015 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. | 1077 // TODO(bradnelson): Change wasm to match Math.min in asm.js mode. |
1016 if (call_type == kAstI32) { | 1078 if (call_type == kAstI32) { |
1017 current_function_builder_->Emit(kExprIfElse); | 1079 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
| 1080 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
| 1081 |
| 1082 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
| 1083 Visit(call->arguments()->at(0)); |
| 1084 current_function_builder_->EmitSetLocal(tmp_x); |
| 1085 |
| 1086 Visit(call->arguments()->at(1)); |
| 1087 current_function_builder_->EmitSetLocal(tmp_y); |
| 1088 |
1018 current_function_builder_->Emit(kExprI32LeS); | 1089 current_function_builder_->Emit(kExprI32LeS); |
1019 Visit(args->at(0)); | 1090 current_function_builder_->Emit(kExprIf); |
1020 Visit(args->at(1)); | 1091 |
| 1092 // then tmp_x |
| 1093 current_function_builder_->EmitGetLocal(tmp_x); |
| 1094 |
| 1095 // else tmp_y |
| 1096 current_function_builder_->Emit(kExprElse); |
| 1097 current_function_builder_->EmitGetLocal(tmp_y); |
| 1098 current_function_builder_->Emit(kExprEnd); |
| 1099 |
1021 } else if (call_type == kAstF32) { | 1100 } else if (call_type == kAstF32) { |
| 1101 VisitCallArgs(call); |
1022 current_function_builder_->Emit(kExprF32Min); | 1102 current_function_builder_->Emit(kExprF32Min); |
1023 } else if (call_type == kAstF64) { | 1103 } else if (call_type == kAstF64) { |
| 1104 VisitCallArgs(call); |
1024 current_function_builder_->Emit(kExprF64Min); | 1105 current_function_builder_->Emit(kExprF64Min); |
1025 } else { | 1106 } else { |
1026 UNREACHABLE(); | 1107 UNREACHABLE(); |
1027 } | 1108 } |
1028 break; | 1109 break; |
1029 } | 1110 } |
1030 case AsmTyper::kMathMax: { | 1111 case AsmTyper::kMathMax: { |
1031 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. | 1112 // TODO(bradnelson): Change wasm to match Math.max in asm.js mode. |
1032 if (call_type == kAstI32) { | 1113 if (call_type == kAstI32) { |
1033 current_function_builder_->Emit(kExprIfElse); | 1114 uint16_t tmp_x = current_function_builder_->AddLocal(kAstI32); |
1034 current_function_builder_->Emit(kExprI32GtS); | 1115 uint16_t tmp_y = current_function_builder_->AddLocal(kAstI32); |
1035 Visit(args->at(0)); | 1116 |
1036 Visit(args->at(1)); | 1117 // if set_local(tmp_x, x) < set_local(tmp_y, y) |
| 1118 Visit(call->arguments()->at(0)); |
| 1119 |
| 1120 current_function_builder_->EmitSetLocal(tmp_x); |
| 1121 |
| 1122 Visit(call->arguments()->at(1)); |
| 1123 current_function_builder_->EmitSetLocal(tmp_y); |
| 1124 |
| 1125 current_function_builder_->Emit(kExprI32LeS); |
| 1126 current_function_builder_->Emit(kExprIf); |
| 1127 |
| 1128 // then tmp_y |
| 1129 current_function_builder_->EmitGetLocal(tmp_y); |
| 1130 |
| 1131 // else tmp_x |
| 1132 current_function_builder_->Emit(kExprElse); |
| 1133 current_function_builder_->EmitGetLocal(tmp_x); |
| 1134 current_function_builder_->Emit(kExprEnd); |
| 1135 |
1037 } else if (call_type == kAstF32) { | 1136 } else if (call_type == kAstF32) { |
| 1137 VisitCallArgs(call); |
1038 current_function_builder_->Emit(kExprF32Max); | 1138 current_function_builder_->Emit(kExprF32Max); |
1039 } else if (call_type == kAstF64) { | 1139 } else if (call_type == kAstF64) { |
| 1140 VisitCallArgs(call); |
1040 current_function_builder_->Emit(kExprF64Max); | 1141 current_function_builder_->Emit(kExprF64Max); |
1041 } else { | 1142 } else { |
1042 UNREACHABLE(); | 1143 UNREACHABLE(); |
1043 } | 1144 } |
1044 break; | 1145 break; |
1045 } | 1146 } |
1046 case AsmTyper::kMathAtan2: { | 1147 case AsmTyper::kMathAtan2: { |
| 1148 VisitCallArgs(call); |
1047 DCHECK_EQ(kAstF64, call_type); | 1149 DCHECK_EQ(kAstF64, call_type); |
1048 current_function_builder_->Emit(kExprF64Atan2); | 1150 current_function_builder_->Emit(kExprF64Atan2); |
1049 break; | 1151 break; |
1050 } | 1152 } |
1051 case AsmTyper::kMathPow: { | 1153 case AsmTyper::kMathPow: { |
| 1154 VisitCallArgs(call); |
1052 DCHECK_EQ(kAstF64, call_type); | 1155 DCHECK_EQ(kAstF64, call_type); |
1053 current_function_builder_->Emit(kExprF64Pow); | 1156 current_function_builder_->Emit(kExprF64Pow); |
1054 break; | 1157 break; |
1055 } | 1158 } |
1056 case AsmTyper::kMathImul: { | 1159 case AsmTyper::kMathImul: { |
| 1160 VisitCallArgs(call); |
1057 current_function_builder_->Emit(kExprI32Mul); | 1161 current_function_builder_->Emit(kExprI32Mul); |
1058 break; | 1162 break; |
1059 } | 1163 } |
1060 case AsmTyper::kMathFround: { | 1164 case AsmTyper::kMathFround: { |
1061 DCHECK(args->length() == 1); | 1165 DCHECK(args->length() == 1); |
1062 Literal* literal = args->at(0)->AsLiteral(); | 1166 Literal* literal = args->at(0)->AsLiteral(); |
1063 if (literal != nullptr) { | 1167 if (literal != nullptr) { |
| 1168 // constant fold Math.fround(#const); |
1064 if (literal->raw_value()->IsNumber()) { | 1169 if (literal->raw_value()->IsNumber()) { |
1065 float val = static_cast<float>(literal->raw_value()->AsNumber()); | 1170 float val = static_cast<float>(literal->raw_value()->AsNumber()); |
1066 byte code[] = {WASM_F32(val)}; | 1171 byte code[] = {WASM_F32(val)}; |
1067 current_function_builder_->EmitCode(code, sizeof(code)); | 1172 current_function_builder_->EmitCode(code, sizeof(code)); |
1068 return true; | 1173 return true; |
1069 } | 1174 } |
1070 } | 1175 } |
| 1176 VisitCallArgs(call); |
1071 switch (TypeIndexOf(args->at(0))) { | 1177 switch (TypeIndexOf(args->at(0))) { |
1072 case kInt32: | 1178 case kInt32: |
1073 case kFixnum: | 1179 case kFixnum: |
1074 current_function_builder_->Emit(kExprF32SConvertI32); | 1180 current_function_builder_->Emit(kExprF32SConvertI32); |
1075 break; | 1181 break; |
1076 case kUint32: | 1182 case kUint32: |
1077 current_function_builder_->Emit(kExprF32UConvertI32); | 1183 current_function_builder_->Emit(kExprF32UConvertI32); |
1078 break; | 1184 break; |
1079 case kFloat32: | 1185 case kFloat32: |
1080 break; | 1186 break; |
1081 case kFloat64: | 1187 case kFloat64: |
1082 current_function_builder_->Emit(kExprF32ConvertF64); | 1188 current_function_builder_->Emit(kExprF32ConvertF64); |
1083 break; | 1189 break; |
1084 default: | 1190 default: |
1085 UNREACHABLE(); | 1191 UNREACHABLE(); |
1086 } | 1192 } |
1087 break; | 1193 break; |
1088 } | 1194 } |
1089 default: { | 1195 default: { |
1090 UNREACHABLE(); | 1196 UNREACHABLE(); |
1091 break; | 1197 break; |
1092 } | 1198 } |
1093 } | 1199 } |
1094 VisitCallArgs(call); | |
1095 return true; | 1200 return true; |
1096 } | 1201 } |
1097 | 1202 |
1098 void VisitCallArgs(Call* expr) { | 1203 void VisitCallArgs(Call* expr) { |
1099 ZoneList<Expression*>* args = expr->arguments(); | 1204 ZoneList<Expression*>* args = expr->arguments(); |
1100 for (int i = 0; i < args->length(); ++i) { | 1205 for (int i = 0; i < args->length(); ++i) { |
1101 Expression* arg = args->at(i); | 1206 Expression* arg = args->at(i); |
1102 RECURSE(Visit(arg)); | 1207 RECURSE(Visit(arg)); |
1103 } | 1208 } |
1104 } | 1209 } |
1105 | 1210 |
1106 void VisitCall(Call* expr) { | 1211 void VisitCall(Call* expr) { |
1107 Call::CallType call_type = expr->GetCallType(isolate_); | 1212 Call::CallType call_type = expr->GetCallType(isolate_); |
1108 switch (call_type) { | 1213 switch (call_type) { |
1109 case Call::OTHER_CALL: { | 1214 case Call::OTHER_CALL: { |
1110 DCHECK(in_function_); | 1215 DCHECK_EQ(kFuncScope, scope_); |
1111 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1216 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
1112 if (proxy != nullptr) { | 1217 if (proxy != nullptr) { |
1113 if (VisitStdlibFunction(expr, proxy)) { | 1218 if (VisitStdlibFunction(expr, proxy)) { |
1114 return; | 1219 return; |
1115 } | 1220 } |
1116 } | 1221 } |
1117 uint16_t index; | 1222 uint16_t index; |
1118 VariableProxy* vp = expr->expression()->AsVariableProxy(); | 1223 VariableProxy* vp = expr->expression()->AsVariableProxy(); |
1119 if (vp != nullptr && | 1224 if (vp != nullptr && |
1120 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { | 1225 Type::Any()->Is(vp->bounds().lower->AsFunction()->Result())) { |
1121 LocalType return_type = TypeOf(expr); | 1226 LocalType return_type = TypeOf(expr); |
1122 ZoneList<Expression*>* args = expr->arguments(); | 1227 ZoneList<Expression*>* args = expr->arguments(); |
1123 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, | 1228 FunctionSig::Builder sig(zone(), return_type == kAstStmt ? 0 : 1, |
1124 args->length()); | 1229 args->length()); |
1125 if (return_type != kAstStmt) { | 1230 if (return_type != kAstStmt) { |
1126 sig.AddReturn(return_type); | 1231 sig.AddReturn(return_type); |
1127 } | 1232 } |
1128 for (int i = 0; i < args->length(); i++) { | 1233 for (int i = 0; i < args->length(); i++) { |
1129 sig.AddParam(TypeOf(args->at(i))); | 1234 sig.AddParam(TypeOf(args->at(i))); |
1130 } | 1235 } |
1131 index = | 1236 index = |
1132 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); | 1237 imported_function_table_.GetFunctionIndex(vp->var(), sig.Build()); |
1133 } else { | 1238 } else { |
1134 index = LookupOrInsertFunction(vp->var()); | 1239 index = LookupOrInsertFunction(vp->var()); |
1135 } | 1240 } |
| 1241 VisitCallArgs(expr); |
1136 current_function_builder_->Emit(kExprCallFunction); | 1242 current_function_builder_->Emit(kExprCallFunction); |
| 1243 current_function_builder_->EmitVarInt(expr->arguments()->length()); |
1137 current_function_builder_->EmitVarInt(index); | 1244 current_function_builder_->EmitVarInt(index); |
1138 break; | 1245 break; |
1139 } | 1246 } |
1140 case Call::KEYED_PROPERTY_CALL: { | 1247 case Call::KEYED_PROPERTY_CALL: { |
1141 DCHECK(in_function_); | 1248 DCHECK_EQ(kFuncScope, scope_); |
1142 Property* p = expr->expression()->AsProperty(); | 1249 Property* p = expr->expression()->AsProperty(); |
1143 DCHECK_NOT_NULL(p); | 1250 DCHECK_NOT_NULL(p); |
1144 VariableProxy* var = p->obj()->AsVariableProxy(); | 1251 VariableProxy* var = p->obj()->AsVariableProxy(); |
1145 DCHECK_NOT_NULL(var); | 1252 DCHECK_NOT_NULL(var); |
1146 FunctionTableIndices* indices = LookupFunctionTable(var->var()); | 1253 FunctionTableIndices* indices = LookupFunctionTable(var->var()); |
1147 current_function_builder_->EmitWithVarInt(kExprCallIndirect, | 1254 RECURSE(Visit(p->key())); |
1148 indices->signature_index); | 1255 current_function_builder_->EmitI32Const(indices->start_index); |
1149 current_function_builder_->Emit(kExprI32Add); | 1256 current_function_builder_->Emit(kExprI32Add); |
1150 // TODO(bradnelson): variable size | 1257 VisitCallArgs(expr); |
1151 byte code[] = {WASM_I32V(indices->start_index)}; | 1258 current_function_builder_->Emit(kExprCallIndirect); |
1152 current_function_builder_->EmitCode(code, sizeof(code)); | 1259 current_function_builder_->EmitVarInt(expr->arguments()->length()); |
1153 RECURSE(Visit(p->key())); | 1260 current_function_builder_->EmitVarInt(indices->signature_index); |
1154 break; | 1261 break; |
1155 } | 1262 } |
1156 default: | 1263 default: |
1157 UNREACHABLE(); | 1264 UNREACHABLE(); |
1158 } | 1265 } |
1159 VisitCallArgs(expr); | |
1160 } | 1266 } |
1161 | 1267 |
1162 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } | 1268 void VisitCallNew(CallNew* expr) { UNREACHABLE(); } |
1163 | 1269 |
1164 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } | 1270 void VisitCallRuntime(CallRuntime* expr) { UNREACHABLE(); } |
1165 | 1271 |
1166 void VisitUnaryOperation(UnaryOperation* expr) { | 1272 void VisitUnaryOperation(UnaryOperation* expr) { |
| 1273 RECURSE(Visit(expr->expression())); |
1167 switch (expr->op()) { | 1274 switch (expr->op()) { |
1168 case Token::NOT: { | 1275 case Token::NOT: { |
1169 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); | 1276 DCHECK_EQ(kAstI32, TypeOf(expr->expression())); |
1170 current_function_builder_->Emit(kExprI32Eqz); | 1277 current_function_builder_->Emit(kExprI32Eqz); |
1171 break; | 1278 break; |
1172 } | 1279 } |
1173 default: | 1280 default: |
1174 UNREACHABLE(); | 1281 UNREACHABLE(); |
1175 } | 1282 } |
1176 RECURSE(Visit(expr->expression())); | |
1177 } | 1283 } |
1178 | 1284 |
1179 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } | 1285 void VisitCountOperation(CountOperation* expr) { UNREACHABLE(); } |
1180 | 1286 |
1181 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, | 1287 bool MatchIntBinaryOperation(BinaryOperation* expr, Token::Value op, |
1182 int32_t val) { | 1288 int32_t val) { |
1183 DCHECK_NOT_NULL(expr->right()); | 1289 DCHECK_NOT_NULL(expr->right()); |
1184 if (expr->op() == op && expr->right()->IsLiteral() && | 1290 if (expr->op() == op && expr->right()->IsLiteral() && |
1185 TypeOf(expr) == kAstI32) { | 1291 TypeOf(expr) == kAstI32) { |
1186 Literal* right = expr->right()->AsLiteral(); | 1292 Literal* right = expr->right()->AsLiteral(); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 if (expr->op() == Token::BIT_XOR) { | 1418 if (expr->op() == Token::BIT_XOR) { |
1313 return expr->left()->AsBinaryOperation()->left(); | 1419 return expr->left()->AsBinaryOperation()->left(); |
1314 } else { | 1420 } else { |
1315 return expr->left(); | 1421 return expr->left(); |
1316 } | 1422 } |
1317 } | 1423 } |
1318 | 1424 |
1319 void VisitBinaryOperation(BinaryOperation* expr) { | 1425 void VisitBinaryOperation(BinaryOperation* expr) { |
1320 ConvertOperation convertOperation = MatchBinaryOperation(expr); | 1426 ConvertOperation convertOperation = MatchBinaryOperation(expr); |
1321 if (convertOperation == kToDouble) { | 1427 if (convertOperation == kToDouble) { |
| 1428 RECURSE(Visit(expr->left())); |
1322 TypeIndex type = TypeIndexOf(expr->left()); | 1429 TypeIndex type = TypeIndexOf(expr->left()); |
1323 if (type == kInt32 || type == kFixnum) { | 1430 if (type == kInt32 || type == kFixnum) { |
1324 current_function_builder_->Emit(kExprF64SConvertI32); | 1431 current_function_builder_->Emit(kExprF64SConvertI32); |
1325 } else if (type == kUint32) { | 1432 } else if (type == kUint32) { |
1326 current_function_builder_->Emit(kExprF64UConvertI32); | 1433 current_function_builder_->Emit(kExprF64UConvertI32); |
1327 } else if (type == kFloat32) { | 1434 } else if (type == kFloat32) { |
1328 current_function_builder_->Emit(kExprF64ConvertF32); | 1435 current_function_builder_->Emit(kExprF64ConvertF32); |
1329 } else { | 1436 } else { |
1330 UNREACHABLE(); | 1437 UNREACHABLE(); |
1331 } | 1438 } |
1332 RECURSE(Visit(expr->left())); | |
1333 } else if (convertOperation == kToInt) { | 1439 } else if (convertOperation == kToInt) { |
| 1440 RECURSE(Visit(GetLeft(expr))); |
1334 TypeIndex type = TypeIndexOf(GetLeft(expr)); | 1441 TypeIndex type = TypeIndexOf(GetLeft(expr)); |
1335 if (type == kFloat32) { | 1442 if (type == kFloat32) { |
1336 current_function_builder_->Emit(kExprI32SConvertF32); | 1443 current_function_builder_->Emit(kExprI32SConvertF32); |
1337 } else if (type == kFloat64) { | 1444 } else if (type == kFloat64) { |
1338 current_function_builder_->Emit(kExprI32SConvertF64); | 1445 current_function_builder_->Emit(kExprI32SConvertF64); |
1339 } else { | 1446 } else { |
1340 UNREACHABLE(); | 1447 UNREACHABLE(); |
1341 } | 1448 } |
1342 RECURSE(Visit(GetLeft(expr))); | |
1343 } else if (convertOperation == kAsIs) { | 1449 } else if (convertOperation == kAsIs) { |
1344 RECURSE(Visit(GetLeft(expr))); | 1450 RECURSE(Visit(GetLeft(expr))); |
1345 } else { | 1451 } else { |
| 1452 if (expr->op() == Token::COMMA) { |
| 1453 current_function_builder_->Emit(kExprBlock); |
| 1454 } |
| 1455 |
| 1456 RECURSE(Visit(expr->left())); |
| 1457 RECURSE(Visit(expr->right())); |
| 1458 |
| 1459 if (expr->op() == Token::COMMA) { |
| 1460 current_function_builder_->Emit(kExprEnd); |
| 1461 } |
| 1462 |
1346 switch (expr->op()) { | 1463 switch (expr->op()) { |
1347 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); | 1464 BINOP_CASE(Token::ADD, Add, NON_SIGNED_BINOP, true); |
1348 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); | 1465 BINOP_CASE(Token::SUB, Sub, NON_SIGNED_BINOP, true); |
1349 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); | 1466 BINOP_CASE(Token::MUL, Mul, NON_SIGNED_BINOP, true); |
1350 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); | 1467 BINOP_CASE(Token::DIV, Div, SIGNED_BINOP, false); |
1351 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); | 1468 BINOP_CASE(Token::BIT_OR, Ior, NON_SIGNED_INT_BINOP, true); |
1352 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); | 1469 BINOP_CASE(Token::BIT_AND, And, NON_SIGNED_INT_BINOP, true); |
1353 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); | 1470 BINOP_CASE(Token::BIT_XOR, Xor, NON_SIGNED_INT_BINOP, true); |
1354 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); | 1471 BINOP_CASE(Token::SHL, Shl, NON_SIGNED_INT_BINOP, true); |
1355 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); | 1472 BINOP_CASE(Token::SAR, ShrS, NON_SIGNED_INT_BINOP, true); |
1356 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); | 1473 BINOP_CASE(Token::SHR, ShrU, NON_SIGNED_INT_BINOP, true); |
1357 case Token::MOD: { | 1474 case Token::MOD: { |
1358 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); | 1475 TypeIndex type = TypeIndexOf(expr->left(), expr->right(), false); |
1359 if (type == kInt32) { | 1476 if (type == kInt32) { |
1360 current_function_builder_->Emit(kExprI32RemS); | 1477 current_function_builder_->Emit(kExprI32RemS); |
1361 } else if (type == kUint32) { | 1478 } else if (type == kUint32) { |
1362 current_function_builder_->Emit(kExprI32RemU); | 1479 current_function_builder_->Emit(kExprI32RemU); |
1363 } else if (type == kFloat64) { | 1480 } else if (type == kFloat64) { |
1364 current_function_builder_->Emit(kExprF64Mod); | 1481 current_function_builder_->Emit(kExprF64Mod); |
1365 return; | 1482 return; |
1366 } else { | 1483 } else { |
1367 UNREACHABLE(); | 1484 UNREACHABLE(); |
1368 } | 1485 } |
1369 break; | 1486 break; |
1370 } | 1487 } |
1371 case Token::COMMA: { | 1488 case Token::COMMA: { |
1372 current_function_builder_->EmitWithVarInt(kExprBlock, 2); | |
1373 break; | 1489 break; |
1374 } | 1490 } |
1375 default: | 1491 default: |
1376 UNREACHABLE(); | 1492 UNREACHABLE(); |
1377 } | 1493 } |
1378 RECURSE(Visit(expr->left())); | |
1379 RECURSE(Visit(expr->right())); | |
1380 } | 1494 } |
1381 } | 1495 } |
1382 | 1496 |
1383 void VisitCompareOperation(CompareOperation* expr) { | 1497 void VisitCompareOperation(CompareOperation* expr) { |
| 1498 RECURSE(Visit(expr->left())); |
| 1499 RECURSE(Visit(expr->right())); |
1384 switch (expr->op()) { | 1500 switch (expr->op()) { |
1385 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); | 1501 BINOP_CASE(Token::EQ, Eq, NON_SIGNED_BINOP, false); |
1386 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); | 1502 BINOP_CASE(Token::LT, Lt, SIGNED_BINOP, false); |
1387 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); | 1503 BINOP_CASE(Token::LTE, Le, SIGNED_BINOP, false); |
1388 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); | 1504 BINOP_CASE(Token::GT, Gt, SIGNED_BINOP, false); |
1389 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); | 1505 BINOP_CASE(Token::GTE, Ge, SIGNED_BINOP, false); |
1390 default: | 1506 default: |
1391 UNREACHABLE(); | 1507 UNREACHABLE(); |
1392 } | 1508 } |
1393 RECURSE(Visit(expr->left())); | |
1394 RECURSE(Visit(expr->right())); | |
1395 } | 1509 } |
1396 | 1510 |
1397 #undef BINOP_CASE | 1511 #undef BINOP_CASE |
1398 #undef NON_SIGNED_INT_BINOP | 1512 #undef NON_SIGNED_INT_BINOP |
1399 #undef SIGNED_BINOP | 1513 #undef SIGNED_BINOP |
1400 #undef NON_SIGNED_BINOP | 1514 #undef NON_SIGNED_BINOP |
1401 | 1515 |
1402 enum TypeIndex { | 1516 enum TypeIndex { |
1403 kInt32 = 0, | 1517 kInt32 = 0, |
1404 kUint32 = 1, | 1518 kUint32 = 1, |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1546 } else { | 1660 } else { |
1547 return kAstStmt; | 1661 return kAstStmt; |
1548 } | 1662 } |
1549 } | 1663 } |
1550 | 1664 |
1551 Zone* zone() { return zone_; } | 1665 Zone* zone() { return zone_; } |
1552 | 1666 |
1553 ZoneHashMap local_variables_; | 1667 ZoneHashMap local_variables_; |
1554 ZoneHashMap functions_; | 1668 ZoneHashMap functions_; |
1555 ZoneHashMap global_variables_; | 1669 ZoneHashMap global_variables_; |
1556 bool in_function_; | 1670 AsmScope scope_; |
1557 bool is_set_op_; | |
1558 bool marking_exported; | |
1559 WasmModuleBuilder* builder_; | 1671 WasmModuleBuilder* builder_; |
1560 WasmFunctionBuilder* current_function_builder_; | 1672 WasmFunctionBuilder* current_function_builder_; |
1561 FunctionLiteral* literal_; | 1673 FunctionLiteral* literal_; |
1562 Isolate* isolate_; | 1674 Isolate* isolate_; |
1563 Zone* zone_; | 1675 Zone* zone_; |
1564 Handle<Object> foreign_; | 1676 Handle<Object> foreign_; |
1565 AsmTyper* typer_; | 1677 AsmTyper* typer_; |
1566 TypeCache const& cache_; | 1678 TypeCache const& cache_; |
1567 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; | 1679 ZoneVector<std::pair<BreakableStatement*, bool>> breakable_blocks_; |
1568 int block_size_; | |
1569 uint16_t init_function_index_; | 1680 uint16_t init_function_index_; |
1570 uint32_t next_table_index_; | 1681 uint32_t next_table_index_; |
1571 ZoneHashMap function_tables_; | 1682 ZoneHashMap function_tables_; |
1572 ImportedFunctionTable imported_function_table_; | 1683 ImportedFunctionTable imported_function_table_; |
1573 | 1684 |
1574 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); | 1685 DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); |
1575 | 1686 |
1576 private: | 1687 private: |
1577 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); | 1688 DISALLOW_COPY_AND_ASSIGN(AsmWasmBuilderImpl); |
1578 }; | 1689 }; |
(...skipping 11 matching lines...) Expand all Loading... |
1590 // that zone in constructor may be thrown away once wasm module is written. | 1701 // that zone in constructor may be thrown away once wasm module is written. |
1591 WasmModuleIndex* AsmWasmBuilder::Run() { | 1702 WasmModuleIndex* AsmWasmBuilder::Run() { |
1592 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); | 1703 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); |
1593 impl.Compile(); | 1704 impl.Compile(); |
1594 WasmModuleWriter* writer = impl.builder_->Build(zone_); | 1705 WasmModuleWriter* writer = impl.builder_->Build(zone_); |
1595 return writer->WriteTo(zone_); | 1706 return writer->WriteTo(zone_); |
1596 } | 1707 } |
1597 } // namespace wasm | 1708 } // namespace wasm |
1598 } // namespace internal | 1709 } // namespace internal |
1599 } // namespace v8 | 1710 } // namespace v8 |
OLD | NEW |