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

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

Issue 15934025: Enables more VM tests for SIMMIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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/intermediate_language_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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 } 380 }
381 381
382 382
383 // Generates inlined check if 'type' is a type parameter or type itself 383 // Generates inlined check if 'type' is a type parameter or type itself
384 // A0: instance (preserved). 384 // A0: instance (preserved).
385 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 385 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
386 intptr_t token_pos, 386 intptr_t token_pos,
387 const AbstractType& type, 387 const AbstractType& type,
388 Label* is_instance_lbl, 388 Label* is_instance_lbl,
389 Label* is_not_instance_lbl) { 389 Label* is_not_instance_lbl) {
390 __ TraceSimMsg("UninstantiatedTypeTest");
390 __ Comment("UninstantiatedTypeTest"); 391 __ Comment("UninstantiatedTypeTest");
391 ASSERT(!type.IsInstantiated()); 392 ASSERT(!type.IsInstantiated());
392 // Skip check if destination is a dynamic type. 393 // Skip check if destination is a dynamic type.
393 if (type.IsTypeParameter()) { 394 if (type.IsTypeParameter()) {
394 const TypeParameter& type_param = TypeParameter::Cast(type); 395 const TypeParameter& type_param = TypeParameter::Cast(type);
395 // Load instantiator (or null) and instantiator type arguments on stack. 396 // Load instantiator (or null) and instantiator type arguments on stack.
396 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. 397 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments.
397 // A1: instantiator type arguments. 398 // A1: instantiator type arguments.
398 // Check if type argument is dynamic. 399 // Check if type argument is dynamic.
399 __ beq(A1, NULLREG, is_instance_lbl); 400 __ beq(A1, NULLREG, is_instance_lbl);
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 __ subu(T1, T1, T2); 711 __ subu(T1, T1, T2);
711 __ sll(T1, T1, 1); 712 __ sll(T1, T1, 1);
712 __ addu(T1, FP, T1); 713 __ addu(T1, FP, T1);
713 __ AddImmediate(T1, (kParamEndSlotFromFp + 1) * kWordSize); 714 __ AddImmediate(T1, (kParamEndSlotFromFp + 1) * kWordSize);
714 715
715 // Let T0 point to the last copied positional argument, i.e. to 716 // Let T0 point to the last copied positional argument, i.e. to
716 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)]. 717 // fp[kFirstLocalSlotFromFp - (num_pos_args - 1)].
717 __ AddImmediate(T0, FP, (kFirstLocalSlotFromFp + 1) * kWordSize); 718 __ AddImmediate(T0, FP, (kFirstLocalSlotFromFp + 1) * kWordSize);
718 __ sll(T2, T2, 1); // T2 is a Smi. 719 __ sll(T2, T2, 1); // T2 is a Smi.
719 720
721 __ Comment("Argument Copy Loop");
720 Label loop, loop_exit; 722 Label loop, loop_exit;
721 __ blez(T2, &loop_exit); 723 __ blez(T2, &loop_exit);
722 __ delay_slot()->subu(T0, T0, T2); 724 __ delay_slot()->subu(T0, T0, T2);
723 __ Bind(&loop); 725 __ Bind(&loop);
724 __ addu(T4, T1, T2); 726 __ addu(T4, T1, T2);
725 __ lw(T3, Address(T4, -kWordSize)); 727 __ lw(T3, Address(T4, -kWordSize));
726 __ addiu(T2, T2, Immediate(-kWordSize)); 728 __ addiu(T2, T2, Immediate(-kWordSize));
727 __ addu(T5, T0, T2); 729 __ addu(T5, T0, T2);
728 __ bgtz(T2, &loop); 730 __ bgtz(T2, &loop);
729 __ delay_slot()->sw(T3, Address(T5)); 731 __ delay_slot()->sw(T3, Address(T5));
730 __ Bind(&loop_exit); 732 __ Bind(&loop_exit);
731 733
732 // Copy or initialize optional named arguments. 734 // Copy or initialize optional named arguments.
733 Label all_arguments_processed; 735 Label all_arguments_processed;
734 if (num_opt_named_params > 0) { 736 if (num_opt_named_params > 0) {
737 __ Comment("There are named parameters");
735 // Start by alphabetically sorting the names of the optional parameters. 738 // Start by alphabetically sorting the names of the optional parameters.
736 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params]; 739 LocalVariable** opt_param = new LocalVariable*[num_opt_named_params];
737 int* opt_param_position = new int[num_opt_named_params]; 740 int* opt_param_position = new int[num_opt_named_params];
738 for (int pos = num_fixed_params; pos < num_params; pos++) { 741 for (int pos = num_fixed_params; pos < num_params; pos++) {
739 LocalVariable* parameter = scope->VariableAt(pos); 742 LocalVariable* parameter = scope->VariableAt(pos);
740 const String& opt_param_name = parameter->name(); 743 const String& opt_param_name = parameter->name();
741 int i = pos - num_fixed_params; 744 int i = pos - num_fixed_params;
742 while (--i >= 0) { 745 while (--i >= 0) {
743 LocalVariable* param_i = opt_param[i]; 746 LocalVariable* param_i = opt_param[i];
744 const intptr_t result = opt_param_name.CompareTo(param_i->name()); 747 const intptr_t result = opt_param_name.CompareTo(param_i->name());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
797 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos; 800 const intptr_t computed_param_pos = kFirstLocalSlotFromFp - param_pos;
798 __ sw(T3, Address(FP, computed_param_pos * kWordSize)); 801 __ sw(T3, Address(FP, computed_param_pos * kWordSize));
799 } 802 }
800 delete[] opt_param; 803 delete[] opt_param;
801 delete[] opt_param_position; 804 delete[] opt_param_position;
802 // Check that T0 now points to the null terminator in the array descriptor. 805 // Check that T0 now points to the null terminator in the array descriptor.
803 __ lw(T3, Address(T0)); 806 __ lw(T3, Address(T0));
804 __ beq(T3, NULLREG, &all_arguments_processed); 807 __ beq(T3, NULLREG, &all_arguments_processed);
805 } else { 808 } else {
806 ASSERT(num_opt_pos_params > 0); 809 ASSERT(num_opt_pos_params > 0);
810 __ Comment("There are optional positional parameters");
807 __ lw(T2, 811 __ lw(T2,
808 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset())); 812 FieldAddress(S4, ArgumentsDescriptor::positional_count_offset()));
809 __ SmiUntag(T2); 813 __ SmiUntag(T2);
810 for (int i = 0; i < num_opt_pos_params; i++) { 814 for (int i = 0; i < num_opt_pos_params; i++) {
811 Label next_parameter; 815 Label next_parameter;
812 // Handle this optional positional parameter only if k or fewer positional 816 // Handle this optional positional parameter only if k or fewer positional
813 // 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
814 // optional parameter in the formal parameter list. 818 // optional parameter in the formal parameter list.
815 const int param_pos = num_fixed_params + i; 819 const int param_pos = num_fixed_params + i;
816 __ BranchSignedGreater(T2, param_pos, &next_parameter); 820 __ BranchSignedGreater(T2, param_pos, &next_parameter);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 // Nullify originally passed arguments only after they have been copied and 879 // Nullify originally passed arguments only after they have been copied and
876 // checked, otherwise noSuchMethod would not see their original values. 880 // checked, otherwise noSuchMethod would not see their original values.
877 // 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
878 // implicitly final, since garbage collecting the unmodified value is not 882 // implicitly final, since garbage collecting the unmodified value is not
879 // an issue anymore. 883 // an issue anymore.
880 884
881 // S4 : arguments descriptor array. 885 // S4 : arguments descriptor array.
882 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 886 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
883 __ sll(T2, T2, 1); // T2 is a Smi. 887 __ sll(T2, T2, 1); // T2 is a Smi.
884 888
889 __ Comment("Null arguments loop");
885 Label null_args_loop, null_args_loop_exit; 890 Label null_args_loop, null_args_loop_exit;
886 __ blez(T2, &null_args_loop_exit); 891 __ blez(T2, &null_args_loop_exit);
887 __ delay_slot()->addiu(T1, FP, 892 __ delay_slot()->addiu(T1, FP,
888 Immediate((kParamEndSlotFromFp + 1) * kWordSize)); 893 Immediate((kParamEndSlotFromFp + 1) * kWordSize));
889 __ Bind(&null_args_loop); 894 __ Bind(&null_args_loop);
890 __ addiu(T2, T2, Immediate(-kWordSize)); 895 __ addiu(T2, T2, Immediate(-kWordSize));
891 __ addu(T3, T1, T2); 896 __ addu(T3, T1, T2);
892 __ bgtz(T2, &null_args_loop); 897 __ bgtz(T2, &null_args_loop);
893 __ delay_slot()->sw(NULLREG, Address(T3)); 898 __ delay_slot()->sw(NULLREG, Address(T3));
894 __ Bind(&null_args_loop_exit); 899 __ Bind(&null_args_loop_exit);
(...skipping 17 matching lines...) Expand all
912 // Sequence node has one store node and one return NULL node. 917 // Sequence node has one store node and one return NULL node.
913 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver. 918 __ lw(T0, Address(SP, 1 * kWordSize)); // Receiver.
914 __ lw(T1, Address(SP, 0 * kWordSize)); // Value. 919 __ lw(T1, Address(SP, 0 * kWordSize)); // Value.
915 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1); 920 __ StoreIntoObject(T0, FieldAddress(T0, offset), T1);
916 __ Ret(); 921 __ Ret();
917 __ delay_slot()->mov(V0, NULLREG); 922 __ delay_slot()->mov(V0, NULLREG);
918 } 923 }
919 924
920 925
921 void FlowGraphCompiler::EmitFrameEntry() { 926 void FlowGraphCompiler::EmitFrameEntry() {
922 __ TraceSimMsg("FrameEntry");
923 const Function& function = parsed_function().function(); 927 const Function& function = parsed_function().function();
924 if (CanOptimizeFunction() && function.is_optimizable()) { 928 if (CanOptimizeFunction() && function.is_optimizable()) {
925 const bool can_optimize = !is_optimizing() || may_reoptimize(); 929 const bool can_optimize = !is_optimizing() || may_reoptimize();
926 const Register function_reg = T0; 930 const Register function_reg = T0;
927 if (can_optimize) { 931 if (can_optimize) {
928 Label next; 932 Label next;
929 // The pool pointer is not setup before entering the Dart frame. 933 // The pool pointer is not setup before entering the Dart frame.
930 934
931 __ mov(TMP1, RA); // Save RA. 935 __ mov(TMP1, RA); // Save RA.
932 __ bal(&next); // Branch and link to next instruction to get PC in RA. 936 __ bal(&next); // Branch and link to next instruction to get PC in RA.
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 Isolate::kNoDeoptId, 1141 Isolate::kNoDeoptId,
1138 0); // No token position. 1142 0); // No token position.
1139 __ Branch(&StubCode::DeoptimizeLazyLabel()); 1143 __ Branch(&StubCode::DeoptimizeLazyLabel());
1140 } 1144 }
1141 1145
1142 1146
1143 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, 1147 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
1144 const ExternalLabel* label, 1148 const ExternalLabel* label,
1145 PcDescriptors::Kind kind, 1149 PcDescriptors::Kind kind,
1146 LocationSummary* locs) { 1150 LocationSummary* locs) {
1147 __ TraceSimMsg("Call");
1148 __ BranchLinkPatchable(label); 1151 __ BranchLinkPatchable(label);
1149 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); 1152 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos);
1150 RecordSafepoint(locs); 1153 RecordSafepoint(locs);
1151 } 1154 }
1152 1155
1153 1156
1154 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, 1157 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
1155 intptr_t token_pos, 1158 intptr_t token_pos,
1156 const ExternalLabel* label, 1159 const ExternalLabel* label,
1157 PcDescriptors::Kind kind, 1160 PcDescriptors::Kind kind,
1158 LocationSummary* locs) { 1161 LocationSummary* locs) {
1159 __ TraceSimMsg("DartCall");
1160 __ BranchLinkPatchable(label); 1162 __ BranchLinkPatchable(label);
1161 AddCurrentDescriptor(kind, deopt_id, token_pos); 1163 AddCurrentDescriptor(kind, deopt_id, token_pos);
1162 RecordSafepoint(locs); 1164 RecordSafepoint(locs);
1163 // Marks either the continuation point in unoptimized code or the 1165 // Marks either the continuation point in unoptimized code or the
1164 // deoptimization point in optimized code, after call. 1166 // deoptimization point in optimized code, after call.
1165 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); 1167 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id);
1166 if (is_optimizing()) { 1168 if (is_optimizing()) {
1167 AddDeoptIndexAtCall(deopt_id_after, token_pos); 1169 AddDeoptIndexAtCall(deopt_id_after, token_pos);
1168 } else { 1170 } else {
1169 // Add deoptimization continuation point after the call and before the 1171 // Add deoptimization continuation point after the call and before the
1170 // arguments are removed. 1172 // arguments are removed.
1171 AddCurrentDescriptor(PcDescriptors::kDeopt, 1173 AddCurrentDescriptor(PcDescriptors::kDeopt,
1172 deopt_id_after, 1174 deopt_id_after,
1173 token_pos); 1175 token_pos);
1174 } 1176 }
1175 } 1177 }
1176 1178
1177 1179
1178 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, 1180 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
1179 intptr_t deopt_id, 1181 intptr_t deopt_id,
1180 const RuntimeEntry& entry, 1182 const RuntimeEntry& entry,
1181 LocationSummary* locs) { 1183 LocationSummary* locs) {
1182 __ TraceSimMsg("CallRuntime");
1183 __ CallRuntime(entry); 1184 __ CallRuntime(entry);
1184 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); 1185 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos);
1185 RecordSafepoint(locs); 1186 RecordSafepoint(locs);
1186 if (deopt_id != Isolate::kNoDeoptId) { 1187 if (deopt_id != Isolate::kNoDeoptId) {
1187 // Marks either the continuation point in unoptimized code or the 1188 // Marks either the continuation point in unoptimized code or the
1188 // deoptimization point in optimized code, after call. 1189 // deoptimization point in optimized code, after call.
1189 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); 1190 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id);
1190 if (is_optimizing()) { 1191 if (is_optimizing()) {
1191 AddDeoptIndexAtCall(deopt_id_after, token_pos); 1192 AddDeoptIndexAtCall(deopt_id_after, token_pos);
1192 } else { 1193 } else {
1193 // Add deoptimization continuation point after the call and before the 1194 // Add deoptimization continuation point after the call and before the
1194 // arguments are removed. 1195 // arguments are removed.
1195 AddCurrentDescriptor(PcDescriptors::kDeopt, 1196 AddCurrentDescriptor(PcDescriptors::kDeopt,
1196 deopt_id_after, 1197 deopt_id_after,
1197 token_pos); 1198 token_pos);
1198 } 1199 }
1199 } 1200 }
1200 __ TraceSimMsg("CallRuntime return");
1201 } 1201 }
1202 1202
1203 1203
1204 void FlowGraphCompiler::EmitOptimizedInstanceCall( 1204 void FlowGraphCompiler::EmitOptimizedInstanceCall(
1205 ExternalLabel* target_label, 1205 ExternalLabel* target_label,
1206 const ICData& ic_data, 1206 const ICData& ic_data,
1207 const Array& arguments_descriptor, 1207 const Array& arguments_descriptor,
1208 intptr_t argument_count, 1208 intptr_t argument_count,
1209 intptr_t deopt_id, 1209 intptr_t deopt_id,
1210 intptr_t token_pos, 1210 intptr_t token_pos,
1211 LocationSummary* locs) { 1211 LocationSummary* locs) {
1212 // Each ICData propagated from unoptimized to optimized code contains the 1212 // Each ICData propagated from unoptimized to optimized code contains the
1213 // function that corresponds to the Dart function of that IC call. Due 1213 // function that corresponds to the Dart function of that IC call. Due
1214 // to inlining in optimized code, that function may not correspond to the 1214 // to inlining in optimized code, that function may not correspond to the
1215 // top-level function (parsed_function().function()) which could be 1215 // top-level function (parsed_function().function()) which could be
1216 // reoptimized and which counter needs to be incremented. 1216 // reoptimized and which counter needs to be incremented.
1217 // Pass the function explicitly, it is used in IC stub. 1217 // Pass the function explicitly, it is used in IC stub.
1218 __ TraceSimMsg("OptimizedInstanceCall");
1218 __ LoadObject(T0, parsed_function().function()); 1219 __ LoadObject(T0, parsed_function().function());
1219 __ LoadObject(S4, arguments_descriptor); 1220 __ LoadObject(S4, arguments_descriptor);
1220 __ LoadObject(S5, ic_data); 1221 __ LoadObject(S5, ic_data);
1221 GenerateDartCall(deopt_id, 1222 GenerateDartCall(deopt_id,
1222 token_pos, 1223 token_pos,
1223 target_label, 1224 target_label,
1224 PcDescriptors::kIcCall, 1225 PcDescriptors::kIcCall,
1225 locs); 1226 locs);
1226 __ Drop(argument_count); 1227 __ Drop(argument_count);
1227 } 1228 }
(...skipping 19 matching lines...) Expand all
1247 } 1248 }
1248 1249
1249 1250
1250 void FlowGraphCompiler::EmitMegamorphicInstanceCall( 1251 void FlowGraphCompiler::EmitMegamorphicInstanceCall(
1251 const ICData& ic_data, 1252 const ICData& ic_data,
1252 const Array& arguments_descriptor, 1253 const Array& arguments_descriptor,
1253 intptr_t argument_count, 1254 intptr_t argument_count,
1254 intptr_t deopt_id, 1255 intptr_t deopt_id,
1255 intptr_t token_pos, 1256 intptr_t token_pos,
1256 LocationSummary* locs) { 1257 LocationSummary* locs) {
1257 UNIMPLEMENTED(); 1258 MegamorphicCacheTable* table = Isolate::Current()->megamorphic_cache_table();
1259 const String& name = String::Handle(ic_data.target_name());
1260 const MegamorphicCache& cache =
1261 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor));
1262 Label not_smi, load_cache;
1263 __ TraceSimMsg("MegamorphicInstanceCall");
1264 __ lw(T0, Address(SP, (argument_count - 1) * kWordSize));
1265 __ andi(CMPRES, T0, Immediate(kSmiTagMask));
1266 __ bne(CMPRES, ZR, &not_smi);
1267 __ LoadImmediate(T0, Smi::RawValue(kSmiCid));
1268 __ b(&load_cache);
1269
1270 __ Bind(&not_smi);
1271 __ LoadClassId(T0, T0);
1272 __ SmiTag(T0);
1273
1274 // T0: class ID of the receiver (smi).
1275 __ Bind(&load_cache);
1276 __ LoadObject(T1, cache);
1277 __ lw(T2, FieldAddress(T1, MegamorphicCache::buckets_offset()));
1278 __ lw(T1, FieldAddress(T1, MegamorphicCache::mask_offset()));
1279 // T2: cache buckets array.
1280 // T1: mask.
1281 __ mov(T3, T0);
1282
1283 Label loop, update, call_target_function;
1284 __ b(&loop);
1285
1286 __ Bind(&update);
1287 __ addiu(T3, T3, Immediate(Smi::RawValue(1)));
1288 __ Bind(&loop);
1289 __ and_(T3, T3, T1);
1290 const intptr_t base = Array::data_offset();
1291 // T3 is smi tagged, but table entries are two words, so LSL 2.
1292 __ sll(TMP1, T3, 2);
1293 __ addu(TMP1, T2, TMP1);
1294 __ lw(T4, FieldAddress(TMP, base));
1295
1296 ASSERT(kIllegalCid == 0);
1297 __ beq(T4, ZR, &call_target_function);
1298 __ bne(T4, T0, &update);
1299
1300 __ Bind(&call_target_function);
1301 // Call the target found in the cache. For a class id match, this is a
1302 // proper target for the given name and arguments descriptor. If the
1303 // illegal class id was found, the target is a cache miss handler that can
1304 // be invoked as a normal Dart function.
1305 __ sll(TMP1, T3, 2);
1306 __ addu(TMP1, T2, TMP1);
1307 __ lw(T0, FieldAddress(TMP, base + kWordSize));
1308 __ lw(T0, FieldAddress(T0, Function::code_offset()));
1309 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
1310 __ LoadObject(S5, ic_data);
1311 __ LoadObject(S4, arguments_descriptor);
1312 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
1313 __ jalr(T0);
1314 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
1315 RecordSafepoint(locs);
1316 AddDeoptIndexAtCall(Isolate::ToDeoptAfter(deopt_id), token_pos);
1317 __ Drop(argument_count);
1258 } 1318 }
1259 1319
1260 1320
1261 void FlowGraphCompiler::EmitStaticCall(const Function& function, 1321 void FlowGraphCompiler::EmitStaticCall(const Function& function,
1262 const Array& arguments_descriptor, 1322 const Array& arguments_descriptor,
1263 intptr_t argument_count, 1323 intptr_t argument_count,
1264 intptr_t deopt_id, 1324 intptr_t deopt_id,
1265 intptr_t token_pos, 1325 intptr_t token_pos,
1266 LocationSummary* locs) { 1326 LocationSummary* locs) {
1267 __ TraceSimMsg("StaticCall"); 1327 __ TraceSimMsg("StaticCall");
1268 __ LoadObject(S4, arguments_descriptor); 1328 __ LoadObject(S4, arguments_descriptor);
1269 // Do not use the code from the function, but let the code be patched so that 1329 // Do not use the code from the function, but let the code be patched so that
1270 // we can record the outgoing edges to other code. 1330 // we can record the outgoing edges to other code.
1271 GenerateDartCall(deopt_id, 1331 GenerateDartCall(deopt_id,
1272 token_pos, 1332 token_pos,
1273 &StubCode::CallStaticFunctionLabel(), 1333 &StubCode::CallStaticFunctionLabel(),
1274 PcDescriptors::kFuncCall, 1334 PcDescriptors::kFuncCall,
1275 locs); 1335 locs);
1276 AddStaticCallTarget(function); 1336 AddStaticCallTarget(function);
1277 __ Drop(argument_count); 1337 __ Drop(argument_count);
1278 } 1338 }
1279 1339
1280 1340
1281 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, 1341 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg,
1282 const Object& obj, 1342 const Object& obj,
1283 bool needs_number_check, 1343 bool needs_number_check,
1284 intptr_t token_pos) { 1344 intptr_t token_pos) {
1345 __ TraceSimMsg("EqualityRegConstCompare");
1285 if (needs_number_check && 1346 if (needs_number_check &&
1286 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) { 1347 (obj.IsMint() || obj.IsDouble() || obj.IsBigint())) {
1287 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1348 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1288 __ sw(reg, Address(SP, 1 * kWordSize)); 1349 __ sw(reg, Address(SP, 1 * kWordSize));
1289 __ LoadObject(TMP1, obj); 1350 __ LoadObject(TMP1, obj);
1290 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); 1351 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel());
1291 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, 1352 AddCurrentDescriptor(PcDescriptors::kRuntimeCall,
1292 Isolate::kNoDeoptId, 1353 Isolate::kNoDeoptId,
1293 token_pos); 1354 token_pos);
1294 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize)); 1355 __ delay_slot()->sw(TMP1, Address(SP, 0 * kWordSize));
1356 __ TraceSimMsg("EqualityRegConstCompare return");
1295 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. 1357 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'.
1296 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. 1358 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant.
1297 return; 1359 return;
1298 } 1360 }
1299 __ CompareObject(CMPRES, TMP1, reg, obj); 1361 __ CompareObject(CMPRES, TMP1, reg, obj);
1300 } 1362 }
1301 1363
1302 1364
1303 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, 1365 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left,
1304 Register right, 1366 Register right,
(...skipping 13 matching lines...) Expand all
1318 __ lw(right, Address(SP, 0 * kWordSize)); 1380 __ lw(right, Address(SP, 0 * kWordSize));
1319 __ lw(left, Address(SP, 1 * kWordSize)); 1381 __ lw(left, Address(SP, 1 * kWordSize));
1320 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1382 __ addiu(SP, SP, Immediate(2 * kWordSize));
1321 } else { 1383 } else {
1322 __ slt(CMPRES, left, right); 1384 __ slt(CMPRES, left, right);
1323 __ slt(TMP1, right, left); 1385 __ slt(TMP1, right, left);
1324 } 1386 }
1325 } 1387 }
1326 1388
1327 1389
1390 // Implement equality spec: if any of the arguments is null do identity check.
1391 // Fallthrough calls super equality.
1328 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, 1392 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result,
1329 Label* skip_call) { 1393 Label* skip_call) {
1330 UNIMPLEMENTED(); 1394 Label check_identity, is_false, fall_through;
1395 __ TraceSimMsg("SuperEqualityCallPrologue");
1396 __ lw(result, Address(SP, 0 * kWordSize)); // Load right operand.
1397 __ lw(TMP1, Address(SP, 1 * kWordSize)); // Load left operand.
1398 __ beq(result, NULLREG, &check_identity); // Is right null?
1399 __ bne(TMP1, NULLREG, &fall_through); // If right is non-null, check left.
1400
1401 __ Bind(&check_identity);
1402 __ bne(result, TMP1, &is_false);
1403 __ LoadObject(result, Bool::True());
1404 __ Drop(2);
1405 __ b(skip_call);
1406 __ Bind(&is_false);
1407 __ LoadObject(result, Bool::False());
1408 __ Drop(2);
1409 __ b(skip_call);
1410 __ Bind(&fall_through);
1331 } 1411 }
1332 1412
1333 1413
1334 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { 1414 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) {
1335 __ TraceSimMsg("SaveLiveRegisters"); 1415 __ TraceSimMsg("SaveLiveRegisters");
1336 // TODO(vegorov): consider saving only caller save (volatile) registers. 1416 // TODO(vegorov): consider saving only caller save (volatile) registers.
1337 const intptr_t fpu_registers = locs->live_registers()->fpu_registers(); 1417 const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
1338 if (fpu_registers > 0) { 1418 if (fpu_registers > 0) {
1339 UNIMPLEMENTED(); 1419 UNIMPLEMENTED();
1340 } 1420 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1377 1457
1378 const intptr_t fpu_registers = locs->live_registers()->fpu_registers(); 1458 const intptr_t fpu_registers = locs->live_registers()->fpu_registers();
1379 if (fpu_registers > 0) { 1459 if (fpu_registers > 0) {
1380 UNIMPLEMENTED(); 1460 UNIMPLEMENTED();
1381 } 1461 }
1382 } 1462 }
1383 1463
1384 1464
1385 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, 1465 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data,
1386 Register class_id_reg, 1466 Register class_id_reg,
1387 intptr_t arg_count, 1467 intptr_t argument_count,
1388 const Array& arg_names, 1468 const Array& argument_names,
1389 Label* deopt, 1469 Label* deopt,
1390 intptr_t deopt_id, 1470 intptr_t deopt_id,
1391 intptr_t token_index, 1471 intptr_t token_index,
1392 LocationSummary* locs) { 1472 LocationSummary* locs) {
1393 UNIMPLEMENTED(); 1473 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
1474 Label match_found;
1475 const intptr_t len = ic_data.NumberOfChecks();
1476 GrowableArray<CidTarget> sorted(len);
1477 SortICDataByCount(ic_data, &sorted);
1478 ASSERT(class_id_reg != S4);
1479 ASSERT(len > 0); // Why bother otherwise.
1480 const Array& arguments_descriptor =
1481 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count,
1482 argument_names));
1483 __ TraceSimMsg("EmitTestAndCall");
1484 __ LoadObject(S4, arguments_descriptor);
1485 for (intptr_t i = 0; i < len; i++) {
1486 const bool is_last_check = (i == (len - 1));
1487 Label next_test;
1488 if (is_last_check) {
1489 __ BranchNotEqual(class_id_reg, sorted[i].cid, deopt);
1490 } else {
1491 __ BranchNotEqual(class_id_reg, sorted[i].cid, &next_test);
1492 }
1493 // Do not use the code from the function, but let the code be patched so
1494 // that we can record the outgoing edges to other code.
1495 GenerateDartCall(deopt_id,
1496 token_index,
1497 &StubCode::CallStaticFunctionLabel(),
1498 PcDescriptors::kFuncCall,
1499 locs);
1500 const Function& function = *sorted[i].target;
1501 AddStaticCallTarget(function);
1502 __ Drop(argument_count);
1503 if (!is_last_check) {
1504 __ b(&match_found);
1505 }
1506 __ Bind(&next_test);
1507 }
1508 __ Bind(&match_found);
1394 } 1509 }
1395 1510
1396 1511
1397 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition, 1512 void FlowGraphCompiler::EmitDoubleCompareBranch(Condition true_condition,
1398 FpuRegister left, 1513 FpuRegister left,
1399 FpuRegister right, 1514 FpuRegister right,
1400 BranchInstr* branch) { 1515 BranchInstr* branch) {
1401 UNIMPLEMENTED(); 1516 UNIMPLEMENTED();
1402 } 1517 }
1403 1518
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 __ AddImmediate(SP, kDoubleSize); 1756 __ AddImmediate(SP, kDoubleSize);
1642 } 1757 }
1643 1758
1644 1759
1645 #undef __ 1760 #undef __
1646 1761
1647 1762
1648 } // namespace dart 1763 } // namespace dart
1649 1764
1650 #endif // defined TARGET_ARCH_MIPS 1765 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/assembler_mips.cc ('k') | runtime/vm/intermediate_language_arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698