OLD | NEW |
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 "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 Assembler* assem = compiler->assembler(); | 182 Assembler* assem = compiler->assembler(); |
183 #define __ assem-> | 183 #define __ assem-> |
184 __ Comment("%s", Name()); | 184 __ Comment("%s", Name()); |
185 __ Bind(entry_label()); | 185 __ Bind(entry_label()); |
186 if (FLAG_trap_on_deoptimization) { | 186 if (FLAG_trap_on_deoptimization) { |
187 __ break_(0); | 187 __ break_(0); |
188 } | 188 } |
189 | 189 |
190 ASSERT(deopt_env() != NULL); | 190 ASSERT(deopt_env() != NULL); |
191 | 191 |
192 StubCode* stub_code = compiler->isolate()->stub_code(); | 192 __ BranchLink(&StubCode::DeoptimizeLabel()); |
193 __ BranchLink(&stub_code->DeoptimizeLabel()); | |
194 set_pc_offset(assem->CodeSize()); | 193 set_pc_offset(assem->CodeSize()); |
195 #undef __ | 194 #undef __ |
196 } | 195 } |
197 | 196 |
198 | 197 |
199 #define __ assembler()-> | 198 #define __ assembler()-> |
200 | 199 |
201 | 200 |
202 // Fall through if bool_register contains null. | 201 // Fall through if bool_register contains null. |
203 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 202 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
(...skipping 15 matching lines...) Expand all Loading... |
219 Register instance_reg, | 218 Register instance_reg, |
220 Register type_arguments_reg, | 219 Register type_arguments_reg, |
221 Register temp_reg, | 220 Register temp_reg, |
222 Label* is_instance_lbl, | 221 Label* is_instance_lbl, |
223 Label* is_not_instance_lbl) { | 222 Label* is_not_instance_lbl) { |
224 __ Comment("CallSubtypeTestStub"); | 223 __ Comment("CallSubtypeTestStub"); |
225 ASSERT(instance_reg == A0); | 224 ASSERT(instance_reg == A0); |
226 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. | 225 ASSERT(temp_reg == kNoRegister); // Unused on MIPS. |
227 const SubtypeTestCache& type_test_cache = | 226 const SubtypeTestCache& type_test_cache = |
228 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 227 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
229 StubCode* stub_code = isolate()->stub_code(); | |
230 __ LoadUniqueObject(A2, type_test_cache); | 228 __ LoadUniqueObject(A2, type_test_cache); |
231 if (test_kind == kTestTypeOneArg) { | 229 if (test_kind == kTestTypeOneArg) { |
232 ASSERT(type_arguments_reg == kNoRegister); | 230 ASSERT(type_arguments_reg == kNoRegister); |
233 __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null())); | 231 __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null())); |
234 __ BranchLink(&stub_code->Subtype1TestCacheLabel()); | 232 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); |
235 } else if (test_kind == kTestTypeTwoArgs) { | 233 } else if (test_kind == kTestTypeTwoArgs) { |
236 ASSERT(type_arguments_reg == kNoRegister); | 234 ASSERT(type_arguments_reg == kNoRegister); |
237 __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null())); | 235 __ LoadImmediate(A1, reinterpret_cast<int32_t>(Object::null())); |
238 __ BranchLink(&stub_code->Subtype2TestCacheLabel()); | 236 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); |
239 } else if (test_kind == kTestTypeThreeArgs) { | 237 } else if (test_kind == kTestTypeThreeArgs) { |
240 ASSERT(type_arguments_reg == A1); | 238 ASSERT(type_arguments_reg == A1); |
241 __ BranchLink(&stub_code->Subtype3TestCacheLabel()); | 239 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
242 } else { | 240 } else { |
243 UNREACHABLE(); | 241 UNREACHABLE(); |
244 } | 242 } |
245 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. | 243 // Result is in V0: null -> not found, otherwise Bool::True or Bool::False. |
246 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); | 244 GenerateBoolToJump(V0, is_instance_lbl, is_not_instance_lbl); |
247 return type_test_cache.raw(); | 245 return type_test_cache.raw(); |
248 } | 246 } |
249 | 247 |
250 | 248 |
251 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 249 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 921 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
924 __ SmiUntag(T1); | 922 __ SmiUntag(T1); |
925 // Check that T2 equals T1, i.e. no named arguments passed. | 923 // Check that T2 equals T1, i.e. no named arguments passed. |
926 __ beq(T2, T1, &all_arguments_processed); | 924 __ beq(T2, T1, &all_arguments_processed); |
927 } | 925 } |
928 } | 926 } |
929 | 927 |
930 __ Bind(&wrong_num_arguments); | 928 __ Bind(&wrong_num_arguments); |
931 if (function.IsClosureFunction()) { | 929 if (function.IsClosureFunction()) { |
932 __ LeaveDartFrame(); // The arguments are still on the stack. | 930 __ LeaveDartFrame(); // The arguments are still on the stack. |
933 __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel()); | 931 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
934 // The noSuchMethod call may return to the caller, but not here. | 932 // The noSuchMethod call may return to the caller, but not here. |
935 } else if (check_correct_named_args) { | 933 } else if (check_correct_named_args) { |
936 __ Stop("Wrong arguments"); | 934 __ Stop("Wrong arguments"); |
937 } | 935 } |
938 | 936 |
939 __ Bind(&all_arguments_processed); | 937 __ Bind(&all_arguments_processed); |
940 // Nullify originally passed arguments only after they have been copied and | 938 // Nullify originally passed arguments only after they have been copied and |
941 // checked, otherwise noSuchMethod would not see their original values. | 939 // checked, otherwise noSuchMethod would not see their original values. |
942 // This step can be skipped in case we decide that formal parameters are | 940 // This step can be skipped in case we decide that formal parameters are |
943 // implicitly final, since garbage collecting the unmodified value is not | 941 // implicitly final, since garbage collecting the unmodified value is not |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 __ Ret(); | 984 __ Ret(); |
987 } | 985 } |
988 | 986 |
989 | 987 |
990 void FlowGraphCompiler::EmitFrameEntry() { | 988 void FlowGraphCompiler::EmitFrameEntry() { |
991 const Function& function = parsed_function().function(); | 989 const Function& function = parsed_function().function(); |
992 if (CanOptimizeFunction() && | 990 if (CanOptimizeFunction() && |
993 function.IsOptimizable() && | 991 function.IsOptimizable() && |
994 (!is_optimizing() || may_reoptimize())) { | 992 (!is_optimizing() || may_reoptimize())) { |
995 const Register function_reg = T0; | 993 const Register function_reg = T0; |
996 StubCode* stub_code = isolate()->stub_code(); | |
997 | 994 |
998 __ GetNextPC(T2, TMP); | 995 __ GetNextPC(T2, TMP); |
999 | 996 |
1000 // Calculate offset of pool pointer from the PC. | 997 // Calculate offset of pool pointer from the PC. |
1001 const intptr_t object_pool_pc_dist = | 998 const intptr_t object_pool_pc_dist = |
1002 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 999 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
1003 assembler()->CodeSize() - 1 * Instr::kInstrSize; | 1000 assembler()->CodeSize() - 1 * Instr::kInstrSize; |
1004 | 1001 |
1005 // Preserve PP of caller. | 1002 // Preserve PP of caller. |
1006 __ mov(T1, PP); | 1003 __ mov(T1, PP); |
(...skipping 14 matching lines...) Expand all Loading... |
1021 __ addiu(T1, T1, Immediate(1)); | 1018 __ addiu(T1, T1, Immediate(1)); |
1022 __ sw(T1, FieldAddress(function_reg, Function::usage_counter_offset())); | 1019 __ sw(T1, FieldAddress(function_reg, Function::usage_counter_offset())); |
1023 } | 1020 } |
1024 | 1021 |
1025 // Skip Branch if T1 is less than the threshold. | 1022 // Skip Branch if T1 is less than the threshold. |
1026 Label dont_branch; | 1023 Label dont_branch; |
1027 __ BranchSignedLess( | 1024 __ BranchSignedLess( |
1028 T1, Immediate(GetOptimizationThreshold()), &dont_branch); | 1025 T1, Immediate(GetOptimizationThreshold()), &dont_branch); |
1029 | 1026 |
1030 ASSERT(function_reg == T0); | 1027 ASSERT(function_reg == T0); |
1031 __ Branch(&stub_code->OptimizeFunctionLabel()); | 1028 __ Branch(&StubCode::OptimizeFunctionLabel()); |
1032 | 1029 |
1033 __ Bind(&dont_branch); | 1030 __ Bind(&dont_branch); |
1034 | 1031 |
1035 } else if (!flow_graph().IsCompiledForOsr()) { | 1032 } else if (!flow_graph().IsCompiledForOsr()) { |
1036 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1033 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1037 } | 1034 } |
1038 __ Comment("Enter frame"); | 1035 __ Comment("Enter frame"); |
1039 if (flow_graph().IsCompiledForOsr()) { | 1036 if (flow_graph().IsCompiledForOsr()) { |
1040 intptr_t extra_slots = StackSize() | 1037 intptr_t extra_slots = StackSize() |
1041 - flow_graph().num_stack_locals() | 1038 - flow_graph().num_stack_locals() |
(...skipping 19 matching lines...) Expand all Loading... |
1061 | 1058 |
1062 TryIntrinsify(); | 1059 TryIntrinsify(); |
1063 | 1060 |
1064 EmitFrameEntry(); | 1061 EmitFrameEntry(); |
1065 | 1062 |
1066 const Function& function = parsed_function().function(); | 1063 const Function& function = parsed_function().function(); |
1067 | 1064 |
1068 const int num_fixed_params = function.num_fixed_parameters(); | 1065 const int num_fixed_params = function.num_fixed_parameters(); |
1069 const int num_copied_params = parsed_function().num_copied_params(); | 1066 const int num_copied_params = parsed_function().num_copied_params(); |
1070 const int num_locals = parsed_function().num_stack_locals(); | 1067 const int num_locals = parsed_function().num_stack_locals(); |
1071 StubCode* stub_code = isolate()->stub_code(); | |
1072 | 1068 |
1073 // We check the number of passed arguments when we have to copy them due to | 1069 // We check the number of passed arguments when we have to copy them due to |
1074 // the presence of optional parameters. | 1070 // the presence of optional parameters. |
1075 // No such checking code is generated if only fixed parameters are declared, | 1071 // No such checking code is generated if only fixed parameters are declared, |
1076 // unless we are in debug mode or unless we are compiling a closure. | 1072 // unless we are in debug mode or unless we are compiling a closure. |
1077 if (num_copied_params == 0) { | 1073 if (num_copied_params == 0) { |
1078 #ifdef DEBUG | 1074 #ifdef DEBUG |
1079 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1075 ASSERT(!parsed_function().function().HasOptionalParameters()); |
1080 const bool check_arguments = !flow_graph().IsCompiledForOsr(); | 1076 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
1081 #else | 1077 #else |
1082 const bool check_arguments = | 1078 const bool check_arguments = |
1083 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); | 1079 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); |
1084 #endif | 1080 #endif |
1085 if (check_arguments) { | 1081 if (check_arguments) { |
1086 __ Comment("Check argument count"); | 1082 __ Comment("Check argument count"); |
1087 // Check that exactly num_fixed arguments are passed in. | 1083 // Check that exactly num_fixed arguments are passed in. |
1088 Label correct_num_arguments, wrong_num_arguments; | 1084 Label correct_num_arguments, wrong_num_arguments; |
1089 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 1085 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
1090 __ BranchNotEqual(T0, Immediate(Smi::RawValue(num_fixed_params)), | 1086 __ BranchNotEqual(T0, Immediate(Smi::RawValue(num_fixed_params)), |
1091 &wrong_num_arguments); | 1087 &wrong_num_arguments); |
1092 | 1088 |
1093 __ lw(T1, FieldAddress(S4, | 1089 __ lw(T1, FieldAddress(S4, |
1094 ArgumentsDescriptor::positional_count_offset())); | 1090 ArgumentsDescriptor::positional_count_offset())); |
1095 __ beq(T0, T1, &correct_num_arguments); | 1091 __ beq(T0, T1, &correct_num_arguments); |
1096 __ Bind(&wrong_num_arguments); | 1092 __ Bind(&wrong_num_arguments); |
1097 if (function.IsClosureFunction()) { | 1093 if (function.IsClosureFunction()) { |
1098 __ LeaveDartFrame(); // The arguments are still on the stack. | 1094 __ LeaveDartFrame(); // The arguments are still on the stack. |
1099 __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel()); | 1095 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
1100 // The noSuchMethod call may return to the caller, but not here. | 1096 // The noSuchMethod call may return to the caller, but not here. |
1101 } else { | 1097 } else { |
1102 __ Stop("Wrong number of arguments"); | 1098 __ Stop("Wrong number of arguments"); |
1103 } | 1099 } |
1104 __ Bind(&correct_num_arguments); | 1100 __ Bind(&correct_num_arguments); |
1105 } | 1101 } |
1106 } else if (!flow_graph().IsCompiledForOsr()) { | 1102 } else if (!flow_graph().IsCompiledForOsr()) { |
1107 CopyParameters(); | 1103 CopyParameters(); |
1108 } | 1104 } |
1109 | 1105 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 } | 1140 } |
1145 } | 1141 } |
1146 | 1142 |
1147 VisitBlocks(); | 1143 VisitBlocks(); |
1148 | 1144 |
1149 __ break_(0); | 1145 __ break_(0); |
1150 GenerateDeferredCode(); | 1146 GenerateDeferredCode(); |
1151 // Emit function patching code. This will be swapped with the first 5 bytes | 1147 // Emit function patching code. This will be swapped with the first 5 bytes |
1152 // at entry point. | 1148 // at entry point. |
1153 patch_code_pc_offset_ = assembler()->CodeSize(); | 1149 patch_code_pc_offset_ = assembler()->CodeSize(); |
1154 __ BranchPatchable(&stub_code->FixCallersTargetLabel()); | 1150 __ BranchPatchable(&StubCode::FixCallersTargetLabel()); |
1155 | 1151 |
1156 if (is_optimizing()) { | 1152 if (is_optimizing()) { |
1157 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1153 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1158 __ Branch(&stub_code->DeoptimizeLazyLabel()); | 1154 __ Branch(&StubCode::DeoptimizeLazyLabel()); |
1159 } | 1155 } |
1160 } | 1156 } |
1161 | 1157 |
1162 | 1158 |
1163 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1159 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1164 const ExternalLabel* label, | 1160 const ExternalLabel* label, |
1165 RawPcDescriptors::Kind kind, | 1161 RawPcDescriptors::Kind kind, |
1166 LocationSummary* locs) { | 1162 LocationSummary* locs) { |
1167 __ BranchLinkPatchable(label); | 1163 __ BranchLinkPatchable(label); |
1168 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1164 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1293 const MegamorphicCache& cache = | 1289 const MegamorphicCache& cache = |
1294 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); | 1290 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); |
1295 __ Comment("MegamorphicInstanceCall"); | 1291 __ Comment("MegamorphicInstanceCall"); |
1296 const Register receiverR = T0; | 1292 const Register receiverR = T0; |
1297 const Register cacheR = T1; | 1293 const Register cacheR = T1; |
1298 const Register targetR = T1; | 1294 const Register targetR = T1; |
1299 __ lw(receiverR, Address(SP, (argument_count - 1) * kWordSize)); | 1295 __ lw(receiverR, Address(SP, (argument_count - 1) * kWordSize)); |
1300 __ LoadObject(cacheR, cache); | 1296 __ LoadObject(cacheR, cache); |
1301 | 1297 |
1302 if (FLAG_use_megamorphic_stub) { | 1298 if (FLAG_use_megamorphic_stub) { |
1303 StubCode* stub_code = isolate()->stub_code(); | 1299 __ BranchLink(&StubCode::MegamorphicLookupLabel()); |
1304 __ BranchLink(&stub_code->MegamorphicLookupLabel()); | |
1305 } else { | 1300 } else { |
1306 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); | 1301 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
1307 } | 1302 } |
1308 __ LoadObject(S5, ic_data); | 1303 __ LoadObject(S5, ic_data); |
1309 __ LoadObject(S4, arguments_descriptor); | 1304 __ LoadObject(S4, arguments_descriptor); |
1310 __ jalr(targetR); | 1305 __ jalr(targetR); |
1311 AddCurrentDescriptor(RawPcDescriptors::kOther, | 1306 AddCurrentDescriptor(RawPcDescriptors::kOther, |
1312 Isolate::kNoDeoptId, token_pos); | 1307 Isolate::kNoDeoptId, token_pos); |
1313 RecordSafepoint(locs); | 1308 RecordSafepoint(locs); |
1314 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1309 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1315 if (is_optimizing()) { | 1310 if (is_optimizing()) { |
1316 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1311 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1317 } else { | 1312 } else { |
1318 // Add deoptimization continuation point after the call and before the | 1313 // Add deoptimization continuation point after the call and before the |
1319 // arguments are removed. | 1314 // arguments are removed. |
1320 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1315 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1321 } | 1316 } |
1322 __ Drop(argument_count); | 1317 __ Drop(argument_count); |
1323 } | 1318 } |
1324 | 1319 |
1325 | 1320 |
1326 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1321 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1327 intptr_t argument_count, | 1322 intptr_t argument_count, |
1328 intptr_t deopt_id, | 1323 intptr_t deopt_id, |
1329 intptr_t token_pos, | 1324 intptr_t token_pos, |
1330 LocationSummary* locs, | 1325 LocationSummary* locs, |
1331 const ICData& ic_data) { | 1326 const ICData& ic_data) { |
1332 StubCode* stub_code = isolate()->stub_code(); | |
1333 const uword label_address = | 1327 const uword label_address = |
1334 stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); | 1328 StubCode::UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); |
1335 ExternalLabel target_label(label_address); | 1329 ExternalLabel target_label(label_address); |
1336 __ LoadObject(S5, ic_data); | 1330 __ LoadObject(S5, ic_data); |
1337 GenerateDartCall(deopt_id, | 1331 GenerateDartCall(deopt_id, |
1338 token_pos, | 1332 token_pos, |
1339 &target_label, | 1333 &target_label, |
1340 RawPcDescriptors::kUnoptStaticCall, | 1334 RawPcDescriptors::kUnoptStaticCall, |
1341 locs); | 1335 locs); |
1342 __ Drop(argument_count); | 1336 __ Drop(argument_count); |
1343 } | 1337 } |
1344 | 1338 |
1345 | 1339 |
1346 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1340 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1347 const Function& function, | 1341 const Function& function, |
1348 const Array& arguments_descriptor, | 1342 const Array& arguments_descriptor, |
1349 intptr_t argument_count, | 1343 intptr_t argument_count, |
1350 intptr_t deopt_id, | 1344 intptr_t deopt_id, |
1351 intptr_t token_pos, | 1345 intptr_t token_pos, |
1352 LocationSummary* locs) { | 1346 LocationSummary* locs) { |
1353 StubCode* stub_code = isolate()->stub_code(); | |
1354 __ Comment("StaticCall"); | 1347 __ Comment("StaticCall"); |
1355 __ LoadObject(S4, arguments_descriptor); | 1348 __ LoadObject(S4, arguments_descriptor); |
1356 // Do not use the code from the function, but let the code be patched so that | 1349 // Do not use the code from the function, but let the code be patched so that |
1357 // we can record the outgoing edges to other code. | 1350 // we can record the outgoing edges to other code. |
1358 GenerateDartCall(deopt_id, | 1351 GenerateDartCall(deopt_id, |
1359 token_pos, | 1352 token_pos, |
1360 &stub_code->CallStaticFunctionLabel(), | 1353 &StubCode::CallStaticFunctionLabel(), |
1361 RawPcDescriptors::kOther, | 1354 RawPcDescriptors::kOther, |
1362 locs); | 1355 locs); |
1363 AddStaticCallTarget(function); | 1356 AddStaticCallTarget(function); |
1364 __ Drop(argument_count); | 1357 __ Drop(argument_count); |
1365 } | 1358 } |
1366 | 1359 |
1367 | 1360 |
1368 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1361 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1369 Register reg, | 1362 Register reg, |
1370 const Object& obj, | 1363 const Object& obj, |
1371 bool needs_number_check, | 1364 bool needs_number_check, |
1372 intptr_t token_pos) { | 1365 intptr_t token_pos) { |
1373 __ Comment("EqualityRegConstCompare"); | 1366 __ Comment("EqualityRegConstCompare"); |
1374 ASSERT(!needs_number_check || | 1367 ASSERT(!needs_number_check || |
1375 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); | 1368 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); |
1376 if (needs_number_check) { | 1369 if (needs_number_check) { |
1377 StubCode* stub_code = isolate()->stub_code(); | |
1378 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1370 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1379 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1371 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1380 __ sw(reg, Address(SP, 1 * kWordSize)); | 1372 __ sw(reg, Address(SP, 1 * kWordSize)); |
1381 __ LoadObject(TMP, obj); | 1373 __ LoadObject(TMP, obj); |
1382 __ sw(TMP, Address(SP, 0 * kWordSize)); | 1374 __ sw(TMP, Address(SP, 0 * kWordSize)); |
1383 if (is_optimizing()) { | 1375 if (is_optimizing()) { |
1384 __ BranchLinkPatchable( | 1376 __ BranchLinkPatchable( |
1385 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1377 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1386 } else { | 1378 } else { |
1387 __ BranchLinkPatchable( | 1379 __ BranchLinkPatchable( |
1388 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1380 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1389 } | 1381 } |
1390 if (token_pos != Scanner::kNoSourcePos) { | 1382 if (token_pos != Scanner::kNoSourcePos) { |
1391 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1383 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1392 Isolate::kNoDeoptId, | 1384 Isolate::kNoDeoptId, |
1393 token_pos); | 1385 token_pos); |
1394 } | 1386 } |
1395 __ Comment("EqualityRegConstCompare return"); | 1387 __ Comment("EqualityRegConstCompare return"); |
1396 // Stub returns result in CMPRES1 (if it is 0, then reg and obj are equal). | 1388 // Stub returns result in CMPRES1 (if it is 0, then reg and obj are equal). |
1397 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. | 1389 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. |
1398 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. | 1390 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. |
1399 return Condition(CMPRES1, ZR, EQ); | 1391 return Condition(CMPRES1, ZR, EQ); |
1400 } else { | 1392 } else { |
1401 int16_t imm = 0; | 1393 int16_t imm = 0; |
1402 const Register obj_reg = __ LoadConditionOperand(CMPRES1, obj, &imm); | 1394 const Register obj_reg = __ LoadConditionOperand(CMPRES1, obj, &imm); |
1403 return Condition(reg, obj_reg, EQ, imm); | 1395 return Condition(reg, obj_reg, EQ, imm); |
1404 } | 1396 } |
1405 } | 1397 } |
1406 | 1398 |
1407 | 1399 |
1408 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1400 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1409 Register right, | 1401 Register right, |
1410 bool needs_number_check, | 1402 bool needs_number_check, |
1411 intptr_t token_pos) { | 1403 intptr_t token_pos) { |
1412 __ Comment("EqualityRegRegCompare"); | 1404 __ Comment("EqualityRegRegCompare"); |
1413 if (needs_number_check) { | 1405 if (needs_number_check) { |
1414 StubCode* stub_code = isolate()->stub_code(); | |
1415 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1406 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1416 __ sw(left, Address(SP, 1 * kWordSize)); | 1407 __ sw(left, Address(SP, 1 * kWordSize)); |
1417 __ sw(right, Address(SP, 0 * kWordSize)); | 1408 __ sw(right, Address(SP, 0 * kWordSize)); |
1418 if (is_optimizing()) { | 1409 if (is_optimizing()) { |
1419 __ BranchLinkPatchable( | 1410 __ BranchLinkPatchable( |
1420 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1411 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1421 } else { | 1412 } else { |
1422 __ BranchLinkPatchable( | 1413 __ BranchLinkPatchable( |
1423 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1414 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1424 } | 1415 } |
1425 if (token_pos != Scanner::kNoSourcePos) { | 1416 if (token_pos != Scanner::kNoSourcePos) { |
1426 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1417 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1427 Isolate::kNoDeoptId, | 1418 Isolate::kNoDeoptId, |
1428 token_pos); | 1419 token_pos); |
1429 } | 1420 } |
1430 __ Comment("EqualityRegRegCompare return"); | 1421 __ Comment("EqualityRegRegCompare return"); |
1431 // Stub returns result in CMPRES1 (if it is 0, then left and right are | 1422 // Stub returns result in CMPRES1 (if it is 0, then left and right are |
1432 // equal). | 1423 // equal). |
1433 __ lw(right, Address(SP, 0 * kWordSize)); | 1424 __ lw(right, Address(SP, 0 * kWordSize)); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1545 Label* failed, | 1536 Label* failed, |
1546 Label* match_found, | 1537 Label* match_found, |
1547 intptr_t deopt_id, | 1538 intptr_t deopt_id, |
1548 intptr_t token_index, | 1539 intptr_t token_index, |
1549 LocationSummary* locs) { | 1540 LocationSummary* locs) { |
1550 ASSERT(is_optimizing()); | 1541 ASSERT(is_optimizing()); |
1551 __ Comment("EmitTestAndCall"); | 1542 __ Comment("EmitTestAndCall"); |
1552 const Array& arguments_descriptor = | 1543 const Array& arguments_descriptor = |
1553 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 1544 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
1554 argument_names)); | 1545 argument_names)); |
1555 StubCode* stub_code = isolate()->stub_code(); | |
1556 | 1546 |
1557 // Load receiver into T0. | 1547 // Load receiver into T0. |
1558 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); | 1548 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); |
1559 __ LoadObject(S4, arguments_descriptor); | 1549 __ LoadObject(S4, arguments_descriptor); |
1560 | 1550 |
1561 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; | 1551 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
1562 const intptr_t kNumChecks = ic_data.NumberOfChecks(); | 1552 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
1563 | 1553 |
1564 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1554 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
1565 | 1555 |
1566 Label after_smi_test; | 1556 Label after_smi_test; |
1567 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 1557 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
1568 if (kFirstCheckIsSmi) { | 1558 if (kFirstCheckIsSmi) { |
1569 // Jump if receiver is not Smi. | 1559 // Jump if receiver is not Smi. |
1570 if (kNumChecks == 1) { | 1560 if (kNumChecks == 1) { |
1571 __ bne(CMPRES1, ZR, failed); | 1561 __ bne(CMPRES1, ZR, failed); |
1572 } else { | 1562 } else { |
1573 __ bne(CMPRES1, ZR, &after_smi_test); | 1563 __ bne(CMPRES1, ZR, &after_smi_test); |
1574 } | 1564 } |
1575 // Do not use the code from the function, but let the code be patched so | 1565 // Do not use the code from the function, but let the code be patched so |
1576 // that we can record the outgoing edges to other code. | 1566 // that we can record the outgoing edges to other code. |
1577 GenerateDartCall(deopt_id, | 1567 GenerateDartCall(deopt_id, |
1578 token_index, | 1568 token_index, |
1579 &stub_code->CallStaticFunctionLabel(), | 1569 &StubCode::CallStaticFunctionLabel(), |
1580 RawPcDescriptors::kOther, | 1570 RawPcDescriptors::kOther, |
1581 locs); | 1571 locs); |
1582 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); | 1572 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); |
1583 AddStaticCallTarget(function); | 1573 AddStaticCallTarget(function); |
1584 __ Drop(argument_count); | 1574 __ Drop(argument_count); |
1585 if (kNumChecks > 1) { | 1575 if (kNumChecks > 1) { |
1586 __ b(match_found); | 1576 __ b(match_found); |
1587 } | 1577 } |
1588 } else { | 1578 } else { |
1589 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1579 // Receiver is Smi, but Smi is not a valid class therefore fail. |
(...skipping 19 matching lines...) Expand all Loading... |
1609 Label next_test; | 1599 Label next_test; |
1610 if (kIsLastCheck) { | 1600 if (kIsLastCheck) { |
1611 __ BranchNotEqual(T2, Immediate(sorted[i].cid), failed); | 1601 __ BranchNotEqual(T2, Immediate(sorted[i].cid), failed); |
1612 } else { | 1602 } else { |
1613 __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test); | 1603 __ BranchNotEqual(T2, Immediate(sorted[i].cid), &next_test); |
1614 } | 1604 } |
1615 // Do not use the code from the function, but let the code be patched so | 1605 // Do not use the code from the function, but let the code be patched so |
1616 // that we can record the outgoing edges to other code. | 1606 // that we can record the outgoing edges to other code. |
1617 GenerateDartCall(deopt_id, | 1607 GenerateDartCall(deopt_id, |
1618 token_index, | 1608 token_index, |
1619 &stub_code->CallStaticFunctionLabel(), | 1609 &StubCode::CallStaticFunctionLabel(), |
1620 RawPcDescriptors::kOther, | 1610 RawPcDescriptors::kOther, |
1621 locs); | 1611 locs); |
1622 const Function& function = *sorted[i].target; | 1612 const Function& function = *sorted[i].target; |
1623 AddStaticCallTarget(function); | 1613 AddStaticCallTarget(function); |
1624 __ Drop(argument_count); | 1614 __ Drop(argument_count); |
1625 if (!kIsLastCheck) { | 1615 if (!kIsLastCheck) { |
1626 __ b(match_found); | 1616 __ b(match_found); |
1627 } | 1617 } |
1628 __ Bind(&next_test); | 1618 __ Bind(&next_test); |
1629 } | 1619 } |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1868 __ AddImmediate(SP, kDoubleSize); | 1858 __ AddImmediate(SP, kDoubleSize); |
1869 } | 1859 } |
1870 | 1860 |
1871 | 1861 |
1872 #undef __ | 1862 #undef __ |
1873 | 1863 |
1874 | 1864 |
1875 } // namespace dart | 1865 } // namespace dart |
1876 | 1866 |
1877 #endif // defined TARGET_ARCH_MIPS | 1867 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |