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-generator.h" | 9 #include "src/interpreter/bytecode-generator.h" |
9 #include "src/interpreter/interpreter.h" | 10 #include "src/interpreter/interpreter.h" |
10 #include "test/cctest/cctest.h" | 11 #include "test/cctest/cctest.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace interpreter { | 15 namespace interpreter { |
15 | 16 |
16 class BytecodeGeneratorHelper { | 17 class BytecodeGeneratorHelper { |
17 public: | 18 public: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 } | 51 } |
51 | 52 |
52 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { | 53 Handle<BytecodeArray> MakeBytecodeForFunction(const char* function) { |
53 ScopedVector<char> program(1024); | 54 ScopedVector<char> program(1024); |
54 SNPrintF(program, "%s\n%s();", function, kFunctionName); | 55 SNPrintF(program, "%s\n%s();", function, kFunctionName); |
55 return MakeBytecode(program.start(), kFunctionName); | 56 return MakeBytecode(program.start(), kFunctionName); |
56 } | 57 } |
57 }; | 58 }; |
58 | 59 |
59 | 60 |
| 61 // Helper macros for handcrafting bytecode sequences. |
| 62 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
| 63 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
| 64 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
| 65 #define _ static_cast<uint8_t>(0x5a) |
| 66 |
| 67 |
60 // Structure for containing expected bytecode snippets. | 68 // Structure for containing expected bytecode snippets. |
61 template<typename T> | 69 template<typename T> |
62 struct ExpectedSnippet { | 70 struct ExpectedSnippet { |
63 const char* code_snippet; | 71 const char* code_snippet; |
64 int frame_size; | 72 int frame_size; |
65 int parameter_count; | 73 int parameter_count; |
66 int bytecode_length; | 74 int bytecode_length; |
67 const uint8_t bytecode[32]; | 75 const uint8_t bytecode[32]; |
68 int constant_count; | 76 int constant_count; |
69 T constants[16]; | 77 T constants[16]; |
70 }; | 78 }; |
71 | 79 |
72 | 80 |
73 // Helper macros for handcrafting bytecode sequences. | 81 static void CheckConstant(int expected, Object* actual) { |
74 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 82 CHECK_EQ(expected, Smi::cast(actual)->value()); |
75 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 83 } |
76 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 84 |
| 85 |
| 86 static void CheckConstant(double expected, Object* actual) { |
| 87 CHECK_EQ(expected, HeapNumber::cast(actual)->value()); |
| 88 } |
| 89 |
| 90 |
| 91 static void CheckConstant(const char* expected, Object* actual) { |
| 92 Handle<String> expected_string = |
| 93 CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(expected); |
| 94 CHECK(String::cast(actual)->Equals(*expected_string)); |
| 95 } |
| 96 |
| 97 |
| 98 template <typename T> |
| 99 static void CheckBytecodeArrayEqual(struct ExpectedSnippet<T> expected, |
| 100 Handle<BytecodeArray> actual, |
| 101 bool has_unknown = false) { |
| 102 CHECK_EQ(actual->frame_size(), expected.frame_size); |
| 103 CHECK_EQ(actual->parameter_count(), expected.parameter_count); |
| 104 CHECK_EQ(actual->length(), expected.bytecode_length); |
| 105 if (expected.constant_count == 0) { |
| 106 CHECK_EQ(actual->constant_pool(), CcTest::heap()->empty_fixed_array()); |
| 107 } else { |
| 108 CHECK_EQ(actual->constant_pool()->length(), expected.constant_count); |
| 109 for (int i = 0; i < expected.constant_count; i++) { |
| 110 CheckConstant(expected.constants[i], actual->constant_pool()->get(i)); |
| 111 } |
| 112 } |
| 113 |
| 114 BytecodeArrayIterator iterator(actual); |
| 115 int i = 0; |
| 116 while (!iterator.done()) { |
| 117 int bytecode_index = i++; |
| 118 Bytecode bytecode = iterator.current_bytecode(); |
| 119 if (Bytecodes::ToByte(bytecode) != expected.bytecode[bytecode_index]) { |
| 120 std::ostringstream stream; |
| 121 stream << "Check failed: expected bytecode [" << bytecode_index |
| 122 << "] to be " << Bytecodes::ToString(static_cast<Bytecode>( |
| 123 expected.bytecode[bytecode_index])) |
| 124 << " but got " << Bytecodes::ToString(bytecode); |
| 125 FATAL(stream.str().c_str()); |
| 126 } |
| 127 for (int j = 0; j < Bytecodes::NumberOfOperands(bytecode); ++j, ++i) { |
| 128 if (has_unknown) { |
| 129 // Check actual bytecode array doesn't have the same byte as the |
| 130 // one we use to specify an unknown byte. |
| 131 CHECK_NE(iterator.GetRawOperand(j), _); |
| 132 if (expected.bytecode[i] == _) { |
| 133 continue; |
| 134 } |
| 135 } |
| 136 if (iterator.GetRawOperand(j) != expected.bytecode[i]) { |
| 137 std::ostringstream stream; |
| 138 stream << "Check failed: expected operand [" << j << "] for bytecode [" |
| 139 << bytecode_index << "] to be " |
| 140 << static_cast<unsigned int>(expected.bytecode[i]) << " but got " |
| 141 << static_cast<unsigned int>(iterator.GetRawOperand(j)); |
| 142 FATAL(stream.str().c_str()); |
| 143 } |
| 144 } |
| 145 iterator.Advance(); |
| 146 } |
| 147 } |
77 | 148 |
78 | 149 |
79 TEST(PrimitiveReturnStatements) { | 150 TEST(PrimitiveReturnStatements) { |
80 InitializedHandleScope handle_scope; | 151 InitializedHandleScope handle_scope; |
81 BytecodeGeneratorHelper helper; | 152 BytecodeGeneratorHelper helper; |
82 | 153 |
83 ExpectedSnippet<void*> snippets[] = { | 154 ExpectedSnippet<int> snippets[] = { |
84 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, | 155 {"", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
85 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, | 156 {"return;", 0, 1, 2, {B(LdaUndefined), B(Return)}, 0}, |
86 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, | 157 {"return null;", 0, 1, 2, {B(LdaNull), B(Return)}, 0}, |
87 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, | 158 {"return true;", 0, 1, 2, {B(LdaTrue), B(Return)}, 0}, |
88 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, | 159 {"return false;", 0, 1, 2, {B(LdaFalse), B(Return)}, 0}, |
89 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, | 160 {"return 0;", 0, 1, 2, {B(LdaZero), B(Return)}, 0}, |
90 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, | 161 {"return +1;", 0, 1, 3, {B(LdaSmi8), U8(1), B(Return)}, 0}, |
91 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, | 162 {"return -1;", 0, 1, 3, {B(LdaSmi8), U8(-1), B(Return)}, 0}, |
92 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, | 163 {"return +127;", 0, 1, 3, {B(LdaSmi8), U8(127), B(Return)}, 0}, |
93 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, | 164 {"return -128;", 0, 1, 3, {B(LdaSmi8), U8(-128), B(Return)}, 0}, |
94 }; | 165 }; |
95 | 166 |
96 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 167 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
97 for (size_t i = 0; i < num_snippets; i++) { | 168 for (size_t i = 0; i < num_snippets; i++) { |
98 Handle<BytecodeArray> ba = | 169 Handle<BytecodeArray> bytecode_array = |
99 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 170 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
100 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 171 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
101 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
102 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
103 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
104 ba->length())); | |
105 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
106 } | 172 } |
107 } | 173 } |
108 | 174 |
109 | 175 |
110 TEST(PrimitiveExpressions) { | 176 TEST(PrimitiveExpressions) { |
111 InitializedHandleScope handle_scope; | 177 InitializedHandleScope handle_scope; |
112 BytecodeGeneratorHelper helper; | 178 BytecodeGeneratorHelper helper; |
113 | 179 |
114 ExpectedSnippet<void*> snippets[] = { | 180 ExpectedSnippet<int> snippets[] = { |
115 {"var x = 0; return x;", | 181 {"var x = 0; return x;", |
116 kPointerSize, | 182 kPointerSize, |
117 1, | 183 1, |
118 6, | 184 6, |
119 { | 185 { |
120 B(LdaZero), // | 186 B(LdaZero), // |
121 B(Star), R(0), // | 187 B(Star), R(0), // |
122 B(Ldar), R(0), // | 188 B(Ldar), R(0), // |
123 B(Return) // | 189 B(Return) // |
124 }, | 190 }, |
(...skipping 10 matching lines...) Expand all Loading... |
135 B(Star), R(1), // Dead store. | 201 B(Star), R(1), // Dead store. |
136 B(LdaSmi8), U8(3), // | 202 B(LdaSmi8), U8(3), // |
137 B(Add), R(1), // | 203 B(Add), R(1), // |
138 B(Return) // | 204 B(Return) // |
139 }, | 205 }, |
140 0 | 206 0 |
141 }}; | 207 }}; |
142 | 208 |
143 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 209 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
144 for (size_t i = 0; i < num_snippets; i++) { | 210 for (size_t i = 0; i < num_snippets; i++) { |
145 Handle<BytecodeArray> ba = | 211 Handle<BytecodeArray> bytecode_array = |
146 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 212 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
147 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 213 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
148 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
149 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
150 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
151 ba->length())); | |
152 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
153 } | 214 } |
154 } | 215 } |
155 | 216 |
156 | 217 |
157 TEST(Parameters) { | 218 TEST(Parameters) { |
158 InitializedHandleScope handle_scope; | 219 InitializedHandleScope handle_scope; |
159 BytecodeGeneratorHelper helper; | 220 BytecodeGeneratorHelper helper; |
160 | 221 |
161 ExpectedSnippet<void*> snippets[] = { | 222 ExpectedSnippet<int> snippets[] = { |
162 {"function f() { return this; }", | 223 {"function f() { return this; }", |
163 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 224 0, 1, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
164 {"function f(arg1) { return arg1; }", | 225 {"function f(arg1) { return arg1; }", |
165 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, | 226 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex), B(Return)}, 0}, |
166 {"function f(arg1) { return this; }", | 227 {"function f(arg1) { return this; }", |
167 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, | 228 0, 2, 3, {B(Ldar), R(helper.kLastParamIndex - 1), B(Return)}, 0}, |
168 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", | 229 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }", |
169 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, | 230 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 3), B(Return)}, 0}, |
170 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", | 231 {"function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }", |
171 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0} | 232 0, 8, 3, {B(Ldar), R(helper.kLastParamIndex - 7), B(Return)}, 0} |
172 }; | 233 }; |
173 | 234 |
174 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 235 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
175 for (size_t i = 0; i < num_snippets; i++) { | 236 for (size_t i = 0; i < num_snippets; i++) { |
176 Handle<BytecodeArray> ba = | 237 Handle<BytecodeArray> bytecode_array = |
177 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | 238 helper.MakeBytecodeForFunction(snippets[i].code_snippet); |
178 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 239 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
179 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
180 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
181 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
182 ba->length())); | |
183 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | |
184 } | 240 } |
185 } | 241 } |
186 | 242 |
187 | 243 |
188 TEST(Constants) { | 244 TEST(Constants) { |
189 InitializedHandleScope handle_scope; | 245 InitializedHandleScope handle_scope; |
190 BytecodeGeneratorHelper helper; | 246 BytecodeGeneratorHelper helper; |
191 | 247 |
192 // Check large SMIs. | 248 // Check large SMIs. |
193 { | 249 { |
(...skipping 18 matching lines...) Expand all Loading... |
212 B(LdaConstant), U8(0), | 268 B(LdaConstant), U8(0), |
213 B(Star), R(0), | 269 B(Star), R(0), |
214 B(LdaConstant), U8(0), | 270 B(LdaConstant), U8(0), |
215 B(Return) | 271 B(Return) |
216 }, 1, { 1234 } | 272 }, 1, { 1234 } |
217 } | 273 } |
218 }; | 274 }; |
219 | 275 |
220 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 276 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
221 for (size_t i = 0; i < num_snippets; i++) { | 277 for (size_t i = 0; i < num_snippets; i++) { |
222 Handle<BytecodeArray> ba = | 278 Handle<BytecodeArray> bytecode_array = |
223 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 279 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
224 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 280 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
225 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
226 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
227 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
228 ba->length())); | |
229 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
230 for (int j = 0; j < snippets[i].constant_count; j++) { | |
231 CHECK_EQ(Smi::cast(ba->constant_pool()->get(j))->value(), | |
232 snippets[i].constants[j]); | |
233 } | |
234 } | 281 } |
235 } | 282 } |
236 | 283 |
237 // Check heap number double constants | 284 // Check heap number double constants |
238 { | 285 { |
239 ExpectedSnippet<double> snippets[] = { | 286 ExpectedSnippet<double> snippets[] = { |
240 {"return 1.2;", | 287 {"return 1.2;", |
241 0, 1, 3, | 288 0, 1, 3, |
242 { | 289 { |
243 B(LdaConstant), U8(0), | 290 B(LdaConstant), U8(0), |
(...skipping 17 matching lines...) Expand all Loading... |
261 }, 2, | 308 }, 2, |
262 // TODO(rmcilroy): Currently multiple identical double literals end up | 309 // TODO(rmcilroy): Currently multiple identical double literals end up |
263 // being allocated as new HeapNumbers and so require multiple constant | 310 // being allocated as new HeapNumbers and so require multiple constant |
264 // pool entries. De-dup identical values. | 311 // pool entries. De-dup identical values. |
265 { 3.14, 3.14 } | 312 { 3.14, 3.14 } |
266 } | 313 } |
267 }; | 314 }; |
268 | 315 |
269 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 316 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
270 for (size_t i = 0; i < num_snippets; i++) { | 317 for (size_t i = 0; i < num_snippets; i++) { |
271 Handle<BytecodeArray> ba = | 318 Handle<BytecodeArray> bytecode_array = |
272 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 319 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
273 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 320 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
274 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
275 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
276 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
277 ba->length())); | |
278 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
279 for (int j = 0; j < snippets[i].constant_count; j++) { | |
280 CHECK_EQ(HeapNumber::cast(ba->constant_pool()->get(j))->value(), | |
281 snippets[i].constants[j]); | |
282 } | |
283 } | 321 } |
284 } | 322 } |
285 | 323 |
286 // Check string literals | 324 // Check string literals |
287 { | 325 { |
288 ExpectedSnippet<const char*> snippets[] = { | 326 ExpectedSnippet<const char*> snippets[] = { |
289 {"return \"This is a string\";", 0, 1, 3, | 327 {"return \"This is a string\";", 0, 1, 3, |
290 { | 328 { |
291 B(LdaConstant), U8(0), | 329 B(LdaConstant), U8(0), |
292 B(Return) | 330 B(Return) |
(...skipping 15 matching lines...) Expand all Loading... |
308 B(LdaConstant), U8(0), | 346 B(LdaConstant), U8(0), |
309 B(Star), R(0), | 347 B(Star), R(0), |
310 B(LdaConstant), U8(0), | 348 B(LdaConstant), U8(0), |
311 B(Return) | 349 B(Return) |
312 }, 1, { "Same string" } | 350 }, 1, { "Same string" } |
313 } | 351 } |
314 }; | 352 }; |
315 | 353 |
316 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 354 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
317 for (size_t i = 0; i < num_snippets; i++) { | 355 for (size_t i = 0; i < num_snippets; i++) { |
318 Handle<BytecodeArray> ba = | 356 Handle<BytecodeArray> bytecode_array = |
319 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 357 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
320 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 358 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
321 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
322 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
323 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
324 ba->length())); | |
325 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
326 for (int j = 0; j < snippets[i].constant_count; j++) { | |
327 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( | |
328 snippets[i].constants[j]); | |
329 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
330 } | |
331 } | 359 } |
332 } | 360 } |
333 } | 361 } |
334 | 362 |
335 | 363 |
336 TEST(PropertyLoads) { | 364 TEST(PropertyLoads) { |
337 InitializedHandleScope handle_scope; | 365 InitializedHandleScope handle_scope; |
338 BytecodeGeneratorHelper helper; | 366 BytecodeGeneratorHelper helper; |
339 | 367 |
340 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; | 368 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 B(Star), R(1), | 426 B(Star), R(1), |
399 B(LdaSmi8), U8(-124), | 427 B(LdaSmi8), U8(-124), |
400 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 428 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), |
401 B(Return) | 429 B(Return) |
402 }, | 430 }, |
403 1, { "name" } | 431 1, { "name" } |
404 } | 432 } |
405 }; | 433 }; |
406 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 434 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
407 for (size_t i = 0; i < num_snippets; i++) { | 435 for (size_t i = 0; i < num_snippets; i++) { |
408 Handle<BytecodeArray> ba = | 436 Handle<BytecodeArray> bytecode_array = |
409 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 437 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
410 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 438 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
411 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
412 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
413 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
414 ba->length())); | |
415 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
416 for (int j = 0; j < snippets[i].constant_count; j++) { | |
417 Handle<String> expected = helper.factory()->NewStringFromAsciiChecked( | |
418 snippets[i].constants[j]); | |
419 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
420 } | |
421 } | 439 } |
422 } | 440 } |
423 | 441 |
424 | 442 |
425 TEST(PropertyStores) { | 443 TEST(PropertyStores) { |
426 InitializedHandleScope handle_scope; | 444 InitializedHandleScope handle_scope; |
427 BytecodeGeneratorHelper helper; | 445 BytecodeGeneratorHelper helper; |
428 | 446 |
429 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; | 447 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; |
430 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); | 448 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), | 520 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), |
503 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), | 521 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), |
504 B(LdaUndefined), | 522 B(LdaUndefined), |
505 B(Return) | 523 B(Return) |
506 }, | 524 }, |
507 1, { "name" } | 525 1, { "name" } |
508 } | 526 } |
509 }; | 527 }; |
510 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 528 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
511 for (size_t i = 0; i < num_snippets; i++) { | 529 for (size_t i = 0; i < num_snippets; i++) { |
512 Handle<BytecodeArray> ba = | 530 Handle<BytecodeArray> bytecode_array = |
513 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 531 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
514 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 532 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
515 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
516 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
517 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
518 ba->length())); | |
519 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
520 for (int j = 0; j < snippets[i].constant_count; j++) { | |
521 Handle<String> expected = | |
522 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | |
523 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
524 } | |
525 } | 533 } |
526 } | 534 } |
527 | 535 |
528 | 536 |
529 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" | 537 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" |
530 | 538 |
531 | 539 |
532 TEST(PropertyCall) { | 540 TEST(PropertyCall) { |
533 InitializedHandleScope handle_scope; | 541 InitializedHandleScope handle_scope; |
534 BytecodeGeneratorHelper helper; | 542 BytecodeGeneratorHelper helper; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 B(Ldar), R(helper.kLastParamIndex), | 593 B(Ldar), R(helper.kLastParamIndex), |
586 B(Star), R(3), | 594 B(Star), R(3), |
587 B(Call), R(0), R(1), U8(2), | 595 B(Call), R(0), R(1), U8(2), |
588 B(Return) | 596 B(Return) |
589 }, | 597 }, |
590 1, { "func" } | 598 1, { "func" } |
591 } | 599 } |
592 }; | 600 }; |
593 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 601 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
594 for (size_t i = 0; i < num_snippets; i++) { | 602 for (size_t i = 0; i < num_snippets; i++) { |
595 Handle<BytecodeArray> ba = | 603 Handle<BytecodeArray> bytecode_array = |
596 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 604 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
597 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 605 CheckBytecodeArrayEqual(snippets[i], bytecode_array); |
598 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
599 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
600 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
601 ba->length())); | |
602 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
603 for (int j = 0; j < snippets[i].constant_count; j++) { | |
604 Handle<String> expected = | |
605 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | |
606 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
607 } | |
608 } | 606 } |
609 } | 607 } |
610 | 608 |
| 609 |
| 610 TEST(LoadGlobal) { |
| 611 InitializedHandleScope handle_scope; |
| 612 BytecodeGeneratorHelper helper; |
| 613 |
| 614 ExpectedSnippet<const char*> snippets[] = { |
| 615 {"var a = 1;\nfunction f() { return a; }\nf()", |
| 616 0, 1, 3, |
| 617 { |
| 618 B(LdaGlobal), _, |
| 619 B(Return) |
| 620 }, |
| 621 }, |
| 622 {"function t() { }\nfunction f() { return t; }\nf()", |
| 623 0, 1, 3, |
| 624 { |
| 625 B(LdaGlobal), _, |
| 626 B(Return) |
| 627 }, |
| 628 }, |
| 629 }; |
| 630 |
| 631 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 632 for (size_t i = 0; i < num_snippets; i++) { |
| 633 Handle<BytecodeArray> bytecode_array = |
| 634 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 635 bytecode_array->Print(); |
| 636 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 637 } |
| 638 } |
| 639 |
| 640 |
| 641 TEST(CallGlobal) { |
| 642 InitializedHandleScope handle_scope; |
| 643 BytecodeGeneratorHelper helper; |
| 644 |
| 645 ExpectedSnippet<const char*> snippets[] = { |
| 646 {"function t() { }\nfunction f() { return t(); }\nf()", |
| 647 2 * kPointerSize, 1, 12, |
| 648 { |
| 649 B(LdaUndefined), |
| 650 B(Star), R(1), |
| 651 B(LdaGlobal), _, |
| 652 B(Star), R(0), |
| 653 B(Call), R(0), R(1), U8(0), |
| 654 B(Return) |
| 655 }, |
| 656 }, |
| 657 {"function t(a, b, c) { }\nfunction f() { return t(1, 2, 3); }\nf()", |
| 658 5 * kPointerSize, 1, 24, |
| 659 { |
| 660 B(LdaUndefined), |
| 661 B(Star), R(1), |
| 662 B(LdaGlobal), _, |
| 663 B(Star), R(0), |
| 664 B(LdaSmi8), U8(1), |
| 665 B(Star), R(2), |
| 666 B(LdaSmi8), U8(2), |
| 667 B(Star), R(3), |
| 668 B(LdaSmi8), U8(3), |
| 669 B(Star), R(4), |
| 670 B(Call), R(0), R(1), U8(3), |
| 671 B(Return) |
| 672 }, |
| 673 }, |
| 674 }; |
| 675 |
| 676 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
| 677 for (size_t i = 0; i < num_snippets; i++) { |
| 678 Handle<BytecodeArray> bytecode_array = |
| 679 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
| 680 CheckBytecodeArrayEqual(snippets[i], bytecode_array, true); |
| 681 } |
| 682 } |
| 683 |
611 } // namespace interpreter | 684 } // namespace interpreter |
612 } // namespace internal | 685 } // namespace internal |
613 } // namespance v8 | 686 } // namespance v8 |
OLD | NEW |