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" |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 }; | 57 }; |
58 | 58 |
59 | 59 |
60 // Structure for containing expected bytecode snippets. | 60 // Structure for containing expected bytecode snippets. |
61 template<typename T> | 61 template<typename T> |
62 struct ExpectedSnippet { | 62 struct ExpectedSnippet { |
63 const char* code_snippet; | 63 const char* code_snippet; |
64 int frame_size; | 64 int frame_size; |
65 int parameter_count; | 65 int parameter_count; |
66 int bytecode_length; | 66 int bytecode_length; |
67 const uint8_t bytecode[32]; | 67 const uint8_t bytecode[512]; |
68 int constant_count; | 68 int constant_count; |
69 T constants[16]; | 69 T constants[16]; |
70 }; | 70 }; |
71 | 71 |
72 | 72 |
73 // Helper macros for handcrafting bytecode sequences. | 73 // Helper macros for handcrafting bytecode sequences. |
74 #define B(x) static_cast<uint8_t>(Bytecode::k##x) | 74 #define B(x) static_cast<uint8_t>(Bytecode::k##x) |
75 #define U8(x) static_cast<uint8_t>((x) & 0xff) | 75 #define U8(x) static_cast<uint8_t>((x) & 0xff) |
76 #define R(x) static_cast<uint8_t>(-(x) & 0xff) | 76 #define R(x) static_cast<uint8_t>(-(x) & 0xff) |
77 | 77 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 178 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
179 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | 179 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
180 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 180 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
181 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 181 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
182 ba->length())); | 182 ba->length())); |
183 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); | 183 CHECK_EQ(ba->constant_pool(), CcTest::heap()->empty_fixed_array()); |
184 } | 184 } |
185 } | 185 } |
186 | 186 |
187 | 187 |
188 TEST(Constants) { | 188 TEST(IntegerConstants) { |
189 InitializedHandleScope handle_scope; | 189 InitializedHandleScope handle_scope; |
190 BytecodeGeneratorHelper helper; | 190 BytecodeGeneratorHelper helper; |
191 | 191 |
192 // Check large SMIs. | 192 ExpectedSnippet<int> snippets[] = {{"return 12345678;", |
193 { | 193 0, |
194 ExpectedSnippet<int> snippets[] = { | 194 1, |
195 {"return 12345678;", 0, 1, 3, | 195 3, |
196 { | 196 { |
197 B(LdaConstant), U8(0), | 197 B(LdaConstant), U8(0), // |
198 B(Return) | 198 B(Return) // |
199 }, 1, { 12345678 } | 199 }, |
200 }, | 200 1, |
201 {"var a = 1234; return 5678;", 1 * kPointerSize, 1, 7, | 201 {12345678}}, |
202 { | 202 {"var a = 1234; return 5678;", |
203 B(LdaConstant), U8(0), | 203 1 * kPointerSize, |
204 B(Star), R(0), | 204 1, |
205 B(LdaConstant), U8(1), | 205 7, |
206 B(Return) | 206 { |
207 }, 2, { 1234, 5678 } | 207 B(LdaConstant), U8(0), // |
208 }, | 208 B(Star), R(0), // |
209 {"var a = 1234; return 1234;", | 209 B(LdaConstant), U8(1), // |
210 1 * kPointerSize, 1, 7, | 210 B(Return) // |
211 { | 211 }, |
212 B(LdaConstant), U8(0), | 212 2, |
213 B(Star), R(0), | 213 {1234, 5678}}, |
214 B(LdaConstant), U8(0), | 214 {"var a = 1234; return 1234;", |
215 B(Return) | 215 1 * kPointerSize, |
216 }, 1, { 1234 } | 216 1, |
217 } | 217 7, |
218 }; | 218 { |
219 B(LdaConstant), U8(0), // | |
220 B(Star), R(0), // | |
221 B(LdaConstant), U8(0), // | |
222 B(Return) // | |
223 }, | |
224 1, | |
225 {1234}}}; | |
rmcilroy
2015/09/24 11:44:36
was this reformat intended?
| |
219 | 226 |
220 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 227 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
221 for (size_t i = 0; i < num_snippets; i++) { | 228 for (size_t i = 0; i < num_snippets; i++) { |
222 Handle<BytecodeArray> ba = | 229 Handle<BytecodeArray> ba = |
223 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | 230 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); |
224 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 231 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
225 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | 232 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
226 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 233 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
227 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 234 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
228 ba->length())); | 235 ba->length())); |
229 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | 236 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
230 for (int j = 0; j < snippets[i].constant_count; j++) { | 237 for (int j = 0; j < snippets[i].constant_count; j++) { |
231 CHECK_EQ(Smi::cast(ba->constant_pool()->get(j))->value(), | 238 CHECK_EQ(Smi::cast(ba->constant_pool()->get(j))->value(), |
232 snippets[i].constants[j]); | 239 snippets[i].constants[j]); |
233 } | |
234 } | |
235 } | |
236 | |
237 // Check heap number double constants | |
238 { | |
239 ExpectedSnippet<double> snippets[] = { | |
240 {"return 1.2;", | |
241 0, 1, 3, | |
242 { | |
243 B(LdaConstant), U8(0), | |
244 B(Return) | |
245 }, 1, { 1.2 } | |
246 }, | |
247 {"var a = 1.2; return 2.6;", 1 * kPointerSize, 1, 7, | |
248 { | |
249 B(LdaConstant), U8(0), | |
250 B(Star), R(0), | |
251 B(LdaConstant), U8(1), | |
252 B(Return) | |
253 }, 2, { 1.2, 2.6 } | |
254 }, | |
255 {"var a = 3.14; return 3.14;", 1 * kPointerSize, 1, 7, | |
256 { | |
257 B(LdaConstant), U8(0), | |
258 B(Star), R(0), | |
259 B(LdaConstant), U8(1), | |
260 B(Return) | |
261 }, 2, | |
262 // TODO(rmcilroy): Currently multiple identical double literals end up | |
263 // being allocated as new HeapNumbers and so require multiple constant | |
264 // pool entries. De-dup identical values. | |
265 { 3.14, 3.14 } | |
266 } | |
267 }; | |
268 | |
269 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
270 for (size_t i = 0; i < num_snippets; i++) { | |
271 Handle<BytecodeArray> ba = | |
272 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | |
273 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | |
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 } | |
284 } | |
285 | |
286 // Check string literals | |
287 { | |
288 ExpectedSnippet<const char*> snippets[] = { | |
289 {"return \"This is a string\";", 0, 1, 3, | |
290 { | |
291 B(LdaConstant), U8(0), | |
292 B(Return) | |
293 }, 1, | |
294 { "This is a string" } | |
295 }, | |
296 {"var a = \"First string\"; return \"Second string\";", | |
297 1 * kPointerSize, 1, 7, | |
298 { | |
299 B(LdaConstant), U8(0), | |
300 B(Star), R(0), | |
301 B(LdaConstant), U8(1), | |
302 B(Return) | |
303 }, 2, { "First string", "Second string"} | |
304 }, | |
305 {"var a = \"Same string\"; return \"Same string\";", | |
306 1 * kPointerSize, 1, 7, | |
307 { | |
308 B(LdaConstant), U8(0), | |
309 B(Star), R(0), | |
310 B(LdaConstant), U8(0), | |
311 B(Return) | |
312 }, 1, { "Same string" } | |
313 } | |
314 }; | |
315 | |
316 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
317 for (size_t i = 0; i < num_snippets; i++) { | |
318 Handle<BytecodeArray> ba = | |
319 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | |
320 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | |
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 } | 240 } |
332 } | 241 } |
333 } | 242 } |
243 | |
244 | |
245 TEST(HeapNumberConstants) { | |
246 InitializedHandleScope handle_scope; | |
247 BytecodeGeneratorHelper helper; | |
248 | |
249 ExpectedSnippet<double> snippets[] = { | |
250 {"return 1.2;", | |
251 0, | |
252 1, | |
253 3, | |
254 { | |
255 B(LdaConstant), U8(0), // | |
256 B(Return) // | |
257 }, | |
258 1, | |
259 {1.2}}, | |
260 {"var a = 1.2; return 2.6;", | |
261 1 * kPointerSize, | |
262 1, | |
263 7, | |
264 { | |
265 B(LdaConstant), U8(0), // | |
266 B(Star), R(0), // | |
267 B(LdaConstant), U8(1), // | |
268 B(Return) // | |
269 }, | |
270 2, | |
271 {1.2, 2.6}}, | |
272 {"var a = 3.14; return 3.14;", | |
273 1 * kPointerSize, | |
274 1, | |
275 7, | |
276 { | |
277 B(LdaConstant), U8(0), // | |
278 B(Star), R(0), // | |
279 B(LdaConstant), U8(1), // | |
280 B(Return) // | |
281 }, | |
282 2, | |
283 // TODO(rmcilroy): Currently multiple identical double literals end up | |
284 // being allocated as new HeapNumbers and so require multiple constant | |
285 // pool entries. De-dup identical values. | |
286 {3.14, 3.14}}}; | |
287 | |
288 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
289 for (size_t i = 0; i < num_snippets; i++) { | |
290 Handle<BytecodeArray> ba = | |
291 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | |
292 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | |
293 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
294 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
295 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
296 ba->length())); | |
297 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
298 for (int j = 0; j < snippets[i].constant_count; j++) { | |
299 CHECK_EQ(HeapNumber::cast(ba->constant_pool()->get(j))->value(), | |
300 snippets[i].constants[j]); | |
301 } | |
302 } | |
303 } | |
304 | |
305 | |
306 TEST(StringConstants) { | |
307 InitializedHandleScope handle_scope; | |
308 BytecodeGeneratorHelper helper; | |
309 | |
310 ExpectedSnippet<const char*> snippets[] = { | |
311 {"return \"This is a string\";", | |
312 0, | |
313 1, | |
314 3, | |
315 { | |
316 B(LdaConstant), U8(0), // | |
317 B(Return) // | |
318 }, | |
319 1, | |
320 {"This is a string"}}, | |
321 {"var a = \"First string\"; return \"Second string\";", | |
322 1 * kPointerSize, | |
323 1, | |
324 7, | |
325 { | |
326 B(LdaConstant), U8(0), // | |
327 B(Star), R(0), // | |
328 B(LdaConstant), U8(1), // | |
329 B(Return) // | |
330 }, | |
331 2, | |
332 {"First string", "Second string"}}, | |
333 {"var a = \"Same string\"; return \"Same string\";", | |
334 1 * kPointerSize, | |
335 1, | |
336 7, | |
337 { | |
338 B(LdaConstant), U8(0), // | |
339 B(Star), R(0), // | |
340 B(LdaConstant), U8(0), // | |
341 B(Return) // | |
342 }, | |
343 1, | |
344 {"Same string"}}}; | |
345 | |
346 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
347 for (size_t i = 0; i < num_snippets; i++) { | |
348 Handle<BytecodeArray> ba = | |
349 helper.MakeBytecodeForFunctionBody(snippets[i].code_snippet); | |
350 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | |
351 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
352 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
353 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
354 ba->length())); | |
355 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
356 for (int j = 0; j < snippets[i].constant_count; j++) { | |
357 Handle<String> expected = | |
358 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | |
359 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | |
360 } | |
361 } | |
362 } | |
334 | 363 |
335 | 364 |
336 TEST(PropertyLoads) { | 365 TEST(PropertyLoads) { |
337 InitializedHandleScope handle_scope; | 366 InitializedHandleScope handle_scope; |
338 BytecodeGeneratorHelper helper; | 367 BytecodeGeneratorHelper helper; |
339 | 368 |
340 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; | 369 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; |
341 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); | 370 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); |
342 Handle<i::TypeFeedbackVector> vector = | 371 Handle<i::TypeFeedbackVector> vector = |
343 helper.factory()->NewTypeFeedbackVector(&feedback_spec); | 372 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
344 | 373 |
345 ExpectedSnippet<const char*> snippets[] = { | 374 ExpectedSnippet<const char*> snippets[] = { |
346 {"function f(a) { return a.name; }\nf({name : \"test\"})", | 375 {"function f(a) { return a.name; }\nf({name : \"test\"})", |
347 1 * kPointerSize, 2, 10, | 376 1 * kPointerSize, |
377 2, | |
378 10, | |
348 { | 379 { |
349 B(Ldar), R(helper.kLastParamIndex), | 380 B(Ldar), R(helper.kLastParamIndex), // |
350 B(Star), R(0), | 381 B(Star), R(0), // |
351 B(LdaConstant), U8(0), | 382 B(LdaConstant), U8(0), // |
352 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), | 383 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), // |
353 B(Return) | 384 B(Return) // |
354 }, | 385 }, |
355 1, { "name" } | 386 1, |
356 }, | 387 {"name"}}, |
357 {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})", | 388 {"function f(a) { return a[\"key\"]; }\nf({key : \"test\"})", |
358 1 * kPointerSize, 2, 10, | 389 1 * kPointerSize, |
390 2, | |
391 10, | |
359 { | 392 { |
360 B(Ldar), R(helper.kLastParamIndex), | 393 B(Ldar), R(helper.kLastParamIndex), // |
361 B(Star), R(0), | 394 B(Star), R(0), // |
362 B(LdaConstant), U8(0), | 395 B(LdaConstant), U8(0), // |
363 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), | 396 B(LoadIC), R(0), U8(vector->first_ic_slot_index()), // |
364 B(Return) | 397 B(Return) // |
365 }, | 398 }, |
366 1, { "key" } | 399 1, |
367 }, | 400 {"key"}}, |
368 {"function f(a) { return a[100]; }\nf({100 : \"test\"})", | 401 {"function f(a) { return a[100]; }\nf({100 : \"test\"})", |
369 1 * kPointerSize, 2, 10, | 402 1 * kPointerSize, |
403 2, | |
404 10, | |
370 { | 405 { |
371 B(Ldar), R(helper.kLastParamIndex), | 406 B(Ldar), R(helper.kLastParamIndex), // |
372 B(Star), R(0), | 407 B(Star), R(0), // |
373 B(LdaSmi8), U8(100), | 408 B(LdaSmi8), U8(100), // |
374 B(KeyedLoadIC), R(0), U8(vector->first_ic_slot_index()), | 409 B(KeyedLoadIC), R(0), U8(vector->first_ic_slot_index()), // |
375 B(Return) | 410 B(Return) // |
376 }, 0 | 411 }, |
377 }, | 412 0}, |
378 {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")", | 413 {"function f(a, b) { return a[b]; }\nf({arg : \"test\"}, \"arg\")", |
379 1 * kPointerSize, 3, 10, | 414 1 * kPointerSize, |
415 3, | |
416 10, | |
380 { | 417 { |
381 B(Ldar), R(helper.kLastParamIndex - 1), | 418 B(Ldar), R(helper.kLastParamIndex - 1), // |
382 B(Star), R(0), | 419 B(Star), R(0), // |
383 B(Ldar), R(helper.kLastParamIndex), | 420 B(Ldar), R(helper.kLastParamIndex), // |
384 B(KeyedLoadIC), R(0), U8(vector->first_ic_slot_index()), | 421 B(KeyedLoadIC), R(0), U8(vector->first_ic_slot_index()), // |
385 B(Return) | 422 B(Return) // |
386 }, 0 | 423 }, |
387 }, | 424 0}, |
388 {"function f(a) { var b = a.name; return a[-124]; }\n" | 425 {"function f(a) { var b = a.name; return a[-124]; }\n" |
389 "f({\"-124\" : \"test\", name : 123 })", | 426 "f({\"-124\" : \"test\", name : 123 })", |
390 2 * kPointerSize, 2, 21, | 427 2 * kPointerSize, |
428 2, | |
429 21, | |
391 { | 430 { |
392 B(Ldar), R(helper.kLastParamIndex), | 431 B(Ldar), R(helper.kLastParamIndex), // |
393 B(Star), R(1), | 432 B(Star), R(1), // |
394 B(LdaConstant), U8(0), | 433 B(LdaConstant), U8(0), // |
395 B(LoadIC), R(1), U8(vector->first_ic_slot_index()), | 434 B(LoadIC), R(1), U8(vector->first_ic_slot_index()), // |
396 B(Star), R(0), | 435 B(Star), R(0), // |
397 B(Ldar), R(helper.kLastParamIndex), | 436 B(Ldar), R(helper.kLastParamIndex), // |
398 B(Star), R(1), | 437 B(Star), R(1), // |
399 B(LdaSmi8), U8(-124), | 438 B(LdaSmi8), U8(-124), // |
400 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 439 B(KeyedLoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // |
401 B(Return) | 440 B(Return) // |
402 }, | 441 }, |
403 1, { "name" } | 442 1, |
404 } | 443 {"name"}}}; |
405 }; | |
406 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 444 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
407 for (size_t i = 0; i < num_snippets; i++) { | 445 for (size_t i = 0; i < num_snippets; i++) { |
408 Handle<BytecodeArray> ba = | 446 Handle<BytecodeArray> ba = |
409 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 447 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
410 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 448 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
411 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | 449 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
412 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 450 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
413 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 451 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
414 ba->length())); | 452 ba->length())); |
415 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | 453 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
(...skipping 10 matching lines...) Expand all Loading... | |
426 InitializedHandleScope handle_scope; | 464 InitializedHandleScope handle_scope; |
427 BytecodeGeneratorHelper helper; | 465 BytecodeGeneratorHelper helper; |
428 | 466 |
429 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; | 467 Code::Kind ic_kinds[] = { i::Code::STORE_IC, i::Code::STORE_IC }; |
430 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); | 468 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); |
431 Handle<i::TypeFeedbackVector> vector = | 469 Handle<i::TypeFeedbackVector> vector = |
432 helper.factory()->NewTypeFeedbackVector(&feedback_spec); | 470 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
433 | 471 |
434 ExpectedSnippet<const char*> snippets[] = { | 472 ExpectedSnippet<const char*> snippets[] = { |
435 {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})", | 473 {"function f(a) { a.name = \"val\"; }\nf({name : \"test\"})", |
436 2 * kPointerSize, 2, 16, | 474 2 * kPointerSize, |
475 2, | |
476 16, | |
437 { | 477 { |
438 B(Ldar), R(helper.kLastParamIndex), | 478 B(Ldar), R(helper.kLastParamIndex), // |
439 B(Star), R(0), | 479 B(Star), R(0), // |
440 B(LdaConstant), U8(0), | 480 B(LdaConstant), U8(0), // |
441 B(Star), R(1), | 481 B(Star), R(1), // |
442 B(LdaConstant), U8(1), | 482 B(LdaConstant), U8(1), // |
443 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), | 483 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), // |
444 B(LdaUndefined), | 484 B(LdaUndefined), // |
445 B(Return) | 485 B(Return) // |
446 }, | 486 }, |
447 2, { "name", "val" } | 487 2, |
448 }, | 488 {"name", "val"}}, |
449 {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})", | 489 {"function f(a) { a[\"key\"] = \"val\"; }\nf({key : \"test\"})", |
450 2 * kPointerSize, 2, 16, | 490 2 * kPointerSize, |
491 2, | |
492 16, | |
451 { | 493 { |
452 B(Ldar), R(helper.kLastParamIndex), | 494 B(Ldar), R(helper.kLastParamIndex), // |
453 B(Star), R(0), | 495 B(Star), R(0), // |
454 B(LdaConstant), U8(0), | 496 B(LdaConstant), U8(0), // |
455 B(Star), R(1), | 497 B(Star), R(1), // |
456 B(LdaConstant), U8(1), | 498 B(LdaConstant), U8(1), // |
457 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), | 499 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), // |
458 B(LdaUndefined), | 500 B(LdaUndefined), // |
459 B(Return) | 501 B(Return) // |
460 }, | 502 }, |
461 2, { "key", "val" } | 503 2, |
462 }, | 504 {"key", "val"}}, |
463 {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})", | 505 {"function f(a) { a[100] = \"val\"; }\nf({100 : \"test\"})", |
464 2 * kPointerSize, 2, 16, | 506 2 * kPointerSize, |
507 2, | |
508 16, | |
465 { | 509 { |
466 B(Ldar), R(helper.kLastParamIndex), | 510 B(Ldar), R(helper.kLastParamIndex), // |
467 B(Star), R(0), | 511 B(Star), R(0), // |
468 B(LdaSmi8), U8(100), | 512 B(LdaSmi8), U8(100), // |
469 B(Star), R(1), | 513 B(Star), R(1), // |
470 B(LdaConstant), U8(0), | 514 B(LdaConstant), U8(0), // |
471 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), | 515 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), // |
472 B(LdaUndefined), | 516 B(LdaUndefined), // |
473 B(Return) | 517 B(Return) // |
474 }, | 518 }, |
475 1, { "val" } | 519 1, |
476 }, | 520 {"val"}}, |
477 {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")", | 521 {"function f(a, b) { a[b] = \"val\"; }\nf({arg : \"test\"}, \"arg\")", |
478 2 * kPointerSize, 3, 16, | 522 2 * kPointerSize, |
523 3, | |
524 16, | |
479 { | 525 { |
480 B(Ldar), R(helper.kLastParamIndex - 1), | 526 B(Ldar), R(helper.kLastParamIndex - 1), // |
481 B(Star), R(0), | 527 B(Star), R(0), // |
482 B(Ldar), R(helper.kLastParamIndex), | 528 B(Ldar), R(helper.kLastParamIndex), // |
483 B(Star), R(1), | 529 B(Star), R(1), // |
484 B(LdaConstant), U8(0), | 530 B(LdaConstant), U8(0), // |
485 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), | 531 B(KeyedStoreIC), R(0), R(1), U8(vector->first_ic_slot_index()), // |
486 B(LdaUndefined), | 532 B(LdaUndefined), // |
487 B(Return) | 533 B(Return) // |
488 }, | 534 }, |
489 1, { "val" } | 535 1, |
490 }, | 536 {"val"}}, |
491 {"function f(a) { a.name = a[-124]; }\n" | 537 {"function f(a) { a.name = a[-124]; }\n" |
492 "f({\"-124\" : \"test\", name : 123 })", | 538 "f({\"-124\" : \"test\", name : 123 })", |
493 3 * kPointerSize, 2, 23, | 539 3 * kPointerSize, |
540 2, | |
541 23, | |
494 { | 542 { |
495 B(Ldar), R(helper.kLastParamIndex), | 543 B(Ldar), R(helper.kLastParamIndex), // |
496 B(Star), R(0), | 544 B(Star), R(0), // |
497 B(LdaConstant), U8(0), | 545 B(LdaConstant), U8(0), // |
498 B(Star), R(1), | 546 B(Star), R(1), // |
499 B(Ldar), R(helper.kLastParamIndex), | 547 B(Ldar), R(helper.kLastParamIndex), // |
500 B(Star), R(2), | 548 B(Star), R(2), // |
501 B(LdaSmi8), U8(-124), | 549 B(LdaSmi8), U8(-124), // |
502 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), | 550 B(KeyedLoadIC), R(2), U8(vector->first_ic_slot_index()), // |
503 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), | 551 B(StoreIC), R(0), R(1), U8(vector->first_ic_slot_index() + 2), // |
504 B(LdaUndefined), | 552 B(LdaUndefined), // |
505 B(Return) | 553 B(Return) // |
506 }, | 554 }, |
507 1, { "name" } | 555 1, |
508 } | 556 {"name"}}}; |
509 }; | |
510 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 557 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
511 for (size_t i = 0; i < num_snippets; i++) { | 558 for (size_t i = 0; i < num_snippets; i++) { |
512 Handle<BytecodeArray> ba = | 559 Handle<BytecodeArray> ba = |
513 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 560 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
514 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 561 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
515 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | 562 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
516 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 563 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
517 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 564 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
518 ba->length())); | 565 ba->length())); |
519 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | 566 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
520 for (int j = 0; j < snippets[i].constant_count; j++) { | 567 for (int j = 0; j < snippets[i].constant_count; j++) { |
521 Handle<String> expected = | 568 Handle<String> expected = |
522 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | 569 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); |
523 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | 570 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); |
524 } | 571 } |
525 } | 572 } |
526 } | 573 } |
527 | 574 |
528 | 575 |
529 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" | 576 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()" |
530 | 577 |
531 | 578 |
532 TEST(PropertyCall) { | 579 TEST(PropertyCall) { |
533 InitializedHandleScope handle_scope; | 580 InitializedHandleScope handle_scope; |
534 BytecodeGeneratorHelper helper; | 581 BytecodeGeneratorHelper helper; // |
535 | 582 |
536 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; | 583 Code::Kind ic_kinds[] = { i::Code::LOAD_IC, i::Code::LOAD_IC }; |
537 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); | 584 FeedbackVectorSpec feedback_spec(0, 2, ic_kinds); |
538 Handle<i::TypeFeedbackVector> vector = | 585 Handle<i::TypeFeedbackVector> vector = |
539 helper.factory()->NewTypeFeedbackVector(&feedback_spec); | 586 helper.factory()->NewTypeFeedbackVector(&feedback_spec); |
540 | 587 |
541 ExpectedSnippet<const char*> snippets[] = { | 588 ExpectedSnippet<const char*> snippets[] = { |
542 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", | 589 {"function f(a) { return a.func(); }\nf(" FUNC_ARG ")", |
543 2 * kPointerSize, 2, 16, | 590 2 * kPointerSize, |
591 2, | |
592 16, | |
544 { | 593 { |
545 B(Ldar), R(helper.kLastParamIndex), | 594 B(Ldar), R(helper.kLastParamIndex), // |
546 B(Star), R(1), | 595 B(Star), R(1), // |
547 B(LdaConstant), U8(0), | 596 B(LdaConstant), U8(0), // |
548 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 597 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // |
549 B(Star), R(0), | 598 B(Star), R(0), // |
550 B(Call), R(0), R(1), U8(0), | 599 B(Call), R(0), R(1), U8(0), // |
551 B(Return) | 600 B(Return) // |
552 }, | 601 }, |
553 1, { "func" } | 602 1, |
554 }, | 603 {"func"}}, |
555 {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)", | 604 {"function f(a, b, c) { return a.func(b, c); }\nf(" FUNC_ARG ", 1, 2)", |
556 4 * kPointerSize, 4, 24, | 605 4 * kPointerSize, |
606 4, | |
607 24, | |
557 { | 608 { |
558 B(Ldar), R(helper.kLastParamIndex - 2), | 609 B(Ldar), R(helper.kLastParamIndex - 2), // |
559 B(Star), R(1), | 610 B(Star), R(1), // |
560 B(LdaConstant), U8(0), | 611 B(LdaConstant), U8(0), // |
561 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 612 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // |
562 B(Star), R(0), | 613 B(Star), R(0), // |
563 B(Ldar), R(helper.kLastParamIndex - 1), | 614 B(Ldar), R(helper.kLastParamIndex - 1), // |
564 B(Star), R(2), | 615 B(Star), R(2), // |
565 B(Ldar), R(helper.kLastParamIndex), | 616 B(Ldar), R(helper.kLastParamIndex), // |
566 B(Star), R(3), | 617 B(Star), R(3), // |
567 B(Call), R(0), R(1), U8(2), | 618 B(Call), R(0), R(1), U8(2), // |
568 B(Return) | 619 B(Return) // |
569 }, | 620 }, |
570 1, { "func" } | 621 1, |
571 }, | 622 {"func"}}, |
572 {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)", | 623 {"function f(a, b) { return a.func(b + b, b); }\nf(" FUNC_ARG ", 1)", |
573 4 * kPointerSize, 3, 30, | 624 4 * kPointerSize, |
574 { | 625 3, |
575 B(Ldar), R(helper.kLastParamIndex - 1), | 626 30, |
576 B(Star), R(1), | 627 { |
577 B(LdaConstant), U8(0), | 628 B(Ldar), R(helper.kLastParamIndex - 1), // |
578 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), | 629 B(Star), R(1), // |
579 B(Star), R(0), | 630 B(LdaConstant), U8(0), // |
580 B(Ldar), R(helper.kLastParamIndex), | 631 B(LoadIC), R(1), U8(vector->first_ic_slot_index() + 2), // |
581 B(Star), R(2), | 632 B(Star), R(0), // |
582 B(Ldar), R(helper.kLastParamIndex), | 633 B(Ldar), R(helper.kLastParamIndex), // |
583 B(Add), R(2), | 634 B(Star), R(2), // |
584 B(Star), R(2), | 635 B(Ldar), R(helper.kLastParamIndex), // |
585 B(Ldar), R(helper.kLastParamIndex), | 636 B(Add), R(2), // |
586 B(Star), R(3), | 637 B(Star), R(2), // |
587 B(Call), R(0), R(1), U8(2), | 638 B(Ldar), R(helper.kLastParamIndex), // |
588 B(Return) | 639 B(Star), R(3), // |
640 B(Call), R(0), R(1), U8(2), // | |
641 B(Return) // | |
rmcilroy
2015/09/24 11:44:36
Thanks for fixing all these other tests!
| |
589 }, | 642 }, |
590 1, { "func" } | 643 1, |
591 } | 644 {"func"}}}; |
592 }; | |
593 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | 645 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); |
594 for (size_t i = 0; i < num_snippets; i++) { | 646 for (size_t i = 0; i < num_snippets; i++) { |
595 Handle<BytecodeArray> ba = | 647 Handle<BytecodeArray> ba = |
596 helper.MakeBytecode(snippets[i].code_snippet, "f"); | 648 helper.MakeBytecode(snippets[i].code_snippet, "f"); |
597 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | 649 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); |
598 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | 650 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); |
599 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | 651 CHECK_EQ(ba->length(), snippets[i].bytecode_length); |
600 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | 652 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, |
601 ba->length())); | 653 ba->length())); |
602 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | 654 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); |
603 for (int j = 0; j < snippets[i].constant_count; j++) { | 655 for (int j = 0; j < snippets[i].constant_count; j++) { |
604 Handle<String> expected = | 656 Handle<String> expected = |
605 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); | 657 helper.factory()->NewStringFromAsciiChecked(snippets[i].constants[j]); |
606 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); | 658 CHECK(String::cast(ba->constant_pool()->get(j))->Equals(*expected)); |
607 } | 659 } |
608 } | 660 } |
609 } | 661 } |
610 | 662 |
663 | |
664 TEST(IfConditions) { | |
665 InitializedHandleScope handle_scope; | |
666 BytecodeGeneratorHelper helper; | |
667 | |
668 ExpectedSnippet<void*> snippets[] = { | |
669 {"function f() { if (0) { return 1; } else { return -1; } }", | |
670 0, | |
671 1, | |
672 14, | |
673 {B(LdaZero), // | |
674 B(ToBoolean), // | |
675 B(JumpIfFalse), U8(7), // | |
676 B(LdaSmi8), U8(1), // | |
677 B(Return), // | |
678 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | |
679 B(LdaSmi8), U8(-1), // | |
680 B(Return), // | |
681 B(LdaUndefined), // | |
682 B(Return)}, // | |
683 0}, | |
684 {"function f() { if ('lucky') { return 1; } else { return -1; } }", | |
685 0, | |
686 1, | |
687 15, | |
688 {B(LdaConstant), U8(0), // | |
689 B(ToBoolean), // | |
690 B(JumpIfFalse), U8(7), // | |
691 B(LdaSmi8), U8(1), // | |
692 B(Return), // | |
693 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | |
694 B(LdaSmi8), U8(-1), // | |
695 B(Return), // | |
696 B(LdaUndefined), // | |
697 B(Return)}, // | |
698 1}, | |
699 {"function f() { if (false) { return 1; } else { return -1; } }", | |
700 0, | |
701 1, | |
702 13, | |
703 {B(LdaFalse), // | |
704 B(JumpIfFalse), U8(7), // | |
705 B(LdaSmi8), U8(1), // | |
706 B(Return), // | |
707 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | |
708 B(LdaSmi8), U8(-1), // | |
709 B(Return), // | |
710 B(LdaUndefined), // | |
711 B(Return)}, // | |
712 0}, | |
713 {"function f(a) { if (a <= 0) { return 200; } else { return -200; } }", | |
714 kPointerSize, | |
715 2, | |
716 19, | |
717 {B(Ldar), R(-5), // | |
718 B(Star), R(0), // | |
719 B(LdaZero), // | |
720 B(TestLessThanEqual), R(0), // | |
721 B(JumpIfFalse), U8(7), // | |
722 B(LdaConstant), U8(0), // | |
723 B(Return), // | |
724 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | |
725 B(LdaConstant), U8(1), // | |
726 B(Return), // | |
727 B(LdaUndefined), // | |
728 B(Return)}, // | |
729 2}, | |
730 {"function f(a, b) { if (a in b) { return 200; } }", | |
731 kPointerSize, | |
732 3, | |
733 17, | |
734 {B(Ldar), R(-6), // | |
735 B(Star), R(0), // | |
736 B(Ldar), R(-5), // | |
737 B(TestIn), R(0), // | |
738 B(JumpIfFalse), U8(7), // | |
739 B(LdaConstant), U8(0), // | |
740 B(Return), // | |
741 B(Jump), U8(2), // TODO(oth): Unreachable jump after return | |
742 B(LdaUndefined), // | |
743 B(Return)}, // | |
744 1}, | |
745 {"function f(a, b) { if (a instanceof b) { return 200; } }", | |
746 kPointerSize, | |
747 3, | |
748 17, | |
749 {B(Ldar), R(-6), // | |
750 B(Star), R(0), // | |
751 B(Ldar), R(-5), // | |
752 B(TestInstanceOf), R(0), // | |
753 B(JumpIfFalse), U8(7), // | |
754 B(LdaConstant), U8(0), // | |
755 B(Return), // | |
756 B(Jump), U8(2), // TODO(oth): Unreachable jump after return | |
757 B(LdaUndefined), // | |
758 B(Return)}, // | |
759 1}, | |
760 {"function f(z) { var a = 0; var b = 0; if (a === 0.01) { " | |
761 #define X "b = a; a = b; " | |
762 X X X X X X X X X X X X X X X X X X X X X X X X | |
763 #undef X | |
764 " return 200; } else { return -200; } }", | |
765 3 * kPointerSize, | |
766 2, | |
767 218, | |
768 {B(LdaZero), // | |
769 B(Star), R(0), // | |
770 B(LdaZero), // | |
771 B(Star), R(1), // | |
772 B(Ldar), R(0), // | |
773 B(Star), R(2), // | |
774 B(LdaConstant), U8(0), // | |
775 B(TestEqualStrict), R(2), // | |
776 B(JumpIfFalseConstant), U8(2), // | |
777 #define X B(Ldar), R(0), B(Star), R(1), B(Ldar), R(1), B(Star), R(0), | |
778 X X X X X X X X X X X X X X X X X X X X X X X X | |
779 #undef X | |
780 B(LdaConstant), | |
781 U8(1), // | |
782 B(Return), // | |
783 B(Jump), U8(5), // TODO(oth): Unreachable jump after return | |
784 B(LdaConstant), U8(3), // | |
785 B(Return), // | |
786 B(LdaUndefined), // | |
787 B(Return)}, // | |
788 4}, // | |
789 }; | |
790 | |
791 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
792 for (size_t i = 0; i < num_snippets; i++) { | |
793 Handle<BytecodeArray> ba = | |
794 helper.MakeBytecodeForFunction(snippets[i].code_snippet); | |
795 CHECK_EQ(ba->frame_size(), snippets[i].frame_size); | |
796 CHECK_EQ(ba->parameter_count(), snippets[i].parameter_count); | |
797 CHECK_EQ(ba->length(), snippets[i].bytecode_length); | |
798 CHECK(!memcmp(ba->GetFirstBytecodeAddress(), snippets[i].bytecode, | |
799 ba->length())); | |
800 CHECK_EQ(ba->constant_pool()->length(), snippets[i].constant_count); | |
801 } | |
802 } | |
803 | |
804 | |
611 } // namespace interpreter | 805 } // namespace interpreter |
612 } // namespace internal | 806 } // namespace internal |
613 } // namespance v8 | 807 } // namespance v8 |
OLD | NEW |