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

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

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