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

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

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

Powered by Google App Engine
This is Rietveld 408576698