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 = (InstanceType)-1; | |
Michael Starzinger
2016/02/04 13:40:20
nit: Can we use static_cast instead of C-style cas
oth
2016/02/04 14:00:59
Done.
| |
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 7483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7688 }; | 7692 }; |
7689 | 7693 |
7690 for (size_t i = 0; i < arraysize(snippets); i++) { | 7694 for (size_t i = 0; i < arraysize(snippets); i++) { |
7691 Handle<BytecodeArray> bytecode_array = | 7695 Handle<BytecodeArray> bytecode_array = |
7692 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 7696 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
7693 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 7697 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
7694 } | 7698 } |
7695 FLAG_harmony_do_expressions = old_flag; | 7699 FLAG_harmony_do_expressions = old_flag; |
7696 } | 7700 } |
7697 | 7701 |
7702 | |
7698 TEST(WithStatement) { | 7703 TEST(WithStatement) { |
7699 InitializedHandleScope handle_scope; | 7704 InitializedHandleScope handle_scope; |
7700 BytecodeGeneratorHelper helper; | 7705 BytecodeGeneratorHelper helper; |
7701 | 7706 |
7702 int deep_elements_flags = | 7707 int deep_elements_flags = |
7703 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; | 7708 ObjectLiteral::kFastElements | ObjectLiteral::kDisableMementos; |
7704 int context = Register::current_context().index(); | 7709 int context = Register::current_context().index(); |
7705 int closure = Register::function_closure().index(); | 7710 int closure = Register::function_closure().index(); |
7706 int new_target = Register::new_target().index(); | 7711 int new_target = Register::new_target().index(); |
7707 | 7712 |
(...skipping 29 matching lines...) Expand all Loading... | |
7737 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, | 7742 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE}}, |
7738 }; | 7743 }; |
7739 | 7744 |
7740 for (size_t i = 0; i < arraysize(snippets); i++) { | 7745 for (size_t i = 0; i < arraysize(snippets); i++) { |
7741 Handle<BytecodeArray> bytecode_array = | 7746 Handle<BytecodeArray> bytecode_array = |
7742 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 7747 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
7743 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | 7748 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
7744 } | 7749 } |
7745 } | 7750 } |
7746 | 7751 |
7752 | |
7753 TEST(ClassDeclarations) { | |
7754 InitializedHandleScope handle_scope; | |
7755 BytecodeGeneratorHelper helper; | |
7756 | |
7757 int closure = Register::function_closure().index(); | |
7758 int context = Register::current_context().index(); | |
7759 | |
7760 ExpectedSnippet<InstanceType, 12> snippets[] = { | |
7761 {"class Person {\n" | |
7762 " constructor(name) { this.name = name; }\n" | |
7763 " speak() { console.log(this.name + ' is speaking.'); }\n" | |
7764 "}\n", | |
7765 8 * kPointerSize, | |
7766 1, | |
7767 60, | |
7768 { | |
7769 B(LdaTheHole), // | |
7770 B(Star), R(1), // | |
7771 B(LdaTheHole), // | |
7772 B(Star), R(0), // | |
7773 B(LdaTheHole), // | |
7774 B(Star), R(2), // | |
7775 B(CreateClosure), U8(0), U8(0), // | |
7776 B(Star), R(3), // | |
7777 B(LdaSmi8), U8(15), // | |
7778 B(Star), R(4), // | |
7779 B(LdaConstant), U8(1), // | |
7780 B(Star), R(5), // | |
7781 B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), // | |
7782 B(Star), R(2), // | |
7783 B(LdaInitialMap), // | |
7784 B(Star), R(3), // | |
7785 B(Mov), R(3), R(4), // | |
7786 B(LdaConstant), U8(2), // | |
7787 B(Star), R(5), // | |
7788 B(CreateClosure), U8(3), U8(0), // | |
7789 B(Star), R(6), // | |
7790 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(4), U8(3), // | |
7791 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(2), U8(2), // | |
7792 B(Star), R(0), // | |
7793 B(Star), R(1), // | |
7794 B(LdaUndefined), // | |
7795 B(Return) // | |
7796 }, | |
7797 4, | |
7798 { InstanceType::SHARED_FUNCTION_INFO_TYPE, kInstanceTypeDontCare, | |
7799 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7800 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, | |
7801 {"var n0 = 'a';" | |
7802 "var n1 = 'b';" | |
7803 "class N {\n" | |
7804 " [n0]() { return n0; }\n" | |
7805 " static [n1]() { return n1; }\n" | |
7806 "}\n", | |
7807 9 * kPointerSize, | |
7808 1, | |
7809 109, | |
7810 { | |
7811 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), // | |
7812 /* */ U8(1), // | |
7813 B(PushContext), R(2), // | |
7814 B(LdaTheHole), // | |
7815 B(Star), R(1), // | |
7816 B(LdaConstant), U8(0), // | |
7817 B(StaContextSlot), R(context), U8(4), // | |
7818 B(LdaConstant), U8(1), // | |
7819 B(StaContextSlot), R(context), U8(5), // | |
7820 B(LdaTheHole), // | |
7821 B(Star), R(0), // | |
7822 B(LdaTheHole), // | |
7823 B(Star), R(3), // | |
7824 B(CreateClosure), U8(2), U8(0), // | |
7825 B(Star), R(4), // | |
7826 B(LdaSmi8), U8(41), // | |
7827 B(Star), R(5), // | |
7828 B(LdaSmi8), U8(107), // | |
7829 B(Star), R(6), // | |
7830 B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), // | |
7831 B(Star), R(3), // | |
7832 B(LdaInitialMap), // | |
7833 B(Star), R(4), // | |
7834 B(Mov), R(4), R(5), // | |
7835 B(LdaContextSlot), R(context), U8(4), // | |
7836 B(ToName), // | |
7837 B(Star), R(6), // | |
7838 B(CreateClosure), U8(3), U8(0), // | |
7839 B(Star), R(7), // | |
7840 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(5), U8(3), // | |
7841 B(Mov), R(3), R(5), // | |
7842 B(LdaContextSlot), R(context), U8(5), // | |
7843 B(ToName), // | |
7844 B(Star), R(6), // | |
7845 B(LdaConstant), U8(4), // | |
7846 B(TestEqualStrict), R(6), // | |
7847 B(JumpIfFalse), U8(7), // | |
7848 B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), // | |
7849 /* */ R(0), U8(0), // | |
7850 B(CreateClosure), U8(5), U8(0), // | |
7851 B(Star), R(7), // | |
7852 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(5), U8(3), // | |
7853 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), // | |
7854 B(Star), R(0), // | |
7855 B(Star), R(1), // | |
7856 B(LdaUndefined), // | |
7857 B(Return), // | |
7858 }, | |
7859 6, | |
7860 { InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7861 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7862 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7863 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7864 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7865 InstanceType::SHARED_FUNCTION_INFO_TYPE}}, | |
7866 {"class Person {\n" | |
7867 "}\n" | |
7868 "class Cyborg extends Person {\n" | |
7869 " constructor() { this.battery_ = 0; }" | |
7870 " get battery() { return battery_; }" | |
7871 " set battery(new_level) { battery_ = new_level; }" | |
7872 " charge() { battery(100); }" | |
7873 " static diet() { return 'metal bolts'; }\n" | |
7874 "}\n" | |
7875 "return new Cyborg();\n", | |
7876 10 * kPointerSize, | |
7877 1, | |
7878 156, | |
7879 { | |
7880 B(LdaTheHole), // | |
7881 B(Star), R(2), // | |
7882 B(LdaTheHole), // | |
7883 B(Star), R(3), // | |
7884 B(LdaTheHole), // | |
7885 B(Star), R(0), // | |
7886 B(LdaTheHole), // | |
7887 B(Star), R(4), // | |
7888 B(CreateClosure), U8(0), U8(0), // | |
7889 B(Star), R(5), // | |
7890 B(LdaSmi8), U8(15), // | |
7891 B(Star), R(6), // | |
7892 B(LdaSmi8), U8(31), // | |
7893 B(Star), R(7), // | |
7894 B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), // | |
7895 B(Star), R(4), // | |
7896 B(LdaInitialMap), // | |
7897 B(Star), R(5), // | |
7898 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(4), U8(2), // | |
7899 B(Star), R(0), // | |
7900 B(Star), R(2), // | |
7901 B(LdaTheHole), // | |
7902 B(Star), R(1), // | |
7903 B(Ldar), R(2), // | |
7904 B(Star), R(4), // | |
7905 B(CreateClosure), U8(1), U8(0), // | |
7906 B(Star), R(5), // | |
7907 B(LdaSmi8), U8(32), // | |
7908 B(Star), R(6), // | |
7909 B(LdaConstant), U8(2), // | |
7910 B(Star), R(7), // | |
7911 B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), // | |
7912 B(Star), R(4), // | |
7913 B(LdaInitialMap), // | |
7914 B(Star), R(5), // | |
7915 B(Mov), R(5), R(6), // | |
7916 B(LdaConstant), U8(3), // | |
7917 B(Star), R(7), // | |
7918 B(CreateClosure), U8(4), U8(0), // | |
7919 B(Star), R(8), // | |
7920 B(LdaSmi8), U8(2), // | |
7921 B(Star), R(9), // | |
7922 B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), // | |
7923 /* */ R(6), U8(4), // | |
7924 B(LdaConstant), U8(3), // | |
7925 B(Star), R(7), // | |
7926 B(CreateClosure), U8(5), U8(0), // | |
7927 B(Star), R(8), // | |
7928 B(CallRuntime), U16(Runtime::kDefineSetterPropertyUnchecked), // | |
7929 /* */ R(6), U8(4), // | |
7930 B(LdaConstant), U8(6), // | |
7931 B(Star), R(7), // | |
7932 B(CreateClosure), U8(7), U8(0), // | |
7933 B(Star), R(8), // | |
7934 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(6), U8(3), // | |
7935 B(Mov), R(4), R(6), // | |
7936 B(LdaConstant), U8(8), // | |
7937 B(Star), R(7), // | |
7938 B(CreateClosure), U8(9), U8(0), // | |
7939 B(Star), R(8), // | |
7940 B(CallRuntime), U16(Runtime::kDefineClassMethod), R(6), U8(3), // | |
7941 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(4), U8(2), // | |
7942 B(Star), R(1), // | |
7943 B(Star), R(3), // | |
7944 B(Star), R(4), // | |
7945 B(New), R(4), R(0), U8(0), // | |
7946 B(Return), // | |
7947 }, | |
7948 10, | |
7949 { InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7950 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7951 kInstanceTypeDontCare, | |
7952 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7953 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7954 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7955 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7956 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7957 InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE, | |
7958 InstanceType::SHARED_FUNCTION_INFO_TYPE, | |
7959 } | |
7960 }, | |
7961 {"var count = 0;\n" | |
7962 "class C { constructor() { count++; }}\n" | |
7963 "return new C();\n", | |
7964 9 * kPointerSize, | |
7965 1, | |
7966 59, | |
7967 { | |
7968 B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1), // | |
7969 B(PushContext), R(2), // | |
7970 B(LdaTheHole), // | |
7971 B(Star), R(1), // | |
7972 B(LdaZero), // | |
7973 B(StaContextSlot), R(context), U8(4), // | |
7974 B(LdaTheHole), // | |
7975 B(Star), R(0), // | |
7976 B(LdaTheHole), // | |
7977 B(Star), R(3), // | |
7978 B(CreateClosure), U8(0), U8(0), // | |
7979 B(Star), R(4), // | |
7980 B(LdaSmi8), U8(30), // | |
7981 B(Star), R(5), // | |
7982 B(LdaSmi8), U8(67), // | |
7983 B(Star), R(6), // | |
7984 B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), // | |
7985 B(Star), R(3), // | |
7986 B(LdaInitialMap), // | |
7987 B(Star), R(4), // | |
7988 B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), // | |
7989 B(Star), R(0), // | |
7990 B(Star), R(1), // | |
7991 B(Star), R(3), // | |
7992 B(New), R(3), R(0), U8(0), // | |
7993 B(Return), // | |
7994 }, | |
7995 1, | |
7996 { InstanceType::SHARED_FUNCTION_INFO_TYPE}}, | |
7997 }; | |
7998 | |
7999 for (size_t i = 0; i < arraysize(snippets); i++) { | |
8000 Handle<BytecodeArray> bytecode_array = | |
8001 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | |
8002 CheckBytecodeArrayEqual(snippets[i], bytecode_array); | |
8003 } | |
8004 } | |
8005 | |
7747 } // namespace interpreter | 8006 } // namespace interpreter |
7748 } // namespace internal | 8007 } // namespace internal |
7749 } // namespace v8 | 8008 } // namespace v8 |
OLD | NEW |