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 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
187 Assembler* assem = compiler->assembler(); | 187 Assembler* assem = compiler->assembler(); |
188 #define __ assem-> | 188 #define __ assem-> |
189 __ Comment("%s", Name()); | 189 __ Comment("%s", Name()); |
190 __ Bind(entry_label()); | 190 __ Bind(entry_label()); |
191 if (FLAG_trap_on_deoptimization) { | 191 if (FLAG_trap_on_deoptimization) { |
192 __ bkpt(0); | 192 __ bkpt(0); |
193 } | 193 } |
194 | 194 |
195 ASSERT(deopt_env() != NULL); | 195 ASSERT(deopt_env() != NULL); |
196 | 196 |
197 StubCode* stub_code = compiler->isolate()->stub_code(); | |
198 // LR may be live. It will be clobbered by BranchLink, so cache it in IP. | 197 // LR may be live. It will be clobbered by BranchLink, so cache it in IP. |
199 // It will be restored at the top of the deoptimization stub, specifically in | 198 // It will be restored at the top of the deoptimization stub, specifically in |
200 // GenerateDeoptimizationSequence in stub_code_arm.cc. | 199 // GenerateDeoptimizationSequence in stub_code_arm.cc. |
201 __ mov(IP, Operand(LR)); | 200 __ mov(IP, Operand(LR)); |
202 __ BranchLink(&stub_code->DeoptimizeLabel()); | 201 __ BranchLink(&StubCode::DeoptimizeLabel()); |
koda
2015/07/23 00:58:01
True already before your change, but even more obv
Florian Schneider
2015/07/23 10:43:22
I would also prefer a const-reference. I'll see if
| |
203 set_pc_offset(assem->CodeSize()); | 202 set_pc_offset(assem->CodeSize()); |
204 #undef __ | 203 #undef __ |
205 } | 204 } |
206 | 205 |
207 | 206 |
208 #define __ assembler()-> | 207 #define __ assembler()-> |
209 | 208 |
210 | 209 |
211 // Fall through if bool_register contains null. | 210 // Fall through if bool_register contains null. |
212 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 211 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
(...skipping 16 matching lines...) Expand all Loading... | |
229 TypeTestStubKind test_kind, | 228 TypeTestStubKind test_kind, |
230 Register instance_reg, | 229 Register instance_reg, |
231 Register type_arguments_reg, | 230 Register type_arguments_reg, |
232 Register temp_reg, | 231 Register temp_reg, |
233 Label* is_instance_lbl, | 232 Label* is_instance_lbl, |
234 Label* is_not_instance_lbl) { | 233 Label* is_not_instance_lbl) { |
235 ASSERT(instance_reg == R0); | 234 ASSERT(instance_reg == R0); |
236 ASSERT(temp_reg == kNoRegister); // Unused on ARM. | 235 ASSERT(temp_reg == kNoRegister); // Unused on ARM. |
237 const SubtypeTestCache& type_test_cache = | 236 const SubtypeTestCache& type_test_cache = |
238 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); | 237 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
239 StubCode* stub_code = isolate()->stub_code(); | |
240 __ LoadUniqueObject(R2, type_test_cache); | 238 __ LoadUniqueObject(R2, type_test_cache); |
241 if (test_kind == kTestTypeOneArg) { | 239 if (test_kind == kTestTypeOneArg) { |
242 ASSERT(type_arguments_reg == kNoRegister); | 240 ASSERT(type_arguments_reg == kNoRegister); |
243 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 241 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
244 __ BranchLink(&stub_code->Subtype1TestCacheLabel()); | 242 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); |
245 } else if (test_kind == kTestTypeTwoArgs) { | 243 } else if (test_kind == kTestTypeTwoArgs) { |
246 ASSERT(type_arguments_reg == kNoRegister); | 244 ASSERT(type_arguments_reg == kNoRegister); |
247 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); | 245 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
248 __ BranchLink(&stub_code->Subtype2TestCacheLabel()); | 246 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); |
249 } else if (test_kind == kTestTypeThreeArgs) { | 247 } else if (test_kind == kTestTypeThreeArgs) { |
250 ASSERT(type_arguments_reg == R1); | 248 ASSERT(type_arguments_reg == R1); |
251 __ BranchLink(&stub_code->Subtype3TestCacheLabel()); | 249 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
252 } else { | 250 } else { |
253 UNREACHABLE(); | 251 UNREACHABLE(); |
254 } | 252 } |
255 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. | 253 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. |
256 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); | 254 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); |
257 return type_test_cache.raw(); | 255 return type_test_cache.raw(); |
258 } | 256 } |
259 | 257 |
260 | 258 |
261 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 259 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
916 __ SmiUntag(R7); | 914 __ SmiUntag(R7); |
917 // Check that R9 equals R7, i.e. no named arguments passed. | 915 // Check that R9 equals R7, i.e. no named arguments passed. |
918 __ cmp(R9, Operand(R7)); | 916 __ cmp(R9, Operand(R7)); |
919 __ b(&all_arguments_processed, EQ); | 917 __ b(&all_arguments_processed, EQ); |
920 } | 918 } |
921 } | 919 } |
922 | 920 |
923 __ Bind(&wrong_num_arguments); | 921 __ Bind(&wrong_num_arguments); |
924 if (function.IsClosureFunction()) { | 922 if (function.IsClosureFunction()) { |
925 __ LeaveDartFrame(); // The arguments are still on the stack. | 923 __ LeaveDartFrame(); // The arguments are still on the stack. |
926 __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel()); | 924 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
927 // The noSuchMethod call may return to the caller, but not here. | 925 // The noSuchMethod call may return to the caller, but not here. |
928 } else if (check_correct_named_args) { | 926 } else if (check_correct_named_args) { |
929 __ Stop("Wrong arguments"); | 927 __ Stop("Wrong arguments"); |
930 } | 928 } |
931 | 929 |
932 __ Bind(&all_arguments_processed); | 930 __ Bind(&all_arguments_processed); |
933 // Nullify originally passed arguments only after they have been copied and | 931 // Nullify originally passed arguments only after they have been copied and |
934 // checked, otherwise noSuchMethod would not see their original values. | 932 // checked, otherwise noSuchMethod would not see their original values. |
935 // This step can be skipped in case we decide that formal parameters are | 933 // This step can be skipped in case we decide that formal parameters are |
936 // implicitly final, since garbage collecting the unmodified value is not | 934 // implicitly final, since garbage collecting the unmodified value is not |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
976 __ Ret(); | 974 __ Ret(); |
977 } | 975 } |
978 | 976 |
979 | 977 |
980 void FlowGraphCompiler::EmitFrameEntry() { | 978 void FlowGraphCompiler::EmitFrameEntry() { |
981 const Function& function = parsed_function().function(); | 979 const Function& function = parsed_function().function(); |
982 if (CanOptimizeFunction() && | 980 if (CanOptimizeFunction() && |
983 function.IsOptimizable() && | 981 function.IsOptimizable() && |
984 (!is_optimizing() || may_reoptimize())) { | 982 (!is_optimizing() || may_reoptimize())) { |
985 const Register function_reg = R6; | 983 const Register function_reg = R6; |
986 StubCode* stub_code = isolate()->stub_code(); | |
987 | 984 |
988 // The pool pointer is not setup before entering the Dart frame. | 985 // The pool pointer is not setup before entering the Dart frame. |
989 // Preserve PP of caller. | 986 // Preserve PP of caller. |
990 __ mov(R7, Operand(PP)); | 987 __ mov(R7, Operand(PP)); |
991 // Temporarily setup pool pointer for this dart function. | 988 // Temporarily setup pool pointer for this dart function. |
992 __ LoadPoolPointer(); | 989 __ LoadPoolPointer(); |
993 // Load function object from object pool. | 990 // Load function object from object pool. |
994 __ LoadObject(function_reg, function); // Uses PP. | 991 __ LoadObject(function_reg, function); // Uses PP. |
995 // Restore PP of caller. | 992 // Restore PP of caller. |
996 __ mov(PP, Operand(R7)); | 993 __ mov(PP, Operand(R7)); |
997 | 994 |
998 // Patch point is after the eventually inlined function object. | 995 // Patch point is after the eventually inlined function object. |
999 entry_patch_pc_offset_ = assembler()->CodeSize(); | 996 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1000 | 997 |
1001 __ ldr(R7, FieldAddress(function_reg, | 998 __ ldr(R7, FieldAddress(function_reg, |
1002 Function::usage_counter_offset())); | 999 Function::usage_counter_offset())); |
1003 // Reoptimization of an optimized function is triggered by counting in | 1000 // Reoptimization of an optimized function is triggered by counting in |
1004 // IC stubs, but not at the entry of the function. | 1001 // IC stubs, but not at the entry of the function. |
1005 if (!is_optimizing()) { | 1002 if (!is_optimizing()) { |
1006 __ add(R7, R7, Operand(1)); | 1003 __ add(R7, R7, Operand(1)); |
1007 __ str(R7, FieldAddress(function_reg, | 1004 __ str(R7, FieldAddress(function_reg, |
1008 Function::usage_counter_offset())); | 1005 Function::usage_counter_offset())); |
1009 } | 1006 } |
1010 __ CompareImmediate(R7, GetOptimizationThreshold()); | 1007 __ CompareImmediate(R7, GetOptimizationThreshold()); |
1011 ASSERT(function_reg == R6); | 1008 ASSERT(function_reg == R6); |
1012 __ Branch(&stub_code->OptimizeFunctionLabel(), GE); | 1009 __ Branch(&StubCode::OptimizeFunctionLabel(), GE); |
1013 } else if (!flow_graph().IsCompiledForOsr()) { | 1010 } else if (!flow_graph().IsCompiledForOsr()) { |
1014 entry_patch_pc_offset_ = assembler()->CodeSize(); | 1011 entry_patch_pc_offset_ = assembler()->CodeSize(); |
1015 } | 1012 } |
1016 __ Comment("Enter frame"); | 1013 __ Comment("Enter frame"); |
1017 if (flow_graph().IsCompiledForOsr()) { | 1014 if (flow_graph().IsCompiledForOsr()) { |
1018 intptr_t extra_slots = StackSize() | 1015 intptr_t extra_slots = StackSize() |
1019 - flow_graph().num_stack_locals() | 1016 - flow_graph().num_stack_locals() |
1020 - flow_graph().num_copied_params(); | 1017 - flow_graph().num_copied_params(); |
1021 ASSERT(extra_slots >= 0); | 1018 ASSERT(extra_slots >= 0); |
1022 __ EnterOsrFrame(extra_slots * kWordSize); | 1019 __ EnterOsrFrame(extra_slots * kWordSize); |
(...skipping 16 matching lines...) Expand all Loading... | |
1039 | 1036 |
1040 TryIntrinsify(); | 1037 TryIntrinsify(); |
1041 | 1038 |
1042 EmitFrameEntry(); | 1039 EmitFrameEntry(); |
1043 | 1040 |
1044 const Function& function = parsed_function().function(); | 1041 const Function& function = parsed_function().function(); |
1045 | 1042 |
1046 const int num_fixed_params = function.num_fixed_parameters(); | 1043 const int num_fixed_params = function.num_fixed_parameters(); |
1047 const int num_copied_params = parsed_function().num_copied_params(); | 1044 const int num_copied_params = parsed_function().num_copied_params(); |
1048 const int num_locals = parsed_function().num_stack_locals(); | 1045 const int num_locals = parsed_function().num_stack_locals(); |
1049 StubCode* stub_code = isolate()->stub_code(); | |
1050 | 1046 |
1051 // We check the number of passed arguments when we have to copy them due to | 1047 // We check the number of passed arguments when we have to copy them due to |
1052 // the presence of optional parameters. | 1048 // the presence of optional parameters. |
1053 // No such checking code is generated if only fixed parameters are declared, | 1049 // No such checking code is generated if only fixed parameters are declared, |
1054 // unless we are in debug mode or unless we are compiling a closure. | 1050 // unless we are in debug mode or unless we are compiling a closure. |
1055 if (num_copied_params == 0) { | 1051 if (num_copied_params == 0) { |
1056 #ifdef DEBUG | 1052 #ifdef DEBUG |
1057 ASSERT(!parsed_function().function().HasOptionalParameters()); | 1053 ASSERT(!parsed_function().function().HasOptionalParameters()); |
1058 const bool check_arguments = !flow_graph().IsCompiledForOsr(); | 1054 const bool check_arguments = !flow_graph().IsCompiledForOsr(); |
1059 #else | 1055 #else |
1060 const bool check_arguments = | 1056 const bool check_arguments = |
1061 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); | 1057 function.IsClosureFunction() && !flow_graph().IsCompiledForOsr(); |
1062 #endif | 1058 #endif |
1063 if (check_arguments) { | 1059 if (check_arguments) { |
1064 __ Comment("Check argument count"); | 1060 __ Comment("Check argument count"); |
1065 // Check that exactly num_fixed arguments are passed in. | 1061 // Check that exactly num_fixed arguments are passed in. |
1066 Label correct_num_arguments, wrong_num_arguments; | 1062 Label correct_num_arguments, wrong_num_arguments; |
1067 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1063 __ ldr(R0, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
1068 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); | 1064 __ CompareImmediate(R0, Smi::RawValue(num_fixed_params)); |
1069 __ b(&wrong_num_arguments, NE); | 1065 __ b(&wrong_num_arguments, NE); |
1070 __ ldr(R1, FieldAddress(R4, | 1066 __ ldr(R1, FieldAddress(R4, |
1071 ArgumentsDescriptor::positional_count_offset())); | 1067 ArgumentsDescriptor::positional_count_offset())); |
1072 __ cmp(R0, Operand(R1)); | 1068 __ cmp(R0, Operand(R1)); |
1073 __ b(&correct_num_arguments, EQ); | 1069 __ b(&correct_num_arguments, EQ); |
1074 __ Bind(&wrong_num_arguments); | 1070 __ Bind(&wrong_num_arguments); |
1075 if (function.IsClosureFunction()) { | 1071 if (function.IsClosureFunction()) { |
1076 __ LeaveDartFrame(); // The arguments are still on the stack. | 1072 __ LeaveDartFrame(); // The arguments are still on the stack. |
1077 __ Branch(&isolate()->stub_code()->CallClosureNoSuchMethodLabel()); | 1073 __ Branch(&StubCode::CallClosureNoSuchMethodLabel()); |
1078 // The noSuchMethod call may return to the caller, but not here. | 1074 // The noSuchMethod call may return to the caller, but not here. |
1079 } else { | 1075 } else { |
1080 __ Stop("Wrong number of arguments"); | 1076 __ Stop("Wrong number of arguments"); |
1081 } | 1077 } |
1082 __ Bind(&correct_num_arguments); | 1078 __ Bind(&correct_num_arguments); |
1083 } | 1079 } |
1084 } else if (!flow_graph().IsCompiledForOsr()) { | 1080 } else if (!flow_graph().IsCompiledForOsr()) { |
1085 CopyParameters(); | 1081 CopyParameters(); |
1086 } | 1082 } |
1087 | 1083 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1122 } | 1118 } |
1123 } | 1119 } |
1124 | 1120 |
1125 VisitBlocks(); | 1121 VisitBlocks(); |
1126 | 1122 |
1127 __ bkpt(0); | 1123 __ bkpt(0); |
1128 GenerateDeferredCode(); | 1124 GenerateDeferredCode(); |
1129 // Emit function patching code. This will be swapped with the first 3 | 1125 // Emit function patching code. This will be swapped with the first 3 |
1130 // instructions at entry point. | 1126 // instructions at entry point. |
1131 patch_code_pc_offset_ = assembler()->CodeSize(); | 1127 patch_code_pc_offset_ = assembler()->CodeSize(); |
1132 __ BranchPatchable(&stub_code->FixCallersTargetLabel()); | 1128 __ BranchPatchable(&StubCode::FixCallersTargetLabel()); |
1133 | 1129 |
1134 if (is_optimizing()) { | 1130 if (is_optimizing()) { |
1135 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1131 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1136 __ Branch(&stub_code->DeoptimizeLazyLabel()); | 1132 __ Branch(&StubCode::DeoptimizeLazyLabel()); |
1137 } | 1133 } |
1138 } | 1134 } |
1139 | 1135 |
1140 | 1136 |
1141 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1137 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, |
1142 const ExternalLabel* label, | 1138 const ExternalLabel* label, |
1143 RawPcDescriptors::Kind kind, | 1139 RawPcDescriptors::Kind kind, |
1144 LocationSummary* locs) { | 1140 LocationSummary* locs) { |
1145 __ BranchLinkPatchable(label); | 1141 __ BranchLinkPatchable(label); |
1146 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); | 1142 AddCurrentDescriptor(kind, Isolate::kNoDeoptId, token_pos); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1288 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1284 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
1289 const MegamorphicCache& cache = | 1285 const MegamorphicCache& cache = |
1290 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); | 1286 MegamorphicCache::ZoneHandle(table->Lookup(name, arguments_descriptor)); |
1291 const Register receiverR = R0; | 1287 const Register receiverR = R0; |
1292 const Register cacheR = R1; | 1288 const Register cacheR = R1; |
1293 const Register targetR = R1; | 1289 const Register targetR = R1; |
1294 __ LoadFromOffset(kWord, receiverR, SP, (argument_count - 1) * kWordSize); | 1290 __ LoadFromOffset(kWord, receiverR, SP, (argument_count - 1) * kWordSize); |
1295 __ LoadObject(cacheR, cache); | 1291 __ LoadObject(cacheR, cache); |
1296 | 1292 |
1297 if (FLAG_use_megamorphic_stub) { | 1293 if (FLAG_use_megamorphic_stub) { |
1298 StubCode* stub_code = isolate()->stub_code(); | 1294 __ BranchLink(&StubCode::MegamorphicLookupLabel()); |
1299 __ BranchLink(&stub_code->MegamorphicLookupLabel()); | |
1300 } else { | 1295 } else { |
1301 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); | 1296 StubCode::EmitMegamorphicLookup(assembler(), receiverR, cacheR, targetR); |
1302 } | 1297 } |
1303 __ LoadObject(R5, ic_data); | 1298 __ LoadObject(R5, ic_data); |
1304 __ LoadObject(R4, arguments_descriptor); | 1299 __ LoadObject(R4, arguments_descriptor); |
1305 __ blx(targetR); | 1300 __ blx(targetR); |
1306 AddCurrentDescriptor(RawPcDescriptors::kOther, | 1301 AddCurrentDescriptor(RawPcDescriptors::kOther, |
1307 Isolate::kNoDeoptId, token_pos); | 1302 Isolate::kNoDeoptId, token_pos); |
1308 RecordSafepoint(locs); | 1303 RecordSafepoint(locs); |
1309 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); | 1304 const intptr_t deopt_id_after = Isolate::ToDeoptAfter(deopt_id); |
1310 if (is_optimizing()) { | 1305 if (is_optimizing()) { |
1311 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1306 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1312 } else { | 1307 } else { |
1313 // Add deoptimization continuation point after the call and before the | 1308 // Add deoptimization continuation point after the call and before the |
1314 // arguments are removed. | 1309 // arguments are removed. |
1315 AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 1310 AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
1316 deopt_id_after, token_pos); | 1311 deopt_id_after, token_pos); |
1317 } | 1312 } |
1318 __ Drop(argument_count); | 1313 __ Drop(argument_count); |
1319 } | 1314 } |
1320 | 1315 |
1321 | 1316 |
1322 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1317 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1323 intptr_t argument_count, | 1318 intptr_t argument_count, |
1324 intptr_t deopt_id, | 1319 intptr_t deopt_id, |
1325 intptr_t token_pos, | 1320 intptr_t token_pos, |
1326 LocationSummary* locs, | 1321 LocationSummary* locs, |
1327 const ICData& ic_data) { | 1322 const ICData& ic_data) { |
1328 StubCode* stub_code = isolate()->stub_code(); | |
1329 const uword label_address = | 1323 const uword label_address = |
1330 stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); | 1324 StubCode::UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested()); |
1331 ExternalLabel target_label(label_address); | 1325 ExternalLabel target_label(label_address); |
1332 __ LoadObject(R5, ic_data); | 1326 __ LoadObject(R5, ic_data); |
1333 GenerateDartCall(deopt_id, | 1327 GenerateDartCall(deopt_id, |
1334 token_pos, | 1328 token_pos, |
1335 &target_label, | 1329 &target_label, |
1336 RawPcDescriptors::kUnoptStaticCall, | 1330 RawPcDescriptors::kUnoptStaticCall, |
1337 locs); | 1331 locs); |
1338 __ Drop(argument_count); | 1332 __ Drop(argument_count); |
1339 } | 1333 } |
1340 | 1334 |
1341 | 1335 |
1342 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1336 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1343 const Function& function, | 1337 const Function& function, |
1344 const Array& arguments_descriptor, | 1338 const Array& arguments_descriptor, |
1345 intptr_t argument_count, | 1339 intptr_t argument_count, |
1346 intptr_t deopt_id, | 1340 intptr_t deopt_id, |
1347 intptr_t token_pos, | 1341 intptr_t token_pos, |
1348 LocationSummary* locs) { | 1342 LocationSummary* locs) { |
1349 StubCode* stub_code = isolate()->stub_code(); | |
1350 __ LoadObject(R4, arguments_descriptor); | 1343 __ LoadObject(R4, arguments_descriptor); |
1351 // Do not use the code from the function, but let the code be patched so that | 1344 // Do not use the code from the function, but let the code be patched so that |
1352 // we can record the outgoing edges to other code. | 1345 // we can record the outgoing edges to other code. |
1353 GenerateDartCall(deopt_id, | 1346 GenerateDartCall(deopt_id, |
1354 token_pos, | 1347 token_pos, |
1355 &stub_code->CallStaticFunctionLabel(), | 1348 &StubCode::CallStaticFunctionLabel(), |
1356 RawPcDescriptors::kOther, | 1349 RawPcDescriptors::kOther, |
1357 locs); | 1350 locs); |
1358 AddStaticCallTarget(function); | 1351 AddStaticCallTarget(function); |
1359 __ Drop(argument_count); | 1352 __ Drop(argument_count); |
1360 } | 1353 } |
1361 | 1354 |
1362 | 1355 |
1363 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1356 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1364 Register reg, | 1357 Register reg, |
1365 const Object& obj, | 1358 const Object& obj, |
1366 bool needs_number_check, | 1359 bool needs_number_check, |
1367 intptr_t token_pos) { | 1360 intptr_t token_pos) { |
1368 if (needs_number_check) { | 1361 if (needs_number_check) { |
1369 StubCode* stub_code = isolate()->stub_code(); | |
1370 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1362 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1371 __ Push(reg); | 1363 __ Push(reg); |
1372 __ PushObject(obj); | 1364 __ PushObject(obj); |
1373 if (is_optimizing()) { | 1365 if (is_optimizing()) { |
1374 __ BranchLinkPatchable( | 1366 __ BranchLinkPatchable( |
1375 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1367 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1376 } else { | 1368 } else { |
1377 __ BranchLinkPatchable( | 1369 __ BranchLinkPatchable( |
1378 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1370 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1379 } | 1371 } |
1380 if (token_pos != Scanner::kNoSourcePos) { | 1372 if (token_pos != Scanner::kNoSourcePos) { |
1381 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1373 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1382 Isolate::kNoDeoptId, | 1374 Isolate::kNoDeoptId, |
1383 token_pos); | 1375 token_pos); |
1384 } | 1376 } |
1385 // Stub returns result in flags (result of a cmp, we need Z computed). | 1377 // Stub returns result in flags (result of a cmp, we need Z computed). |
1386 __ Drop(1); // Discard constant. | 1378 __ Drop(1); // Discard constant. |
1387 __ Pop(reg); // Restore 'reg'. | 1379 __ Pop(reg); // Restore 'reg'. |
1388 } else { | 1380 } else { |
1389 __ CompareObject(reg, obj); | 1381 __ CompareObject(reg, obj); |
1390 } | 1382 } |
1391 return EQ; | 1383 return EQ; |
1392 } | 1384 } |
1393 | 1385 |
1394 | 1386 |
1395 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1387 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
1396 Register right, | 1388 Register right, |
1397 bool needs_number_check, | 1389 bool needs_number_check, |
1398 intptr_t token_pos) { | 1390 intptr_t token_pos) { |
1399 if (needs_number_check) { | 1391 if (needs_number_check) { |
1400 StubCode* stub_code = isolate()->stub_code(); | |
1401 __ Push(left); | 1392 __ Push(left); |
1402 __ Push(right); | 1393 __ Push(right); |
1403 if (is_optimizing()) { | 1394 if (is_optimizing()) { |
1404 __ BranchLinkPatchable( | 1395 __ BranchLinkPatchable( |
1405 &stub_code->OptimizedIdenticalWithNumberCheckLabel()); | 1396 &StubCode::OptimizedIdenticalWithNumberCheckLabel()); |
1406 } else { | 1397 } else { |
1407 __ BranchLinkPatchable( | 1398 __ BranchLinkPatchable( |
1408 &stub_code->UnoptimizedIdenticalWithNumberCheckLabel()); | 1399 &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); |
1409 } | 1400 } |
1410 if (token_pos != Scanner::kNoSourcePos) { | 1401 if (token_pos != Scanner::kNoSourcePos) { |
1411 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1402 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1412 Isolate::kNoDeoptId, | 1403 Isolate::kNoDeoptId, |
1413 token_pos); | 1404 token_pos); |
1414 } | 1405 } |
1415 // Stub returns result in flags (result of a cmp, we need Z computed). | 1406 // Stub returns result in flags (result of a cmp, we need Z computed). |
1416 __ Pop(right); | 1407 __ Pop(right); |
1417 __ Pop(left); | 1408 __ Pop(left); |
1418 } else { | 1409 } else { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1517 Label* failed, | 1508 Label* failed, |
1518 Label* match_found, | 1509 Label* match_found, |
1519 intptr_t deopt_id, | 1510 intptr_t deopt_id, |
1520 intptr_t token_index, | 1511 intptr_t token_index, |
1521 LocationSummary* locs) { | 1512 LocationSummary* locs) { |
1522 ASSERT(is_optimizing()); | 1513 ASSERT(is_optimizing()); |
1523 __ Comment("EmitTestAndCall"); | 1514 __ Comment("EmitTestAndCall"); |
1524 const Array& arguments_descriptor = | 1515 const Array& arguments_descriptor = |
1525 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 1516 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
1526 argument_names)); | 1517 argument_names)); |
1527 StubCode* stub_code = isolate()->stub_code(); | |
1528 | 1518 |
1529 // Load receiver into R0. | 1519 // Load receiver into R0. |
1530 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); | 1520 __ LoadFromOffset(kWord, R0, SP, (argument_count - 1) * kWordSize); |
1531 __ LoadObject(R4, arguments_descriptor); | 1521 __ LoadObject(R4, arguments_descriptor); |
1532 | 1522 |
1533 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; | 1523 const bool kFirstCheckIsSmi = ic_data.GetReceiverClassIdAt(0) == kSmiCid; |
1534 const intptr_t kNumChecks = ic_data.NumberOfChecks(); | 1524 const intptr_t kNumChecks = ic_data.NumberOfChecks(); |
1535 | 1525 |
1536 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); | 1526 ASSERT(!ic_data.IsNull() && (kNumChecks > 0)); |
1537 | 1527 |
1538 Label after_smi_test; | 1528 Label after_smi_test; |
1539 __ tst(R0, Operand(kSmiTagMask)); | 1529 __ tst(R0, Operand(kSmiTagMask)); |
1540 if (kFirstCheckIsSmi) { | 1530 if (kFirstCheckIsSmi) { |
1541 // Jump if receiver is not Smi. | 1531 // Jump if receiver is not Smi. |
1542 if (kNumChecks == 1) { | 1532 if (kNumChecks == 1) { |
1543 __ b(failed, NE); | 1533 __ b(failed, NE); |
1544 } else { | 1534 } else { |
1545 __ b(&after_smi_test, NE); | 1535 __ b(&after_smi_test, NE); |
1546 } | 1536 } |
1547 // Do not use the code from the function, but let the code be patched so | 1537 // Do not use the code from the function, but let the code be patched so |
1548 // that we can record the outgoing edges to other code. | 1538 // that we can record the outgoing edges to other code. |
1549 GenerateDartCall(deopt_id, | 1539 GenerateDartCall(deopt_id, |
1550 token_index, | 1540 token_index, |
1551 &stub_code->CallStaticFunctionLabel(), | 1541 &StubCode::CallStaticFunctionLabel(), |
1552 RawPcDescriptors::kOther, | 1542 RawPcDescriptors::kOther, |
1553 locs); | 1543 locs); |
1554 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); | 1544 const Function& function = Function::Handle(ic_data.GetTargetAt(0)); |
1555 AddStaticCallTarget(function); | 1545 AddStaticCallTarget(function); |
1556 __ Drop(argument_count); | 1546 __ Drop(argument_count); |
1557 if (kNumChecks > 1) { | 1547 if (kNumChecks > 1) { |
1558 __ b(match_found); | 1548 __ b(match_found); |
1559 } | 1549 } |
1560 } else { | 1550 } else { |
1561 // Receiver is Smi, but Smi is not a valid class therefore fail. | 1551 // Receiver is Smi, but Smi is not a valid class therefore fail. |
(...skipping 20 matching lines...) Expand all Loading... | |
1582 __ CompareImmediate(R2, sorted[i].cid); | 1572 __ CompareImmediate(R2, sorted[i].cid); |
1583 if (kIsLastCheck) { | 1573 if (kIsLastCheck) { |
1584 __ b(failed, NE); | 1574 __ b(failed, NE); |
1585 } else { | 1575 } else { |
1586 __ b(&next_test, NE); | 1576 __ b(&next_test, NE); |
1587 } | 1577 } |
1588 // Do not use the code from the function, but let the code be patched so | 1578 // Do not use the code from the function, but let the code be patched so |
1589 // that we can record the outgoing edges to other code. | 1579 // that we can record the outgoing edges to other code. |
1590 GenerateDartCall(deopt_id, | 1580 GenerateDartCall(deopt_id, |
1591 token_index, | 1581 token_index, |
1592 &stub_code->CallStaticFunctionLabel(), | 1582 &StubCode::CallStaticFunctionLabel(), |
1593 RawPcDescriptors::kOther, | 1583 RawPcDescriptors::kOther, |
1594 locs); | 1584 locs); |
1595 const Function& function = *sorted[i].target; | 1585 const Function& function = *sorted[i].target; |
1596 AddStaticCallTarget(function); | 1586 AddStaticCallTarget(function); |
1597 __ Drop(argument_count); | 1587 __ Drop(argument_count); |
1598 if (!kIsLastCheck) { | 1588 if (!kIsLastCheck) { |
1599 __ b(match_found); | 1589 __ b(match_found); |
1600 } | 1590 } |
1601 __ Bind(&next_test); | 1591 __ Bind(&next_test); |
1602 } | 1592 } |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1899 DRegister dreg = EvenDRegisterOf(reg); | 1889 DRegister dreg = EvenDRegisterOf(reg); |
1900 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); | 1890 __ vldrd(dreg, Address(SP, kDoubleSize, Address::PostIndex)); |
1901 } | 1891 } |
1902 | 1892 |
1903 | 1893 |
1904 #undef __ | 1894 #undef __ |
1905 | 1895 |
1906 } // namespace dart | 1896 } // namespace dart |
1907 | 1897 |
1908 #endif // defined TARGET_ARCH_ARM | 1898 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |