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 = "my_function"; | 18 const char* kFunctionName = "f"; |
19 | 19 |
20 BytecodeGeneratorHelper() { | 20 BytecodeGeneratorHelper() { |
21 i::FLAG_ignition = true; | 21 i::FLAG_ignition = true; |
22 i::FLAG_ignition_filter = kFunctionName; | 22 i::FLAG_ignition_filter = kFunctionName; |
23 CcTest::i_isolate()->interpreter()->Initialize(); | 23 CcTest::i_isolate()->interpreter()->Initialize(); |
24 } | 24 } |
25 | 25 |
26 | 26 |
27 Handle<BytecodeArray> MakeBytecode(const char* script, | 27 Handle<BytecodeArray> MakeBytecode(const char* script, |
28 const char* function_name) { | 28 const char* function_name) { |
29 CompileRun(script); | 29 CompileRun(script); |
30 Local<Function> function = | 30 Local<Function> function = |
31 Local<Function>::Cast(CcTest::global()->Get(v8_str(function_name))); | 31 Local<Function>::Cast(CcTest::global()->Get(v8_str(function_name))); |
32 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*function); | 32 i::Handle<i::JSFunction> js_function = v8::Utils::OpenHandle(*function); |
33 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); | 33 return handle(js_function->shared()->bytecode_array(), CcTest::i_isolate()); |
34 } | 34 } |
35 | 35 |
36 | 36 |
37 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { | 37 Handle<BytecodeArray> MakeBytecodeForFunctionBody(const char* body) { |
38 ScopedVector<char> program(1024); | 38 ScopedVector<char> program(1024); |
39 SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, | 39 SNPrintF(program, "function %s() { %s }\n%s();", kFunctionName, body, |
40 kFunctionName); | 40 kFunctionName); |
41 return MakeBytecode(program.start(), kFunctionName); | 41 return MakeBytecode(program.start(), kFunctionName); |
42 } | 42 } |
| 43 |
| 44 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { |
| 45 ScopedVector<char> program(1024); |
| 46 SNPrintF(program, "%s\n%s();", function, kFunctionName); |
| 47 return MakeBytecode(program.start(), kFunctionName); |
| 48 } |
43 }; | 49 }; |
44 | 50 |
45 | 51 |
46 // Structure for containing expected bytecode snippets. | 52 // Structure for containing expected bytecode snippets. |
47 struct ExpectedSnippet { | 53 struct ExpectedSnippet { |
48 const char* body; | 54 const char* body; |
49 int frame_size; | 55 int frame_size; |
| 56 int parameter_count; |
50 int bytecode_length; | 57 int bytecode_length; |
51 const uint8_t bytecode[16]; | 58 const uint8_t bytecode[16]; |
52 }; | 59 }; |
53 | 60 |
54 | 61 |
55 // Helper macros for handcrafting bytecode sequences. | 62 // Helper macros for handcrafting bytecode sequences. |
56 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 63 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
57 #define U8(x) static_cast<uint8_t>(x & 0xff) | 64 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
58 #define R(x) static_cast<uint8_t>(-x & 0xff) | 65 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
59 | 66 |
60 | 67 |
61 TEST(PrimitiveReturnStatements) { | 68 TEST(PrimitiveReturnStatements) { |
62 InitializedHandleScope handle_scope; | 69 InitializedHandleScope handle_scope; |
63 BytecodeGeneratorHelper helper; | 70 BytecodeGeneratorHelper helper; |
64 | 71 |
65 ExpectedSnippet snippets[] = { | 72 ExpectedSnippet snippets[] = { |
66 {"return;", 0, 2, {B(LdaUndefined), B(Return)}}, | 73 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}}, |
67 {"return null;", 0, 2, {B(LdaNull), B(Return)}}, | 74 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}}, |
68 {"return true;", 0, 2, {B(LdaTrue), B(Return)}}, | 75 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}}, |
69 {"return false;", 0, 2, {B(LdaFalse), B(Return)}}, | 76 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}}, |
70 {"return 0;", 0, 2, {B(LdaZero), B(Return)}}, | 77 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}}, |
71 {"return +1;", 0, 3, {B(LdaSmi8), U8(1), B(Return)}}, | 78 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}}, |
72 {"return -1;", 0, 3, {B(LdaSmi8), U8(-1), B(Return)}}, | 79 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}}, |
73 {"return +127;", 0, 3, {B(LdaSmi8), U8(127), B(Return)}}, | 80 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}}, |
74 {"return -128;", 0, 3, {B(LdaSmi8), U8(-128), B(Return)}}, | 81 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}}, |
75 }; | 82 }; |
76 | 83 |
77 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 84 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
78 for (size_t i = 0; i < num_snippets; i++) { | 85 for (size_t i = 0; i < num_snippets; i++) { |
79 Handle<BytecodeArray> ba = | 86 Handle<BytecodeArray> ba = |
80 helper.MakeBytecodeForFunctionBody(snippets[i].body); | 87 helper.MakeBytecodeForFunctionBody(snippets[i].body); |
81 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 88 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
| 89 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
82 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 90 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
83 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 91 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
84 ba->length())); | 92 ba->length())); |
85 } | 93 } |
86 } | 94 } |
87 | 95 |
88 | 96 |
89 TEST(PrimitiveExpressions) { | 97 TEST(PrimitiveExpressions) { |
90 InitializedHandleScope handle_scope; | 98 InitializedHandleScope handle_scope; |
91 BytecodeGeneratorHelper helper; | 99 BytecodeGeneratorHelper helper; |
92 | 100 |
93 ExpectedSnippet snippets[] = { | 101 ExpectedSnippet snippets[] = { |
94 {"var x = 0; return x;", | 102 {"var x = 0; return x;", |
95 kPointerSize, | 103 kPointerSize, |
| 104 1, |
96 6, | 105 6, |
97 { | 106 { |
98 B(LdaZero), // | 107 B(LdaZero), // |
99 B(Star), R(0), // | 108 B(Star), R(0), // |
100 B(Ldar), R(0), // | 109 B(Ldar), R(0), // |
101 B(Return) // | 110 B(Return) // |
102 }}, | 111 }}, |
103 {"var x = 0; return x + 3;", | 112 {"var x = 0; return x + 3;", |
104 2 * kPointerSize, | 113 2 * kPointerSize, |
| 114 1, |
105 12, | 115 12, |
106 { | 116 { |
107 B(LdaZero), // | 117 B(LdaZero), // |
108 B(Star), R(0), // | 118 B(Star), R(0), // |
109 B(Ldar), R(0), // Easy to spot r1 not really needed here. | 119 B(Ldar), R(0), // Easy to spot r1 not really needed here. |
110 B(Star), R(1), // Dead store. | 120 B(Star), R(1), // Dead store. |
111 B(LdaSmi8), U8(3), // | 121 B(LdaSmi8), U8(3), // |
112 B(Add), R(1), // | 122 B(Add), R(1), // |
113 B(Return) // | 123 B(Return) // |
114 }}}; | 124 }}}; |
115 | 125 |
116 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 126 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
117 for (size_t i = 0; i < num_snippets; i++) { | 127 for (size_t i = 0; i < num_snippets; i++) { |
118 Handle<BytecodeArray> ba = | 128 Handle<BytecodeArray> ba = |
119 helper.MakeBytecodeForFunctionBody(snippets[i].body); | 129 helper.MakeBytecodeForFunctionBody(snippets[i].body); |
120 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 130 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
| 131 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
121 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 132 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
122 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 133 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
123 ba->length())); | 134 ba->length())); |
| 135 } |
| 136 } |
| 137 |
| 138 |
| 139 TEST(Parameters) { |
| 140 InitializedHandleScope handle_scope; |
| 141 BytecodeGeneratorHelper helper; |
| 142 |
| 143 int last_param_index = |
| 144 -InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize; |
| 145 ExpectedSnippet snippets[] = { |
| 146 {"function f() { return this; }", |
| 147 0, 1, 3, {B(Ldar), R(last_param_index), B(Return)}}, |
| 148 {"function f(arg1) { return arg1; }", |
| 149 0, 2, 3, {B(Ldar), R(last_param_index), B(Return)}}, |
| 150 {"function f(arg1) { return this; }", |
| 151 0, 2, 3, {B(Ldar), R(last_param_index - 1), B(Return)}}, |
| 152 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", |
| 153 0, 8, 3, {B(Ldar), R(last_param_index - 3), B(Return)}}, |
| 154 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", |
| 155 0, 8, 3, {B(Ldar), R(last_param_index - 7), B(Return)}} |
| 156 }; |
| 157 |
| 158 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 159 for (size_t i = 0; i < num_snippets; i++) { |
| 160 Handle<BytecodeArray> ba = helper.MakeBytecodeForFunction(snippets[i].body); |
| 161 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
| 162 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
| 163 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
| 164 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
| 165 ba->length())); |
124 } | 166 } |
125 } | 167 } |
126 | 168 |
127 } // namespace interpreter | 169 } // namespace interpreter |
128 } // namespace internal | 170 } // namespace internal |
129 } // namespance v8 | 171 } // namespance v8 |
OLD | NEW |