OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "test/unittests/test-utils.h" | 10 #include "test/unittests/test-utils.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 BytecodeArrayBuilderTest : public TestWithIsolateAndZone { | 16 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { |
17 public: | 17 public: |
18 BytecodeArrayBuilderTest() {} | 18 BytecodeArrayBuilderTest() {} |
19 ~BytecodeArrayBuilderTest() override {} | 19 ~BytecodeArrayBuilderTest() override {} |
20 }; | 20 }; |
21 | 21 |
22 | 22 |
23 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { | 23 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { |
24 BytecodeArrayBuilder builder(isolate(), zone()); | 24 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); |
25 | 25 |
26 builder.set_locals_count(131); | |
27 builder.set_context_count(1); | |
28 builder.set_parameter_count(0); | |
29 CHECK_EQ(builder.locals_count(), 131); | 26 CHECK_EQ(builder.locals_count(), 131); |
30 CHECK_EQ(builder.context_count(), 1); | 27 CHECK_EQ(builder.context_count(), 1); |
31 CHECK_EQ(builder.fixed_register_count(), 132); | 28 CHECK_EQ(builder.fixed_register_count(), 132); |
32 | 29 |
33 // Emit constant loads. | 30 // Emit constant loads. |
34 builder.LoadLiteral(Smi::FromInt(0)) | 31 builder.LoadLiteral(Smi::FromInt(0)) |
35 .LoadLiteral(Smi::FromInt(8)) | 32 .LoadLiteral(Smi::FromInt(8)) |
36 .LoadLiteral(Smi::FromInt(10000000)) | 33 .LoadLiteral(Smi::FromInt(10000000)) |
37 .LoadUndefined() | 34 .LoadUndefined() |
38 .LoadNull() | 35 .LoadNull() |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); | 302 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); |
306 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) | 303 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) |
307 #undef CHECK_BYTECODE_PRESENT | 304 #undef CHECK_BYTECODE_PRESENT |
308 } | 305 } |
309 | 306 |
310 | 307 |
311 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { | 308 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { |
312 for (int locals = 0; locals < 5; locals++) { | 309 for (int locals = 0; locals < 5; locals++) { |
313 for (int contexts = 0; contexts < 4; contexts++) { | 310 for (int contexts = 0; contexts < 4; contexts++) { |
314 for (int temps = 0; temps < 3; temps++) { | 311 for (int temps = 0; temps < 3; temps++) { |
315 BytecodeArrayBuilder builder(isolate(), zone()); | 312 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); |
316 builder.set_parameter_count(0); | 313 BytecodeRegisterAllocator temporaries( |
317 builder.set_locals_count(locals); | 314 zone(), builder.temporary_register_allocator()); |
318 builder.set_context_count(contexts); | |
319 | |
320 BytecodeRegisterAllocator temporaries(&builder); | |
321 for (int i = 0; i < temps; i++) { | 315 for (int i = 0; i < temps; i++) { |
322 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); | 316 builder.StoreAccumulatorInRegister(temporaries.NewRegister()); |
323 } | 317 } |
324 builder.Return(); | 318 builder.Return(); |
325 | 319 |
326 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 320 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
327 int total_registers = locals + contexts + temps; | 321 int total_registers = locals + contexts + temps; |
328 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); | 322 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); |
329 } | 323 } |
330 } | 324 } |
(...skipping 10 matching lines...) Expand all Loading... |
341 | 335 |
342 int actual_operand = the_register.ToOperand(); | 336 int actual_operand = the_register.ToOperand(); |
343 CHECK_EQ(actual_operand, operand); | 337 CHECK_EQ(actual_operand, operand); |
344 | 338 |
345 int actual_index = Register::FromOperand(actual_operand).index(); | 339 int actual_index = Register::FromOperand(actual_operand).index(); |
346 CHECK_EQ(actual_index, index); | 340 CHECK_EQ(actual_index, index); |
347 } | 341 } |
348 | 342 |
349 | 343 |
350 TEST_F(BytecodeArrayBuilderTest, Parameters) { | 344 TEST_F(BytecodeArrayBuilderTest, Parameters) { |
351 BytecodeArrayBuilder builder(isolate(), zone()); | 345 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); |
352 builder.set_parameter_count(10); | |
353 builder.set_locals_count(0); | |
354 builder.set_context_count(0); | |
355 | |
356 Register param0(builder.Parameter(0)); | 346 Register param0(builder.Parameter(0)); |
357 Register param9(builder.Parameter(9)); | 347 Register param9(builder.Parameter(9)); |
358 CHECK_EQ(param9.index() - param0.index(), 9); | 348 CHECK_EQ(param9.index() - param0.index(), 9); |
359 } | 349 } |
360 | 350 |
361 | 351 |
362 TEST_F(BytecodeArrayBuilderTest, RegisterType) { | 352 TEST_F(BytecodeArrayBuilderTest, RegisterType) { |
363 BytecodeArrayBuilder builder(isolate(), zone()); | 353 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); |
364 builder.set_parameter_count(10); | 354 BytecodeRegisterAllocator register_allocator( |
365 builder.set_locals_count(3); | 355 zone(), builder.temporary_register_allocator()); |
366 builder.set_context_count(0); | |
367 | |
368 BytecodeRegisterAllocator register_allocator(&builder); | |
369 Register temp0 = register_allocator.NewRegister(); | 356 Register temp0 = register_allocator.NewRegister(); |
370 Register param0(builder.Parameter(0)); | 357 Register param0(builder.Parameter(0)); |
371 Register param9(builder.Parameter(9)); | 358 Register param9(builder.Parameter(9)); |
372 Register temp1 = register_allocator.NewRegister(); | 359 Register temp1 = register_allocator.NewRegister(); |
373 Register reg0(0); | 360 Register reg0(0); |
374 Register reg1(1); | 361 Register reg1(1); |
375 Register reg2(2); | 362 Register reg2(2); |
376 Register temp2 = register_allocator.NewRegister(); | 363 Register temp2 = register_allocator.NewRegister(); |
377 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false); | 364 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false); |
378 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false); | 365 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false); |
379 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false); | 366 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false); |
380 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); | 367 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); |
381 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); | 368 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); |
382 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); | 369 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); |
383 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); | 370 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); |
384 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); | 371 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); |
385 } | 372 } |
386 | 373 |
387 | 374 |
388 TEST_F(BytecodeArrayBuilderTest, Constants) { | 375 TEST_F(BytecodeArrayBuilderTest, Constants) { |
389 BytecodeArrayBuilder builder(isolate(), zone()); | 376 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
390 builder.set_parameter_count(0); | |
391 builder.set_locals_count(0); | |
392 builder.set_context_count(0); | |
393 | |
394 Factory* factory = isolate()->factory(); | 377 Factory* factory = isolate()->factory(); |
395 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); | 378 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); |
396 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); | 379 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); |
397 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); | 380 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); |
398 Handle<HeapObject> heap_num_2_copy(*heap_num_2); | 381 Handle<HeapObject> heap_num_2_copy(*heap_num_2); |
399 builder.LoadLiteral(heap_num_1) | 382 builder.LoadLiteral(heap_num_1) |
400 .LoadLiteral(heap_num_2) | 383 .LoadLiteral(heap_num_2) |
401 .LoadLiteral(large_smi) | 384 .LoadLiteral(large_smi) |
402 .LoadLiteral(heap_num_1) | 385 .LoadLiteral(heap_num_1) |
403 .LoadLiteral(heap_num_1) | 386 .LoadLiteral(heap_num_1) |
404 .LoadLiteral(heap_num_2_copy); | 387 .LoadLiteral(heap_num_2_copy); |
405 | 388 |
406 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 389 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
407 // Should only have one entry for each identical constant. | 390 // Should only have one entry for each identical constant. |
408 CHECK_EQ(array->constant_pool()->length(), 3); | 391 CHECK_EQ(array->constant_pool()->length(), 3); |
409 } | 392 } |
410 | 393 |
411 | 394 |
412 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 395 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
413 static const int kFarJumpDistance = 256; | 396 static const int kFarJumpDistance = 256; |
414 | 397 |
415 BytecodeArrayBuilder builder(isolate(), zone()); | 398 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
416 builder.set_parameter_count(0); | |
417 builder.set_locals_count(1); | |
418 builder.set_context_count(0); | |
419 | |
420 Register reg(0); | 399 Register reg(0); |
421 BytecodeLabel far0, far1, far2, far3, far4; | 400 BytecodeLabel far0, far1, far2, far3, far4; |
422 BytecodeLabel near0, near1, near2, near3, near4; | 401 BytecodeLabel near0, near1, near2, near3, near4; |
423 | 402 |
424 builder.Jump(&near0) | 403 builder.Jump(&near0) |
425 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 404 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
426 .JumpIfTrue(&near1) | 405 .JumpIfTrue(&near1) |
427 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 406 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
428 .JumpIfFalse(&near2) | 407 .JumpIfFalse(&near2) |
429 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 408 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 | 500 |
522 CHECK_EQ(iterator.current_bytecode(), | 501 CHECK_EQ(iterator.current_bytecode(), |
523 Bytecode::kJumpIfToBooleanFalseConstant); | 502 Bytecode::kJumpIfToBooleanFalseConstant); |
524 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 503 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
525 Smi::FromInt(kFarJumpDistance - 16)); | 504 Smi::FromInt(kFarJumpDistance - 16)); |
526 iterator.Advance(); | 505 iterator.Advance(); |
527 } | 506 } |
528 | 507 |
529 | 508 |
530 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 509 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
531 BytecodeArrayBuilder builder(isolate(), zone()); | 510 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
532 builder.set_parameter_count(0); | |
533 builder.set_locals_count(1); | |
534 builder.set_context_count(0); | |
535 Register reg(0); | 511 Register reg(0); |
536 | 512 |
537 BytecodeLabel label0, label1, label2, label3, label4; | 513 BytecodeLabel label0, label1, label2, label3, label4; |
538 builder.Bind(&label0) | 514 builder.Bind(&label0) |
539 .Jump(&label0) | 515 .Jump(&label0) |
540 .Bind(&label1) | 516 .Bind(&label1) |
541 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 517 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
542 .JumpIfTrue(&label1) | 518 .JumpIfTrue(&label1) |
543 .Bind(&label2) | 519 .Bind(&label2) |
544 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 520 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 593 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
618 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -160); | 594 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -160); |
619 iterator.Advance(); | 595 iterator.Advance(); |
620 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 596 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
621 iterator.Advance(); | 597 iterator.Advance(); |
622 CHECK(iterator.done()); | 598 CHECK(iterator.done()); |
623 } | 599 } |
624 | 600 |
625 | 601 |
626 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 602 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
627 BytecodeArrayBuilder builder(isolate(), zone()); | 603 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
628 builder.set_parameter_count(0); | |
629 builder.set_locals_count(0); | |
630 builder.set_context_count(0); | |
631 | 604 |
632 // Labels can only have 1 forward reference, but | 605 // Labels can only have 1 forward reference, but |
633 // can be referred to mulitple times once bound. | 606 // can be referred to mulitple times once bound. |
634 BytecodeLabel label; | 607 BytecodeLabel label; |
635 | 608 |
636 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return(); | 609 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return(); |
637 | 610 |
638 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 611 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
639 BytecodeArrayIterator iterator(array); | 612 BytecodeArrayIterator iterator(array); |
640 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 613 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
641 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 614 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
642 iterator.Advance(); | 615 iterator.Advance(); |
643 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 616 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
644 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 617 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
645 iterator.Advance(); | 618 iterator.Advance(); |
646 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 619 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
647 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 620 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
648 iterator.Advance(); | 621 iterator.Advance(); |
649 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 622 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
650 iterator.Advance(); | 623 iterator.Advance(); |
651 CHECK(iterator.done()); | 624 CHECK(iterator.done()); |
652 } | 625 } |
653 | 626 |
654 | 627 |
655 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { | 628 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { |
656 static const int kRepeats = 3; | 629 static const int kRepeats = 3; |
657 | 630 |
658 BytecodeArrayBuilder builder(isolate(), zone()); | 631 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
659 builder.set_parameter_count(0); | |
660 builder.set_locals_count(0); | |
661 builder.set_context_count(0); | |
662 | |
663 for (int i = 0; i < kRepeats; i++) { | 632 for (int i = 0; i < kRepeats; i++) { |
664 BytecodeLabel label; | 633 BytecodeLabel label; |
665 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); | 634 builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label); |
666 } | 635 } |
667 | |
668 builder.Return(); | 636 builder.Return(); |
669 | 637 |
670 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 638 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
671 BytecodeArrayIterator iterator(array); | 639 BytecodeArrayIterator iterator(array); |
672 for (int i = 0; i < kRepeats; i++) { | 640 for (int i = 0; i < kRepeats; i++) { |
673 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 641 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
674 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 642 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
675 iterator.Advance(); | 643 iterator.Advance(); |
676 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 644 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
677 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 645 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
678 iterator.Advance(); | 646 iterator.Advance(); |
679 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 647 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
680 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 648 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
681 iterator.Advance(); | 649 iterator.Advance(); |
682 } | 650 } |
683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 651 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
684 iterator.Advance(); | 652 iterator.Advance(); |
685 CHECK(iterator.done()); | 653 CHECK(iterator.done()); |
686 } | 654 } |
687 | 655 |
688 } // namespace interpreter | 656 } // namespace interpreter |
689 } // namespace internal | 657 } // namespace internal |
690 } // namespace v8 | 658 } // namespace v8 |
OLD | NEW |