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

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
« no previous file with comments | « runtime/vm/assembler_mips.cc ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 Register type_arguments_reg, 84 Register type_arguments_reg,
85 Register temp_reg, 85 Register temp_reg,
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 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
95 uint16_t null_lo = Utils::Low16Bits(null);
96 uint16_t null_hi = Utils::High16Bits(null);
94 if (test_kind == kTestTypeOneArg) { 97 if (test_kind == kTestTypeOneArg) {
95 ASSERT(type_arguments_reg == kNoRegister); 98 ASSERT(type_arguments_reg == kNoRegister);
96 __ LoadImmediate(A1, reinterpret_cast<intptr_t>(Object::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 __ lui(A1, Immediate(null_hi));
101 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); 105 __ BranchLink(&StubCode::Subtype2TestCacheLabel());
106 __ delay_slot()->ori(A1, A1, Immediate(null_lo));
102 } else if (test_kind == kTestTypeThreeArgs) { 107 } else if (test_kind == kTestTypeThreeArgs) {
103 ASSERT(type_arguments_reg == A1); 108 ASSERT(type_arguments_reg == A1);
104 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); 109 __ BranchLink(&StubCode::Subtype3TestCacheLabel());
105 } else { 110 } else {
106 UNREACHABLE(); 111 UNREACHABLE();
107 } 112 }
108 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. 113 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False.
109 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); 114 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl);
110 return type_test_cache.raw(); 115 return type_test_cache.raw();
111 } 116 }
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 __ TraceSimMsg("AssertAssignable"); 467 __ TraceSimMsg("AssertAssignable");
463 ASSERT(token_pos >= 0); 468 ASSERT(token_pos >= 0);
464 ASSERT(!dst_type.IsNull()); 469 ASSERT(!dst_type.IsNull());
465 ASSERT(dst_type.IsFinalized()); 470 ASSERT(dst_type.IsFinalized());
466 // Assignable check is skipped in FlowGraphBuilder, not here. 471 // Assignable check is skipped in FlowGraphBuilder, not here.
467 ASSERT(dst_type.IsMalformed() || 472 ASSERT(dst_type.IsMalformed() ||
468 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 473 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
469 // Preserve instantiator and its type arguments. 474 // Preserve instantiator and its type arguments.
470 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 475 __ addiu(SP, SP, Immediate(-2 * kWordSize));
471 __ sw(A2, Address(SP, 1 * kWordSize)); 476 __ sw(A2, Address(SP, 1 * kWordSize));
472 __ sw(A1, Address(SP, 0 * kWordSize)); 477
473 // A null object is always assignable and is returned as result. 478 // A null object is always assignable and is returned as result.
474 Label is_assignable, runtime_call; 479 Label is_assignable, runtime_call;
475 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable); 480 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable);
481 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
476 482
477 if (!FLAG_eliminate_type_checks) { 483 if (!FLAG_eliminate_type_checks) {
478 // If type checks are not eliminated during the graph building then 484 // If type checks are not eliminated during the graph building then
479 // a transition sentinel can be seen here. 485 // a transition sentinel can be seen here.
480 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable); 486 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable);
481 } 487 }
482 488
483 // Generate throw new TypeError() if the type is malformed. 489 // Generate throw new TypeError() if the type is malformed.
484 if (dst_type.IsMalformed()) { 490 if (dst_type.IsMalformed()) {
485 const Error& error = Error::Handle(dst_type.malformed_error()); 491 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); 625 __ subu(T1, T1, T2);
620 __ sll(T1, T1, 1); 626 __ sll(T1, T1, 1);
621 __ addu(T1, FP, T1); 627 __ addu(T1, FP, T1);
622 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize); 628 __ AddImmediate(T1, kLastParamSlotIndex * kWordSize);
623 629
624 // Let T0 point to the last copied positional argument, i.e. to 630 // Let T0 point to the last copied positional argument, i.e. to
625 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)]. 631 // fp[kFirstLocalSlotIndex - (num_pos_args - 1)].
626 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize); 632 __ AddImmediate(T0, FP, (kFirstLocalSlotIndex + 1) * kWordSize);
627 __ sll(T2, T2, 1); // T2 is a Smi. 633 __ sll(T2, T2, 1); // T2 is a Smi.
628 634
629 Label loop, loop_condition; 635 Label loop, loop_exit;
630 __ b(&loop_condition); 636 __ blez(T2, &loop_exit);
631 __ delay_slot()->subu(T0, T0, T2); 637 __ 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); 638 __ Bind(&loop);
636 __ addu(T4, T1, T2); 639 __ addu(T4, T1, T2);
640 __ lw(T3, Address(T4, -kWordSize));
641 __ addiu(T2, T2, Immediate(-kWordSize));
637 __ addu(T5, T0, T2); 642 __ addu(T5, T0, T2);
638 __ lw(T3, Address(T4)); 643 __ bgtz(T2, &loop);
639 __ sw(T3, Address(T5)); 644 __ delay_slot()->sw(T3, Address(T5));
640 __ Bind(&loop_condition); 645 __ Bind(&loop_exit);
641 __ addiu(T2, T2, Immediate(-kWordSize));
642 __ bgez(T2, &loop);
643 646
644 // Copy or initialize optional named arguments. 647 // Copy or initialize optional named arguments.
645 Label all_arguments_processed; 648 Label all_arguments_processed;
646 if (num_opt_named_params > 0) { 649 if (num_opt_named_params > 0) {
647 // Start by alphabetically sorting the names of the optional parameters. 650 // Start by alphabetically sorting the names of the optional parameters.
648 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; 651 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
649 int* opt_param_position = new int[num_opt_named_params]; 652 int* opt_param_position = new int[num_opt_named_params];
650 for (int pos = num_fixed_params; pos < num_params; pos++) { 653 for (int pos = num_fixed_params; pos < num_params; pos++) {
651 LocalVariable* parameter = scope->VariableAt(pos); 654 LocalVariable* parameter = scope->VariableAt(pos);
652 const String& opt_param_name = parameter->name(); 655 const String& opt_param_name = parameter->name();
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
785 __ LeaveDartFrame(); 788 __ LeaveDartFrame();
786 __ Ret(); 789 __ Ret();
787 790
788 __ Bind(&all_arguments_processed); 791 __ Bind(&all_arguments_processed);
789 // Nullify originally passed arguments only after they have been copied and 792 // Nullify originally passed arguments only after they have been copied and
790 // checked, otherwise noSuchMethod would not see their original values. 793 // checked, otherwise noSuchMethod would not see their original values.
791 // This step can be skipped in case we decide that formal parameters are 794 // This step can be skipped in case we decide that formal parameters are
792 // implicitly final, since garbage collecting the unmodified value is not 795 // implicitly final, since garbage collecting the unmodified value is not
793 // an issue anymore. 796 // an issue anymore.
794 797
798 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
799
795 // S4 : arguments descriptor array. 800 // S4 : arguments descriptor array.
796 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 801 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
797 __ sll(T2, T2, 1); // T2 is a Smi. 802 __ sll(T2, T2, 1); // T2 is a Smi.
798 803
799 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null())); 804 Label null_args_loop, null_args_loop_exit;
800 Label null_args_loop, null_args_loop_condition; 805 __ blez(T2, &null_args_loop_exit);
801
802 __ b(&null_args_loop_condition);
803 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize)); 806 __ delay_slot()->addiu(T1, FP, Immediate(kLastParamSlotIndex * kWordSize));
804
805 __ Bind(&null_args_loop); 807 __ Bind(&null_args_loop);
808 __ addiu(T2, T2, Immediate(-kWordSize));
806 __ addu(T3, T1, T2); 809 __ addu(T3, T1, T2);
807 __ sw(T0, Address(T3)); 810 __ bgtz(T2, &null_args_loop);
808 811 __ delay_slot()->sw(T0, Address(T3));
809 __ Bind(&null_args_loop_condition); 812 __ Bind(&null_args_loop_exit);
810 __ addiu(T2, T2, Immediate(-kWordSize));
811 __ bgez(T2, &null_args_loop);
812 } 813 }
813 814
814 815
815 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 816 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
816 // RA: return address. 817 // RA: return address.
817 // SP: receiver. 818 // SP: receiver.
818 // Sequence node has one return node, its input is load field node. 819 // Sequence node has one return node, its input is load field node.
819 __ lw(V0, Address(SP, 0 * kWordSize)); 820 __ lw(V0, Address(SP, 0 * kWordSize));
820 __ lw(V0, Address(V0, offset - kHeapObjectTag)); 821 __ lw(V0, Address(V0, offset - kHeapObjectTag));
821 __ Ret(); 822 __ Ret();
822 } 823 }
823 824
824 825
825 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 826 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
826 // RA: return address. 827 // RA: return address.
827 // SP+1: receiver. 828 // SP+1: receiver.
828 // SP+0: value. 829 // SP+0: value.
829 // Sequence node has one store node and one return NULL node. 830 // Sequence node has one store node and one return NULL node.
830 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver. 831 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
831 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. 832 __ lw(T1, Address(SP, 0 * kWordSize)); // Value.
832 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); 833 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
833 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null())); 834 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
835 uint16_t null_lo = Utils::Low16Bits(null);
836 uint16_t null_hi = Utils::High16Bits(null);
837 __ lui(V0, Immediate(null_hi));
834 __ Ret(); 838 __ Ret();
839 __ delay_slot()->ori(V0, V0, Immediate(null_lo));
835 } 840 }
836 841
837 842
838 void FlowGraphCompiler::EmitFrameEntry() { 843 void FlowGraphCompiler::EmitFrameEntry() {
839 __ TraceSimMsg("FrameEntry"); 844 __ TraceSimMsg("FrameEntry");
840 const Function& function = parsed_function().function(); 845 const Function& function = parsed_function().function();
841 if (CanOptimizeFunction() && function.is_optimizable()) { 846 if (CanOptimizeFunction() && function.is_optimizable()) {
842 const bool can_optimize = !is_optimizing() || may_reoptimize(); 847 const bool can_optimize = !is_optimizing() || may_reoptimize();
843 const Register function_reg = T0; 848 const Register function_reg = T0;
844 if (can_optimize) { 849 if (can_optimize) {
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
1198 1203
1199 1204
1200 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1205 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1201 const Object& obj, 1206 const Object& obj,
1202 bool needs_number_check) { 1207 bool needs_number_check) {
1203 if (needs_number_check && 1208 if (needs_number_check &&
1204 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) { 1209 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) {
1205 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1210 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1206 __ sw(reg, Address(SP, 1 * kWordSize)); 1211 __ sw(reg, Address(SP, 1 * kWordSize));
1207 __ LoadObject(TMP1, obj); 1212 __ LoadObject(TMP1, obj);
1208 __ sw(TMP1, Address(SP, 0 * kWordSize));
1209 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1213 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1214 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize));
1210 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. 1215 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'.
1211 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. 1216 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant.
1212 return; 1217 return;
1213 } 1218 }
1214 __ CompareObject(CMPRES, reg, obj); 1219 __ CompareObject(CMPRES, reg, obj);
1215 } 1220 }
1216 1221
1217 1222
1218 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1223 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1219 Register right, 1224 Register right,
1220 bool needs_number_check) { 1225 bool needs_number_check) {
1221 __ TraceSimMsg("EqualityRegRegCompare"); 1226 __ TraceSimMsg("EqualityRegRegCompare");
1222 if (needs_number_check) { 1227 if (needs_number_check) {
1223 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1228 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1224 __ sw(left, Address(SP, 1 * kWordSize)); 1229 __ sw(left, Address(SP, 1 * kWordSize));
1225 __ sw(right, Address(SP, 0 * kWordSize));
1226 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1230 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1231 __ delay_slot()->sw(right, Address(SP, 0 * kWordSize));
1227 __ TraceSimMsg("EqualityRegRegCompare return"); 1232 __ TraceSimMsg("EqualityRegRegCompare return");
1228 // Stub returns result in CMPRES. If it is 0, then left and right are equal. 1233 // Stub returns result in CMPRES. If it is 0, then left and right are equal.
1229 __ lw(right, Address(SP, 0 * kWordSize)); 1234 __ lw(right, Address(SP, 0 * kWordSize));
1230 __ lw(left, Address(SP, 1 * kWordSize)); 1235 __ lw(left, Address(SP, 1 * kWordSize));
1231 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1236 __ addiu(SP, SP, Immediate(2 * kWordSize));
1232 } else { 1237 } else {
1233 __ subu(CMPRES, left, right); 1238 __ subu(CMPRES, left, right);
1234 } 1239 }
1235 } 1240 }
1236 1241
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 __ AddImmediate(SP, kDoubleSize); 1570 __ AddImmediate(SP, kDoubleSize);
1566 } 1571 }
1567 1572
1568 1573
1569 #undef __ 1574 #undef __
1570 1575
1571 1576
1572 } // namespace dart 1577 } // namespace dart
1573 1578
1574 #endif // defined TARGET_ARCH_MIPS 1579 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/assembler_mips.cc ('k') | runtime/vm/stub_code_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698