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

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

Powered by Google App Engine
This is Rietveld 408576698