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

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

Issue 16022011: Enables optimization on MIPS (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/disassembler_mips.cc ('k') | runtime/vm/instructions_mips.h » ('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 27 matching lines...) Expand all
38 } 38 }
39 39
40 40
41 bool FlowGraphCompiler::SupportsUnboxedMints() { 41 bool FlowGraphCompiler::SupportsUnboxedMints() {
42 return false; 42 return false;
43 } 43 }
44 44
45 45
46 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler, 46 RawDeoptInfo* CompilerDeoptInfo::CreateDeoptInfo(FlowGraphCompiler* compiler,
47 DeoptInfoBuilder* builder) { 47 DeoptInfoBuilder* builder) {
48 UNIMPLEMENTED(); // TODO(regis): Copy ARM version. 48 if (deopt_env_ == NULL) return DeoptInfo::null();
49 return NULL; 49
50 intptr_t stack_height = compiler->StackSize();
51 AllocateIncomingParametersRecursive(deopt_env_, &stack_height);
52
53 intptr_t slot_ix = 0;
54 Environment* current = deopt_env_;
55
56 // Emit all kMaterializeObject instructions describing objects to be
57 // materialized on the deoptimization as a prefix to the deoptimization info.
58 EmitMaterializations(deopt_env_, builder);
59
60 // The real frame starts here.
61 builder->MarkFrameStart();
62
63 // Current PP, FP, and PC.
64 builder->AddPp(current->function(), slot_ix++);
65 builder->AddCallerFp(slot_ix++);
66 builder->AddReturnAddress(current->function(), deopt_id(), slot_ix++);
67
68 // Callee's PC marker is not used anymore. Pass Function::null() to set to 0.
69 builder->AddPcMarker(Function::Handle(), slot_ix++);
70
71 // Emit all values that are needed for materialization as a part of the
72 // expression stack for the bottom-most frame. This guarantees that GC
73 // will be able to find them during materialization.
74 slot_ix = builder->EmitMaterializationArguments(slot_ix);
75
76 // For the innermost environment, set outgoing arguments and the locals.
77 for (intptr_t i = current->Length() - 1;
78 i >= current->fixed_parameter_count();
79 i--) {
80 builder->AddCopy(current->ValueAt(i), current->LocationAt(i), slot_ix++);
81 }
82
83 Environment* previous = current;
84 current = current->outer();
85 while (current != NULL) {
86 // PP, FP, and PC.
87 builder->AddPp(current->function(), slot_ix++);
88 builder->AddCallerFp(slot_ix++);
89
90 // For any outer environment the deopt id is that of the call instruction
91 // which is recorded in the outer environment.
92 builder->AddReturnAddress(current->function(),
93 Isolate::ToDeoptAfter(current->deopt_id()),
94 slot_ix++);
95
96 // PC marker.
97 builder->AddPcMarker(previous->function(), slot_ix++);
98
99 // The values of outgoing arguments can be changed from the inlined call so
100 // we must read them from the previous environment.
101 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
102 builder->AddCopy(previous->ValueAt(i),
103 previous->LocationAt(i),
104 slot_ix++);
105 }
106
107 // Set the locals, note that outgoing arguments are not in the environment.
108 for (intptr_t i = current->Length() - 1;
109 i >= current->fixed_parameter_count();
110 i--) {
111 builder->AddCopy(current->ValueAt(i),
112 current->LocationAt(i),
113 slot_ix++);
114 }
115
116 // Iterate on the outer environment.
117 previous = current;
118 current = current->outer();
119 }
120 // The previous pointer is now the outermost environment.
121 ASSERT(previous != NULL);
122
123 // For the outermost environment, set caller PC, caller PP, and caller FP.
124 builder->AddCallerPp(slot_ix++);
125 builder->AddCallerFp(slot_ix++);
126 builder->AddCallerPc(slot_ix++);
127
128 // PC marker.
129 builder->AddPcMarker(previous->function(), slot_ix++);
130
131 // For the outermost environment, set the incoming arguments.
132 for (intptr_t i = previous->fixed_parameter_count() - 1; i >= 0; i--) {
133 builder->AddCopy(previous->ValueAt(i), previous->LocationAt(i), slot_ix++);
134 }
135
136 const DeoptInfo& deopt_info = DeoptInfo::Handle(builder->CreateDeoptInfo());
137 return deopt_info.raw();
50 } 138 }
51 139
52 140
53 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, 141 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler,
54 intptr_t stub_ix) { 142 intptr_t stub_ix) {
55 // Calls do not need stubs, they share a deoptimization trampoline. 143 // Calls do not need stubs, they share a deoptimization trampoline.
56 ASSERT(reason() != kDeoptAtCall); 144 ASSERT(reason() != kDeoptAtCall);
57 Assembler* assem = compiler->assembler(); 145 Assembler* assem = compiler->assembler();
58 #define __ assem-> 146 #define __ assem->
59 __ Comment("Deopt stub for id %"Pd"", deopt_id()); 147 __ Comment("Deopt stub for id %"Pd"", deopt_id());
(...skipping 11 matching lines...) Expand all
71 159
72 #define __ assembler()-> 160 #define __ assembler()->
73 161
74 162
75 // Fall through if bool_register contains null. 163 // Fall through if bool_register contains null.
76 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, 164 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
77 Label* is_true, 165 Label* is_true,
78 Label* is_false) { 166 Label* is_false) {
79 __ TraceSimMsg("BoolToJump"); 167 __ TraceSimMsg("BoolToJump");
80 Label fall_through; 168 Label fall_through;
81 __ BranchEqual(bool_register, reinterpret_cast<intptr_t>(Object::null()), 169 __ beq(bool_register, NULLREG, &fall_through);
82 &fall_through);
83 __ BranchEqual(bool_register, Bool::True(), is_true); 170 __ BranchEqual(bool_register, Bool::True(), is_true);
84 __ b(is_false); 171 __ b(is_false);
85 __ Bind(&fall_through); 172 __ Bind(&fall_through);
86 } 173 }
87 174
88 175
89 // A0: instance (must be preserved). 176 // A0: instance (must be preserved).
90 // A1: instantiator type arguments (if used). 177 // A1: instantiator type arguments (if used).
91 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 178 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
92 TypeTestStubKind test_kind, 179 TypeTestStubKind test_kind,
93 Register instance_reg, 180 Register instance_reg,
94 Register type_arguments_reg, 181 Register type_arguments_reg,
95 Register temp_reg, 182 Register temp_reg,
96 Label* is_instance_lbl, 183 Label* is_instance_lbl,
97 Label* is_not_instance_lbl) { 184 Label* is_not_instance_lbl) {
98 __ TraceSimMsg("CallSubtypeTestStub"); 185 __ TraceSimMsg("CallSubtypeTestStub");
99 ASSERT(instance_reg == A0); 186 ASSERT(instance_reg == A0);
100 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. 187 ASSERT(temp_reg == kNoRegister); // Unused on MIPS.
101 const SubtypeTestCache& type_test_cache = 188 const SubtypeTestCache& type_test_cache =
102 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); 189 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
103 __ LoadObject(A2, type_test_cache); 190 __ LoadObject(A2, type_test_cache);
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 if (test_kind == kTestTypeOneArg) { 191 if (test_kind == kTestTypeOneArg) {
108 ASSERT(type_arguments_reg == kNoRegister); 192 ASSERT(type_arguments_reg == kNoRegister);
109 __ lui(A1, Immediate(null_hi));
110 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); 193 __ BranchLink(&StubCode::Subtype1TestCacheLabel());
111 __ delay_slot()->ori(A1, A1, Immediate(null_lo)); 194 __ delay_slot()->mov(A1, NULLREG);
112 } else if (test_kind == kTestTypeTwoArgs) { 195 } else if (test_kind == kTestTypeTwoArgs) {
113 ASSERT(type_arguments_reg == kNoRegister); 196 ASSERT(type_arguments_reg == kNoRegister);
114 __ lui(A1, Immediate(null_hi));
115 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); 197 __ BranchLink(&StubCode::Subtype2TestCacheLabel());
116 __ delay_slot()->ori(A1, A1, Immediate(null_lo)); 198 __ delay_slot()->mov(A1, NULLREG);
117 } else if (test_kind == kTestTypeThreeArgs) { 199 } else if (test_kind == kTestTypeThreeArgs) {
118 ASSERT(type_arguments_reg == A1); 200 ASSERT(type_arguments_reg == A1);
119 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); 201 __ BranchLink(&StubCode::Subtype3TestCacheLabel());
120 } else { 202 } else {
121 UNREACHABLE(); 203 UNREACHABLE();
122 } 204 }
123 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. 205 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False.
124 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); 206 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl);
125 return type_test_cache.raw(); 207 return type_test_cache.raw();
126 } 208 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 // Bool interface can be implemented only by core class Bool. 322 // Bool interface can be implemented only by core class Bool.
241 if (type.IsBoolType()) { 323 if (type.IsBoolType()) {
242 __ BranchEqual(kClassIdReg, kBoolCid, is_instance_lbl); 324 __ BranchEqual(kClassIdReg, kBoolCid, is_instance_lbl);
243 __ b(is_not_instance_lbl); 325 __ b(is_not_instance_lbl);
244 return false; 326 return false;
245 } 327 }
246 if (type.IsFunctionType()) { 328 if (type.IsFunctionType()) {
247 // Check if instance is a closure. 329 // Check if instance is a closure.
248 __ LoadClassById(T1, kClassIdReg); 330 __ LoadClassById(T1, kClassIdReg);
249 __ lw(T1, FieldAddress(T1, Class::signature_function_offset())); 331 __ lw(T1, FieldAddress(T1, Class::signature_function_offset()));
250 __ BranchNotEqual(T1, reinterpret_cast<int32_t>(Object::null()), 332 __ bne(T1, NULLREG, is_instance_lbl);
251 is_instance_lbl);
252 } 333 }
253 // Custom checking for numbers (Smi, Mint, Bigint and Double). 334 // Custom checking for numbers (Smi, Mint, Bigint and Double).
254 // Note that instance is not Smi (checked above). 335 // Note that instance is not Smi (checked above).
255 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) { 336 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
256 GenerateNumberTypeCheck( 337 GenerateNumberTypeCheck(
257 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 338 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
258 return false; 339 return false;
259 } 340 }
260 if (type.IsStringType()) { 341 if (type.IsStringType()) {
261 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 342 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 Label* is_not_instance_lbl) { 389 Label* is_not_instance_lbl) {
309 __ Comment("UninstantiatedTypeTest"); 390 __ Comment("UninstantiatedTypeTest");
310 ASSERT(!type.IsInstantiated()); 391 ASSERT(!type.IsInstantiated());
311 // Skip check if destination is a dynamic type. 392 // Skip check if destination is a dynamic type.
312 if (type.IsTypeParameter()) { 393 if (type.IsTypeParameter()) {
313 const TypeParameter& type_param = TypeParameter::Cast(type); 394 const TypeParameter& type_param = TypeParameter::Cast(type);
314 // Load instantiator (or null) and instantiator type arguments on stack. 395 // Load instantiator (or null) and instantiator type arguments on stack.
315 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. 396 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments.
316 // A1: instantiator type arguments. 397 // A1: instantiator type arguments.
317 // Check if type argument is dynamic. 398 // Check if type argument is dynamic.
318 __ BranchEqual(A1, reinterpret_cast<intptr_t>(Object::null()), 399 __ beq(A1, NULLREG, is_instance_lbl);
319 is_instance_lbl);
320 // Can handle only type arguments that are instances of TypeArguments. 400 // Can handle only type arguments that are instances of TypeArguments.
321 // (runtime checks canonicalize type arguments). 401 // (runtime checks canonicalize type arguments).
322 Label fall_through; 402 Label fall_through;
323 __ LoadClassId(T2, A1); 403 __ LoadClassId(T2, A1);
324 __ BranchNotEqual(T2, kTypeArgumentsCid, &fall_through); 404 __ BranchNotEqual(T2, kTypeArgumentsCid, &fall_through);
325 __ lw(T2, 405 __ lw(T2,
326 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index()))); 406 FieldAddress(A1, TypeArguments::type_at_offset(type_param.index())));
327 // R2: concrete type of type. 407 // R2: concrete type of type.
328 // Check if type argument is dynamic. 408 // Check if type argument is dynamic.
329 __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl); 409 __ BranchEqual(T2, Type::ZoneHandle(Type::DynamicType()), is_instance_lbl);
330 __ BranchEqual(T2, reinterpret_cast<intptr_t>(Object::null()), 410 __ beq(T2, NULLREG, is_instance_lbl);
331 is_instance_lbl);
332 const Type& object_type = Type::ZoneHandle(Type::ObjectType()); 411 const Type& object_type = Type::ZoneHandle(Type::ObjectType());
333 __ BranchEqual(T2, object_type, is_instance_lbl); 412 __ BranchEqual(T2, object_type, is_instance_lbl);
334 413
335 // For Smi check quickly against int and num interfaces. 414 // For Smi check quickly against int and num interfaces.
336 Label not_smi; 415 Label not_smi;
337 __ andi(CMPRES, A0, Immediate(kSmiTagMask)); 416 __ andi(CMPRES, A0, Immediate(kSmiTagMask));
338 __ bne(CMPRES, ZR, &not_smi); // Value is Smi? 417 __ bne(CMPRES, ZR, &not_smi); // Value is Smi?
339 __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl); 418 __ BranchEqual(T2, Type::ZoneHandle(Type::IntType()), is_instance_lbl);
340 __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl); 419 __ BranchEqual(T2, Type::ZoneHandle(Type::Number()), is_instance_lbl);
341 420
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 ASSERT(dst_type.IsFinalized()); 559 ASSERT(dst_type.IsFinalized());
481 // Assignable check is skipped in FlowGraphBuilder, not here. 560 // Assignable check is skipped in FlowGraphBuilder, not here.
482 ASSERT(dst_type.IsMalformed() || 561 ASSERT(dst_type.IsMalformed() ||
483 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 562 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
484 // Preserve instantiator and its type arguments. 563 // Preserve instantiator and its type arguments.
485 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 564 __ addiu(SP, SP, Immediate(-2 * kWordSize));
486 __ sw(A2, Address(SP, 1 * kWordSize)); 565 __ sw(A2, Address(SP, 1 * kWordSize));
487 566
488 // A null object is always assignable and is returned as result. 567 // A null object is always assignable and is returned as result.
489 Label is_assignable, runtime_call; 568 Label is_assignable, runtime_call;
490 __ BranchEqual(A0, reinterpret_cast<int32_t>(Object::null()), &is_assignable); 569 __ beq(A0, NULLREG, &is_assignable);
491 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize)); 570 __ delay_slot()->sw(A1, Address(SP, 0 * kWordSize));
492 571
493 if (!FLAG_eliminate_type_checks) { 572 if (!FLAG_eliminate_type_checks) {
494 // If type checks are not eliminated during the graph building then 573 // If type checks are not eliminated during the graph building then
495 // a transition sentinel can be seen here. 574 // a transition sentinel can be seen here.
496 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable); 575 __ BranchEqual(A0, Object::transition_sentinel(), &is_assignable);
497 } 576 }
498 577
499 // Generate throw new TypeError() if the type is malformed. 578 // Generate throw new TypeError() if the type is malformed.
500 if (dst_type.IsMalformed()) { 579 if (dst_type.IsMalformed()) {
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
719 // We do not use the final allocation index of the variable here, i.e. 798 // We do not use the final allocation index of the variable here, i.e.
720 // scope->VariableAt(i)->index(), because captured variables still need 799 // scope->VariableAt(i)->index(), because captured variables still need
721 // to be copied to the context that is not yet allocated. 800 // to be copied to the context that is not yet allocated.
722 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 801 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
723 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); 802 __ sw(T3, Address(FP, computed_param_pos * kWordSize));
724 } 803 }
725 delete[] opt_param; 804 delete[] opt_param;
726 delete[] opt_param_position; 805 delete[] opt_param_position;
727 // Check that T0 now points to the null terminator in the array descriptor. 806 // Check that T0 now points to the null terminator in the array descriptor.
728 __ lw(T3, Address(T0)); 807 __ lw(T3, Address(T0));
729 __ BranchEqual(T3, reinterpret_cast<int32_t>(Object::null()), 808 __ beq(T3, NULLREG, &all_arguments_processed);
730 &all_arguments_processed);
731 } else { 809 } else {
732 ASSERT(num_opt_pos_params > 0); 810 ASSERT(num_opt_pos_params > 0);
733 __ lw(T2, 811 __ lw(T2,
734 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); 812 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset()));
735 __ SmiUntag(T2); 813 __ SmiUntag(T2);
736 for (int i = 0; i < num_opt_pos_params; i++) { 814 for (int i = 0; i < num_opt_pos_params; i++) {
737 Label next_parameter; 815 Label next_parameter;
738 // Handle this optional positional parameter only if k or fewer positional 816 // Handle this optional positional parameter only if k or fewer positional
739 // arguments have been passed, where k is param_pos, the position of this 817 // arguments have been passed, where k is param_pos, the position of this
740 // optional parameter in the formal parameter list. 818 // optional parameter in the formal parameter list.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 // The noSuchMethod call may return. 875 // The noSuchMethod call may return.
798 __ LeaveDartFrameAndReturn(); 876 __ LeaveDartFrameAndReturn();
799 877
800 __ Bind(&all_arguments_processed); 878 __ Bind(&all_arguments_processed);
801 // Nullify originally passed arguments only after they have been copied and 879 // Nullify originally passed arguments only after they have been copied and
802 // checked, otherwise noSuchMethod would not see their original values. 880 // checked, otherwise noSuchMethod would not see their original values.
803 // This step can be skipped in case we decide that formal parameters are 881 // This step can be skipped in case we decide that formal parameters are
804 // implicitly final, since garbage collecting the unmodified value is not 882 // implicitly final, since garbage collecting the unmodified value is not
805 // an issue anymore. 883 // an issue anymore.
806 884
807 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
808
809 // S4 : arguments descriptor array. 885 // S4 : arguments descriptor array.
810 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 886 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
811 __ sll(T2, T2, 1); // T2 is a Smi. 887 __ sll(T2, T2, 1); // T2 is a Smi.
812 888
813 Label null_args_loop, null_args_loop_exit; 889 Label null_args_loop, null_args_loop_exit;
814 __ blez(T2, &null_args_loop_exit); 890 __ blez(T2, &null_args_loop_exit);
815 __ delay_slot()->addiu(T1, FP, 891 __ delay_slot()->addiu(T1, FP,
816 Immediate((kParamEndSlotFromFp + 1) * kWordSize)); 892 Immediate((kParamEndSlotFromFp + 1) * kWordSize));
817 __ Bind(&null_args_loop); 893 __ Bind(&null_args_loop);
818 __ addiu(T2, T2, Immediate(-kWordSize)); 894 __ addiu(T2, T2, Immediate(-kWordSize));
819 __ addu(T3, T1, T2); 895 __ addu(T3, T1, T2);
820 __ bgtz(T2, &null_args_loop); 896 __ bgtz(T2, &null_args_loop);
821 __ delay_slot()->sw(T0, Address(T3)); 897 __ delay_slot()->sw(NULLREG, Address(T3));
822 __ Bind(&null_args_loop_exit); 898 __ Bind(&null_args_loop_exit);
823 } 899 }
824 900
825 901
826 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 902 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
827 // RA: return address. 903 // RA: return address.
828 // SP: receiver. 904 // SP: receiver.
829 // Sequence node has one return node, its input is load field node. 905 // Sequence node has one return node, its input is load field node.
830 __ lw(V0, Address(SP, 0 * kWordSize)); 906 __ lw(V0, Address(SP, 0 * kWordSize));
831 __ lw(V0, Address(V0, offset - kHeapObjectTag)); 907 __ lw(V0, Address(V0, offset - kHeapObjectTag));
832 __ Ret(); 908 __ Ret();
833 } 909 }
834 910
835 911
836 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) { 912 void FlowGraphCompiler::GenerateInlinedSetter(intptr_t offset) {
837 // RA: return address. 913 // RA: return address.
838 // SP+1: receiver. 914 // SP+1: receiver.
839 // SP+0: value. 915 // SP+0: value.
840 // Sequence node has one store node and one return NULL node. 916 // Sequence node has one store node and one return NULL node.
841 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver. 917 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
842 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. 918 __ lw(T1, Address(SP, 0 * kWordSize)); // Value.
843 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); 919 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
844 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
845 uint16_t null_lo = Utils::Low16Bits(null);
846 uint16_t null_hi = Utils::High16Bits(null);
847 __ lui(V0, Immediate(null_hi));
848 __ Ret(); 920 __ Ret();
849 __ delay_slot()->ori(V0, V0, Immediate(null_lo)); 921 __ delay_slot()->mov(V0, NULLREG);
850 } 922 }
851 923
852 924
853 void FlowGraphCompiler::EmitFrameEntry() { 925 void FlowGraphCompiler::EmitFrameEntry() {
854 __ TraceSimMsg("FrameEntry"); 926 __ TraceSimMsg("FrameEntry");
855 const Function& function = parsed_function().function(); 927 const Function& function = parsed_function().function();
856 if (CanOptimizeFunction() && function.is_optimizable()) { 928 if (CanOptimizeFunction() && function.is_optimizable()) {
857 const bool can_optimize = !is_optimizing() || may_reoptimize(); 929 const bool can_optimize = !is_optimizing() || may_reoptimize();
858 const Register function_reg = T0; 930 const Register function_reg = T0;
859 if (can_optimize) { 931 if (can_optimize) {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 } 1104 }
1033 CopyParameters(); 1105 CopyParameters();
1034 } 1106 }
1035 1107
1036 // In unoptimized code, initialize (non-argument) stack allocated slots to 1108 // In unoptimized code, initialize (non-argument) stack allocated slots to
1037 // null. This does not cover the saved_args_desc_var slot. 1109 // null. This does not cover the saved_args_desc_var slot.
1038 if (!is_optimizing() && (num_locals > 0)) { 1110 if (!is_optimizing() && (num_locals > 0)) {
1039 __ TraceSimMsg("Initialize spill slots"); 1111 __ TraceSimMsg("Initialize spill slots");
1040 __ Comment("Initialize spill slots"); 1112 __ Comment("Initialize spill slots");
1041 const intptr_t slot_base = parsed_function().first_stack_local_index(); 1113 const intptr_t slot_base = parsed_function().first_stack_local_index();
1042 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
1043 for (intptr_t i = 0; i < num_locals; ++i) { 1114 for (intptr_t i = 0; i < num_locals; ++i) {
1044 // Subtract index i (locals lie at lower addresses than FP). 1115 // Subtract index i (locals lie at lower addresses than FP).
1045 __ sw(T0, Address(FP, (slot_base - i) * kWordSize)); 1116 __ sw(NULLREG, Address(FP, (slot_base - i) * kWordSize));
1046 } 1117 }
1047 } 1118 }
1048 1119
1049 if (FLAG_print_scopes) { 1120 if (FLAG_print_scopes) {
1050 // Print the function scope (again) after generating the prologue in order 1121 // Print the function scope (again) after generating the prologue in order
1051 // to see annotations such as allocation indices of locals. 1122 // to see annotations such as allocation indices of locals.
1052 if (FLAG_print_ast) { 1123 if (FLAG_print_ast) {
1053 // Second printing. 1124 // Second printing.
1054 OS::Print("Annotated "); 1125 OS::Print("Annotated ");
1055 } 1126 }
1056 AstPrinter::PrintFunctionScope(parsed_function()); 1127 AstPrinter::PrintFunctionScope(parsed_function());
1057 } 1128 }
1058 1129
1059 VisitBlocks(); 1130 VisitBlocks();
1060 1131
1061 __ break_(0); 1132 __ break_(0);
1062 GenerateDeferredCode(); 1133 GenerateDeferredCode();
1063 // Emit function patching code. This will be swapped with the first 5 bytes 1134 // Emit function patching code. This will be swapped with the first 5 bytes
1064 // at entry point. 1135 // at entry point.
1065 AddCurrentDescriptor(PcDescriptors::kPatchCode, 1136 AddCurrentDescriptor(PcDescriptors::kPatchCode,
1066 Isolate::kNoDeoptId, 1137 Isolate::kNoDeoptId,
1067 0); // No token position. 1138 0); // No token position.
1068 __ Branch(&StubCode::FixCallersTargetLabel()); 1139 __ BranchPatchable(&StubCode::FixCallersTargetLabel());
1069 AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump, 1140 AddCurrentDescriptor(PcDescriptors::kLazyDeoptJump,
1070 Isolate::kNoDeoptId, 1141 Isolate::kNoDeoptId,
1071 0); // No token position. 1142 0); // No token position.
1072 __ Branch(&StubCode::DeoptimizeLazyLabel()); 1143 __ Branch(&StubCode::DeoptimizeLazyLabel());
1073 } 1144 }
1074 1145
1075 1146
1076 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, 1147 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
1077 const ExternalLabel* label, 1148 const ExternalLabel* label,
1078 PcDescriptors::Kind kind, 1149 PcDescriptors::Kind kind,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 __ LoadObject(TMP1, obj); 1293 __ LoadObject(TMP1, obj);
1223 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1294 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1224 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, 1295 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1225 Isolate::kNoDeoptId, 1296 Isolate::kNoDeoptId,
1226 token_pos); 1297 token_pos);
1227 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize)); 1298 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize));
1228 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. 1299 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'.
1229 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. 1300 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant.
1230 return; 1301 return;
1231 } 1302 }
1232 __ CompareObject(CMPRES, reg, obj); 1303 __ CompareObject(CMPRES, TMP1, reg, obj);
1233 } 1304 }
1234 1305
1235 1306
1236 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1307 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1237 Register right, 1308 Register right,
1238 bool needs_number_check, 1309 bool needs_number_check,
1239 intptr_t token_pos) { 1310 intptr_t token_pos) {
1240 __ TraceSimMsg("EqualityRegRegCompare"); 1311 __ TraceSimMsg("EqualityRegRegCompare");
1241 if (needs_number_check) { 1312 if (needs_number_check) {
1242 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1313 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1243 __ sw(left, Address(SP, 1 * kWordSize)); 1314 __ sw(left, Address(SP, 1 * kWordSize));
1244 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1315 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1245 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, 1316 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1246 Isolate::kNoDeoptId, 1317 Isolate::kNoDeoptId,
1247 token_pos); 1318 token_pos);
1248 __ delay_slot()->sw(right, Address(SP, 0 * kWordSize)); 1319 __ delay_slot()->sw(right, Address(SP, 0 * kWordSize));
1249 __ TraceSimMsg("EqualityRegRegCompare return"); 1320 __ TraceSimMsg("EqualityRegRegCompare return");
1250 // Stub returns result in CMPRES. If it is 0, then left and right are equal. 1321 // Stub returns result in CMPRES. If it is 0, then left and right are equal.
1251 __ lw(right, Address(SP, 0 * kWordSize)); 1322 __ lw(right, Address(SP, 0 * kWordSize));
1252 __ lw(left, Address(SP, 1 * kWordSize)); 1323 __ lw(left, Address(SP, 1 * kWordSize));
1253 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1324 __ addiu(SP, SP, Immediate(2 * kWordSize));
1254 } else { 1325 } else {
1255 __ subu(CMPRES, left, right); 1326 __ slt(CMPRES, left, right);
1327 __ slt(TMP1, right, left);
1256 } 1328 }
1257 } 1329 }
1258 1330
1259 1331
1260 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, 1332 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result,
1261 Label* skip_call) { 1333 Label* skip_call) {
1262 UNIMPLEMENTED(); 1334 UNIMPLEMENTED();
1263 } 1335 }
1264 1336
1265 1337
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1461 __ movd(FpuTMP, source.fpu_reg()); 1533 __ movd(FpuTMP, source.fpu_reg());
1462 __ movd(source.fpu_reg(), destination.fpu_reg()); 1534 __ movd(source.fpu_reg(), destination.fpu_reg());
1463 __ movd(destination.fpu_reg(), FpuTMP); 1535 __ movd(destination.fpu_reg(), FpuTMP);
1464 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) { 1536 } else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
1465 ASSERT(destination.IsDoubleStackSlot() || 1537 ASSERT(destination.IsDoubleStackSlot() ||
1466 destination.IsQuadStackSlot() || 1538 destination.IsQuadStackSlot() ||
1467 source.IsDoubleStackSlot() || 1539 source.IsDoubleStackSlot() ||
1468 source.IsQuadStackSlot()); 1540 source.IsQuadStackSlot());
1469 bool double_width = destination.IsDoubleStackSlot() || 1541 bool double_width = destination.IsDoubleStackSlot() ||
1470 source.IsDoubleStackSlot(); 1542 source.IsDoubleStackSlot();
1471 FRegister reg = source.IsFpuRegister() ? source.fpu_reg() 1543 DRegister reg = source.IsFpuRegister() ? source.fpu_reg()
1472 : destination.fpu_reg(); 1544 : destination.fpu_reg();
1473 const Address& slot_address = source.IsFpuRegister() 1545 const Address& slot_address = source.IsFpuRegister()
1474 ? destination.ToStackSlotAddress() 1546 ? destination.ToStackSlotAddress()
1475 : source.ToStackSlotAddress(); 1547 : source.ToStackSlotAddress();
1476 1548
1477 if (double_width) { 1549 if (double_width) {
1478 __ ldc1(FpuTMP, slot_address); 1550 __ ldc1(FpuTMP, slot_address);
1479 __ sdc1(reg, slot_address); 1551 __ sdc1(reg, slot_address);
1480 __ movd(reg, FpuTMP); 1552 __ movd(reg, FpuTMP);
1481 } else { 1553 } else {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1573 __ AddImmediate(SP, kDoubleSize); 1645 __ AddImmediate(SP, kDoubleSize);
1574 } 1646 }
1575 1647
1576 1648
1577 #undef __ 1649 #undef __
1578 1650
1579 1651
1580 } // namespace dart 1652 } // namespace dart
1581 1653
1582 #endif // defined TARGET_ARCH_MIPS 1654 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/disassembler_mips.cc ('k') | runtime/vm/instructions_mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698