OLD | NEW |
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 <iostream> | 5 #include <iostream> |
6 | 6 |
7 #include "src/compiler/bytecode-graph-builder.h" | 7 #include "src/compiler/bytecode-graph-builder.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/graph-visualizer.h" | 9 #include "src/compiler/graph-visualizer.h" |
10 #include "src/compiler/instruction.h" | 10 #include "src/compiler/instruction.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 SEP() \ | 49 SEP() \ |
50 REPEAT_32(SEP, __VA_ARGS__) \ | 50 REPEAT_32(SEP, __VA_ARGS__) \ |
51 SEP() \ | 51 SEP() \ |
52 REPEAT_16(SEP, __VA_ARGS__) \ | 52 REPEAT_16(SEP, __VA_ARGS__) \ |
53 SEP() \ | 53 SEP() \ |
54 REPEAT_8(SEP, __VA_ARGS__) \ | 54 REPEAT_8(SEP, __VA_ARGS__) \ |
55 SEP() \ | 55 SEP() \ |
56 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__ | 56 REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__ |
57 | 57 |
58 static const char* kFunctionName = "f"; | 58 static const char* kFunctionName = "f"; |
| 59 static const char* kLanguageModeStatements[] = {"", " 'use strict'; "}; |
59 | 60 |
60 class GraphGeneratorHelper { | 61 class GraphGeneratorHelper { |
61 public: | 62 public: |
62 GraphGeneratorHelper(Isolate* isolate, Zone* zone, const char* script) | 63 GraphGeneratorHelper(Isolate* isolate, Zone* zone, const char* script) |
63 : GraphGeneratorHelper(isolate, zone, script, | 64 : GraphGeneratorHelper(isolate, zone, script, |
64 MaybeHandle<BytecodeArray>()) {} | 65 MaybeHandle<BytecodeArray>()) {} |
65 | 66 |
66 GraphGeneratorHelper(Isolate* isolate, Zone* zone, | 67 GraphGeneratorHelper(Isolate* isolate, Zone* zone, |
67 MaybeHandle<BytecodeArray> bytecode) | 68 MaybeHandle<BytecodeArray> bytecode) |
68 : GraphGeneratorHelper(isolate, zone, nullptr, bytecode) {} | 69 : GraphGeneratorHelper(isolate, zone, nullptr, bytecode) {} |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 Graph* graph = helper.GetCompletedGraph(); | 401 Graph* graph = helper.GetCompletedGraph(); |
401 Node* end = graph->end(); | 402 Node* end = graph->end(); |
402 EXPECT_EQ(1, end->InputCount()); | 403 EXPECT_EQ(1, end->InputCount()); |
403 Node* ret = end->InputAt(0); | 404 Node* ret = end->InputAt(0); |
404 EXPECT_THAT( | 405 EXPECT_THAT( |
405 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), | 406 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), |
406 _, _)); | 407 _, _)); |
407 } | 408 } |
408 | 409 |
409 | 410 |
410 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppy) { | 411 TEST_F(BytecodeGraphBuilderTest, LoadNamed) { |
411 const char* code_snippet = "function f(p1) {return p1.val;}; f({val:10});"; | 412 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
412 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | 413 std::string code_snippet = std::string("function f(p1) {") + language_mode + |
413 Graph* graph = helper.GetCompletedGraph(); | 414 " return p1.val;}; f({val:10});"; |
| 415 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 416 Graph* graph = helper.GetCompletedGraph(); |
414 | 417 |
415 Node* ret = graph->end()->InputAt(0); | 418 Node* ret = graph->end()->InputAt(0); |
416 Node* start = graph->start(); | 419 Node* start = graph->start(); |
417 | 420 |
418 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | 421 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); |
419 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | 422 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
420 Matcher<Node*> load_named_matcher = IsJSLoadNamed( | 423 Matcher<Node*> load_named_matcher = IsJSLoadNamed( |
421 name, IsParameter(1), feedback_vector_matcher, start, start); | 424 name, IsParameter(1), feedback_vector_matcher, start, start); |
422 | 425 |
423 EXPECT_THAT(ret, IsReturn(load_named_matcher, _, _)); | 426 EXPECT_THAT(ret, IsReturn(load_named_matcher, _, _)); |
| 427 } |
424 } | 428 } |
425 | 429 |
426 | 430 |
427 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrict) { | 431 TEST_F(BytecodeGraphBuilderTest, LoadNamedWide) { |
428 const char* code_snippet = | 432 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
429 "function f(p1) {'use strict'; return p1.val;}; f({val:10});"; | 433 std::string code_snippet = std::string("function f(p1) {") + language_mode + |
430 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | 434 REPEAT_127(SPACE, " var b = p1.val_prev; ") |
431 Graph* graph = helper.GetCompletedGraph(); | 435 " return p1.val;}; f({val:10, val_prev:20});"; |
| 436 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 437 Graph* graph = helper.GetCompletedGraph(); |
432 | 438 |
433 Node* ret = graph->end()->InputAt(0); | 439 Node* ret = graph->end()->InputAt(0); |
434 Node* start = graph->start(); | 440 Node* start = graph->start(); |
435 | 441 |
436 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | 442 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); |
437 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | 443 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
438 Matcher<Node*> load_named_matcher = IsJSLoadNamed( | 444 Matcher<Node*> preceeding_load = IsJSLoadNamed( |
439 name, IsParameter(1), feedback_vector_matcher, start, start); | 445 GraphGeneratorHelper::GetName(isolate(), "val_prev"), _, _, _, _); |
| 446 Matcher<Node*> load_named_matcher_wide = |
| 447 IsJSLoadNamed(name, IsParameter(1), feedback_vector_matcher, |
| 448 preceeding_load, IsIfSuccess(_)); |
440 | 449 |
441 EXPECT_THAT(ret, IsReturn(load_named_matcher, _, _)); | 450 EXPECT_THAT(ret, IsReturn(load_named_matcher_wide, _, _)); |
| 451 } |
442 } | 452 } |
443 | 453 |
444 | 454 |
445 TEST_F(BytecodeGraphBuilderTest, NamedLoadSloppyWide) { | |
446 const char code_snippet[] = "function f(p1) {var b; " | |
447 REPEAT_127(SPACE, " b = p1.val_prev; ") | |
448 "return p1.val;}; f({val:10, val_prev:20});"; | |
449 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
450 Graph* graph = helper.GetCompletedGraph(); | |
451 | |
452 Node* ret = graph->end()->InputAt(0); | |
453 Node* start = graph->start(); | |
454 | |
455 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
456 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
457 Matcher<Node*> preceeding_load = IsJSLoadNamed( | |
458 GraphGeneratorHelper::GetName(isolate(), "val_prev"), _, _, _, _); | |
459 Matcher<Node*> load_named_matcher_wide = | |
460 IsJSLoadNamed(name, IsParameter(1), feedback_vector_matcher, | |
461 preceeding_load, IsIfSuccess(_)); | |
462 | |
463 EXPECT_THAT(ret, IsReturn(load_named_matcher_wide, _, _)); | |
464 } | |
465 | |
466 | |
467 TEST_F(BytecodeGraphBuilderTest, NamedLoadStrictWide) { | |
468 const char code_snippet[] = "function f(p1) {'use strict'; var b;" | |
469 REPEAT_127(SPACE, " b = p1.val_prev; ") | |
470 "return p1.val;}; f({val:10, val_prev:20});"; | |
471 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | |
472 Graph* graph = helper.GetCompletedGraph(); | |
473 | |
474 Node* ret = graph->end()->InputAt(0); | |
475 Node* start = graph->start(); | |
476 | |
477 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "val"); | |
478 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); | |
479 Matcher<Node*> preceeding_load = IsJSLoadNamed( | |
480 GraphGeneratorHelper::GetName(isolate(), "val_prev"), _, _, _, _); | |
481 Matcher<Node*> load_named_matcher_wide = | |
482 IsJSLoadNamed(name, IsParameter(1), feedback_vector_matcher, | |
483 preceeding_load, IsIfSuccess(_)); | |
484 | |
485 EXPECT_THAT(ret, IsReturn(load_named_matcher_wide, _, _)); | |
486 } | |
487 | |
488 | |
489 TEST_F(BytecodeGraphBuilderTest, CallProperty0) { | 455 TEST_F(BytecodeGraphBuilderTest, CallProperty0) { |
490 const char* code_snippet = | 456 const char* code_snippet = |
491 "function f(p1) {return p1.func();}; f({func(){}});"; | 457 "function f(p1) {return p1.func();}; f({func(){}});"; |
492 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); | 458 GraphGeneratorHelper helper(isolate(), zone(), code_snippet); |
493 Graph* graph = helper.GetCompletedGraph(); | 459 Graph* graph = helper.GetCompletedGraph(); |
494 | 460 |
495 Node* ret = graph->end()->InputAt(0); | 461 Node* ret = graph->end()->InputAt(0); |
496 Node* start = graph->start(); | 462 Node* start = graph->start(); |
497 | 463 |
498 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "func"); | 464 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "func"); |
(...skipping 27 matching lines...) Expand all Loading... |
526 call_inputs.push_back(load_named_matcher); | 492 call_inputs.push_back(load_named_matcher); |
527 call_inputs.push_back(IsParameter(1)); | 493 call_inputs.push_back(IsParameter(1)); |
528 call_inputs.push_back(IsParameter(2)); | 494 call_inputs.push_back(IsParameter(2)); |
529 call_inputs.push_back(IsParameter(3)); | 495 call_inputs.push_back(IsParameter(3)); |
530 Matcher<Node*> call_matcher = | 496 Matcher<Node*> call_matcher = |
531 IsJSCallFunction(call_inputs, load_named_matcher, IsIfSuccess(_)); | 497 IsJSCallFunction(call_inputs, load_named_matcher, IsIfSuccess(_)); |
532 | 498 |
533 EXPECT_THAT(ret, IsReturn(call_matcher, _, _)); | 499 EXPECT_THAT(ret, IsReturn(call_matcher, _, _)); |
534 } | 500 } |
535 | 501 |
| 502 |
| 503 TEST_F(BytecodeGraphBuilderTest, LoadGlobal) { |
| 504 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
| 505 std::string code_snippet = std::string("var global = 123; function f() {") + |
| 506 language_mode + " return global; }; f();"; |
| 507 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 508 Graph* graph = helper.GetCompletedGraph(); |
| 509 |
| 510 Node* ret = graph->end()->InputAt(0); |
| 511 Node* start = graph->start(); |
| 512 |
| 513 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "global"); |
| 514 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
| 515 Matcher<Node*> load_global_matcher = |
| 516 IsJSLoadGlobal(name, feedback_vector_matcher, start, start); |
| 517 |
| 518 EXPECT_THAT(ret, IsReturn(load_global_matcher, _, _)); |
| 519 } |
| 520 } |
| 521 |
| 522 |
| 523 TEST_F(BytecodeGraphBuilderTest, LoadGlobalWide) { |
| 524 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
| 525 std::string code_snippet = |
| 526 std::string("var global = 123; var global_obj = {name:'abc'};") + |
| 527 "function f() {" + language_mode + |
| 528 REPEAT_127(SPACE, " var b = global_obj.name;\n") + |
| 529 " return global;}; f();"; |
| 530 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 531 Graph* graph = helper.GetCompletedGraph(); |
| 532 |
| 533 Node* ret = graph->end()->InputAt(0); |
| 534 Node* start = graph->start(); |
| 535 |
| 536 Handle<Name> global_name = |
| 537 GraphGeneratorHelper::GetName(isolate(), "global"); |
| 538 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
| 539 Matcher<Node*> preceeding_load = IsJSLoadNamed( |
| 540 GraphGeneratorHelper::GetName(isolate(), "name"), _, _, _, _); |
| 541 Matcher<Node*> load_global_matcher_wide = IsJSLoadGlobal( |
| 542 global_name, feedback_vector_matcher, preceeding_load, IsIfSuccess(_)); |
| 543 |
| 544 EXPECT_THAT(ret, IsReturn(load_global_matcher_wide, _, _)); |
| 545 } |
| 546 } |
| 547 |
| 548 |
| 549 TEST_F(BytecodeGraphBuilderTest, StoreGlobal) { |
| 550 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
| 551 std::string code_snippet = std::string("var global = 123; function f() {") + |
| 552 language_mode + " global = 321; }; f();"; |
| 553 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 554 Graph* graph = helper.GetCompletedGraph(); |
| 555 |
| 556 Node* ret = graph->end()->InputAt(0); |
| 557 Node* start = graph->start(); |
| 558 |
| 559 Handle<Name> name = GraphGeneratorHelper::GetName(isolate(), "global"); |
| 560 Matcher<Node*> value_matcher = IsNumberConstant(321); |
| 561 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
| 562 Matcher<Node*> store_global_matcher = IsJSStoreGlobal( |
| 563 name, value_matcher, feedback_vector_matcher, start, start); |
| 564 |
| 565 EXPECT_THAT(ret, IsReturn(_, store_global_matcher, _)); |
| 566 } |
| 567 } |
| 568 |
| 569 |
| 570 TEST_F(BytecodeGraphBuilderTest, StoreGlobalWide) { |
| 571 TRACED_FOREACH(const char*, language_mode, kLanguageModeStatements) { |
| 572 std::string code_snippet = |
| 573 std::string("var global = 123; var global_obj = {name:'abc'};") + |
| 574 "function f() {" + language_mode + |
| 575 REPEAT_127(SPACE, " var b = global_obj.name;\n") + |
| 576 " global = 321;}; f();"; |
| 577 GraphGeneratorHelper helper(isolate(), zone(), code_snippet.c_str()); |
| 578 Graph* graph = helper.GetCompletedGraph(); |
| 579 |
| 580 Node* ret = graph->end()->InputAt(0); |
| 581 Node* start = graph->start(); |
| 582 |
| 583 Handle<Name> global_name = |
| 584 GraphGeneratorHelper::GetName(isolate(), "global"); |
| 585 Matcher<Node*> value_matcher = IsNumberConstant(321); |
| 586 Matcher<Node*> feedback_vector_matcher = IsFeedbackVector(start, start); |
| 587 Matcher<Node*> preceeding_load = IsJSLoadNamed( |
| 588 GraphGeneratorHelper::GetName(isolate(), "name"), _, _, _, _); |
| 589 Matcher<Node*> store_global_matcher_wide = |
| 590 IsJSStoreGlobal(global_name, value_matcher, feedback_vector_matcher, |
| 591 preceeding_load, IsIfSuccess(_)); |
| 592 |
| 593 EXPECT_THAT(ret, IsReturn(_, store_global_matcher_wide, _)); |
| 594 } |
| 595 } |
| 596 |
536 } // namespace compiler | 597 } // namespace compiler |
537 } // namespace internal | 598 } // namespace internal |
538 } // namespace v8 | 599 } // namespace v8 |
OLD | NEW |