OLD | NEW |
---|---|
1 // Copyright (c) 2016, the Dartino project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dartino project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
4 | 4 |
5 #if defined(DARTINO_TARGET_MIPS) | 5 #if defined(DARTINO_TARGET_MIPS) |
6 | 6 |
7 #include "src/shared/bytecodes.h" | 7 #include "src/shared/bytecodes.h" |
8 #include "src/shared/names.h" | 8 #include "src/shared/names.h" |
9 #include "src/shared/selectors.h" | 9 #include "src/shared/selectors.h" |
10 | 10 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 #undef V | 85 #undef V |
86 } | 86 } |
87 | 87 |
88 class InterpreterGeneratorMIPS: public InterpreterGenerator { | 88 class InterpreterGeneratorMIPS: public InterpreterGenerator { |
89 public: | 89 public: |
90 explicit InterpreterGeneratorMIPS(Assembler* assembler) | 90 explicit InterpreterGeneratorMIPS(Assembler* assembler) |
91 : InterpreterGenerator(assembler) { } | 91 : InterpreterGenerator(assembler) { } |
92 | 92 |
93 // Registers | 93 // Registers |
94 // --------- | 94 // --------- |
95 // s0: current process | 95 // S0: current process |
96 // s1: bytecode pointer | 96 // S1: bytecode pointer |
97 // s2: stack pointer | 97 // S2: stack pointer (top) |
98 // s4: null | 98 // S4: null |
99 // s6: true | 99 // S6: program |
100 // s7: false | 100 // S7: dispatch table |
101 | |
102 virtual void GeneratePrologue(); | 101 virtual void GeneratePrologue(); |
103 virtual void GenerateEpilogue(); | 102 virtual void GenerateEpilogue(); |
104 | 103 |
105 virtual void GenerateMethodEntry(); | 104 virtual void GenerateMethodEntry(); |
106 | 105 |
107 virtual void GenerateBytecodePrologue(const char* name); | 106 virtual void GenerateBytecodePrologue(const char* name); |
108 virtual void GenerateDebugAtBytecode(); | 107 virtual void GenerateDebugAtBytecode(); |
109 | 108 |
110 virtual void DoLoadLocal0(); | 109 virtual void DoLoadLocal0(); |
111 virtual void DoLoadLocal1(); | 110 virtual void DoLoadLocal1(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 Label done_; | 237 Label done_; |
239 Label done_state_saved_; | 238 Label done_state_saved_; |
240 Label check_stack_overflow_; | 239 Label check_stack_overflow_; |
241 Label check_stack_overflow_0_; | 240 Label check_stack_overflow_0_; |
242 Label gc_; | 241 Label gc_; |
243 Label intrinsic_failure_; | 242 Label intrinsic_failure_; |
244 Label interpreter_entry_; | 243 Label interpreter_entry_; |
245 int spill_size_; | 244 int spill_size_; |
246 // Used in GeneratePrologue/Epilogue, S0-S7 + RA + FP. | 245 // Used in GeneratePrologue/Epilogue, S0-S7 + RA + FP. |
247 static const int kSaveFrameSize = 10; | 246 static const int kSaveFrameSize = 10; |
247 static const int kFalseOffset = 8; | |
248 static const int kTrueOffset = 16; | |
248 | 249 |
249 void LoadLocal(Register reg, int index); | 250 void LoadLocal(Register reg, int index); |
250 void StoreLocal(Register reg, int index); | 251 void StoreLocal(Register reg, int index); |
251 | 252 |
252 void Push(Register reg); | 253 void Push(Register reg); |
253 void Pop(Register reg); | 254 void Pop(Register reg); |
254 void Drop(int n); | 255 void Drop(int n); |
255 void Drop(Register reg); | 256 void Drop(Register reg); |
256 void DropNAndSetTop(int dropping_slots, Register reg); | 257 void DropNAndSetTop(int dropping_slots, Register reg); |
257 | 258 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 void InvokeBitXor(const char* fallback); | 291 void InvokeBitXor(const char* fallback); |
291 void InvokeBitShr(const char* fallback); | 292 void InvokeBitShr(const char* fallback); |
292 void InvokeBitShl(const char* fallback); | 293 void InvokeBitShl(const char* fallback); |
293 | 294 |
294 void InvokeMethodUnfold(bool test); | 295 void InvokeMethodUnfold(bool test); |
295 void InvokeMethod(bool test); | 296 void InvokeMethod(bool test); |
296 | 297 |
297 void InvokeNative(bool yield, bool safepoint); | 298 void InvokeNative(bool yield, bool safepoint); |
298 void InvokeStatic(); | 299 void InvokeStatic(); |
299 | 300 |
300 void ConditionalStore(Register cmp, Register reg_if_eq, Register reg_if_ne, | 301 void AddIf(Register reg1, Register reg2, Condition cond, |
301 const Address& address); | 302 Register reg, int immediate); |
303 void ToBoolean(Register reg1, Register reg2, Condition cond, Register reg); | |
304 void LoadFalse(Register reg); | |
305 void LoadTrue(Register reg); | |
302 | 306 |
303 void CheckStackOverflow(int size); | 307 void CheckStackOverflow(int size); |
304 | 308 |
305 void Dispatch(int size); | 309 void Dispatch(int size); |
306 | 310 |
307 void SaveState(Label* resume); | 311 void SaveState(Label* resume); |
308 void RestoreState(); | 312 void RestoreState(); |
309 | 313 |
310 void ShiftAddJump(Register reg1, Register reg2, int imm); | 314 void ShiftAddJump(Register reg1, Register reg2, int imm); |
311 void ShiftAddLoad(Register reg1, Register reg2, Register reg3, int imm); | 315 void ShiftAddLoad(Register reg1, Register reg2, Register reg3, int imm); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 __ B(NEQ, V0, T0, &overflow); | 424 __ B(NEQ, V0, T0, &overflow); |
421 __ b(&done_); | 425 __ b(&done_); |
422 __ ori(V0, ZR, Immediate(Interpreter::kBreakpoint)); // Delay-slot. | 426 __ ori(V0, ZR, Immediate(Interpreter::kBreakpoint)); // Delay-slot. |
423 | 427 |
424 __ Bind(&stay_fast); | 428 __ Bind(&stay_fast); |
425 Dispatch(0); | 429 Dispatch(0); |
426 | 430 |
427 __ Bind(&overflow); | 431 __ Bind(&overflow); |
428 Label throw_resume; | 432 Label throw_resume; |
429 SaveState(&throw_resume); | 433 SaveState(&throw_resume); |
430 __ lw(S3, Address(S0, Process::kProgramOffset)); | 434 __ lw(S3, Address(S6, Program::kStackOverflowErrorOffset)); |
431 __ lw(S3, Address(S3, Program::kStackOverflowErrorOffset)); | |
432 DoThrowAfterSaveState(&throw_resume); | 435 DoThrowAfterSaveState(&throw_resume); |
433 | 436 |
434 // Intrinsic failure: Just invoke the method. | 437 // Intrinsic failure: Just invoke the method. |
435 __ Bind(&intrinsic_failure_); | 438 __ Bind(&intrinsic_failure_); |
436 __ la(T9, "InterpreterMethodEntry"); | 439 __ la(T9, "InterpreterMethodEntry"); |
437 __ Jr(T9); | 440 __ Jr(T9); |
438 } | 441 } |
439 | 442 |
440 void InterpreterGeneratorMIPS::GenerateMethodEntry() { | 443 void InterpreterGeneratorMIPS::GenerateMethodEntry() { |
441 __ SwitchToText(); | 444 __ SwitchToText(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
485 Dispatch(kLoadLocal0Length); | 488 Dispatch(kLoadLocal0Length); |
486 } | 489 } |
487 | 490 |
488 void InterpreterGeneratorMIPS::DoLoadLocal1() { | 491 void InterpreterGeneratorMIPS::DoLoadLocal1() { |
489 LoadLocal(A0, 1); | 492 LoadLocal(A0, 1); |
490 Push(A0); | 493 Push(A0); |
491 Dispatch(kLoadLocal1Length); | 494 Dispatch(kLoadLocal1Length); |
492 } | 495 } |
493 | 496 |
494 void InterpreterGeneratorMIPS::DoLoadLocal2() { | 497 void InterpreterGeneratorMIPS::DoLoadLocal2() { |
498 LoadLocal(A0, 2); | |
499 Push(A0); | |
500 Dispatch(kLoadLocal2Length); | |
495 } | 501 } |
496 | 502 |
497 void InterpreterGeneratorMIPS::DoLoadLocal3() { | 503 void InterpreterGeneratorMIPS::DoLoadLocal3() { |
498 LoadLocal(A0, 3); | 504 LoadLocal(A0, 3); |
499 Push(A0); | 505 Push(A0); |
500 Dispatch(kLoadLocal3Length); | 506 Dispatch(kLoadLocal3Length); |
501 } | 507 } |
502 | 508 |
503 void InterpreterGeneratorMIPS::DoLoadLocal4() { | 509 void InterpreterGeneratorMIPS::DoLoadLocal4() { |
504 LoadLocal(A0, 4); | 510 LoadLocal(A0, 4); |
505 Push(A0); | 511 Push(A0); |
506 Dispatch(kLoadLocal4Length); | 512 Dispatch(kLoadLocal4Length); |
507 } | 513 } |
508 | 514 |
509 void InterpreterGeneratorMIPS::DoLoadLocal5() { | 515 void InterpreterGeneratorMIPS::DoLoadLocal5() { |
516 LoadLocal(A0, 5); | |
517 Push(A0); | |
518 Dispatch(kLoadLocal5Length); | |
510 } | 519 } |
511 | 520 |
512 void InterpreterGeneratorMIPS::DoLoadLocal() { | 521 void InterpreterGeneratorMIPS::DoLoadLocal() { |
522 __ lbu(A0, Address(S1, 1)); | |
523 ShiftAddLoad(A0, S2, A0, TIMES_WORD_SIZE); | |
524 Push(A0); | |
525 Dispatch(kLoadLocalLength); | |
513 } | 526 } |
514 | 527 |
515 void InterpreterGeneratorMIPS::DoLoadLocalWide() { | 528 void InterpreterGeneratorMIPS::DoLoadLocalWide() { |
516 } | 529 } |
517 | 530 |
518 void InterpreterGeneratorMIPS::DoLoadBoxed() { | 531 void InterpreterGeneratorMIPS::DoLoadBoxed() { |
532 __ lbu(A0, Address(S1, 1)); | |
533 ShiftAddLoad(A1, S2, A0, TIMES_WORD_SIZE); | |
534 __ lw(A0, Address(A1, Boxed::kValueOffset - HeapObject::kTag)); | |
535 Push(A0); | |
536 Dispatch(kLoadBoxedLength); | |
519 } | 537 } |
520 | 538 |
521 void InterpreterGeneratorMIPS::DoLoadStatic() { | 539 void InterpreterGeneratorMIPS::DoLoadStatic() { |
522 __ lw(A0, Address(S1, 1)); | 540 __ lw(A0, Address(S1, 1)); |
523 __ lw(A1, Address(S0, Process::kStaticsOffset)); | 541 __ lw(A1, Address(S0, Process::kStaticsOffset)); |
524 __ addiu(A1, A1, Immediate(Array::kSize - HeapObject::kTag)); | 542 __ addiu(A1, A1, Immediate(Array::kSize - HeapObject::kTag)); |
525 ShiftAddLoad(A0, A1, A0, TIMES_WORD_SIZE); | 543 ShiftAddLoad(A0, A1, A0, TIMES_WORD_SIZE); |
526 Push(A0); | 544 Push(A0); |
527 Dispatch(kLoadStaticLength); | 545 Dispatch(kLoadStaticLength); |
528 } | 546 } |
(...skipping 24 matching lines...) Expand all Loading... | |
553 __ lw(A0, Address(A0, | 571 __ lw(A0, Address(A0, |
554 Initializer::kFunctionOffset - HeapObject::kTag)); // Delay-slot. | 572 Initializer::kFunctionOffset - HeapObject::kTag)); // Delay-slot. |
555 RestoreByteCodePointer(A2); | 573 RestoreByteCodePointer(A2); |
556 | 574 |
557 __ Bind(&done); | 575 __ Bind(&done); |
558 Push(A0); | 576 Push(A0); |
559 Dispatch(kLoadStaticInitLength); | 577 Dispatch(kLoadStaticInitLength); |
560 } | 578 } |
561 | 579 |
562 void InterpreterGeneratorMIPS::DoLoadField() { | 580 void InterpreterGeneratorMIPS::DoLoadField() { |
581 __ lbu(A1, Address(S1, 1)); | |
582 LoadLocal(A0, 0); | |
583 __ addiu(A0, A0, Immediate(Instance::kSize - HeapObject::kTag)); | |
584 ShiftAddLoad(A0, A0, A1, TIMES_WORD_SIZE); | |
585 StoreLocal(A0, 0); | |
586 Dispatch(kLoadFieldLength); | |
563 } | 587 } |
564 | 588 |
565 void InterpreterGeneratorMIPS::DoLoadFieldWide() { | 589 void InterpreterGeneratorMIPS::DoLoadFieldWide() { |
566 } | 590 } |
567 | 591 |
568 void InterpreterGeneratorMIPS::DoLoadConst() { | 592 void InterpreterGeneratorMIPS::DoLoadConst() { |
569 __ lw(A0, Address(S1, 1)); | 593 __ lw(A0, Address(S1, 1)); |
570 ShiftAddLoad(A2, S1, A0, TIMES_1); | 594 ShiftAddLoad(A2, S1, A0, TIMES_1); |
571 Push(A2); | 595 Push(A2); |
572 Dispatch(kLoadConstLength); | 596 Dispatch(kLoadConstLength); |
573 } | 597 } |
574 | 598 |
575 void InterpreterGeneratorMIPS::DoStoreLocal() { | 599 void InterpreterGeneratorMIPS::DoStoreLocal() { |
576 LoadLocal(A1, 0); | 600 LoadLocal(A1, 0); |
577 __ lbu(A0, Address(S1, 1)); | 601 __ lbu(A0, Address(S1, 1)); |
578 ShiftAddStore(A1, S2, A0, TIMES_WORD_SIZE); | 602 ShiftAddStore(A1, S2, A0, TIMES_WORD_SIZE); |
579 Dispatch(kStoreLocalLength); | 603 Dispatch(kStoreLocalLength); |
580 } | 604 } |
581 | 605 |
582 void InterpreterGeneratorMIPS::DoStoreBoxed() { | 606 void InterpreterGeneratorMIPS::DoStoreBoxed() { |
607 LoadLocal(A2, 0); | |
608 __ lbu(A0, Address(S1, 1)); | |
609 ShiftAddLoad(A1, S2, A0, TIMES_WORD_SIZE); | |
610 __ sw(A2, Address(A1, Boxed::kValueOffset - HeapObject::kTag)); | |
611 | |
612 AddToRememberedSet(A1, A2, A3); | |
613 | |
614 Dispatch(kStoreBoxedLength); | |
583 } | 615 } |
584 | 616 |
585 void InterpreterGeneratorMIPS::DoStoreStatic() { | 617 void InterpreterGeneratorMIPS::DoStoreStatic() { |
586 LoadLocal(A2, 0); | 618 LoadLocal(A2, 0); |
587 __ lw(A0, Address(S1, 1)); | 619 __ lw(A0, Address(S1, 1)); |
588 __ lw(A1, Address(S0, Process::kStaticsOffset)); | 620 __ lw(A1, Address(S0, Process::kStaticsOffset)); |
589 __ addiu(A3, A1, Immediate(Array::kSize - HeapObject::kTag)); | 621 __ addiu(A3, A1, Immediate(Array::kSize - HeapObject::kTag)); |
590 ShiftAddStore(A2, A3, A0, TIMES_WORD_SIZE); | 622 ShiftAddStore(A2, A3, A0, TIMES_WORD_SIZE); |
591 | 623 |
592 AddToRememberedSet(A1, A2, A0); | 624 AddToRememberedSet(A1, A2, A0); |
593 | 625 |
594 Dispatch(kStoreStaticLength); | 626 Dispatch(kStoreStaticLength); |
595 } | 627 } |
596 | 628 |
597 void InterpreterGeneratorMIPS::DoStoreField() { | 629 void InterpreterGeneratorMIPS::DoStoreField() { |
598 } | 630 } |
599 | 631 |
600 void InterpreterGeneratorMIPS::DoStoreFieldWide() { | 632 void InterpreterGeneratorMIPS::DoStoreFieldWide() { |
601 } | 633 } |
602 | 634 |
603 void InterpreterGeneratorMIPS::DoLoadLiteralNull() { | 635 void InterpreterGeneratorMIPS::DoLoadLiteralNull() { |
604 Push(S4); | 636 Push(S4); |
605 Dispatch(kLoadLiteralNullLength); | 637 Dispatch(kLoadLiteralNullLength); |
606 } | 638 } |
607 | 639 |
608 void InterpreterGeneratorMIPS::DoLoadLiteralTrue() { | 640 void InterpreterGeneratorMIPS::DoLoadLiteralTrue() { |
641 LoadTrue(A2); | |
642 Push(A2); | |
643 Dispatch(kLoadLiteralTrueLength); | |
609 } | 644 } |
610 | 645 |
611 void InterpreterGeneratorMIPS::DoLoadLiteralFalse() { | 646 void InterpreterGeneratorMIPS::DoLoadLiteralFalse() { |
647 LoadFalse(A2); | |
648 Push(A2); | |
649 Dispatch(kLoadLiteralFalseLength); | |
612 } | 650 } |
613 | 651 |
614 void InterpreterGeneratorMIPS::DoLoadLiteral0() { | 652 void InterpreterGeneratorMIPS::DoLoadLiteral0() { |
615 __ li(A0, Immediate(reinterpret_cast<int32_t>(Smi::FromWord(0)))); | 653 __ li(A0, Immediate(reinterpret_cast<int32_t>(Smi::FromWord(0)))); |
616 Push(A0); | 654 Push(A0); |
617 Dispatch(kLoadLiteral0Length); | 655 Dispatch(kLoadLiteral0Length); |
618 } | 656 } |
619 | 657 |
620 void InterpreterGeneratorMIPS::DoLoadLiteral1() { | 658 void InterpreterGeneratorMIPS::DoLoadLiteral1() { |
659 __ li(A0, Immediate(reinterpret_cast<int32_t>(Smi::FromWord(1)))); | |
660 Push(A0); | |
661 Dispatch(kLoadLiteral1Length); | |
621 } | 662 } |
622 | 663 |
623 void InterpreterGeneratorMIPS::DoLoadLiteral() { | 664 void InterpreterGeneratorMIPS::DoLoadLiteral() { |
624 __ lbu(A0, Address(S1, 1)); | 665 __ lbu(A0, Address(S1, 1)); |
625 __ sll(A0, A0, Immediate(Smi::kTagSize)); | 666 __ sll(A0, A0, Immediate(Smi::kTagSize)); |
626 ASSERT(Smi::kTag == 0); | 667 ASSERT(Smi::kTag == 0); |
627 Push(A0); | 668 Push(A0); |
628 Dispatch(kLoadLiteralLength); | 669 Dispatch(kLoadLiteralLength); |
629 } | 670 } |
630 | 671 |
631 void InterpreterGeneratorMIPS::DoLoadLiteralWide() { | 672 void InterpreterGeneratorMIPS::DoLoadLiteralWide() { |
673 ASSERT(Smi::kTag == 0); | |
674 __ lw(A0, Address(S1, 1)); | |
675 __ sll(A0, A0, Immediate(Smi::kTagSize)); | |
676 Push(A0); | |
677 Dispatch(kLoadLiteralWideLength); | |
632 } | 678 } |
633 | 679 |
634 void InterpreterGeneratorMIPS::DoInvokeMethodUnfold() { | 680 void InterpreterGeneratorMIPS::DoInvokeMethodUnfold() { |
635 } | 681 } |
636 | 682 |
637 void InterpreterGeneratorMIPS::DoInvokeMethod() { | 683 void InterpreterGeneratorMIPS::DoInvokeMethod() { |
638 InvokeMethod(false); | 684 InvokeMethod(false); |
639 } | 685 } |
640 | 686 |
641 void InterpreterGeneratorMIPS::DoInvokeNoSuchMethod() { | 687 void InterpreterGeneratorMIPS::DoInvokeNoSuchMethod() { |
642 } | 688 } |
643 | 689 |
644 void InterpreterGeneratorMIPS::DoInvokeTestNoSuchMethod() { | 690 void InterpreterGeneratorMIPS::DoInvokeTestNoSuchMethod() { |
645 } | 691 } |
646 | 692 |
647 void InterpreterGeneratorMIPS::DoInvokeTestUnfold() { | 693 void InterpreterGeneratorMIPS::DoInvokeTestUnfold() { |
648 } | 694 } |
649 | 695 |
650 void InterpreterGeneratorMIPS::DoInvokeTest() { | 696 void InterpreterGeneratorMIPS::DoInvokeTest() { |
697 InvokeMethod(true); | |
651 } | 698 } |
652 | 699 |
653 void InterpreterGeneratorMIPS::DoInvokeStatic() { | 700 void InterpreterGeneratorMIPS::DoInvokeStatic() { |
654 InvokeStatic(); | 701 InvokeStatic(); |
655 } | 702 } |
656 | 703 |
657 void InterpreterGeneratorMIPS::DoInvokeFactory() { | 704 void InterpreterGeneratorMIPS::DoInvokeFactory() { |
705 InvokeStatic(); | |
658 } | 706 } |
659 | 707 |
660 void InterpreterGeneratorMIPS::DoInvokeLeafNative() { | 708 void InterpreterGeneratorMIPS::DoInvokeLeafNative() { |
661 InvokeNative(false, false); | 709 InvokeNative(false, false); |
662 } | 710 } |
663 | 711 |
664 void InterpreterGeneratorMIPS::DoInvokeNative() { | 712 void InterpreterGeneratorMIPS::DoInvokeNative() { |
713 InvokeNative(false, true); | |
665 } | 714 } |
666 | 715 |
667 void InterpreterGeneratorMIPS::DoInvokeNativeYield() { | 716 void InterpreterGeneratorMIPS::DoInvokeNativeYield() { |
668 } | 717 } |
669 | 718 |
670 void InterpreterGeneratorMIPS::DoInvokeSelector() { | 719 void InterpreterGeneratorMIPS::DoInvokeSelector() { |
671 Label resume; | 720 Label resume; |
672 SaveState(&resume); | 721 SaveState(&resume); |
673 PrepareStack(); | 722 PrepareStack(); |
674 __ la(T9, "HandleInvokeSelector"); | 723 __ la(T9, "HandleInvokeSelector"); |
(...skipping 23 matching lines...) Expand all Loading... | |
698 | 747 |
699 StoreLocal(A0, 0); | 748 StoreLocal(A0, 0); |
700 Dispatch(kInvokeSelectorLength); | 749 Dispatch(kInvokeSelectorLength); |
701 } | 750 } |
702 | 751 |
703 void InterpreterGeneratorMIPS::InvokeEq(const char* fallback) { | 752 void InterpreterGeneratorMIPS::InvokeEq(const char* fallback) { |
704 InvokeCompare(fallback, EQ); | 753 InvokeCompare(fallback, EQ); |
705 } | 754 } |
706 | 755 |
707 void InterpreterGeneratorMIPS::InvokeLt(const char* fallback) { | 756 void InterpreterGeneratorMIPS::InvokeLt(const char* fallback) { |
757 InvokeCompare(fallback, LT); | |
708 } | 758 } |
709 | 759 |
710 void InterpreterGeneratorMIPS::InvokeLe(const char* fallback) { | 760 void InterpreterGeneratorMIPS::InvokeLe(const char* fallback) { |
761 InvokeCompare(fallback, LE); | |
711 } | 762 } |
712 | 763 |
713 void InterpreterGeneratorMIPS::InvokeGt(const char* fallback) { | 764 void InterpreterGeneratorMIPS::InvokeGt(const char* fallback) { |
765 InvokeCompare(fallback, GT); | |
714 } | 766 } |
715 | 767 |
716 void InterpreterGeneratorMIPS::InvokeGe(const char* fallback) { | 768 void InterpreterGeneratorMIPS::InvokeGe(const char* fallback) { |
769 InvokeCompare(fallback, GE); | |
717 } | 770 } |
718 | 771 |
719 void InterpreterGeneratorMIPS::InvokeAdd(const char* fallback) { | 772 void InterpreterGeneratorMIPS::InvokeAdd(const char* fallback) { |
720 Label no_overflow; | 773 Label no_overflow; |
721 LoadLocal(A0, 1); | 774 LoadLocal(A0, 1); |
722 __ andi(T0, A0, Immediate(Smi::kTagMask)); | 775 __ andi(T0, A0, Immediate(Smi::kTagMask)); |
723 __ B(NEQ, T0, ZR, fallback); | 776 __ B(NEQ, T0, ZR, fallback); |
724 LoadLocal(A1, 0); | 777 LoadLocal(A1, 0); |
725 __ andi(T1, A1, Immediate(Smi::kTagMask)); | 778 __ andi(T1, A1, Immediate(Smi::kTagMask)); |
726 __ B(NEQ, T1, ZR, fallback); | 779 __ B(NEQ, T1, ZR, fallback); |
727 | 780 |
728 __ xor_(T1, A0, A1); | 781 __ xor_(T1, A0, A1); |
729 __ b(LT, T1, ZR, &no_overflow); | 782 __ b(LT, T1, ZR, &no_overflow); |
730 __ addu(T0, A0, A1); // Delay-slot. | 783 __ addu(T0, A0, A1); // Delay-slot. |
731 __ xor_(T1, T0, A0); | 784 __ xor_(T1, T0, A0); |
732 __ slt(T1, T1, ZR); | 785 __ b(LT, T1, ZR, fallback); |
733 __ b(NEQ, T1, ZR, fallback); | |
734 __ Bind(&no_overflow); | 786 __ Bind(&no_overflow); |
735 __ move(A0, T0); // Delay-slot. | 787 __ move(A0, T0); // Delay-slot. |
736 DropNAndSetTop(1, A0); | 788 DropNAndSetTop(1, A0); |
737 Dispatch(kInvokeAddLength); | 789 Dispatch(kInvokeAddLength); |
738 } | 790 } |
739 | 791 |
740 void InterpreterGeneratorMIPS::InvokeSub(const char* fallback) { | 792 void InterpreterGeneratorMIPS::InvokeSub(const char* fallback) { |
793 Label no_overflow; | |
794 LoadLocal(A0, 1); | |
795 __ andi(T0, A0, Immediate(Smi::kTagMask)); | |
796 __ B(NEQ, T0, ZR, fallback); | |
797 LoadLocal(A1, 0); | |
798 __ andi(T0, A1, Immediate(Smi::kTagMask)); | |
799 __ B(NEQ, T0, ZR, fallback); | |
800 | |
801 __ xor_(T1, A0, A1); | |
802 __ srl(T1, T1, Immediate(31)); | |
803 __ b(EQ, T1, ZR, &no_overflow); | |
804 __ subu(T0, A0, A1); // Delay-slot. | |
805 __ xor_(T1, T0, A0); | |
806 __ b(LT, T1, ZR, fallback); | |
807 __ Bind(&no_overflow); | |
808 __ move(A0, T0); // Delay-slot. | |
809 DropNAndSetTop(1, A0); | |
810 Dispatch(kInvokeAddLength); | |
erikcorry
2016/06/27 15:51:08
kInvokeSubLength
petarj
2016/06/29 02:09:15
Done.
| |
741 } | 811 } |
742 | 812 |
743 void InterpreterGeneratorMIPS::InvokeMod(const char* fallback) { | 813 void InterpreterGeneratorMIPS::InvokeMod(const char* fallback) { |
744 } | 814 } |
745 | 815 |
746 void InterpreterGeneratorMIPS::InvokeMul(const char* fallback) { | 816 void InterpreterGeneratorMIPS::InvokeMul(const char* fallback) { |
817 LoadLocal(A0, 1); | |
818 __ andi(T0, A0, Immediate(Smi::kTagMask)); | |
819 __ B(NEQ, T0, ZR, fallback); | |
820 LoadLocal(A1, 0); | |
821 __ andi(T1, A1, Immediate(Smi::kTagMask)); | |
822 __ B(NEQ, T1, ZR, fallback); | |
823 | |
824 __ sra(A0, A0, Immediate(1)); | |
825 __ mult(A0, A1); | |
826 __ mfhi(T1); | |
827 __ mflo(T0); | |
828 __ move(A0, T0); | |
829 __ sra(T0, T0, Immediate(31)); | |
830 __ B(NEQ, T1, T0, fallback); | |
831 | |
832 DropNAndSetTop(1, A0); | |
833 Dispatch(kInvokeMulLength); | |
747 } | 834 } |
748 | 835 |
749 void InterpreterGeneratorMIPS::InvokeTruncDiv(const char* fallback) { | 836 void InterpreterGeneratorMIPS::InvokeTruncDiv(const char* fallback) { |
750 } | 837 } |
751 | 838 |
752 void InterpreterGeneratorMIPS::InvokeBitNot(const char* fallback) { | 839 void InterpreterGeneratorMIPS::InvokeBitNot(const char* fallback) { |
753 } | 840 } |
754 | 841 |
755 void InterpreterGeneratorMIPS::InvokeBitAnd(const char* fallback) { | 842 void InterpreterGeneratorMIPS::InvokeBitAnd(const char* fallback) { |
843 LoadLocal(A0, 1); | |
844 __ andi(T0, A0, Immediate(Smi::kTagMask)); | |
845 __ B(NEQ, T0, ZR, fallback); | |
846 LoadLocal(A1, 0); | |
847 __ andi(T0, A1, Immediate(Smi::kTagMask)); | |
848 __ B(NEQ, T0, ZR, fallback); | |
849 | |
850 __ and_(A0, A0, A1); | |
851 DropNAndSetTop(1, A0); | |
852 Dispatch(kInvokeBitAndLength); | |
756 } | 853 } |
757 | 854 |
758 void InterpreterGeneratorMIPS::InvokeBitOr(const char* fallback) { | 855 void InterpreterGeneratorMIPS::InvokeBitOr(const char* fallback) { |
759 } | 856 } |
760 | 857 |
761 void InterpreterGeneratorMIPS::InvokeBitXor(const char* fallback) { | 858 void InterpreterGeneratorMIPS::InvokeBitXor(const char* fallback) { |
762 } | 859 } |
763 | 860 |
764 void InterpreterGeneratorMIPS::InvokeBitShr(const char* fallback) { | 861 void InterpreterGeneratorMIPS::InvokeBitShr(const char* fallback) { |
862 LoadLocal(A0, 1); | |
863 __ andi(T0, A0, Immediate(Smi::kTagMask)); | |
864 __ B(NEQ, T0, ZR, fallback); | |
865 LoadLocal(A1, 0); | |
866 __ andi(T0, A1, Immediate(Smi::kTagMask)); | |
867 __ B(NEQ, T0, ZR, fallback); | |
868 | |
869 // Untag and shift. | |
870 __ sra(A0, A0, Immediate(1)); | |
871 __ sra(A1, A1, Immediate(1)); | |
872 | |
873 Label shift; | |
874 __ li(T0, Immediate(32)); | |
875 __ B(LT, A1, T0, &shift); | |
876 __ li(A1, Immediate(31)); | |
877 __ Bind(&shift); | |
878 __ srav(A0, A0, A1); | |
879 | |
880 // Retag and store. | |
881 __ addu(A0, A0, A0); | |
882 DropNAndSetTop(1, A0); | |
883 Dispatch(kInvokeBitAndLength); | |
765 } | 884 } |
766 | 885 |
767 void InterpreterGeneratorMIPS::InvokeBitShl(const char* fallback) { | 886 void InterpreterGeneratorMIPS::InvokeBitShl(const char* fallback) { |
887 LoadLocal(A0, 1); | |
888 __ andi(T0, A0, Immediate(Smi::kTagMask)); | |
889 __ B(NEQ, T0, ZR, fallback); | |
890 LoadLocal(A1, 0); | |
891 __ andi(T0, A1, Immediate(Smi::kTagSize)); | |
892 __ B(NEQ, T0, ZR, fallback); | |
893 | |
894 // Untag the shift count, but not the value. If the shift | |
895 // count is greater than 31 (or negative), the shift is going | |
896 // to misbehave so we have to guard against that. | |
897 __ sra(A1, A1, Immediate(1)); | |
898 __ li(T0, Immediate(31)); | |
erikcorry
2016/06/27 15:51:08
Perhaps save one instruction with
sra(T0, A1, Imm
petarj
2016/06/29 02:09:15
Done, thanks for the idea.
| |
899 __ sltu(T1, T0, A1); | |
900 __ B(GT, T1, ZR, fallback); | |
901 | |
902 // Only allow to shift out "sign bits". If we shift | |
903 // out any other bit, it's an overflow. | |
904 __ sllv(A2, A0, A1); | |
905 __ srav(A3, A2, A1); | |
906 __ B(NEQ, A3, A0, fallback); | |
907 | |
908 DropNAndSetTop(1, A2); | |
909 Dispatch(kInvokeBitShlLength); | |
768 } | 910 } |
769 | 911 |
770 void InterpreterGeneratorMIPS::DoPop() { | 912 void InterpreterGeneratorMIPS::DoPop() { |
771 Drop(1); | 913 Drop(1); |
772 Dispatch(kPopLength); | 914 Dispatch(kPopLength); |
773 } | 915 } |
774 | 916 |
775 void InterpreterGeneratorMIPS::DoDrop() { | 917 void InterpreterGeneratorMIPS::DoDrop() { |
918 __ lbu(A0, Address(S1, 1)); | |
919 Drop(A0); | |
920 Dispatch(kDropLength); | |
776 } | 921 } |
777 | 922 |
778 void InterpreterGeneratorMIPS::DoReturn() { | 923 void InterpreterGeneratorMIPS::DoReturn() { |
779 Return(false); | 924 Return(false); |
780 } | 925 } |
781 | 926 |
782 void InterpreterGeneratorMIPS::DoReturnNull() { | 927 void InterpreterGeneratorMIPS::DoReturnNull() { |
783 Return(true); | 928 Return(true); |
784 } | 929 } |
785 | 930 |
786 void InterpreterGeneratorMIPS::DoBranchWide() { | 931 void InterpreterGeneratorMIPS::DoBranchWide() { |
787 __ lw(A0, Address(S1, 1)); | 932 __ lw(A0, Address(S1, 1)); |
788 __ addu(S1, S1, A0); | 933 __ addu(S1, S1, A0); |
789 Dispatch(0); | 934 Dispatch(0); |
790 } | 935 } |
791 | 936 |
792 void InterpreterGeneratorMIPS::DoBranchIfTrueWide() { | 937 void InterpreterGeneratorMIPS::DoBranchIfTrueWide() { |
793 Label branch; | 938 Label branch; |
794 Pop(S3); | 939 Pop(S3); |
795 __ B(EQ, S3, S6, &branch); | 940 LoadTrue(A2); |
941 __ B(EQ, S3, A2, &branch); | |
796 Dispatch(kBranchIfTrueWideLength); | 942 Dispatch(kBranchIfTrueWideLength); |
797 | 943 |
798 __ Bind(&branch); | 944 __ Bind(&branch); |
799 __ lw(A0, Address(S1, 1)); | 945 __ lw(A0, Address(S1, 1)); |
800 __ addu(S1, S1, A0); | 946 __ addu(S1, S1, A0); |
801 Dispatch(0); | 947 Dispatch(0); |
802 } | 948 } |
803 | 949 |
804 void InterpreterGeneratorMIPS::DoBranchIfFalseWide() { | 950 void InterpreterGeneratorMIPS::DoBranchIfFalseWide() { |
805 Label branch; | 951 Label branch; |
806 Pop(S3); | 952 Pop(S3); |
807 __ B(NEQ, S3, S6, &branch); | 953 LoadTrue(A2); |
954 __ B(NEQ, S3, A2, &branch); | |
808 Dispatch(kBranchIfFalseWideLength); | 955 Dispatch(kBranchIfFalseWideLength); |
809 | 956 |
810 __ Bind(&branch); | 957 __ Bind(&branch); |
811 __ lw(A0, Address(S1, 1)); | 958 __ lw(A0, Address(S1, 1)); |
812 __ addu(S1, S1, A0); | 959 __ addu(S1, S1, A0); |
813 Dispatch(0); | 960 Dispatch(0); |
814 } | 961 } |
815 | 962 |
816 void InterpreterGeneratorMIPS::DoBranchBack() { | 963 void InterpreterGeneratorMIPS::DoBranchBack() { |
964 CheckStackOverflow(0); | |
965 __ lbu(A0, Address(S1, 1)); | |
966 __ subu(S1, S1, A0); | |
967 Dispatch(0); | |
817 } | 968 } |
818 | 969 |
819 void InterpreterGeneratorMIPS::DoBranchBackIfTrue() { | 970 void InterpreterGeneratorMIPS::DoBranchBackIfTrue() { |
820 } | 971 } |
821 | 972 |
822 void InterpreterGeneratorMIPS::DoBranchBackIfFalse() { | 973 void InterpreterGeneratorMIPS::DoBranchBackIfFalse() { |
823 } | 974 } |
824 | 975 |
825 void InterpreterGeneratorMIPS::DoBranchBackWide() { | 976 void InterpreterGeneratorMIPS::DoBranchBackWide() { |
826 } | 977 } |
827 | 978 |
828 void InterpreterGeneratorMIPS::DoBranchBackIfTrueWide() { | 979 void InterpreterGeneratorMIPS::DoBranchBackIfTrueWide() { |
829 } | 980 } |
830 | 981 |
831 void InterpreterGeneratorMIPS::DoBranchBackIfFalseWide() { | 982 void InterpreterGeneratorMIPS::DoBranchBackIfFalseWide() { |
832 } | 983 } |
833 | 984 |
834 void InterpreterGeneratorMIPS::DoPopAndBranchWide() { | 985 void InterpreterGeneratorMIPS::DoPopAndBranchWide() { |
986 __ lbu(A0, Address(S1, 1)); | |
987 ShiftAdd(S2, S2, A0, TIMES_WORD_SIZE); | |
988 | |
989 __ lw(A0, Address(S1, 2)); | |
990 __ addu(S1, S1, A0); | |
991 Dispatch(0); | |
835 } | 992 } |
836 | 993 |
837 void InterpreterGeneratorMIPS::DoPopAndBranchBackWide() { | 994 void InterpreterGeneratorMIPS::DoPopAndBranchBackWide() { |
838 } | 995 } |
839 | 996 |
840 void InterpreterGeneratorMIPS::DoAllocate() { | 997 void InterpreterGeneratorMIPS::DoAllocate() { |
841 Allocate(false); | 998 Allocate(false); |
842 } | 999 } |
843 | 1000 |
844 void InterpreterGeneratorMIPS::DoAllocateImmutable() { | 1001 void InterpreterGeneratorMIPS::DoAllocateImmutable() { |
1002 Allocate(true); | |
845 } | 1003 } |
846 | 1004 |
847 void InterpreterGeneratorMIPS::DoAllocateBoxed() { | 1005 void InterpreterGeneratorMIPS::DoAllocateBoxed() { |
1006 LoadLocal(A1, 0); | |
1007 PrepareStack(); | |
1008 __ la(T9, "HandleAllocateBoxed"); | |
1009 __ jalr(T9); | |
1010 __ move(A0, S0); // Delay-slot. | |
1011 RestoreStack(); | |
1012 __ move(A0, V0); | |
1013 __ andi(A1, A0, Immediate(Failure::kTagMask | Failure::kTypeMask)); | |
1014 __ li(T0, Immediate(Failure::kTag)); | |
1015 __ B(EQ, A1, T0, &gc_); | |
1016 StoreLocal(A0, 0); | |
1017 Dispatch(kAllocateBoxedLength); | |
848 } | 1018 } |
849 | 1019 |
850 void InterpreterGeneratorMIPS::DoNegate() { | 1020 void InterpreterGeneratorMIPS::DoNegate() { |
851 } | 1021 } |
852 | 1022 |
853 void InterpreterGeneratorMIPS::DoStackOverflowCheck() { | 1023 void InterpreterGeneratorMIPS::DoStackOverflowCheck() { |
854 } | 1024 } |
855 | 1025 |
856 void InterpreterGeneratorMIPS::DoThrowAfterSaveState(Label* resume) { | 1026 void InterpreterGeneratorMIPS::DoThrowAfterSaveState(Label* resume) { |
857 // Use the stack to store the stack delta initialized to zero, and the | 1027 // Use the stack to store the stack delta initialized to zero, and the |
(...skipping 29 matching lines...) Expand all Loading... | |
887 ShiftAdd(S2, S2, A3, TIMES_WORD_SIZE); | 1057 ShiftAdd(S2, S2, A3, TIMES_WORD_SIZE); |
888 | 1058 |
889 StoreLocal(S3, 0); | 1059 StoreLocal(S3, 0); |
890 Dispatch(0); | 1060 Dispatch(0); |
891 } | 1061 } |
892 | 1062 |
893 void InterpreterGeneratorMIPS::DoThrow() { | 1063 void InterpreterGeneratorMIPS::DoThrow() { |
894 } | 1064 } |
895 | 1065 |
896 void InterpreterGeneratorMIPS::DoSubroutineCall() { | 1066 void InterpreterGeneratorMIPS::DoSubroutineCall() { |
1067 __ lw(A0, Address(S1, 1)); | |
1068 __ lw(A1, Address(S1, 5)); | |
1069 | |
1070 // Push the return delta as a tagged smi. | |
1071 ASSERT(Smi::kTag == 0); | |
1072 __ sll(A1, A1, Immediate(Smi::kTagSize)); | |
1073 Push(A1); | |
1074 | |
1075 __ addu(S1, S1, A0); | |
1076 Dispatch(0); | |
897 } | 1077 } |
898 | 1078 |
899 void InterpreterGeneratorMIPS::DoSubroutineReturn() { | 1079 void InterpreterGeneratorMIPS::DoSubroutineReturn() { |
1080 Pop(A0); | |
1081 __ srl(A0, A0, Immediate(Smi::kTagSize)); | |
1082 __ subu(S1, S1, A0); | |
1083 Dispatch(0); | |
900 } | 1084 } |
901 | 1085 |
902 void InterpreterGeneratorMIPS::DoProcessYield() { | 1086 void InterpreterGeneratorMIPS::DoProcessYield() { |
903 LoadLocal(A0, 0); | 1087 LoadLocal(A0, 0); |
904 __ sra(V0, A0, Immediate(1)); | 1088 __ sra(V0, A0, Immediate(1)); |
905 __ addiu(S1, S1, Immediate(kProcessYieldLength)); | 1089 __ addiu(S1, S1, Immediate(kProcessYieldLength)); |
906 StoreLocal(S4, 0); | 1090 StoreLocal(S4, 0); |
907 __ B(&done_); | 1091 __ B(&done_); |
908 } | 1092 } |
909 | 1093 |
(...skipping 18 matching lines...) Expand all Loading... | |
928 DropNAndSetTop(1, S3); | 1112 DropNAndSetTop(1, S3); |
929 Dispatch(kCoroutineChangeLength); | 1113 Dispatch(kCoroutineChangeLength); |
930 } | 1114 } |
931 | 1115 |
932 void InterpreterGeneratorMIPS::DoIdentical() { | 1116 void InterpreterGeneratorMIPS::DoIdentical() { |
933 } | 1117 } |
934 | 1118 |
935 void InterpreterGeneratorMIPS::DoIdenticalNonNumeric() { | 1119 void InterpreterGeneratorMIPS::DoIdenticalNonNumeric() { |
936 LoadLocal(A0, 0); | 1120 LoadLocal(A0, 0); |
937 LoadLocal(A1, 1); | 1121 LoadLocal(A1, 1); |
938 __ subu(T0, A0, A1); | 1122 ToBoolean(A0, A1, EQ, A2); |
939 ConditionalStore(T0, S6, S7, Address(S2, kWordSize)); | 1123 StoreLocal(A2, 1); |
1124 | |
940 Drop(1); | 1125 Drop(1); |
941 Dispatch(kIdenticalNonNumericLength); | 1126 Dispatch(kIdenticalNonNumericLength); |
942 } | 1127 } |
943 | 1128 |
944 void InterpreterGeneratorMIPS::DoEnterNoSuchMethod() { | 1129 void InterpreterGeneratorMIPS::DoEnterNoSuchMethod() { |
945 } | 1130 } |
946 | 1131 |
947 void InterpreterGeneratorMIPS::DoExitNoSuchMethod() { | 1132 void InterpreterGeneratorMIPS::DoExitNoSuchMethod() { |
948 } | 1133 } |
949 | 1134 |
950 void InterpreterGeneratorMIPS::DoMethodEnd() { | 1135 void InterpreterGeneratorMIPS::DoMethodEnd() { |
951 } | 1136 } |
952 | 1137 |
953 void InterpreterGeneratorMIPS::DoIntrinsicObjectEquals() { | 1138 void InterpreterGeneratorMIPS::DoIntrinsicObjectEquals() { |
954 } | 1139 } |
955 | 1140 |
956 void InterpreterGeneratorMIPS::DoIntrinsicGetField() { | 1141 void InterpreterGeneratorMIPS::DoIntrinsicGetField() { |
957 __ lbu(A1, Address(A0, 2 + Function::kSize - HeapObject::kTag)); | 1142 __ lbu(A1, Address(A0, 2 + Function::kSize - HeapObject::kTag)); |
958 LoadLocal(A0, 0); | 1143 LoadLocal(A0, 0); |
959 __ addiu(A0, A0, Immediate(Instance::kSize - HeapObject::kTag)); | 1144 __ addiu(A0, A0, Immediate(Instance::kSize - HeapObject::kTag)); |
960 ShiftAddLoad(A0, A0, A1, TIMES_WORD_SIZE); | 1145 ShiftAddLoad(A0, A0, A1, TIMES_WORD_SIZE); |
961 | 1146 |
962 __ Jr(RA); | 1147 __ Jr(RA); |
963 } | 1148 } |
964 | 1149 |
965 void InterpreterGeneratorMIPS::DoIntrinsicSetField() { | 1150 void InterpreterGeneratorMIPS::DoIntrinsicSetField() { |
1151 __ lbu(A1, Address(A0, 3 + Function::kSize - HeapObject::kTag)); | |
1152 LoadLocal(S3, 0); | |
1153 LoadLocal(A2, 1); | |
1154 __ addiu(A3, A2, Immediate(Instance::kSize - HeapObject::kTag)); | |
1155 ShiftAddStore(S3, A3, A1, TIMES_WORD_SIZE); | |
1156 | |
1157 // S3 is not trashed. | |
1158 AddToRememberedSet(A2, S3, A3); | |
1159 | |
1160 __ move(T9, RA); | |
1161 __ jr(T9); | |
1162 __ move(A0, S3); // Delay-slot. | |
966 } | 1163 } |
967 | 1164 |
968 void InterpreterGeneratorMIPS::DoIntrinsicListIndexGet() { | 1165 void InterpreterGeneratorMIPS::DoIntrinsicListIndexGet() { |
969 } | 1166 } |
970 | 1167 |
971 void InterpreterGeneratorMIPS::DoIntrinsicListIndexSet() { | 1168 void InterpreterGeneratorMIPS::DoIntrinsicListIndexSet() { |
972 } | 1169 } |
973 | 1170 |
974 void InterpreterGeneratorMIPS::DoIntrinsicListLength() { | 1171 void InterpreterGeneratorMIPS::DoIntrinsicListLength() { |
975 } | 1172 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1048 void InterpreterGeneratorMIPS::ReadFrameDescriptor(Register scratch) { | 1245 void InterpreterGeneratorMIPS::ReadFrameDescriptor(Register scratch) { |
1049 } | 1246 } |
1050 | 1247 |
1051 void InterpreterGeneratorMIPS::InvokeMethodUnfold(bool test) { | 1248 void InterpreterGeneratorMIPS::InvokeMethodUnfold(bool test) { |
1052 } | 1249 } |
1053 | 1250 |
1054 void InterpreterGeneratorMIPS::InvokeMethod(bool test) { | 1251 void InterpreterGeneratorMIPS::InvokeMethod(bool test) { |
1055 // Get the selector from the bytecodes. | 1252 // Get the selector from the bytecodes. |
1056 __ lw(S3, Address(S1, 1)); | 1253 __ lw(S3, Address(S1, 1)); |
1057 | 1254 |
1058 // Fetch the virtual table from the program. | 1255 // Fetch the virtual table from the program. |
erikcorry
2016/06/27 15:51:08
Comment is out of date.
petarj
2016/06/29 02:09:15
Removed.
| |
1059 __ lw(A1, Address(S0, Process::kProgramOffset)); | 1256 __ lw(A1, Address(S6, Program::kDispatchTableOffset)); |
1060 __ lw(A1, Address(A1, Program::kDispatchTableOffset)); | |
1061 | 1257 |
1062 if (!test) { | 1258 if (!test) { |
1063 // Compute the arity from the selector. | 1259 // Compute the arity from the selector. |
1064 ASSERT(Selector::ArityField::shift() == 0); | 1260 ASSERT(Selector::ArityField::shift() == 0); |
1065 __ andi(A2, S3, Immediate(Selector::ArityField::mask())); | 1261 __ andi(A2, S3, Immediate(Selector::ArityField::mask())); |
1066 } | 1262 } |
1067 | 1263 |
1068 // Compute the selector offset (smi tagged) from the selector. | 1264 // Compute the selector offset (smi tagged) from the selector. |
1069 __ li(S5, Immediate(Selector::IdField::mask())); | 1265 __ li(S5, Immediate(Selector::IdField::mask())); |
1070 __ and_(S3, S3, S5); | 1266 __ and_(S3, S3, S5); |
1071 __ srl(S3, S3, Immediate(Selector::IdField::shift() - Smi::kTagSize)); | 1267 __ srl(S3, S3, Immediate(Selector::IdField::shift() - Smi::kTagSize)); |
1072 | 1268 |
1073 // Get the receiver from the stack. | 1269 // Get the receiver from the stack. |
1074 if (test) { | 1270 if (test) { |
1075 LoadLocal(A2, 0); | 1271 LoadLocal(A2, 0); |
1076 } else { | 1272 } else { |
1077 ShiftAddLoad(A2, S2, A2, TIMES_WORD_SIZE); | 1273 ShiftAddLoad(A2, S2, A2, TIMES_WORD_SIZE); |
1078 } | 1274 } |
1275 | |
1079 // Compute the receiver class. | 1276 // Compute the receiver class. |
1080 Label smi, dispatch; | 1277 Label smi, dispatch; |
1081 ASSERT(Smi::kTag == 0); | 1278 ASSERT(Smi::kTag == 0); |
1082 __ andi(T0, A2, Immediate(Smi::kTagMask)); | 1279 __ andi(T0, A2, Immediate(Smi::kTagMask)); |
1083 __ B(EQ, T0, ZR, &smi); | 1280 __ B(EQ, T0, ZR, &smi); |
1084 __ lw(A2, Address(A2, HeapObject::kClassOffset - HeapObject::kTag)); | 1281 __ lw(A2, Address(A2, HeapObject::kClassOffset - HeapObject::kTag)); |
1085 | 1282 |
1086 // Compute entry index: class id + selector offset. | 1283 // Compute entry index: class id + selector offset. |
1087 int id_offset = Class::kIdOrTransformationTargetOffset - HeapObject::kTag; | 1284 int id_offset = Class::kIdOrTransformationTargetOffset - HeapObject::kTag; |
1088 __ Bind(&dispatch); | 1285 __ Bind(&dispatch); |
1089 __ lw(A2, Address(A2, id_offset)); | 1286 __ lw(A2, Address(A2, id_offset)); |
1090 __ addu(A2, A2, S3); | 1287 __ addu(A2, A2, S3); |
1091 | 1288 |
1092 // Fetch the entry from the table. Because the index is smi tagged | 1289 // Fetch the entry from the table. Because the index is smi tagged |
1093 // we only multiply by two -- not four -- when indexing. | 1290 // we only multiply by two -- not four -- when indexing. |
1094 ASSERT(Smi::kTagSize == 1); | 1291 ASSERT(Smi::kTagSize == 1); |
1095 __ addiu(A1, A1, Immediate(Array::kSize - HeapObject::kTag)); | 1292 __ addiu(A1, A1, Immediate(Array::kSize - HeapObject::kTag)); |
1096 ShiftAddLoad(A1, A1, A2, TIMES_2); | 1293 ShiftAddLoad(A1, A1, A2, TIMES_2); |
1097 | 1294 |
1098 // Validate that the offset stored in the entry matches the offset | 1295 // Validate that the offset stored in the entry matches the offset |
1099 // we used to find it. | 1296 // we used to find it. |
1100 Label invalid; | 1297 Label invalid; |
1101 __ lw(A3, Address(A1, DispatchTableEntry::kOffsetOffset - HeapObject::kTag)); | 1298 __ lw(A3, Address(A1, DispatchTableEntry::kOffsetOffset - HeapObject::kTag)); |
1102 __ B(NEQ, S3, A3, &invalid); | 1299 __ B(NEQ, S3, A3, &invalid); |
1103 | 1300 |
1104 // Load the target and the intrinsic from the entry. | 1301 // Load the target and the intrinsic from the entry. |
1105 Label validated, intrinsified; | 1302 Label validated, intrinsified; |
1106 if (test) { | 1303 if (test) { |
1107 // Valid entry: The answer is true. | 1304 // Valid entry: The answer is true. |
1108 StoreLocal(S6, 0); | 1305 LoadTrue(A2); |
1306 StoreLocal(A2, 0); | |
1109 Dispatch(kInvokeTestLength); | 1307 Dispatch(kInvokeTestLength); |
1110 } else { | 1308 } else { |
1111 __ Bind(&validated); | 1309 __ Bind(&validated); |
1112 | 1310 |
1113 __ lw(A0, Address(A1, | 1311 __ lw(A0, Address(A1, |
1114 DispatchTableEntry::kTargetOffset - HeapObject::kTag)); | 1312 DispatchTableEntry::kTargetOffset - HeapObject::kTag)); |
1115 | 1313 |
1116 SaveByteCodePointer(A2); | 1314 SaveByteCodePointer(A2); |
1117 __ lw(A1, Address(A1, DispatchTableEntry::kCodeOffset - HeapObject::kTag)); | 1315 __ lw(A1, Address(A1, DispatchTableEntry::kCodeOffset - HeapObject::kTag)); |
1118 __ move(T9, A1); | 1316 __ move(T9, A1); |
1119 __ Jalr(T9); | 1317 __ Jalr(T9); |
1120 RestoreByteCodePointer(A2); | 1318 RestoreByteCodePointer(A2); |
1121 | 1319 |
1122 __ lw(S3, Address(S1, 1)); | 1320 __ lw(S3, Address(S1, 1)); |
1123 // Compute the arity from the selector. | 1321 // Compute the arity from the selector. |
1124 ASSERT(Selector::ArityField::shift() == 0); | 1322 ASSERT(Selector::ArityField::shift() == 0); |
1125 __ andi(A2, S3, Immediate(Selector::ArityField::mask())); | 1323 __ andi(A2, S3, Immediate(Selector::ArityField::mask())); |
1126 | 1324 |
1127 Drop(A2); | 1325 Drop(A2); |
1128 | 1326 |
1129 StoreLocal(A0, 0); | 1327 StoreLocal(A0, 0); |
1130 Dispatch(kInvokeMethodLength); | 1328 Dispatch(kInvokeMethodLength); |
1131 } | 1329 } |
1132 | 1330 |
1133 __ Bind(&smi); | 1331 __ Bind(&smi); |
1134 __ lw(A2, Address(S0, Process::kProgramOffset)); | |
1135 __ b(&dispatch); | 1332 __ b(&dispatch); |
1136 __ lw(A2, Address(A2, Program::kSmiClassOffset)); // Delay-slot. | 1333 __ lw(A2, Address(S6, Program::kSmiClassOffset)); // Delay-slot. |
1137 | 1334 |
1138 if (test) { | 1335 if (test) { |
1139 // Invalid entry: The answer is false. | 1336 // Invalid entry: The answer is false. |
1140 __ Bind(&invalid); | 1337 __ Bind(&invalid); |
1141 StoreLocal(S7, 0); | 1338 LoadFalse(A2); |
1339 StoreLocal(A2, 0); | |
1142 Dispatch(kInvokeTestLength); | 1340 Dispatch(kInvokeTestLength); |
1143 } else { | 1341 } else { |
1144 __ Bind(&intrinsified); | 1342 __ Bind(&intrinsified); |
1145 __ move(T9, A2); | 1343 __ move(T9, A2); |
1146 __ Jr(T9); | 1344 __ Jr(T9); |
1147 | 1345 |
1148 // Invalid entry: Use the noSuchMethod entry from entry zero of | 1346 // Invalid entry: Use the noSuchMethod entry from entry zero of |
1149 // the virtual table. | 1347 // the virtual table. |
1150 __ Bind(&invalid); | 1348 __ Bind(&invalid); |
1151 __ lw(A1, Address(S0, Process::kProgramOffset)); | 1349 __ lw(A1, Address(S6, Program::kDispatchTableOffset)); |
1152 __ lw(A1, Address(A1, Program::kDispatchTableOffset)); | |
1153 __ b(&validated); | 1350 __ b(&validated); |
1154 __ lw(A1, Address(A1, Array::kSize - HeapObject::kTag)); // Delay-slot. | 1351 __ lw(A1, Address(A1, Array::kSize - HeapObject::kTag)); // Delay-slot. |
1155 } | 1352 } |
1156 } | 1353 } |
1157 | 1354 |
1158 void InterpreterGeneratorMIPS::InvokeNative(bool yield, bool safepoint) { | 1355 void InterpreterGeneratorMIPS::InvokeNative(bool yield, bool safepoint) { |
1159 __ lbu(A1, Address(S1, 1)); | 1356 __ lbu(A1, Address(S1, 1)); |
1160 // Also skip two empty slots. | 1357 // Also skip two empty slots. |
1161 __ addiu(A1, A1, Immediate(2)); | 1358 __ addiu(A1, A1, Immediate(2)); |
1162 __ lbu(A0, Address(S1, 2)); | 1359 __ lbu(A0, Address(S1, 2)); |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1391 | 1588 |
1392 void InterpreterGeneratorMIPS::InvokeCompare(const char* fallback, | 1589 void InterpreterGeneratorMIPS::InvokeCompare(const char* fallback, |
1393 Condition cond) { | 1590 Condition cond) { |
1394 LoadLocal(A0, 0); | 1591 LoadLocal(A0, 0); |
1395 __ andi(T0, A0, Immediate(Smi::kTagMask)); | 1592 __ andi(T0, A0, Immediate(Smi::kTagMask)); |
1396 __ B(NEQ, T0, ZR, fallback); | 1593 __ B(NEQ, T0, ZR, fallback); |
1397 LoadLocal(A1, 1); | 1594 LoadLocal(A1, 1); |
1398 __ andi(T0, A1, Immediate(Smi::kTagMask)); | 1595 __ andi(T0, A1, Immediate(Smi::kTagMask)); |
1399 __ B(NEQ, T0, ZR, fallback); | 1596 __ B(NEQ, T0, ZR, fallback); |
1400 | 1597 |
1401 Label true_case; | 1598 ToBoolean(A1, A0, cond, A2); |
1402 __ B(cond, A1, A0, &true_case); | 1599 DropNAndSetTop(1, A2); |
1403 | |
1404 DropNAndSetTop(1, S7); | |
1405 Dispatch(5); | 1600 Dispatch(5); |
1406 | 1601 |
1407 __ Bind(&true_case); | |
1408 DropNAndSetTop(1, S6); | 1602 DropNAndSetTop(1, S6); |
1409 Dispatch(5); | 1603 Dispatch(5); |
1410 } | 1604 } |
1411 | 1605 |
1412 void InterpreterGeneratorMIPS::ConditionalStore(Register cmp, | 1606 void InterpreterGeneratorMIPS::AddIf(Register reg1, Register reg2, |
1413 Register reg_if_eq, | 1607 Condition cond, Register dest, |
1414 Register reg_if_ne, | 1608 int add_if_eq) { |
1415 const Address& address) { | 1609 Label done, add; |
1416 Label if_ne, done; | 1610 __ B(cond, reg1, reg2, &add); |
erikcorry
2016/06/27 15:51:08
Optimization idea for a later CL: If the condition
petarj
2016/06/29 02:09:15
Thanks, will use in one of the later CLs.
| |
1417 __ B(NEQ, cmp, ZR, &if_ne); | 1611 __ B(&done); |
1418 __ b(&done); | 1612 __ Bind(&add); |
1419 __ sw(reg_if_eq, address); // Delay-slot. | 1613 __ addiu(dest, dest, Immediate(add_if_eq)); |
1420 __ Bind(&if_ne); | |
1421 __ sw(reg_if_ne, address); | |
1422 __ Bind(&done); | 1614 __ Bind(&done); |
1423 } | 1615 } |
1424 | 1616 |
1617 void InterpreterGeneratorMIPS::LoadTrue(Register reg) { | |
1618 __ addiu(reg, S4, Immediate(kTrueOffset)); | |
1619 } | |
1620 | |
1621 void InterpreterGeneratorMIPS::LoadFalse(Register reg) { | |
1622 __ addiu(reg, S4, Immediate(kFalseOffset)); | |
1623 } | |
1624 | |
1625 void InterpreterGeneratorMIPS::ToBoolean(Register reg1, | |
1626 Register reg2, | |
1627 Condition cond, | |
1628 Register reg) { | |
1629 LoadFalse(reg); | |
1630 AddIf(reg1, reg2, cond, reg, kTrueOffset - kFalseOffset); | |
1631 } | |
1632 | |
1425 void InterpreterGeneratorMIPS::CheckStackOverflow(int size) { | 1633 void InterpreterGeneratorMIPS::CheckStackOverflow(int size) { |
1426 __ lw(A1, Address(S0, Process::kStackLimitOffset)); | 1634 __ lw(A1, Address(S0, Process::kStackLimitOffset)); |
1427 __ sltu(T0, A1, S2); | 1635 __ sltu(T0, A1, S2); |
1428 if (size == 0) { | 1636 if (size == 0) { |
1429 __ B(EQ, T0, ZR, &check_stack_overflow_0_); | 1637 __ B(EQ, T0, ZR, &check_stack_overflow_0_); |
1430 } else { | 1638 } else { |
1431 Label done; | 1639 Label done; |
1432 __ B(GT, T0, ZR, &done); | 1640 __ B(GT, T0, ZR, &done); |
1433 __ b(&check_stack_overflow_); | 1641 __ b(&check_stack_overflow_); |
1434 __ ori(A0, ZR, Immediate(size)); // Delay-slot. | 1642 __ ori(A0, ZR, Immediate(size)); // Delay-slot. |
1435 __ Bind(&done); | 1643 __ Bind(&done); |
1436 } | 1644 } |
1437 } | 1645 } |
1438 | 1646 |
1439 void InterpreterGeneratorMIPS::Dispatch(int size) { | 1647 void InterpreterGeneratorMIPS::Dispatch(int size) { |
1440 __ lbu(S3, Address(S1, size)); | 1648 __ lbu(S3, Address(S1, size)); |
1441 if (size > 0) { | 1649 if (size > 0) { |
1442 __ addiu(S1, S1, Immediate(size)); | 1650 __ addiu(S1, S1, Immediate(size)); |
1443 } | 1651 } |
1444 __ la(S5, "Interpret_DispatchTable"); | 1652 ShiftAddJump(S7, S3, TIMES_WORD_SIZE); |
1445 ShiftAddJump(S5, S3, TIMES_WORD_SIZE); | |
1446 } | 1653 } |
1447 | 1654 |
1448 void InterpreterGeneratorMIPS::SaveState(Label* resume) { | 1655 void InterpreterGeneratorMIPS::SaveState(Label* resume) { |
1449 // Save the bytecode pointer at the return-address slot. | 1656 // Save the bytecode pointer at the return-address slot. |
1450 LoadFramePointer(A3); | 1657 LoadFramePointer(A3); |
1451 __ sw(S1, Address(A3, -kWordSize)); | 1658 __ sw(S1, Address(A3, -kWordSize)); |
1452 | 1659 |
1453 // Push resume address. | 1660 // Push resume address. |
1454 __ la(S1, resume); | 1661 __ la(S1, resume); |
1455 | 1662 |
(...skipping 14 matching lines...) Expand all Loading... | |
1470 void InterpreterGeneratorMIPS::RestoreState() { | 1677 void InterpreterGeneratorMIPS::RestoreState() { |
1471 // Load the current stack pointer into S2. | 1678 // Load the current stack pointer into S2. |
1472 __ lw(S2, Address(S0, Process::kCoroutineOffset)); | 1679 __ lw(S2, Address(S0, Process::kCoroutineOffset)); |
1473 __ lw(S2, Address(S2, Coroutine::kStackOffset - HeapObject::kTag)); | 1680 __ lw(S2, Address(S2, Coroutine::kStackOffset - HeapObject::kTag)); |
1474 __ lw(S1, Address(S2, Stack::kTopOffset - HeapObject::kTag)); | 1681 __ lw(S1, Address(S2, Stack::kTopOffset - HeapObject::kTag)); |
1475 __ addiu(S2, S2, Immediate(Stack::kSize - HeapObject::kTag)); | 1682 __ addiu(S2, S2, Immediate(Stack::kSize - HeapObject::kTag)); |
1476 ShiftAdd(S2, S2, S1, TIMES_2); | 1683 ShiftAdd(S2, S2, S1, TIMES_2); |
1477 | 1684 |
1478 // Load constants into registers. | 1685 // Load constants into registers. |
1479 __ lw(S6, Address(S0, Process::kProgramOffset)); | 1686 __ lw(S6, Address(S0, Process::kProgramOffset)); |
1480 __ lw(S7, Address(S6, Program::kFalseObjectOffset)); | |
1481 __ lw(S4, Address(S6, Program::kNullObjectOffset)); | 1687 __ lw(S4, Address(S6, Program::kNullObjectOffset)); |
1482 __ lw(S6, Address(S6, Program::kTrueObjectOffset)); | 1688 __ la(S7, "Interpret_DispatchTable"); |
1483 | 1689 |
1484 // Pop and store frame pointer. | 1690 // Pop and store frame pointer. |
1485 Pop(S1); | 1691 Pop(S1); |
1486 StoreFramePointer(S1); | 1692 StoreFramePointer(S1); |
1487 // Set the bytecode pointer from the stack. | 1693 // Set the bytecode pointer from the stack. |
1488 __ lw(S1, Address(S1, -kWordSize)); | 1694 __ lw(S1, Address(S1, -kWordSize)); |
1489 | 1695 |
1490 // Pop and branch to resume address. | 1696 // Pop and branch to resume address. |
1491 Pop(RA); | 1697 Pop(RA); |
1492 | 1698 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1576 __ addiu(SP, SP, Immediate(-6 * kWordSize)); | 1782 __ addiu(SP, SP, Immediate(-6 * kWordSize)); |
1577 __ sw(GP, Address(SP, 5 * kWordSize)); | 1783 __ sw(GP, Address(SP, 5 * kWordSize)); |
1578 } | 1784 } |
1579 | 1785 |
1580 void InterpreterGeneratorMIPS::RestoreStack() { | 1786 void InterpreterGeneratorMIPS::RestoreStack() { |
1581 __ lw(GP, Address(SP, 5 * kWordSize)); | 1787 __ lw(GP, Address(SP, 5 * kWordSize)); |
1582 __ addiu(SP, SP, Immediate(6 * kWordSize)); | 1788 __ addiu(SP, SP, Immediate(6 * kWordSize)); |
1583 } | 1789 } |
1584 } // namespace dartino | 1790 } // namespace dartino |
1585 #endif // defined DARTINO_TARGET_MIPS | 1791 #endif // defined DARTINO_TARGET_MIPS |
OLD | NEW |