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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 Assembler* assem = compiler->assembler(); | 164 Assembler* assem = compiler->assembler(); |
165 #define __ assem-> | 165 #define __ assem-> |
166 __ Comment("Deopt stub for id %" Pd "", deopt_id()); | 166 __ Comment("Deopt stub for id %" Pd "", deopt_id()); |
167 __ Bind(entry_label()); | 167 __ Bind(entry_label()); |
168 if (FLAG_trap_on_deoptimization) { | 168 if (FLAG_trap_on_deoptimization) { |
169 __ bkpt(0); | 169 __ bkpt(0); |
170 } | 170 } |
171 | 171 |
172 ASSERT(deopt_env() != NULL); | 172 ASSERT(deopt_env() != NULL); |
173 | 173 |
174 __ BranchLink(&StubCode::DeoptimizeLabel()); | 174 StubCode* stub_code = compiler->isolate()->stub_code(); |
| 175 __ BranchLink(&stub_code->DeoptimizeLabel()); |
175 set_pc_offset(assem->CodeSize()); | 176 set_pc_offset(assem->CodeSize()); |
176 #undef __ | 177 #undef __ |
177 } | 178 } |
178 | 179 |
179 | 180 |
180 #define __ assembler()-> | 181 #define __ assembler()-> |
181 | 182 |
182 | 183 |
183 // Fall through if bool_register contains null. | 184 // Fall through if bool_register contains null. |
184 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 185 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
(...skipping 16 matching lines...) Expand all Loading... |
201 TypeTestStubKind test_kind, | 202 TypeTestStubKind test_kind, |
202 Register instance_reg, | 203 Register instance_reg, |
203 Register type_arguments_reg, | 204 Register type_arguments_reg, |
204 Register temp_reg, | 205 Register temp_reg, |
205 Label* is_instance_lbl, | 206 Label* is_instance_lbl, |
206 Label* is_not_instance_lbl) { | 207 Label* is_not_instance_lbl) { |
207 ASSERT(instance_reg == R0); | 208 ASSERT(instance_reg == R0); |
208 ASSERT(temp_reg == kNoRegister); // Unused on ARM. | 209 ASSERT(temp_reg == kNoRegister); // Unused on ARM. |
209 const SubtypeTestCache& type_test_cache = | 210 const SubtypeTestCache& type_test_cache = |
210 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 211 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 212 StubCode* stub_code = isolate()->stub_code(); |
211 __ LoadObject(R2, type_test_cache); | 213 __ LoadObject(R2, type_test_cache); |
212 if (test_kind == kTestTypeOneArg) { | 214 if (test_kind == kTestTypeOneArg) { |
213 ASSERT(type_arguments_reg == kNoRegister); | 215 ASSERT(type_arguments_reg == kNoRegister); |
214 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 216 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
215 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); | 217 __ BranchLink(&stub_code->Subtype1TestCacheLabel()); |
216 } else if (test_kind == kTestTypeTwoArgs) { | 218 } else if (test_kind == kTestTypeTwoArgs) { |
217 ASSERT(type_arguments_reg == kNoRegister); | 219 ASSERT(type_arguments_reg == kNoRegister); |
218 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 220 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
219 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); | 221 __ BranchLink(&stub_code->Subtype2TestCacheLabel()); |
220 } else if (test_kind == kTestTypeThreeArgs) { | 222 } else if (test_kind == kTestTypeThreeArgs) { |
221 ASSERT(type_arguments_reg == R1); | 223 ASSERT(type_arguments_reg == R1); |
222 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); | 224 __ BranchLink(&stub_code->Subtype3TestCacheLabel()); |
223 } else { | 225 } else { |
224 UNREACHABLE(); | 226 UNREACHABLE(); |
225 } | 227 } |
226 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. | 228 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. |
227 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); | 229 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); |
228 return type_test_cache.raw(); | 230 return type_test_cache.raw(); |
229 } | 231 } |
230 | 232 |
231 | 233 |
232 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 234 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 __ SmiUntag(R7); | 889 __ SmiUntag(R7); |
888 // Check that R8 equals R7, i.e. no named arguments passed. | 890 // Check that R8 equals R7, i.e. no named arguments passed. |
889 __ cmp(R8, Operand(R7)); | 891 __ cmp(R8, Operand(R7)); |
890 __ b(&all_arguments_processed, EQ); | 892 __ b(&all_arguments_processed, EQ); |
891 } | 893 } |
892 } | 894 } |
893 | 895 |
894 __ Bind(&wrong_num_arguments); | 896 __ Bind(&wrong_num_arguments); |
895 if (function.IsClosureFunction()) { | 897 if (function.IsClosureFunction()) { |
896 // Invoke noSuchMethod function passing "call" as the original name. | 898 // Invoke noSuchMethod function passing "call" as the original name. |
| 899 StubCode* stub_code = isolate()->stub_code(); |
897 const int kNumArgsChecked = 1; | 900 const int kNumArgsChecked = 1; |
898 const ICData& ic_data = ICData::ZoneHandle( | 901 const ICData& ic_data = ICData::ZoneHandle( |
899 ICData::New(function, Symbols::Call(), Object::empty_array(), | 902 ICData::New(function, Symbols::Call(), Object::empty_array(), |
900 Isolate::kNoDeoptId, kNumArgsChecked)); | 903 Isolate::kNoDeoptId, kNumArgsChecked)); |
901 __ LoadObject(R5, ic_data); | 904 __ LoadObject(R5, ic_data); |
902 __ LeaveDartFrame(); // The arguments are still on the stack. | 905 __ LeaveDartFrame(); // The arguments are still on the stack. |
903 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); | 906 __ Branch(&stub_code->CallNoSuchMethodFunctionLabel()); |
904 // The noSuchMethod call may return to the caller, but not here. | 907 // The noSuchMethod call may return to the caller, but not here. |
905 __ bkpt(0); | 908 __ bkpt(0); |
906 } else if (check_correct_named_args) { | 909 } else if (check_correct_named_args) { |
907 __ Stop("Wrong arguments"); | 910 __ Stop("Wrong arguments"); |
908 } | 911 } |
909 | 912 |
910 __ Bind(&all_arguments_processed); | 913 __ Bind(&all_arguments_processed); |
911 // Nullify originally passed arguments only after they have been copied and | 914 // Nullify originally passed arguments only after they have been copied and |
912 // checked, otherwise noSuchMethod would not see their original values. | 915 // checked, otherwise noSuchMethod would not see their original values. |
913 // This step can be skipped in case we decide that formal parameters are | 916 // This step can be skipped in case we decide that formal parameters are |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
954 __ Ret(); | 957 __ Ret(); |
955 } | 958 } |
956 | 959 |
957 | 960 |
958 void FlowGraphCompiler::EmitFrameEntry() { | 961 void FlowGraphCompiler::EmitFrameEntry() { |
959 const Function& function = parsed_function().function(); | 962 const Function& function = parsed_function().function(); |
960 if (CanOptimizeFunction() && | 963 if (CanOptimizeFunction() && |
961 function.IsOptimizable() && | 964 function.IsOptimizable() && |
962 (!is_optimizing() || may_reoptimize())) { | 965 (!is_optimizing() || may_reoptimize())) { |
963 const Register function_reg = R6; | 966 const Register function_reg = R6; |
| 967 StubCode* stub_code = isolate()->stub_code(); |
964 | 968 |
965 // The pool pointer is not setup before entering the Dart frame. | 969 // The pool pointer is not setup before entering the Dart frame. |
966 // Preserve PP of caller. | 970 // Preserve PP of caller. |
967 __ mov(R7, Operand(PP)); | 971 __ mov(R7, Operand(PP)); |
968 // Temporarily setup pool pointer for this dart function. | 972 // Temporarily setup pool pointer for this dart function. |
969 __ LoadPoolPointer(); | 973 __ LoadPoolPointer(); |
970 // Load function object from object pool. | 974 // Load function object from object pool. |
971 __ LoadObject(function_reg, function); // Uses PP. | 975 __ LoadObject(function_reg, function); // Uses PP. |
972 // Restore PP of caller. | 976 // Restore PP of caller. |
973 __ mov(PP, Operand(R7)); | 977 __ mov(PP, Operand(R7)); |
974 | 978 |
975 // Patch point is after the eventually inlined function object. | 979 // Patch point is after the eventually inlined function object. |
976 entry_patch_pc_offset_ = assembler()->CodeSize(); | 980 entry_patch_pc_offset_ = assembler()->CodeSize(); |
977 | 981 |
978 intptr_t threshold = FLAG_optimization_counter_threshold; | 982 intptr_t threshold = FLAG_optimization_counter_threshold; |
979 __ ldr(R7, FieldAddress(function_reg, | 983 __ ldr(R7, FieldAddress(function_reg, |
980 Function::usage_counter_offset())); | 984 Function::usage_counter_offset())); |
981 if (is_optimizing()) { | 985 if (is_optimizing()) { |
982 // Reoptimization of an optimized function is triggered by counting in | 986 // Reoptimization of an optimized function is triggered by counting in |
983 // IC stubs, but not at the entry of the function. | 987 // IC stubs, but not at the entry of the function. |
984 threshold = FLAG_reoptimization_counter_threshold; | 988 threshold = FLAG_reoptimization_counter_threshold; |
985 } else { | 989 } else { |
986 __ add(R7, R7, Operand(1)); | 990 __ add(R7, R7, Operand(1)); |
987 __ str(R7, FieldAddress(function_reg, | 991 __ str(R7, FieldAddress(function_reg, |
988 Function::usage_counter_offset())); | 992 Function::usage_counter_offset())); |
989 } | 993 } |
990 __ CompareImmediate(R7, threshold); | 994 __ CompareImmediate(R7, threshold); |
991 ASSERT(function_reg == R6); | 995 ASSERT(function_reg == R6); |
992 __ Branch(&StubCode::OptimizeFunctionLabel(), GE); | 996 __ Branch(&stub_code->OptimizeFunctionLabel(), GE); |
993 } else if (!flow_graph().IsCompiledForOsr()) { | 997 } else if (!flow_graph().IsCompiledForOsr()) { |
994 entry_patch_pc_offset_ = assembler()->CodeSize(); | 998 entry_patch_pc_offset_ = assembler()->CodeSize(); |
995 } | 999 } |
996 __ Comment("Enter frame"); | 1000 __ Comment("Enter frame"); |
997 if (flow_graph().IsCompiledForOsr()) { | 1001 if (flow_graph().IsCompiledForOsr()) { |
998 intptr_t extra_slots = StackSize() | 1002 intptr_t extra_slots = StackSize() |
999 - flow_graph().num_stack_locals() | 1003 - flow_graph().num_stack_locals() |
1000 - flow_graph().num_copied_params(); | 1004 - flow_graph().num_copied_params(); |
1001 ASSERT(extra_slots >= 0); | 1005 ASSERT(extra_slots >= 0); |
1002 __ EnterOsrFrame(extra_slots * kWordSize); | 1006 __ EnterOsrFrame(extra_slots * kWordSize); |
(...skipping 16 matching lines...) Expand all Loading... |
1019 | 1023 |
1020 TryIntrinsify(); | 1024 TryIntrinsify(); |
1021 | 1025 |
1022 EmitFrameEntry(); | 1026 EmitFrameEntry(); |
1023 | 1027 |
1024 const Function& function = parsed_function().function(); | 1028 const Function& function = parsed_function().function(); |
1025 | 1029 |
1026 const int num_fixed_params = function.num_fixed_parameters(); | 1030 const int num_fixed_params = function.num_fixed_parameters(); |
1027 const int num_copied_params = parsed_function().num_copied_params(); | 1031 const int num_copied_params = parsed_function().num_copied_params(); |
1028 const int num_locals = parsed_function().num_stack_locals(); | 1032 const int num_locals = parsed_function().num_stack_locals(); |
| 1033 StubCode* stub_code = isolate()->stub_code(); |
1029 | 1034 |
1030 // We check the number of passed arguments when we have to copy them due to | 1035 // We check the number of passed arguments when we have to copy them due to |
1031 // the presence of optional parameters. | 1036 // the presence of optional parameters. |
1032 // No such checking code is generated if only fixed parameters are declared, | 1037 // No such checking code is generated if only fixed parameters are declared, |
1033 // unless we are in debug mode or unless we are compiling a closure. | 1038 // unless we are in debug mode or unless we are compiling a closure. |
1034 if (num_copied_params == 0) { | 1039 if (num_copied_params == 0) { |
1035 #ifdef DEBUG | 1040 #ifdef DEBUG |
1036 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1041 ASSERT(!parsed_function().function().HasOptionalParameters()); |
1037 const bool check_arguments = !flow_graph().IsCompiledForOsr(); | 1042 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
1038 #else | 1043 #else |
(...skipping 18 matching lines...) Expand all Loading... |
1057 const String& name = | 1062 const String& name = |
1058 String::Handle(function.IsClosureFunction() | 1063 String::Handle(function.IsClosureFunction() |
1059 ? Symbols::Call().raw() | 1064 ? Symbols::Call().raw() |
1060 : function.name()); | 1065 : function.name()); |
1061 const int kNumArgsChecked = 1; | 1066 const int kNumArgsChecked = 1; |
1062 const ICData& ic_data = ICData::ZoneHandle( | 1067 const ICData& ic_data = ICData::ZoneHandle( |
1063 ICData::New(function, name, Object::empty_array(), | 1068 ICData::New(function, name, Object::empty_array(), |
1064 Isolate::kNoDeoptId, kNumArgsChecked)); | 1069 Isolate::kNoDeoptId, kNumArgsChecked)); |
1065 __ LoadObject(R5, ic_data); | 1070 __ LoadObject(R5, ic_data); |
1066 __ LeaveDartFrame(); // The arguments are still on the stack. | 1071 __ LeaveDartFrame(); // The arguments are still on the stack. |
1067 __ Branch(&StubCode::CallNoSuchMethodFunctionLabel()); | 1072 __ Branch(&stub_code->CallNoSuchMethodFunctionLabel()); |
1068 // The noSuchMethod call may return to the caller, but not here. | 1073 // The noSuchMethod call may return to the caller, but not here. |
1069 __ bkpt(0); | 1074 __ bkpt(0); |
1070 } else { | 1075 } else { |
1071 __ Stop("Wrong number of arguments"); | 1076 __ Stop("Wrong number of arguments"); |
1072 } | 1077 } |
1073 __ Bind(&correct_num_arguments); | 1078 __ Bind(&correct_num_arguments); |
1074 } | 1079 } |
1075 } else if (!flow_graph().IsCompiledForOsr()) { | 1080 } else if (!flow_graph().IsCompiledForOsr()) { |
1076 CopyParameters(); | 1081 CopyParameters(); |
1077 } | 1082 } |
(...skipping 10 matching lines...) Expand all Loading... |
1088 } | 1093 } |
1089 } | 1094 } |
1090 | 1095 |
1091 VisitBlocks(); | 1096 VisitBlocks(); |
1092 | 1097 |
1093 __ bkpt(0); | 1098 __ bkpt(0); |
1094 GenerateDeferredCode(); | 1099 GenerateDeferredCode(); |
1095 // Emit function patching code. This will be swapped with the first 3 | 1100 // Emit function patching code. This will be swapped with the first 3 |
1096 // instructions at entry point. | 1101 // instructions at entry point. |
1097 patch_code_pc_offset_ = assembler()->CodeSize(); | 1102 patch_code_pc_offset_ = assembler()->CodeSize(); |
1098 __ BranchPatchable(&StubCode::FixCallersTargetLabel()); | 1103 __ BranchPatchable(&stub_code->FixCallersTargetLabel()); |
1099 | 1104 |
1100 if (is_optimizing()) { | 1105 if (is_optimizing()) { |
1101 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1106 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1102 __ Branch(&StubCode::DeoptimizeLazyLabel()); | 1107 __ Branch(&stub_code->DeoptimizeLazyLabel()); |
1103 } | 1108 } |
1104 } | 1109 } |
1105 | 1110 |
1106 | 1111 |
1107 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1112 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1108 const ExternalLabel* label, | 1113 const ExternalLabel* label, |
1109 PcDescriptors::Kind kind, | 1114 PcDescriptors::Kind kind, |
1110 LocationSummary* locs) { | 1115 LocationSummary* locs) { |
1111 __ BranchLinkPatchable(label); | 1116 __ BranchLinkPatchable(label); |
1112 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1117 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1284 } | 1289 } |
1285 | 1290 |
1286 | 1291 |
1287 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1292 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1288 intptr_t argument_count, | 1293 intptr_t argument_count, |
1289 intptr_t deopt_id, | 1294 intptr_t deopt_id, |
1290 intptr_t token_pos, | 1295 intptr_t token_pos, |
1291 LocationSummary* locs, | 1296 LocationSummary* locs, |
1292 const ICData& ic_data) { | 1297 const ICData& ic_data) { |
1293 uword label_address = 0; | 1298 uword label_address = 0; |
| 1299 StubCode* stub_code = isolate()->stub_code(); |
1294 if (ic_data.NumArgsTested() == 0) { | 1300 if (ic_data.NumArgsTested() == 0) { |
1295 label_address = StubCode::ZeroArgsUnoptimizedStaticCallEntryPoint(); | 1301 label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint(); |
1296 } else if (ic_data.NumArgsTested() == 2) { | 1302 } else if (ic_data.NumArgsTested() == 2) { |
1297 label_address = StubCode::TwoArgsUnoptimizedStaticCallEntryPoint(); | 1303 label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint(); |
1298 } else { | 1304 } else { |
1299 UNIMPLEMENTED(); | 1305 UNIMPLEMENTED(); |
1300 } | 1306 } |
1301 ExternalLabel target_label(label_address); | 1307 ExternalLabel target_label(label_address); |
1302 __ LoadImmediate(R4, 0); | 1308 __ LoadImmediate(R4, 0); |
1303 __ LoadObject(R5, ic_data); | 1309 __ LoadObject(R5, ic_data); |
1304 GenerateDartCall(deopt_id, | 1310 GenerateDartCall(deopt_id, |
1305 token_pos, | 1311 token_pos, |
1306 &target_label, | 1312 &target_label, |
1307 PcDescriptors::kUnoptStaticCall, | 1313 PcDescriptors::kUnoptStaticCall, |
1308 locs); | 1314 locs); |
1309 __ Drop(argument_count); | 1315 __ Drop(argument_count); |
1310 #if defined(DEBUG) | 1316 #if defined(DEBUG) |
1311 __ LoadImmediate(R4, kInvalidObjectPointer); | 1317 __ LoadImmediate(R4, kInvalidObjectPointer); |
1312 #endif | 1318 #endif |
1313 } | 1319 } |
1314 | 1320 |
1315 | 1321 |
1316 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1322 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1317 const Function& function, | 1323 const Function& function, |
1318 const Array& arguments_descriptor, | 1324 const Array& arguments_descriptor, |
1319 intptr_t argument_count, | 1325 intptr_t argument_count, |
1320 intptr_t deopt_id, | 1326 intptr_t deopt_id, |
1321 intptr_t token_pos, | 1327 intptr_t token_pos, |
1322 LocationSummary* locs) { | 1328 LocationSummary* locs) { |
| 1329 StubCode* stub_code = isolate()->stub_code(); |
1323 __ LoadObject(R4, arguments_descriptor); | 1330 __ LoadObject(R4, arguments_descriptor); |
1324 // Do not use the code from the function, but let the code be patched so that | 1331 // Do not use the code from the function, but let the code be patched so that |
1325 // we can record the outgoing edges to other code. | 1332 // we can record the outgoing edges to other code. |
1326 GenerateDartCall(deopt_id, | 1333 GenerateDartCall(deopt_id, |
1327 token_pos, | 1334 token_pos, |
1328 &StubCode::CallStaticFunctionLabel(), | 1335 &stub_code->CallStaticFunctionLabel(), |
1329 PcDescriptors::kOptStaticCall, | 1336 PcDescriptors::kOptStaticCall, |
1330 locs); | 1337 locs); |
1331 AddStaticCallTarget(function); | 1338 AddStaticCallTarget(function); |
1332 __ Drop(argument_count); | 1339 __ Drop(argument_count); |
1333 } | 1340 } |
1334 | 1341 |
1335 | 1342 |
1336 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, | 1343 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, |
1337 const Object& obj, | 1344 const Object& obj, |
1338 bool needs_number_check, | 1345 bool needs_number_check, |
1339 intptr_t token_pos) { | 1346 intptr_t token_pos) { |
1340 if (needs_number_check) { | 1347 if (needs_number_check) { |
| 1348 StubCode* stub_code = isolate()->stub_code(); |
1341 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1349 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1342 __ Push(reg); | 1350 __ Push(reg); |
1343 __ PushObject(obj); | 1351 __ PushObject(obj); |
1344 if (is_optimizing()) { | 1352 if (is_optimizing()) { |
1345 __ BranchLinkPatchable( | 1353 __ BranchLinkPatchable( |
1346 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1354 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); |
1347 } else { | 1355 } else { |
1348 __ BranchLinkPatchable( | 1356 __ BranchLinkPatchable( |
1349 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1357 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); |
1350 } | 1358 } |
1351 if (token_pos != Scanner::kNoSourcePos) { | 1359 if (token_pos != Scanner::kNoSourcePos) { |
1352 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, | 1360 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, |
1353 Isolate::kNoDeoptId, | 1361 Isolate::kNoDeoptId, |
1354 token_pos); | 1362 token_pos); |
1355 } | 1363 } |
1356 __ Drop(1); // Discard constant. | 1364 __ Drop(1); // Discard constant. |
1357 __ Pop(reg); // Restore 'reg'. | 1365 __ Pop(reg); // Restore 'reg'. |
1358 return; | 1366 return; |
1359 } | 1367 } |
1360 | 1368 |
1361 __ CompareObject(reg, obj); | 1369 __ CompareObject(reg, obj); |
1362 } | 1370 } |
1363 | 1371 |
1364 | 1372 |
1365 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1373 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1366 Register right, | 1374 Register right, |
1367 bool needs_number_check, | 1375 bool needs_number_check, |
1368 intptr_t token_pos) { | 1376 intptr_t token_pos) { |
1369 if (needs_number_check) { | 1377 if (needs_number_check) { |
| 1378 StubCode* stub_code = isolate()->stub_code(); |
1370 __ Push(left); | 1379 __ Push(left); |
1371 __ Push(right); | 1380 __ Push(right); |
1372 if (is_optimizing()) { | 1381 if (is_optimizing()) { |
1373 __ BranchLinkPatchable( | 1382 __ BranchLinkPatchable( |
1374 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); | 1383 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); |
1375 } else { | 1384 } else { |
1376 __ LoadImmediate(R4, 0); | 1385 __ LoadImmediate(R4, 0); |
1377 __ LoadImmediate(R5, 0); | 1386 __ LoadImmediate(R5, 0); |
1378 __ BranchLinkPatchable( | 1387 __ BranchLinkPatchable( |
1379 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); | 1388 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); |
1380 } | 1389 } |
1381 if (token_pos != Scanner::kNoSourcePos) { | 1390 if (token_pos != Scanner::kNoSourcePos) { |
1382 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, | 1391 AddCurrentDescriptor(PcDescriptors::kRuntimeCall, |
1383 Isolate::kNoDeoptId, | 1392 Isolate::kNoDeoptId, |
1384 token_pos); | 1393 token_pos); |
1385 } | 1394 } |
1386 #if defined(DEBUG) | 1395 #if defined(DEBUG) |
1387 if (!is_optimizing()) { | 1396 if (!is_optimizing()) { |
1388 // Do this *after* adding the pc descriptor! | 1397 // Do this *after* adding the pc descriptor! |
1389 __ LoadImmediate(R4, kInvalidObjectPointer); | 1398 __ LoadImmediate(R4, kInvalidObjectPointer); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); | 1490 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); |
1482 Label match_found; | 1491 Label match_found; |
1483 const intptr_t len = ic_data.NumberOfChecks(); | 1492 const intptr_t len = ic_data.NumberOfChecks(); |
1484 GrowableArray<CidTarget> sorted(len); | 1493 GrowableArray<CidTarget> sorted(len); |
1485 SortICDataByCount(ic_data, &sorted); | 1494 SortICDataByCount(ic_data, &sorted); |
1486 ASSERT(class_id_reg != R4); | 1495 ASSERT(class_id_reg != R4); |
1487 ASSERT(len > 0); // Why bother otherwise. | 1496 ASSERT(len > 0); // Why bother otherwise. |
1488 const Array& arguments_descriptor = | 1497 const Array& arguments_descriptor = |
1489 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 1498 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
1490 argument_names)); | 1499 argument_names)); |
| 1500 StubCode* stub_code = isolate()->stub_code(); |
| 1501 |
1491 __ LoadObject(R4, arguments_descriptor); | 1502 __ LoadObject(R4, arguments_descriptor); |
1492 for (intptr_t i = 0; i < len; i++) { | 1503 for (intptr_t i = 0; i < len; i++) { |
1493 const bool is_last_check = (i == (len - 1)); | 1504 const bool is_last_check = (i == (len - 1)); |
1494 Label next_test; | 1505 Label next_test; |
1495 __ CompareImmediate(class_id_reg, sorted[i].cid); | 1506 __ CompareImmediate(class_id_reg, sorted[i].cid); |
1496 if (is_last_check) { | 1507 if (is_last_check) { |
1497 __ b(deopt, NE); | 1508 __ b(deopt, NE); |
1498 } else { | 1509 } else { |
1499 __ b(&next_test, NE); | 1510 __ b(&next_test, NE); |
1500 } | 1511 } |
1501 // Do not use the code from the function, but let the code be patched so | 1512 // Do not use the code from the function, but let the code be patched so |
1502 // that we can record the outgoing edges to other code. | 1513 // that we can record the outgoing edges to other code. |
1503 GenerateDartCall(deopt_id, | 1514 GenerateDartCall(deopt_id, |
1504 token_index, | 1515 token_index, |
1505 &StubCode::CallStaticFunctionLabel(), | 1516 &stub_code->CallStaticFunctionLabel(), |
1506 PcDescriptors::kOptStaticCall, | 1517 PcDescriptors::kOptStaticCall, |
1507 locs); | 1518 locs); |
1508 const Function& function = *sorted[i].target; | 1519 const Function& function = *sorted[i].target; |
1509 AddStaticCallTarget(function); | 1520 AddStaticCallTarget(function); |
1510 __ Drop(argument_count); | 1521 __ Drop(argument_count); |
1511 if (!is_last_check) { | 1522 if (!is_last_check) { |
1512 __ b(&match_found); | 1523 __ b(&match_found); |
1513 } | 1524 } |
1514 __ Bind(&next_test); | 1525 __ Bind(&next_test); |
1515 } | 1526 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 DRegister dreg = EvenDRegisterOf(reg); | 1773 DRegister dreg = EvenDRegisterOf(reg); |
1763 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1774 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
1764 } | 1775 } |
1765 | 1776 |
1766 | 1777 |
1767 #undef __ | 1778 #undef __ |
1768 | 1779 |
1769 } // namespace dart | 1780 } // namespace dart |
1770 | 1781 |
1771 #endif // defined TARGET_ARCH_ARM | 1782 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |