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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/bytecode-generator.h" | 8 #include "src/interpreter/bytecode-generator.h" |
9 #include "src/interpreter/interpreter.h" | 9 #include "src/interpreter/interpreter.h" |
10 #include "test/cctest/cctest.h" | 10 #include "test/cctest/cctest.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 namespace interpreter { | 14 namespace interpreter { |
15 | 15 |
16 class BytecodeGeneratorHelper { | 16 class BytecodeGeneratorHelper { |
17 public: | 17 public: |
18 const char* kFunctionName = "f"; | 18 const char* kFunctionName = "f"; |
19 | 19 |
20 const int kLastParamIndex = | 20 const int kLastParamIndex = |
21 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 21 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
22 | 22 |
23 BytecodeGeneratorHelper() { | 23 BytecodeGeneratorHelper() { |
| 24 i::FLAG_vector_stores = true; |
24 i::FLAG_ignition = true; | 25 i::FLAG_ignition = true; |
25 i::FLAG_ignition_filter = kFunctionName; | 26 i::FLAG_ignition_filter = kFunctionName; |
26 CcTest::i_isolate()->interpreter()->Initialize(); | 27 CcTest::i_isolate()->interpreter()->Initialize(); |
27 } | 28 } |
28 | 29 |
29 | 30 |
30 Factory* factory() { return CcTest::i_isolate()->factory(); } | 31 Factory* factory() { return CcTest::i_isolate()->factory(); } |
31 | 32 |
32 | 33 |
33 Handle<BytecodeArray> MakeBytecode(const char* script, | 34 Handle<BytecodeArray> MakeBytecode(const char* script, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 73 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
73 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 74 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
74 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 75 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
75 | 76 |
76 | 77 |
77 TEST(PrimitiveReturnStatements) { | 78 TEST(PrimitiveReturnStatements) { |
78 InitializedHandleScope handle_scope; | 79 InitializedHandleScope handle_scope; |
79 BytecodeGeneratorHelper helper; | 80 BytecodeGeneratorHelper helper; |
80 | 81 |
81 ExpectedSnippet<void*> snippets[] = { | 82 ExpectedSnippet<void*> snippets[] = { |
| 83 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
82 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, | 84 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
83 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, | 85 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, |
84 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, | 86 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, |
85 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, | 87 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, |
86 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, | 88 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, |
87 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, | 89 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, |
88 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, | 90 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, |
89 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, | 91 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, |
90 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, | 92 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, |
91 }; | 93 }; |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
411 ba->length())); | 413 ba->length())); |
412 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | 414 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
413 for (int j = 0; j < snippets[i].constant_count; j++) { | 415 for (int j = 0; j < snippets[i].constant_count; j++) { |
414 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( | 416 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( |
415 snippets[i].constants[j]); | 417 snippets[i].constants[j]); |
416 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | 418 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); |
417 } | 419 } |
418 } | 420 } |
419 } | 421 } |
420 | 422 |
| 423 |
| 424 TEST(PropertyStores) { |
| 425 InitializedHandleScope handle_scope; |
| 426 BytecodeGeneratorHelper helper; |
| 427 |
| 428 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; |
| 429 FeedbackVectorSpec feedback_spec(0, 1, ic_kinds); |
| 430 Handle<i::TypeFeedbackVector> vector = |
| 431 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
| 432 |
| 433 ExpectedSnippet<const char*> snippets[] = { |
| 434 {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})", |
| 435 2 * kPointerSize, 2, 16, |
| 436 { |
| 437 B(Ldar), R(helper.kLastParamIndex), |
| 438 B(Star), R(0), |
| 439 B(LdaConstant), U8(0), |
| 440 B(Star), R(1), |
| 441 B(LdaConstant), U8(1), |
| 442 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), |
| 443 B(LdaUndefined), |
| 444 B(Return) |
| 445 }, |
| 446 2, { "name", "val" } |
| 447 }, |
| 448 {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})", |
| 449 2 * kPointerSize, 2, 16, |
| 450 { |
| 451 B(Ldar), R(helper.kLastParamIndex), |
| 452 B(Star), R(0), |
| 453 B(LdaConstant), U8(0), |
| 454 B(Star), R(1), |
| 455 B(LdaConstant), U8(1), |
| 456 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), |
| 457 B(LdaUndefined), |
| 458 B(Return) |
| 459 }, |
| 460 2, { "key", "val" } |
| 461 }, |
| 462 {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})", |
| 463 2 * kPointerSize, 2, 16, |
| 464 { |
| 465 B(Ldar), R(helper.kLastParamIndex), |
| 466 B(Star), R(0), |
| 467 B(LdaSmi8), U8(100), |
| 468 B(Star), R(1), |
| 469 B(LdaConstant), U8(0), |
| 470 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), |
| 471 B(LdaUndefined), |
| 472 B(Return) |
| 473 }, |
| 474 1, { "val" } |
| 475 }, |
| 476 {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")", |
| 477 2 * kPointerSize, 3, 16, |
| 478 { |
| 479 B(Ldar), R(helper.kLastParamIndex - 1), |
| 480 B(Star), R(0), |
| 481 B(Ldar), R(helper.kLastParamIndex), |
| 482 B(Star), R(1), |
| 483 B(LdaConstant), U8(0), |
| 484 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), |
| 485 B(LdaUndefined), |
| 486 B(Return) |
| 487 }, |
| 488 1, { "val" } |
| 489 }, |
| 490 {"function f(a) { a.name = a[-124]; }\n" |
| 491 "f({\"-124\" : \"test\", name : 123 })", |
| 492 3 * kPointerSize, 2, 23, |
| 493 { |
| 494 B(Ldar), R(helper.kLastParamIndex), |
| 495 B(Star), R(0), |
| 496 B(LdaConstant), U8(0), |
| 497 B(Star), R(1), |
| 498 B(Ldar), R(helper.kLastParamIndex), |
| 499 B(Star), R(2), |
| 500 B(LdaSmi8), U8(-124), |
| 501 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), |
| 502 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), |
| 503 B(LdaUndefined), |
| 504 B(Return) |
| 505 }, |
| 506 1, { "name" } |
| 507 } |
| 508 }; |
| 509 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 510 for (size_t i = 0; i < num_snippets; i++) { |
| 511 Handle<BytecodeArray> ba = |
| 512 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 513 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
| 514 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
| 515 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
| 516 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
| 517 ba->length())); |
| 518 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
| 519 for (int j = 0; j < snippets[i].constant_count; j++) { |
| 520 Handle<String> expected = |
| 521 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); |
| 522 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); |
| 523 } |
| 524 } |
| 525 } |
| 526 |
421 } // namespace interpreter | 527 } // namespace interpreter |
422 } // namespace internal | 528 } // namespace internal |
423 } // namespance v8 | 529 } // namespance v8 |
OLD | NEW |