Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: runtime/vm/flow_graph_compiler_mips.cc

Issue 14733002: On MIPS, uses more branch delay slots. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart 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 file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS.
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 Label* is_instance_lbl, 86 Label* is_instance_lbl,
87 Label* is_not_instance_lbl) { 87 Label* is_not_instance_lbl) {
88 __ TraceSimMsg("CallSubtypeTestStub"); 88 __ TraceSimMsg("CallSubtypeTestStub");
89 ASSERT(instance_reg == A0); 89 ASSERT(instance_reg == A0);
90 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. 90 ASSERT(temp_reg == kNoRegister); // Unused on MIPS.
91 const SubtypeTestCache& type_test_cache = 91 const SubtypeTestCache& type_test_cache =
92 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 92 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
93 __ LoadObject(A2, type_test_cache); 93 __ LoadObject(A2, type_test_cache);
94 if (test_kind == kTestTypeOneArg) { 94 if (test_kind == kTestTypeOneArg) {
95 ASSERT(type_arguments_reg == kNoRegister); 95 ASSERT(type_arguments_reg == kNoRegister);
96 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null())); 96 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
97 uint16_t null_lo = Utils::Low16Bits(null);
98 uint16_t null_hi = Utils::High16Bits(null);
99 __ lui(A1, Immediate(null_hi));
97 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); 100 __ BranchLink(&StubCode::Subtype1TestCacheLabel());
101 __ delay_slot()->ori(A1, A1, Immediate(null_lo));
98 } else if (test_kind == kTestTypeTwoArgs) { 102 } else if (test_kind == kTestTypeTwoArgs) {
99 ASSERT(type_arguments_reg == kNoRegister); 103 ASSERT(type_arguments_reg == kNoRegister);
100 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::null())); 104 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
105 uint16_t null_lo = Utils::Low16Bits(null);
106 uint16_t null_hi = Utils::High16Bits(null);
107 __ lui(A1, Immediate(null_hi));
101 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); 108 __ BranchLink(&StubCode::Subtype2TestCacheLabel());
109 __ delay_slot()->ori(A1, A1, Immediate(null_lo));
102 } else if (test_kind == kTestTypeThreeArgs) { 110 } else if (test_kind == kTestTypeThreeArgs) {
103 ASSERT(type_arguments_reg == A1); 111 ASSERT(type_arguments_reg == A1);
104 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); 112 __ BranchLink(&StubCode::Subtype3TestCacheLabel());
105 } else { 113 } else {
106 UNREACHABLE(); 114 UNREACHABLE();
107 } 115 }
108 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. 116 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False.
109 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); 117 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl);
110 return type_test_cache.raw(); 118 return type_test_cache.raw();
111 } 119 }
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 __ TraceSimMsg("AssertAssignable"); 470 __ TraceSimMsg("AssertAssignable");
463 ASSERT(token_pos >= 0); 471 ASSERT(token_pos >= 0);
464 ASSERT(!dst_type.IsNull()); 472 ASSERT(!dst_type.IsNull());
465 ASSERT(dst_type.IsFinalized()); 473 ASSERT(dst_type.IsFinalized());
466 // Assignable check is skipped in FlowGraphBuilder, not here. 474 // Assignable check is skipped in FlowGraphBuilder, not here.
467 ASSERT(dst_type.IsMalformed() || 475 ASSERT(dst_type.IsMalformed() ||
468 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 476 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
469 // Preserve instantiator and its type arguments. 477 // Preserve instantiator and its type arguments.
470 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 478 __ addiu(SP, SP, Immediate(-2 * kWordSize));
471 __ sw(A2, Address(SP, 1 * kWordSize)); 479 __ sw(A2, Address(SP, 1 * kWordSize));
472 __ sw(A1, Address(SP, 0 * kWordSize)); 480
473 // A null object is always assignable and is returned as result. 481 // A null object is always assignable and is returned as result.
474 Label is_assignable, runtime_call; 482 Label is_assignable, runtime_call;
475 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable); 483 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable);
484 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
476 485
477 if (!FLAG_eliminate_type_checks) { 486 if (!FLAG_eliminate_type_checks) {
478 // If type checks are not eliminated during the graph building then 487 // If type checks are not eliminated during the graph building then
479 // a transition sentinel can be seen here. 488 // a transition sentinel can be seen here.
480 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable); 489 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable);
481 } 490 }
482 491
483 // Generate throw new TypeError() if the type is malformed. 492 // Generate throw new TypeError() if the type is malformed.
484 if (dst_type.IsMalformed()) { 493 if (dst_type.IsMalformed()) {
485 const Error& error = Error::Handle(dst_type.malformed_error()); 494 const Error& error = Error::Handle(dst_type.malformed_error());
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 __ subu(T1, T1, T2); 628 __ subu(T1, T1, T2);
620 __ sll(T1, T1, 1); 629 __ sll(T1, T1, 1);
621 __ addu(T1, FP, T1); 630 __ addu(T1, FP, T1);
622 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize); 631 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize);
623 632
624 // Let T0 point to the last copied positional argument, i.e. to 633 // Let T0 point to the last copied positional argument, i.e. to
625 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. 634 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
626 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize); 635 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
627 __ sll(T2, T2, 1); // T2 is a Smi. 636 __ sll(T2, T2, 1); // T2 is a Smi.
628 637
629 Label loop, loop_condition; 638 Label loop, loop_exit;
630 __ b(&loop_condition); 639 __ blez(T2, &loop_exit);
631 __ delay_slot()->subu(T0, T0, T2); 640 __ delay_slot()->subu(T0, T0, T2);
632 // We do not use the final allocation index of the variable here, i.e.
633 // scope->VariableAt(i)->index(), because captured variables still need
634 // to be copied to the context that is not yet allocated.
635 __ Bind(&loop); 641 __ Bind(&loop);
636 __ addu(T4, T1, T2); 642 __ addu(T4, T1, T2);
643 __ lw(T3, Address(T4, -kWordSize));
644 __ addiu(T2, T2, Immediate(-kWordSize));
637 __ addu(T5, T0, T2); 645 __ addu(T5, T0, T2);
638 __ lw(T3, Address(T4)); 646 __ bgtz(T2, &loop);
639 __ sw(T3, Address(T5)); 647 __ delay_slot()->sw(T3, Address(T5));
640 __ Bind(&loop_condition); 648 __ Bind(&loop_exit);
641 __ addiu(T2, T2, Immediate(-kWordSize));
642 __ bgez(T2, &loop);
643 649
644 // Copy or initialize optional named arguments. 650 // Copy or initialize optional named arguments.
645 Label all_arguments_processed; 651 Label all_arguments_processed;
646 if (num_opt_named_params > 0) { 652 if (num_opt_named_params > 0) {
647 // Start by alphabetically sorting the names of the optional parameters. 653 // Start by alphabetically sorting the names of the optional parameters.
648 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; 654 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
649 int* opt_param_position = new int[num_opt_named_params]; 655 int* opt_param_position = new int[num_opt_named_params];
650 for (int pos = num_fixed_params; pos < num_params; pos++) { 656 for (int pos = num_fixed_params; pos < num_params; pos++) {
651 LocalVariable* parameter = scope->VariableAt(pos); 657 LocalVariable* parameter = scope->VariableAt(pos);
652 const String& opt_param_name = parameter->name(); 658 const String& opt_param_name = parameter->name();
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 __ LeaveDartFrame(); 789 __ LeaveDartFrame();
784 __ Ret(); 790 __ Ret();
785 791
786 __ Bind(&all_arguments_processed); 792 __ Bind(&all_arguments_processed);
787 // Nullify originally passed arguments only after they have been copied and 793 // Nullify originally passed arguments only after they have been copied and
788 // checked, otherwise noSuchMethod would not see their original values. 794 // checked, otherwise noSuchMethod would not see their original values.
789 // This step can be skipped in case we decide that formal parameters are 795 // This step can be skipped in case we decide that formal parameters are
790 // implicitly final, since garbage collecting the unmodified value is not 796 // implicitly final, since garbage collecting the unmodified value is not
791 // an issue anymore. 797 // an issue anymore.
792 798
799 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
800
793 // S4 : arguments descriptor array. 801 // S4 : arguments descriptor array.
794 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 802 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
795 __ sll(T2, T2, 1); // T2 is a Smi. 803 __ sll(T2, T2, 1); // T2 is a Smi.
796 804
797 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null())); 805 Label null_args_loop, null_args_loop_exit;
798 Label null_args_loop, null_args_loop_condition; 806 __ blez(T2, &null_args_loop_exit);
799
800 __ b(&null_args_loop_condition);
801 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize)); 807 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize));
802
803 __ Bind(&null_args_loop); 808 __ Bind(&null_args_loop);
809 __ addiu(T2, T2, Immediate(-kWordSize));
804 __ addu(T3, T1, T2); 810 __ addu(T3, T1, T2);
805 __ sw(T0, Address(T3)); 811 __ bgtz(T2, &null_args_loop);
806 812 __ delay_slot()->sw(T0, Address(T3));
807 __ Bind(&null_args_loop_condition); 813 __ Bind(&null_args_loop_exit);
808 __ addiu(T2, T2, Immediate(-kWordSize));
809 __ bgez(T2, &null_args_loop);
810 } 814 }
811 815
812 816
813 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 817 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
814 // RA: return address. 818 // RA: return address.
815 // SP: receiver. 819 // SP: receiver.
816 // Sequence node has one return node, its input is load field node. 820 // Sequence node has one return node, its input is load field node.
817 __ lw(V0, Address(SP, 0 * kWordSize)); 821 __ lw(V0, Address(SP, 0 * kWordSize));
818 __ lw(V0, Address(V0, offset - kHeapObjectTag)); 822 __ lw(V0, Address(V0, offset - kHeapObjectTag));
819 __ Ret(); 823 __ Ret();
820 } 824 }
821 825
822 826
823 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 827 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
824 // RA: return address. 828 // RA: return address.
825 // SP+1: receiver. 829 // SP+1: receiver.
826 // SP+0: value. 830 // SP+0: value.
827 // Sequence node has one store node and one return NULL node. 831 // Sequence node has one store node and one return NULL node.
828 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver. 832 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
829 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. 833 __ lw(T1, Address(SP, 0 * kWordSize)); // Value.
830 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); 834 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
831 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null())); 835 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
836 uint16_t null_lo = Utils::Low16Bits(null);
837 uint16_t null_hi = Utils::High16Bits(null);
838 __ lui(V0, Immediate(null_hi));
832 __ Ret(); 839 __ Ret();
840 __ delay_slot()->ori(V0, V0, Immediate(null_lo));
833 } 841 }
834 842
835 843
836 void FlowGraphCompiler::EmitFrameEntry() { 844 void FlowGraphCompiler::EmitFrameEntry() {
837 __ TraceSimMsg("FrameEntry"); 845 __ TraceSimMsg("FrameEntry");
838 const Function& function = parsed_function().function(); 846 const Function& function = parsed_function().function();
839 if (CanOptimizeFunction() && function.is_optimizable()) { 847 if (CanOptimizeFunction() && function.is_optimizable()) {
840 const bool can_optimize = !is_optimizing() || may_reoptimize(); 848 const bool can_optimize = !is_optimizing() || may_reoptimize();
841 const Register function_reg = T0; 849 const Register function_reg = T0;
842 if (can_optimize) { 850 if (can_optimize) {
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 1202
1195 1203
1196 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1204 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1197 const Object& obj, 1205 const Object& obj,
1198 bool needs_number_check) { 1206 bool needs_number_check) {
1199 if (needs_number_check && 1207 if (needs_number_check &&
1200 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) { 1208 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) {
1201 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1209 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1202 __ sw(reg, Address(SP, 1 * kWordSize)); 1210 __ sw(reg, Address(SP, 1 * kWordSize));
1203 __ LoadObject(TMP1, obj); 1211 __ LoadObject(TMP1, obj);
1204 __ sw(TMP1, Address(SP, 0 * kWordSize));
1205 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1212 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1213 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize));
1206 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. 1214 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'.
1207 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. 1215 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant.
1208 return; 1216 return;
1209 } 1217 }
1210 __ CompareObject(CMPRES, reg, obj); 1218 __ CompareObject(CMPRES, reg, obj);
1211 } 1219 }
1212 1220
1213 1221
1214 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1222 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1215 Register right, 1223 Register right,
1216 bool needs_number_check) { 1224 bool needs_number_check) {
1217 __ TraceSimMsg("EqualityRegRegCompare"); 1225 __ TraceSimMsg("EqualityRegRegCompare");
1218 if (needs_number_check) { 1226 if (needs_number_check) {
1219 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1227 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1220 __ sw(left, Address(SP, 1 * kWordSize)); 1228 __ sw(left, Address(SP, 1 * kWordSize));
1221 __ sw(right, Address(SP, 0 * kWordSize));
1222 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1229 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1230 __ delay_slot()->sw(right, Address(SP, 0 * kWordSize));
1223 __ TraceSimMsg("EqualityRegRegCompare return"); 1231 __ TraceSimMsg("EqualityRegRegCompare return");
1224 // Stub returns result in CMPRES. If it is 0, then left and right are equal. 1232 // Stub returns result in CMPRES. If it is 0, then left and right are equal.
1225 __ lw(right, Address(SP, 0 * kWordSize)); 1233 __ lw(right, Address(SP, 0 * kWordSize));
1226 __ lw(left, Address(SP, 1 * kWordSize)); 1234 __ lw(left, Address(SP, 1 * kWordSize));
1227 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1235 __ addiu(SP, SP, Immediate(2 * kWordSize));
1228 } else { 1236 } else {
1229 __ subu(CMPRES, left, right); 1237 __ subu(CMPRES, left, right);
1230 } 1238 }
1231 } 1239 }
1232 1240
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
1561 __ AddImmediate(SP, kDoubleSize); 1569 __ AddImmediate(SP, kDoubleSize);
1562 } 1570 }
1563 1571
1564 1572
1565 #undef __ 1573 #undef __
1566 1574
1567 1575
1568 } // namespace dart 1576 } // namespace dart
1569 1577
1570 #endif // defined TARGET_ARCH_MIPS 1578 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698