| 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 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 using ::testing::_; | 22 using ::testing::_; |
| 23 | 23 |
| 24 namespace v8 { | 24 namespace v8 { |
| 25 namespace internal { | 25 namespace internal { |
| 26 namespace compiler { | 26 namespace compiler { |
| 27 | 27 |
| 28 static const LanguageMode kLanguageModes[] = {LanguageMode::SLOPPY, | 28 static const LanguageMode kLanguageModes[] = {LanguageMode::SLOPPY, |
| 29 LanguageMode::STRICT}; | 29 LanguageMode::STRICT}; |
| 30 | 30 |
| 31 static const Token::Value kBinaryOperators[] = { |
| 32 Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND, |
| 33 Token::Value::SHL, Token::Value::SAR, Token::Value::SHR, |
| 34 Token::Value::ADD, Token::Value::SUB, Token::Value::MUL, |
| 35 Token::Value::DIV, Token::Value::MOD}; |
| 36 |
| 37 static IrOpcode::Value getIrOpcode(Token::Value token) { |
| 38 switch (token) { |
| 39 case Token::Value::BIT_OR: |
| 40 return IrOpcode::Value::kJSBitwiseOr; |
| 41 case Token::Value::BIT_XOR: |
| 42 return IrOpcode::Value::kJSBitwiseXor; |
| 43 case Token::Value::BIT_AND: |
| 44 return IrOpcode::Value::kJSBitwiseAnd; |
| 45 case Token::Value::SHL: |
| 46 return IrOpcode::Value::kJSShiftLeft; |
| 47 case Token::Value::SAR: |
| 48 return IrOpcode::Value::kJSShiftRight; |
| 49 case Token::Value::SHR: |
| 50 return IrOpcode::Value::kJSShiftRightLogical; |
| 51 case Token::Value::ADD: |
| 52 return IrOpcode::Value::kJSAdd; |
| 53 case Token::Value::SUB: |
| 54 return IrOpcode::Value::kJSSubtract; |
| 55 case Token::Value::MUL: |
| 56 return IrOpcode::Value::kJSMultiply; |
| 57 case Token::Value::DIV: |
| 58 return IrOpcode::Value::kJSDivide; |
| 59 case Token::Value::MOD: |
| 60 return IrOpcode::Value::kJSModulus; |
| 61 default: |
| 62 UNREACHABLE(); |
| 63 return static_cast<IrOpcode::Value>(-1); |
| 64 } |
| 65 } |
| 66 |
| 31 Handle<TypeFeedbackVector> NewTypeFeedbackVector(Isolate* isolate, | 67 Handle<TypeFeedbackVector> NewTypeFeedbackVector(Isolate* isolate, |
| 32 FeedbackVectorSpec* spec) { | 68 FeedbackVectorSpec* spec) { |
| 33 Handle<TypeFeedbackMetadata> vector_metadata = | 69 Handle<TypeFeedbackMetadata> vector_metadata = |
| 34 TypeFeedbackMetadata::New(isolate, spec); | 70 TypeFeedbackMetadata::New(isolate, spec); |
| 35 return TypeFeedbackVector::New(isolate, vector_metadata); | 71 return TypeFeedbackVector::New(isolate, vector_metadata); |
| 36 } | 72 } |
| 37 | 73 |
| 38 | 74 |
| 39 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { | 75 class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { |
| 40 public: | 76 public: |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 array_builder.set_locals_count(1); | 303 array_builder.set_locals_count(1); |
| 268 array_builder.set_context_count(0); | 304 array_builder.set_context_count(0); |
| 269 array_builder.set_parameter_count(3); | 305 array_builder.set_parameter_count(3); |
| 270 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) | 306 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 271 .BinaryOperation(Token::Value::ADD, array_builder.Parameter(2), | 307 .BinaryOperation(Token::Value::ADD, array_builder.Parameter(2), |
| 272 Strength::WEAK) | 308 Strength::WEAK) |
| 273 .StoreAccumulatorInRegister(interpreter::Register(0)) | 309 .StoreAccumulatorInRegister(interpreter::Register(0)) |
| 274 .Return(); | 310 .Return(); |
| 275 | 311 |
| 276 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); | 312 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 313 Node* start = graph->start(); |
| 277 Node* end = graph->end(); | 314 Node* end = graph->end(); |
| 278 EXPECT_EQ(1, end->InputCount()); | 315 EXPECT_EQ(1, end->InputCount()); |
| 279 Node* ret = end->InputAt(0); | 316 Node* ret = end->InputAt(0); |
| 280 // NB binary operation is <reg> <op> <acc>. The register represents | 317 // NB binary operation is <reg> <op> <acc>. The register represents |
| 281 // the left-hand side, which is why parameters appear in opposite | 318 // the left-hand side, which is why parameters appear in opposite |
| 282 // order to construction via the builder. | 319 // order to construction via the builder. |
| 283 EXPECT_THAT(ret, IsReturn(IsJSAdd(IsParameter(2), IsParameter(1)), _, _)); | 320 Matcher<Node*> js_add_node = IsJSBinaryOperation( |
| 321 IrOpcode::kJSAdd, IsParameter(2), IsParameter(1), start, start); |
| 322 EXPECT_THAT(ret, IsReturn(js_add_node, _, _)); |
| 284 } | 323 } |
| 285 | 324 |
| 286 | 325 |
| 287 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithRegister) { | 326 TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithRegister) { |
| 327 TRACED_FOREACH(Token::Value, token, kBinaryOperators) { |
| 328 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 329 static const int kLeft = -655371; |
| 330 static const int kRight = +2000000; |
| 331 array_builder.set_locals_count(1); |
| 332 array_builder.set_context_count(0); |
| 333 array_builder.set_parameter_count(1); |
| 334 array_builder.LoadLiteral(Smi::FromInt(kLeft)) |
| 335 .StoreAccumulatorInRegister(interpreter::Register(0)) |
| 336 .LoadLiteral(Smi::FromInt(kRight)) |
| 337 .BinaryOperation(token, interpreter::Register(0), Strength::WEAK) |
| 338 .Return(); |
| 339 |
| 340 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 341 Node* end = graph->end(); |
| 342 EXPECT_EQ(1, end->InputCount()); |
| 343 Node* start = graph->start(); |
| 344 Node* ret = end->InputAt(0); |
| 345 Matcher<Node*> compute_node = |
| 346 IsJSBinaryOperation(getIrOpcode(token), IsNumberConstant(kLeft), |
| 347 IsNumberConstant(kRight), start, start); |
| 348 EXPECT_THAT(ret, IsReturn(compute_node, _, _)); |
| 349 } |
| 350 } |
| 351 |
| 352 |
| 353 TEST_F(BytecodeGraphBuilderTest, ToBoolean) { |
| 288 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); | 354 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 289 static const int kLeft = -655371; | |
| 290 static const int kRight = +2000000; | |
| 291 array_builder.set_locals_count(1); | 355 array_builder.set_locals_count(1); |
| 292 array_builder.set_context_count(0); | 356 array_builder.set_context_count(0); |
| 293 array_builder.set_parameter_count(1); | 357 array_builder.set_parameter_count(2); |
| 294 array_builder.LoadLiteral(Smi::FromInt(kLeft)) | 358 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 295 .StoreAccumulatorInRegister(interpreter::Register(0)) | 359 .CastAccumulatorToBoolean() |
| 296 .LoadLiteral(Smi::FromInt(kRight)) | |
| 297 .BinaryOperation(Token::Value::ADD, interpreter::Register(0), | |
| 298 Strength::WEAK) | |
| 299 .Return(); | 360 .Return(); |
| 300 | 361 |
| 301 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); | 362 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 302 Node* end = graph->end(); | 363 Node* ret = graph->end()->InputAt(0); |
| 303 EXPECT_EQ(1, end->InputCount()); | 364 Node* start = graph->start(); |
| 304 Node* ret = end->InputAt(0); | 365 |
| 305 EXPECT_THAT( | 366 Matcher<Node*> to_boolean_node = IsJSToBoolean(IsParameter(1), start); |
| 306 ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), | 367 EXPECT_THAT(ret, IsReturn(to_boolean_node, _, _)); |
| 307 _, _)); | |
| 308 } | 368 } |
| 309 | 369 |
| 310 | 370 |
| 371 TEST_F(BytecodeGraphBuilderTest, ToName) { |
| 372 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 373 array_builder.set_locals_count(1); |
| 374 array_builder.set_context_count(0); |
| 375 array_builder.set_parameter_count(2); |
| 376 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 377 .CastAccumulatorToName() |
| 378 .Return(); |
| 379 |
| 380 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 381 Node* ret = graph->end()->InputAt(0); |
| 382 Node* start = graph->start(); |
| 383 |
| 384 Matcher<Node*> to_name_node = IsJSToName(IsParameter(1), start, start); |
| 385 EXPECT_THAT(ret, IsReturn(to_name_node, _, _)); |
| 386 } |
| 387 |
| 388 |
| 389 TEST_F(BytecodeGraphBuilderTest, ToObject) { |
| 390 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 391 array_builder.set_locals_count(1); |
| 392 array_builder.set_context_count(0); |
| 393 array_builder.set_parameter_count(2); |
| 394 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 395 .CastAccumulatorToJSObject() |
| 396 .Return(); |
| 397 |
| 398 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 399 Node* ret = graph->end()->InputAt(0); |
| 400 Node* start = graph->start(); |
| 401 |
| 402 Matcher<Node*> to_object_node = IsJSToObject(IsParameter(1), start, start); |
| 403 EXPECT_THAT(ret, IsReturn(to_object_node, _, _)); |
| 404 } |
| 405 |
| 406 |
| 407 TEST_F(BytecodeGraphBuilderTest, ToNumber) { |
| 408 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 409 array_builder.set_locals_count(1); |
| 410 array_builder.set_context_count(0); |
| 411 array_builder.set_parameter_count(2); |
| 412 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 413 .CastAccumulatorToNumber() |
| 414 .Return(); |
| 415 |
| 416 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray()); |
| 417 Node* ret = graph->end()->InputAt(0); |
| 418 Node* start = graph->start(); |
| 419 |
| 420 Matcher<Node*> to_number_node = IsToNumber(IsParameter(1), _, start, start); |
| 421 EXPECT_THAT(ret, IsReturn(to_number_node, _, _)); |
| 422 } |
| 423 |
| 424 |
| 311 TEST_F(BytecodeGraphBuilderTest, NamedLoad) { | 425 TEST_F(BytecodeGraphBuilderTest, NamedLoad) { |
| 312 const bool kWideBytecode[] = {false, true}; | 426 const bool kWideBytecode[] = {false, true}; |
| 313 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { | 427 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { |
| 314 TRACED_FOREACH(bool, wide_bytecode, kWideBytecode) { | 428 TRACED_FOREACH(bool, wide_bytecode, kWideBytecode) { |
| 315 FeedbackVectorSpec feedback_spec(zone()); | 429 FeedbackVectorSpec feedback_spec(zone()); |
| 316 if (wide_bytecode) { | 430 if (wide_bytecode) { |
| 317 for (int i = 0; i < 128; i++) { | 431 for (int i = 0; i < 128; i++) { |
| 318 feedback_spec.AddLoadICSlot(); | 432 feedback_spec.AddLoadICSlot(); |
| 319 } | 433 } |
| 320 } | 434 } |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 array_builder.set_parameter_count(2); | 648 array_builder.set_parameter_count(2); |
| 535 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) | 649 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 536 .LogicalNot() | 650 .LogicalNot() |
| 537 .Return(); | 651 .Return(); |
| 538 | 652 |
| 539 FeedbackVectorSpec feedback_spec(zone()); | 653 FeedbackVectorSpec feedback_spec(zone()); |
| 540 Handle<TypeFeedbackVector> vector = | 654 Handle<TypeFeedbackVector> vector = |
| 541 NewTypeFeedbackVector(isolate(), &feedback_spec); | 655 NewTypeFeedbackVector(isolate(), &feedback_spec); |
| 542 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(), vector); | 656 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(), vector); |
| 543 | 657 |
| 658 Node* start = graph->start(); |
| 544 Node* ret = graph->end()->InputAt(0); | 659 Node* ret = graph->end()->InputAt(0); |
| 545 EXPECT_THAT(ret, IsReturn(IsJSUnaryNot(IsParameter(1)), _, _)); | 660 EXPECT_THAT(ret, IsReturn(IsJSUnaryNot(IsParameter(1), start), _, _)); |
| 546 } | 661 } |
| 547 | 662 |
| 548 | 663 |
| 549 TEST_F(BytecodeGraphBuilderTest, TypeOf) { | 664 TEST_F(BytecodeGraphBuilderTest, TypeOf) { |
| 550 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); | 665 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 551 array_builder.set_locals_count(1); | 666 array_builder.set_locals_count(1); |
| 552 array_builder.set_context_count(0); | 667 array_builder.set_context_count(0); |
| 553 array_builder.set_parameter_count(2); | 668 array_builder.set_parameter_count(2); |
| 554 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) | 669 array_builder.LoadAccumulatorWithRegister(array_builder.Parameter(1)) |
| 555 .TypeOf() | 670 .TypeOf() |
| 556 .Return(); | 671 .Return(); |
| 557 | 672 |
| 558 FeedbackVectorSpec feedback_spec(zone()); | 673 FeedbackVectorSpec feedback_spec(zone()); |
| 559 Handle<TypeFeedbackVector> vector = | 674 Handle<TypeFeedbackVector> vector = |
| 560 NewTypeFeedbackVector(isolate(), &feedback_spec); | 675 NewTypeFeedbackVector(isolate(), &feedback_spec); |
| 561 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(), vector); | 676 Graph* graph = GetCompletedGraph(array_builder.ToBytecodeArray(), vector); |
| 562 | 677 |
| 678 Node* start = graph->start(); |
| 563 Node* ret = graph->end()->InputAt(0); | 679 Node* ret = graph->end()->InputAt(0); |
| 564 EXPECT_THAT(ret, IsReturn(IsJSTypeOf(IsParameter(1)), _, _)); | 680 EXPECT_THAT(ret, IsReturn(IsJSTypeOf(IsParameter(1), start), _, _)); |
| 565 } | 681 } |
| 566 | 682 |
| 567 | 683 |
| 568 TEST_F(BytecodeGraphBuilderTest, Delete) { | 684 TEST_F(BytecodeGraphBuilderTest, Delete) { |
| 569 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { | 685 TRACED_FOREACH(LanguageMode, language_mode, kLanguageModes) { |
| 570 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); | 686 interpreter::BytecodeArrayBuilder array_builder(isolate(), zone()); |
| 571 array_builder.set_locals_count(1); | 687 array_builder.set_locals_count(1); |
| 572 array_builder.set_context_count(0); | 688 array_builder.set_context_count(0); |
| 573 array_builder.set_parameter_count(2); | 689 array_builder.set_parameter_count(2); |
| 574 Handle<Name> name = GetName(isolate(), "val"); | 690 Handle<Name> name = GetName(isolate(), "val"); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 construct_inputs.push_back(IsParameter(4)); | 919 construct_inputs.push_back(IsParameter(4)); |
| 804 construct_inputs.push_back(IsParameter(1)); | 920 construct_inputs.push_back(IsParameter(1)); |
| 805 Matcher<Node*> call_construct = | 921 Matcher<Node*> call_construct = |
| 806 IsJSCallConstruct(construct_inputs, start, start); | 922 IsJSCallConstruct(construct_inputs, start, start); |
| 807 EXPECT_THAT(ret, IsReturn(call_construct, call_construct, IsIfSuccess(_))); | 923 EXPECT_THAT(ret, IsReturn(call_construct, call_construct, IsIfSuccess(_))); |
| 808 } | 924 } |
| 809 | 925 |
| 810 } // namespace compiler | 926 } // namespace compiler |
| 811 } // namespace internal | 927 } // namespace internal |
| 812 } // namespace v8 | 928 } // namespace v8 |
| OLD | NEW |