| 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 |