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

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

Issue 1830663002: [wasm] Binary 11: AST changes. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/wasm/ast-decoder.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 // Required to get M_E etc. in MSVC. 7 // Required to get M_E etc. in MSVC.
8 #if defined(_WIN32) 8 #if defined(_WIN32)
9 #define _USE_MATH_DEFINES 9 #define _USE_MATH_DEFINES
10 #endif 10 #endif
(...skipping 13 matching lines...) Expand all
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/wasm/ast-decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698