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

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

Issue 1838973002: optimized switch implementation (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 8 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
11 #include <math.h> 11 #include <math.h>
12 12
13 #include "src/wasm/asm-wasm-builder.h" 13 #include "src/wasm/asm-wasm-builder.h"
14 #include "src/wasm/switch-logic.h"
14 #include "src/wasm/wasm-macro-gen.h" 15 #include "src/wasm/wasm-macro-gen.h"
15 #include "src/wasm/wasm-opcodes.h" 16 #include "src/wasm/wasm-opcodes.h"
16 17
17 #include "src/ast/ast.h" 18 #include "src/ast/ast.h"
18 #include "src/ast/scopes.h" 19 #include "src/ast/scopes.h"
19 #include "src/codegen.h" 20 #include "src/codegen.h"
20 #include "src/type-cache.h" 21 #include "src/type-cache.h"
21 22
22 namespace v8 { 23 namespace v8 {
23 namespace internal { 24 namespace internal {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 local_variables_.Clear(); 93 local_variables_.Clear();
93 } 94 }
94 95
95 void VisitImportDeclaration(ImportDeclaration* decl) {} 96 void VisitImportDeclaration(ImportDeclaration* decl) {}
96 97
97 void VisitExportDeclaration(ExportDeclaration* decl) {} 98 void VisitExportDeclaration(ExportDeclaration* decl) {}
98 99
99 void VisitStatements(ZoneList<Statement*>* stmts) { 100 void VisitStatements(ZoneList<Statement*>* stmts) {
100 for (int i = 0; i < stmts->length(); ++i) { 101 for (int i = 0; i < stmts->length(); ++i) {
101 Statement* stmt = stmts->at(i); 102 Statement* stmt = stmts->at(i);
103 ExpressionStatement* e = stmt->AsExpressionStatement();
104 if (e != nullptr && e->expression()->IsUndefinedLiteral()) {
105 block_size_--;
106 continue;
107 }
102 RECURSE(Visit(stmt)); 108 RECURSE(Visit(stmt));
103 if (stmt->IsJump()) break; 109 if (stmt->IsJump()) break;
104 } 110 }
105 } 111 }
106 112
107 void VisitBlock(Block* stmt) { 113 void VisitBlock(Block* stmt) {
108 if (stmt->statements()->length() == 1) { 114 if (stmt->statements()->length() == 1) {
109 ExpressionStatement* expr = 115 ExpressionStatement* expr =
110 stmt->statements()->at(0)->AsExpressionStatement(); 116 stmt->statements()->at(0)->AsExpressionStatement();
111 if (expr != nullptr) { 117 if (expr != nullptr) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 marking_exported = true; 234 marking_exported = true;
229 } 235 }
230 RECURSE(Visit(stmt->expression())); 236 RECURSE(Visit(stmt->expression()));
231 if (!in_function_) { 237 if (!in_function_) {
232 marking_exported = false; 238 marking_exported = false;
233 } 239 }
234 } 240 }
235 241
236 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); } 242 void VisitWithStatement(WithStatement* stmt) { UNREACHABLE(); }
237 243
238 void SetLocalTo(uint16_t index, int value) { 244 void GenerateCaseComparisonCode(int value, WasmOpcode op,
239 current_function_builder_->Emit(kExprSetLocal); 245 VariableProxy* tag) {
240 AddLeb128(index, true); 246 current_function_builder_->Emit(kExprIfElse);
241 // TODO(bradnelson): variable size 247 current_function_builder_->Emit(op);
248 VisitVariableProxy(tag);
242 byte code[] = {WASM_I32V(value)}; 249 byte code[] = {WASM_I32V(value)};
243 current_function_builder_->EmitCode(code, sizeof(code)); 250 current_function_builder_->EmitCode(code, sizeof(code));
244 block_size_++;
245 } 251 }
246 252
247 void CompileCase(CaseClause* clause, uint16_t fall_through, 253 void HandleCase(CaseNode* node,
248 VariableProxy* tag) { 254 const ZoneMap<int, unsigned int>& case_to_block,
249 Literal* label = clause->label()->AsLiteral(); 255 VariableProxy* tag, int default_block) {
250 DCHECK_NOT_NULL(label); 256 if (node->left != nullptr) {
251 block_size_++; 257 GenerateCaseComparisonCode(node->begin, kExprI32LtS, tag);
252 current_function_builder_->Emit(kExprIf); 258 HandleCase(node->left, case_to_block, tag, default_block);
253 current_function_builder_->Emit(kExprI32Ior); 259 }
254 current_function_builder_->Emit(kExprI32Eq); 260 if (node->right != nullptr) {
255 VisitVariableProxy(tag); 261 GenerateCaseComparisonCode(node->end, kExprI32GtS, tag);
256 VisitLiteral(label); 262 HandleCase(node->right, case_to_block, tag, default_block);
257 current_function_builder_->Emit(kExprGetLocal); 263 }
258 AddLeb128(fall_through, true); 264 if (node->begin == node->end) {
259 BlockVisitor visitor(this, nullptr, kExprBlock, false, 0); 265 current_function_builder_->Emit(kExprIf);
260 SetLocalTo(fall_through, 1); 266 current_function_builder_->Emit(kExprI32Eq);
261 ZoneList<Statement*>* stmts = clause->statements(); 267 VisitVariableProxy(tag);
262 block_size_ += stmts->length(); 268 byte code[] = {WASM_I32V(node->begin)};
263 RECURSE(VisitStatements(stmts)); 269 current_function_builder_->EmitCode(code, sizeof(code));
270 DCHECK(case_to_block.find(node->begin) != case_to_block.end());
271 current_function_builder_->EmitWithVarInt(kExprBr,
272 case_to_block.at(node->begin));
273 current_function_builder_->Emit(kExprNop);
274 } else {
275 current_function_builder_->Emit(kExprBrTable);
276 std::vector<uint8_t> count =
277 UnsignedLEB128From(node->end - node->begin + 1);
278 current_function_builder_->EmitCode(&count[0],
279 static_cast<uint32_t>(count.size()));
280 for (int v = node->begin; v <= node->end; v++) {
281 if (case_to_block.find(v) != case_to_block.end()) {
282 byte break_code[] = {BR_TARGET(case_to_block.at(v))};
283 current_function_builder_->EmitCode(break_code, sizeof(break_code));
284 } else {
285 byte break_code[] = {BR_TARGET(default_block)};
286 current_function_builder_->EmitCode(break_code, sizeof(break_code));
287 }
288 }
289 byte break_code[] = {BR_TARGET(default_block)};
290 current_function_builder_->EmitCode(break_code, sizeof(break_code));
291 if (node->begin != 0) {
bradn 2016/04/07 23:46:59 Can you add a TODO / comment that this is required
aseemgarg 2016/04/11 20:59:19 problem fixed now
aseemgarg 2016/04/11 21:00:32 Problem wasn't fixed. So, put the if back in with
292 current_function_builder_->Emit(kExprI32Sub);
293 VisitVariableProxy(tag);
294 byte code[] = {WASM_I32V(node->begin)};
295 current_function_builder_->EmitCode(code, sizeof(code));
296 } else {
297 VisitVariableProxy(tag);
298 }
299 }
264 } 300 }
265 301
266 void VisitSwitchStatement(SwitchStatement* stmt) { 302 void VisitSwitchStatement(SwitchStatement* stmt) {
267 VariableProxy* tag = stmt->tag()->AsVariableProxy(); 303 VariableProxy* tag = stmt->tag()->AsVariableProxy();
268 DCHECK_NOT_NULL(tag); 304 DCHECK_NOT_NULL(tag);
305 ZoneList<CaseClause*>* clauses = stmt->cases();
306 int case_count = clauses->length();
307 if (case_count == 0) {
308 block_size_--;
309 return;
310 }
269 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false, 311 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprBlock, false,
270 0); 312 1);
271 uint16_t fall_through = current_function_builder_->AddLocal(kAstI32); 313 ZoneVector<BlockVisitor*> blocks(zone_);
272 SetLocalTo(fall_through, 0); 314 ZoneVector<int32_t> cases(zone_);
273 315 ZoneMap<int, unsigned int> case_to_block(zone_);
274 ZoneList<CaseClause*>* clauses = stmt->cases(); 316 bool has_default = false;
275 for (int i = 0; i < clauses->length(); ++i) { 317 for (int i = case_count - 1; i >= 0; i--) {
276 CaseClause* clause = clauses->at(i); 318 CaseClause* clause = clauses->at(i);
319 blocks.push_back(new BlockVisitor(this, nullptr, kExprBlock, false,
320 clause->statements()->length() + 1));
277 if (!clause->is_default()) { 321 if (!clause->is_default()) {
278 CompileCase(clause, fall_through, tag); 322 Literal* label = clause->label()->AsLiteral();
323 Handle<Object> value = label->value();
324 DCHECK(value->IsNumber() &&
325 label->bounds().upper->Is(cache_.kAsmSigned));
326 int32_t label_value;
327 if (!value->ToInt32(&label_value)) {
328 UNREACHABLE();
329 }
330 case_to_block[label_value] = i;
331 cases.push_back(label_value);
279 } else { 332 } else {
280 ZoneList<Statement*>* stmts = clause->statements(); 333 DCHECK_EQ(i, case_count - 1);
281 block_size_ += stmts->length(); 334 has_default = true;
282 RECURSE(VisitStatements(stmts));
283 } 335 }
284 } 336 }
337 if (!has_default || case_count > 1) {
338 int default_block = has_default ? case_count - 1 : case_count;
339 BlockVisitor switch_logic_block(this, nullptr, kExprBlock, false, 1);
340 CaseNode* root = OrderCases(&cases, zone_);
341 HandleCase(root, case_to_block, tag, default_block);
342 if (root->left != nullptr || root->right != nullptr ||
343 root->begin == root->end) {
344 block_size_++;
345 current_function_builder_->EmitWithVarInt(kExprBr, default_block);
346 current_function_builder_->Emit(kExprNop);
347 }
348 } else {
349 block_size_ = clauses->at(0)->statements()->length();
350 }
351 for (int i = 0; i < case_count; i++) {
352 CaseClause* clause = clauses->at(i);
353 RECURSE(VisitStatements(clause->statements()));
354 BlockVisitor* v = blocks.at(case_count - i - 1);
355 blocks.pop_back();
356 delete v;
357 }
285 } 358 }
286 359
287 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); } 360 void VisitCaseClause(CaseClause* clause) { UNREACHABLE(); }
288 361
289 void VisitDoWhileStatement(DoWhileStatement* stmt) { 362 void VisitDoWhileStatement(DoWhileStatement* stmt) {
290 DCHECK(in_function_); 363 DCHECK(in_function_);
291 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true, 364 BlockVisitor visitor(this, stmt->AsBreakableStatement(), kExprLoop, true,
292 2); 365 2);
293 RECURSE(Visit(stmt->body())); 366 RECURSE(Visit(stmt->body()));
294 current_function_builder_->Emit(kExprIf); 367 current_function_builder_->Emit(kExprIf);
(...skipping 1238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 // that zone in constructor may be thrown away once wasm module is written. 1606 // that zone in constructor may be thrown away once wasm module is written.
1534 WasmModuleIndex* AsmWasmBuilder::Run() { 1607 WasmModuleIndex* AsmWasmBuilder::Run() {
1535 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_); 1608 AsmWasmBuilderImpl impl(isolate_, zone_, literal_, foreign_, typer_);
1536 impl.Compile(); 1609 impl.Compile();
1537 WasmModuleWriter* writer = impl.builder_->Build(zone_); 1610 WasmModuleWriter* writer = impl.builder_->Build(zone_);
1538 return writer->WriteTo(zone_); 1611 return writer->WriteTo(zone_);
1539 } 1612 }
1540 } // namespace wasm 1613 } // namespace wasm
1541 } // namespace internal 1614 } // namespace internal
1542 } // namespace v8 1615 } // namespace v8
OLDNEW
« no previous file with comments | « BUILD.gn ('k') | src/wasm/switch-logic.h » ('j') | test/mjsunit/wasm/asm-wasm-switch.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698