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-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
10 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
11 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
12 #include "test/cctest/test-feedback-vector.h" | 12 #include "test/cctest/test-feedback-vector.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace interpreter { | 16 namespace interpreter { |
17 | 17 |
| 18 static const InstanceType kInstanceTypeDontCare = static_cast<InstanceType>(-1); |
| 19 |
18 class BytecodeGeneratorHelper { | 20 class BytecodeGeneratorHelper { |
19 public: | 21 public: |
20 const char* kFunctionName = "f"; | 22 const char* kFunctionName = "f"; |
21 | 23 |
22 static const int kLastParamIndex = | 24 static const int kLastParamIndex = |
23 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; | 25 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
24 | 26 |
25 BytecodeGeneratorHelper() { | 27 BytecodeGeneratorHelper() { |
26 i::FLAG_ignition = true; | 28 i::FLAG_ignition = true; |
27 i::FLAG_ignition_filter = StrDup(kFunctionName); | 29 i::FLAG_ignition_filter = StrDup(kFunctionName); |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 CHECK(String::cast(actual)->Equals(*expected_string)); | 186 CHECK(String::cast(actual)->Equals(*expected_string)); |
185 } | 187 } |
186 | 188 |
187 | 189 |
188 static void CheckConstant(Handle<Object> expected, Object* actual) { | 190 static void CheckConstant(Handle<Object> expected, Object* actual) { |
189 CHECK(actual == *expected || expected->StrictEquals(actual)); | 191 CHECK(actual == *expected || expected->StrictEquals(actual)); |
190 } | 192 } |
191 | 193 |
192 | 194 |
193 static void CheckConstant(InstanceType expected, Object* actual) { | 195 static void CheckConstant(InstanceType expected, Object* actual) { |
194 CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type()); | 196 if (expected != kInstanceTypeDontCare) { |
| 197 CHECK_EQ(expected, HeapObject::cast(actual)->map()->instance_type()); |
| 198 } |
195 } | 199 } |
196 | 200 |
197 | 201 |
198 template <typename T, int C> | 202 template <typename T, int C> |
199 static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected, | 203 static void CheckBytecodeArrayEqual(const ExpectedSnippet<T, C>& expected, |
200 Handle<BytecodeArray> actual) { | 204 Handle<BytecodeArray> actual) { |
201 CHECK_EQ(expected.frame_size, actual->frame_size()); | 205 CHECK_EQ(expected.frame_size, actual->frame_size()); |
202 CHECK_EQ(expected.parameter_count, actual->parameter_count()); | 206 CHECK_EQ(expected.parameter_count, actual->parameter_count()); |
203 CHECK_EQ(expected.bytecode_length, actual->length()); | 207 CHECK_EQ(expected.bytecode_length, actual->length()); |
204 if (expected.constant_count == 0) { | 208 if (expected.constant_count == 0) { |
(...skipping 8165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8370 }, | 8374 }, |
8371 0 | 8375 0 |
8372 }; | 8376 }; |
8373 // clang-format on | 8377 // clang-format on |
8374 | 8378 |
8375 Handle<BytecodeArray> bytecode_array = | 8379 Handle<BytecodeArray> bytecode_array = |
8376 helper.MakeBytecodeForFunctionBody(snippet.code_snippet); | 8380 helper.MakeBytecodeForFunctionBody(snippet.code_snippet); |
8377 CheckBytecodeArrayEqual(snippet, bytecode_array); | 8381 CheckBytecodeArrayEqual(snippet, bytecode_array); |
8378 } | 8382 } |
8379 | 8383 |
| 8384 TEST(ClassDeclarations) { |
| 8385 InitializedHandleScope handle_scope; |
| 8386 BytecodeGeneratorHelper helper; |
| 8387 |
| 8388 int closure = Register::function_closure().index(); |
| 8389 int context = Register::current_context().index(); |
| 8390 |
| 8391 // clang-format off |
| 8392 ExpectedSnippet<InstanceType, 12> snippets[] = { |
| 8393 {"class Person {\n" |
| 8394 " constructor(name) { this.name = name; }\n" |
| 8395 " speak() { console.log(this.name + ' is speaking.'); }\n" |
| 8396 "}\n", |
| 8397 8 * kPointerSize, |
| 8398 1, |
| 8399 61, |
| 8400 { |
| 8401 B(LdaTheHole), // |
| 8402 B(Star), R(1), // |
| 8403 B(StackCheck), // |
| 8404 B(LdaTheHole), // |
| 8405 B(Star), R(0), // |
| 8406 B(LdaTheHole), // |
| 8407 B(Star), R(2), // |
| 8408 B(CreateClosure), U8(0), U8(0), // |
| 8409 B(Star), R(3), // |
| 8410 B(LdaSmi8), U8(15), // |
| 8411 B(Star), R(4), // |
| 8412 B(LdaConstant), U8(1), // |
| 8413 B(Star), R(5), // |
| 8414 B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), // |
| 8415 B(Star), R(2), // |
| 8416 B(LdaInitialMap), // |
| 8417 B(Star), R(3), // |
| 8418 B(Mov), R(3), R(4), // |
| 8419 B(LdaConstant), U8(2), // |
| 8420 B(Star), R(5), // |
| 8421 B(CreateClosure), U8(3), U8(0), // |
| 8422 B(Star), R(6), // |
| 8423 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(4), U8(3), // |
| 8424 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), // |
| 8425 B(Star), R(0), // |
| 8426 B(Star), R(1), // |
| 8427 B(LdaUndefined), // |
| 8428 B(Return) // |
| 8429 }, |
| 8430 4, |
| 8431 { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare, |
| 8432 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 8433 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 8434 {"class person {\n" |
| 8435 " constructor(name) { this.name = name; }\n" |
| 8436 " speak() { console.log(this.name + ' is speaking.'); }\n" |
| 8437 "}\n", |
| 8438 8 * kPointerSize, |
| 8439 1, |
| 8440 61, |
| 8441 { |
| 8442 B(LdaTheHole), // |
| 8443 B(Star), R(1), // |
| 8444 B(StackCheck), // |
| 8445 B(LdaTheHole), // |
| 8446 B(Star), R(0), // |
| 8447 B(LdaTheHole), // |
| 8448 B(Star), R(2), // |
| 8449 B(CreateClosure), U8(0), U8(0), // |
| 8450 B(Star), R(3), // |
| 8451 B(LdaSmi8), U8(15), // |
| 8452 B(Star), R(4), // |
| 8453 B(LdaConstant), U8(1), // |
| 8454 B(Star), R(5), // |
| 8455 B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), // |
| 8456 B(Star), R(2), // |
| 8457 B(LdaInitialMap), // |
| 8458 B(Star), R(3), // |
| 8459 B(Mov), R(3), R(4), // |
| 8460 B(LdaConstant), U8(2), // |
| 8461 B(Star), R(5), // |
| 8462 B(CreateClosure), U8(3), U8(0), // |
| 8463 B(Star), R(6), // |
| 8464 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(4), U8(3), // |
| 8465 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), // |
| 8466 B(Star), R(0), // |
| 8467 B(Star), R(1), // |
| 8468 B(LdaUndefined), // |
| 8469 B(Return) // |
| 8470 }, |
| 8471 4, |
| 8472 { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare, |
| 8473 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 8474 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 8475 {"var n0 = 'a';" |
| 8476 "var n1 = 'b';" |
| 8477 "class N {\n" |
| 8478 " [n0]() { return n0; }\n" |
| 8479 " static [n1]() { return n1; }\n" |
| 8480 "}\n", |
| 8481 9 * kPointerSize, |
| 8482 1, |
| 8483 110, |
| 8484 { |
| 8485 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // |
| 8486 /* */ U8(1), // |
| 8487 B(PushContext), R(2), // |
| 8488 B(LdaTheHole), // |
| 8489 B(Star), R(1), // |
| 8490 B(StackCheck), // |
| 8491 B(LdaConstant), U8(0), // |
| 8492 B(StaContextSlot), R(context), U8(4), // |
| 8493 B(LdaConstant), U8(1), // |
| 8494 B(StaContextSlot), R(context), U8(5), // |
| 8495 B(LdaTheHole), // |
| 8496 B(Star), R(0), // |
| 8497 B(LdaTheHole), // |
| 8498 B(Star), R(3), // |
| 8499 B(CreateClosure), U8(2), U8(0), // |
| 8500 B(Star), R(4), // |
| 8501 B(LdaSmi8), U8(41), // |
| 8502 B(Star), R(5), // |
| 8503 B(LdaSmi8), U8(107), // |
| 8504 B(Star), R(6), // |
| 8505 B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), // |
| 8506 B(Star), R(3), // |
| 8507 B(LdaInitialMap), // |
| 8508 B(Star), R(4), // |
| 8509 B(Mov), R(4), R(5), // |
| 8510 B(LdaContextSlot), R(context), U8(4), // |
| 8511 B(ToName), // |
| 8512 B(Star), R(6), // |
| 8513 B(CreateClosure), U8(3), U8(0), // |
| 8514 B(Star), R(7), // |
| 8515 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(5), U8(3), // |
| 8516 B(Mov), R(3), R(5), // |
| 8517 B(LdaContextSlot), R(context), U8(5), // |
| 8518 B(ToName), // |
| 8519 B(Star), R(6), // |
| 8520 B(LdaConstant), U8(4), // |
| 8521 B(TestEqualStrict), R(6), // |
| 8522 B(JumpIfFalse), U8(7), // |
| 8523 B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), // |
| 8524 /* */ R(0), U8(0), // |
| 8525 B(CreateClosure), U8(5), U8(0), // |
| 8526 B(Star), R(7), // |
| 8527 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(5), U8(3), // |
| 8528 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), // |
| 8529 B(Star), R(0), // |
| 8530 B(Star), R(1), // |
| 8531 B(LdaUndefined), // |
| 8532 B(Return), // |
| 8533 }, |
| 8534 6, |
| 8535 { InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 8536 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 8537 InstanceType::SHARED_FUNCTION_INFO_TYPE, |
| 8538 InstanceType::SHARED_FUNCTION_INFO_TYPE, |
| 8539 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, |
| 8540 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 8541 {"var count = 0;\n" |
| 8542 "class C { constructor() { count++; }}\n" |
| 8543 "return new C();\n", |
| 8544 9 * kPointerSize, |
| 8545 1, |
| 8546 60, |
| 8547 { |
| 8548 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), // |
| 8549 B(PushContext), R(2), // |
| 8550 B(LdaTheHole), // |
| 8551 B(Star), R(1), // |
| 8552 B(StackCheck), // |
| 8553 B(LdaZero), // |
| 8554 B(StaContextSlot), R(context), U8(4), // |
| 8555 B(LdaTheHole), // |
| 8556 B(Star), R(0), // |
| 8557 B(LdaTheHole), // |
| 8558 B(Star), R(3), // |
| 8559 B(CreateClosure), U8(0), U8(0), // |
| 8560 B(Star), R(4), // |
| 8561 B(LdaSmi8), U8(30), // |
| 8562 B(Star), R(5), // |
| 8563 B(LdaSmi8), U8(67), // |
| 8564 B(Star), R(6), // |
| 8565 B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), // |
| 8566 B(Star), R(3), // |
| 8567 B(LdaInitialMap), // |
| 8568 B(Star), R(4), // |
| 8569 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), // |
| 8570 B(Star), R(0), // |
| 8571 B(Star), R(1), // |
| 8572 B(Star), R(3), // |
| 8573 B(New), R(3), R(0), U8(0), // |
| 8574 B(Return), // |
| 8575 }, |
| 8576 1, |
| 8577 { InstanceType::SHARED_FUNCTION_INFO_TYPE}}, |
| 8578 }; |
| 8579 // clang-format on |
| 8580 |
| 8581 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 8582 Handle<BytecodeArray> bytecode_array = |
| 8583 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
| 8584 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
| 8585 } |
| 8586 } |
| 8587 |
8380 } // namespace interpreter | 8588 } // namespace interpreter |
8381 } // namespace internal | 8589 } // namespace internal |
8382 } // namespace v8 | 8590 } // namespace v8 |
OLD | NEW |