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

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

Powered by Google App Engine
This is Rietveld 408576698