OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
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 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 } | 252 } |
253 | 253 |
254 | 254 |
255 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if | 255 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
256 // type test is conclusive, otherwise fallthrough if a type test could not | 256 // type test is conclusive, otherwise fallthrough if a type test could not |
257 // be completed. | 257 // be completed. |
258 // R0: instance being type checked (preserved). | 258 // R0: instance being type checked (preserved). |
259 // Clobbers R2. | 259 // Clobbers R2. |
260 RawSubtypeTestCache* | 260 RawSubtypeTestCache* |
261 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 261 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
262 intptr_t token_pos, | 262 TokenPosition token_pos, |
263 const AbstractType& type, | 263 const AbstractType& type, |
264 Label* is_instance_lbl, | 264 Label* is_instance_lbl, |
265 Label* is_not_instance_lbl) { | 265 Label* is_not_instance_lbl) { |
266 __ Comment("InstantiatedTypeWithArgumentsTest"); | 266 __ Comment("InstantiatedTypeWithArgumentsTest"); |
267 ASSERT(type.IsInstantiated()); | 267 ASSERT(type.IsInstantiated()); |
268 const Class& type_class = Class::ZoneHandle(zone(), type.type_class()); | 268 const Class& type_class = Class::ZoneHandle(zone(), type.type_class()); |
269 ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0)); | 269 ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0)); |
270 const Register kInstanceReg = R0; | 270 const Register kInstanceReg = R0; |
271 Error& bound_error = Error::Handle(zone()); | 271 Error& bound_error = Error::Handle(zone()); |
272 const Type& int_type = Type::Handle(zone(), Type::IntType()); | 272 const Type& int_type = Type::Handle(zone(), Type::IntType()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 __ b(is_not_equal_lbl); | 342 __ b(is_not_equal_lbl); |
343 } | 343 } |
344 | 344 |
345 | 345 |
346 // Testing against an instantiated type with no arguments, without | 346 // Testing against an instantiated type with no arguments, without |
347 // SubtypeTestCache. | 347 // SubtypeTestCache. |
348 // R0: instance being type checked (preserved). | 348 // R0: instance being type checked (preserved). |
349 // Clobbers R2, R3. | 349 // Clobbers R2, R3. |
350 // Returns true if there is a fallthrough. | 350 // Returns true if there is a fallthrough. |
351 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( | 351 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( |
352 intptr_t token_pos, | 352 TokenPosition token_pos, |
353 const AbstractType& type, | 353 const AbstractType& type, |
354 Label* is_instance_lbl, | 354 Label* is_instance_lbl, |
355 Label* is_not_instance_lbl) { | 355 Label* is_not_instance_lbl) { |
356 __ Comment("InstantiatedTypeNoArgumentsTest"); | 356 __ Comment("InstantiatedTypeNoArgumentsTest"); |
357 ASSERT(type.IsInstantiated()); | 357 ASSERT(type.IsInstantiated()); |
358 if (type.IsFunctionType()) { | 358 if (type.IsFunctionType()) { |
359 // Fallthrough. | 359 // Fallthrough. |
360 return true; | 360 return true; |
361 } | 361 } |
362 const Class& type_class = Class::Handle(zone(), type.type_class()); | 362 const Class& type_class = Class::Handle(zone(), type.type_class()); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 | 412 |
413 | 413 |
414 // Uses SubtypeTestCache to store instance class and result. | 414 // Uses SubtypeTestCache to store instance class and result. |
415 // R0: instance to test. | 415 // R0: instance to test. |
416 // Clobbers R1-R5. | 416 // Clobbers R1-R5. |
417 // Immediate class test already done. | 417 // Immediate class test already done. |
418 // TODO(srdjan): Implement a quicker subtype check, as type test | 418 // TODO(srdjan): Implement a quicker subtype check, as type test |
419 // arrays can grow too high, but they may be useful when optimizing | 419 // arrays can grow too high, but they may be useful when optimizing |
420 // code (type-feedback). | 420 // code (type-feedback). |
421 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 421 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
422 intptr_t token_pos, | 422 TokenPosition token_pos, |
423 const Class& type_class, | 423 const Class& type_class, |
424 Label* is_instance_lbl, | 424 Label* is_instance_lbl, |
425 Label* is_not_instance_lbl) { | 425 Label* is_not_instance_lbl) { |
426 __ Comment("Subtype1TestCacheLookup"); | 426 __ Comment("Subtype1TestCacheLookup"); |
427 const Register kInstanceReg = R0; | 427 const Register kInstanceReg = R0; |
428 __ LoadClass(R1, kInstanceReg); | 428 __ LoadClass(R1, kInstanceReg); |
429 // R1: instance class. | 429 // R1: instance class. |
430 // Check immediate superclass equality. | 430 // Check immediate superclass equality. |
431 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset()); | 431 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset()); |
432 __ LoadFieldFromOffset(R2, R2, Type::type_class_offset()); | 432 __ LoadFieldFromOffset(R2, R2, Type::type_class_offset()); |
433 __ CompareObject(R2, type_class); | 433 __ CompareObject(R2, type_class); |
434 __ b(is_instance_lbl, EQ); | 434 __ b(is_instance_lbl, EQ); |
435 | 435 |
436 const Register kTypeArgumentsReg = kNoRegister; | 436 const Register kTypeArgumentsReg = kNoRegister; |
437 const Register kTempReg = kNoRegister; | 437 const Register kTempReg = kNoRegister; |
438 return GenerateCallSubtypeTestStub(kTestTypeOneArg, | 438 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
439 kInstanceReg, | 439 kInstanceReg, |
440 kTypeArgumentsReg, | 440 kTypeArgumentsReg, |
441 kTempReg, | 441 kTempReg, |
442 is_instance_lbl, | 442 is_instance_lbl, |
443 is_not_instance_lbl); | 443 is_not_instance_lbl); |
444 } | 444 } |
445 | 445 |
446 | 446 |
447 // Generates inlined check if 'type' is a type parameter or type itself | 447 // Generates inlined check if 'type' is a type parameter or type itself |
448 // R0: instance (preserved). | 448 // R0: instance (preserved). |
449 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 449 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
450 intptr_t token_pos, | 450 TokenPosition token_pos, |
451 const AbstractType& type, | 451 const AbstractType& type, |
452 Label* is_instance_lbl, | 452 Label* is_instance_lbl, |
453 Label* is_not_instance_lbl) { | 453 Label* is_not_instance_lbl) { |
454 __ Comment("UninstantiatedTypeTest"); | 454 __ Comment("UninstantiatedTypeTest"); |
455 ASSERT(!type.IsInstantiated()); | 455 ASSERT(!type.IsInstantiated()); |
456 // Skip check if destination is a dynamic type. | 456 // Skip check if destination is a dynamic type. |
457 if (type.IsTypeParameter()) { | 457 if (type.IsTypeParameter()) { |
458 const TypeParameter& type_param = TypeParameter::Cast(type); | 458 const TypeParameter& type_param = TypeParameter::Cast(type); |
459 // Load instantiator type arguments on stack. | 459 // Load instantiator type arguments on stack. |
460 __ ldr(R1, Address(SP)); // Get instantiator type arguments. | 460 __ ldr(R1, Address(SP)); // Get instantiator type arguments. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 // Inputs: | 523 // Inputs: |
524 // - R0: instance being type checked (preserved). | 524 // - R0: instance being type checked (preserved). |
525 // - R1: optional instantiator type arguments (preserved). | 525 // - R1: optional instantiator type arguments (preserved). |
526 // Clobbers R2, R3. | 526 // Clobbers R2, R3. |
527 // Returns: | 527 // Returns: |
528 // - preserved instance in R0 and optional instantiator type arguments in R1. | 528 // - preserved instance in R0 and optional instantiator type arguments in R1. |
529 // Note that this inlined code must be followed by the runtime_call code, as it | 529 // Note that this inlined code must be followed by the runtime_call code, as it |
530 // may fall through to it. Otherwise, this inline code will jump to the label | 530 // may fall through to it. Otherwise, this inline code will jump to the label |
531 // is_instance or to the label is_not_instance. | 531 // is_instance or to the label is_not_instance. |
532 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( | 532 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( |
533 intptr_t token_pos, | 533 TokenPosition token_pos, |
534 const AbstractType& type, | 534 const AbstractType& type, |
535 Label* is_instance_lbl, | 535 Label* is_instance_lbl, |
536 Label* is_not_instance_lbl) { | 536 Label* is_not_instance_lbl) { |
537 __ Comment("InlineInstanceof"); | 537 __ Comment("InlineInstanceof"); |
538 if (type.IsVoidType()) { | 538 if (type.IsVoidType()) { |
539 // A non-null value is returned from a void function, which will result in a | 539 // A non-null value is returned from a void function, which will result in a |
540 // type error. A null value is handled prior to executing this inline code. | 540 // type error. A null value is handled prior to executing this inline code. |
541 return SubtypeTestCache::null(); | 541 return SubtypeTestCache::null(); |
542 } | 542 } |
543 if (type.IsInstantiated()) { | 543 if (type.IsInstantiated()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 // If instanceof type test cannot be performed successfully at compile time and | 576 // If instanceof type test cannot be performed successfully at compile time and |
577 // therefore eliminated, optimize it by adding inlined tests for: | 577 // therefore eliminated, optimize it by adding inlined tests for: |
578 // - NULL -> return false. | 578 // - NULL -> return false. |
579 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 579 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
580 // - Class equality (only if class is not parameterized). | 580 // - Class equality (only if class is not parameterized). |
581 // Inputs: | 581 // Inputs: |
582 // - R0: object. | 582 // - R0: object. |
583 // - R1: instantiator type arguments or raw_null. | 583 // - R1: instantiator type arguments or raw_null. |
584 // Returns: | 584 // Returns: |
585 // - true or false in R0. | 585 // - true or false in R0. |
586 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, | 586 void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, |
587 intptr_t deopt_id, | 587 intptr_t deopt_id, |
588 const AbstractType& type, | 588 const AbstractType& type, |
589 bool negate_result, | 589 bool negate_result, |
590 LocationSummary* locs) { | 590 LocationSummary* locs) { |
591 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); | 591 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
592 | 592 |
593 // Preserve instantiator type arguments (R1). | 593 // Preserve instantiator type arguments (R1). |
594 __ Push(R1); | 594 __ Push(R1); |
595 | 595 |
596 Label is_instance, is_not_instance; | 596 Label is_instance, is_not_instance; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
656 // - NULL -> return NULL. | 656 // - NULL -> return NULL. |
657 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 657 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
658 // - Class equality (only if class is not parameterized). | 658 // - Class equality (only if class is not parameterized). |
659 // Inputs: | 659 // Inputs: |
660 // - R0: instance being type checked. | 660 // - R0: instance being type checked. |
661 // - R1: instantiator type arguments or raw_null. | 661 // - R1: instantiator type arguments or raw_null. |
662 // Returns: | 662 // Returns: |
663 // - object in R0 for successful assignable check (or throws TypeError). | 663 // - object in R0 for successful assignable check (or throws TypeError). |
664 // Performance notes: positive checks must be quick, negative checks can be slow | 664 // Performance notes: positive checks must be quick, negative checks can be slow |
665 // as they throw an exception. | 665 // as they throw an exception. |
666 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, | 666 void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, |
667 intptr_t deopt_id, | 667 intptr_t deopt_id, |
668 const AbstractType& dst_type, | 668 const AbstractType& dst_type, |
669 const String& dst_name, | 669 const String& dst_name, |
670 LocationSummary* locs) { | 670 LocationSummary* locs) { |
671 ASSERT(!Token::IsClassifying(token_pos)); | 671 ASSERT(!TokenPosition(token_pos).IsClassifying()); |
672 ASSERT(!dst_type.IsNull()); | 672 ASSERT(!dst_type.IsNull()); |
673 ASSERT(dst_type.IsFinalized()); | 673 ASSERT(dst_type.IsFinalized()); |
674 // Assignable check is skipped in FlowGraphBuilder, not here. | 674 // Assignable check is skipped in FlowGraphBuilder, not here. |
675 ASSERT(dst_type.IsMalformedOrMalbounded() || | 675 ASSERT(dst_type.IsMalformedOrMalbounded() || |
676 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 676 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
677 // Preserve instantiator type arguments (R1). | 677 // Preserve instantiator type arguments (R1). |
678 __ Push(R1); | 678 __ Push(R1); |
679 // A null object is always assignable and is returned as result. | 679 // A null object is always assignable and is returned as result. |
680 Label is_assignable, runtime_call; | 680 Label is_assignable, runtime_call; |
681 __ CompareObject(R0, Object::null_object()); | 681 __ CompareObject(R0, Object::null_object()); |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 i < CallPattern::kDeoptCallLengthInInstructions; | 1125 i < CallPattern::kDeoptCallLengthInInstructions; |
1126 ++i) { | 1126 ++i) { |
1127 __ orr(R0, ZR, Operand(R0)); // nop | 1127 __ orr(R0, ZR, Operand(R0)); // nop |
1128 } | 1128 } |
1129 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1129 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1130 __ BranchPatchable(*StubCode::DeoptimizeLazy_entry()); | 1130 __ BranchPatchable(*StubCode::DeoptimizeLazy_entry()); |
1131 } | 1131 } |
1132 } | 1132 } |
1133 | 1133 |
1134 | 1134 |
1135 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1135 void FlowGraphCompiler::GenerateCall(TokenPosition token_pos, |
1136 const StubEntry& stub_entry, | 1136 const StubEntry& stub_entry, |
1137 RawPcDescriptors::Kind kind, | 1137 RawPcDescriptors::Kind kind, |
1138 LocationSummary* locs) { | 1138 LocationSummary* locs) { |
1139 __ BranchLinkPatchable(stub_entry); | 1139 __ BranchLinkPatchable(stub_entry); |
1140 AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos); | 1140 AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos); |
1141 RecordSafepoint(locs); | 1141 RecordSafepoint(locs); |
1142 } | 1142 } |
1143 | 1143 |
1144 | 1144 |
1145 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1145 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
1146 intptr_t token_pos, | 1146 TokenPosition token_pos, |
1147 const StubEntry& stub_entry, | 1147 const StubEntry& stub_entry, |
1148 RawPcDescriptors::Kind kind, | 1148 RawPcDescriptors::Kind kind, |
1149 LocationSummary* locs) { | 1149 LocationSummary* locs) { |
1150 __ BranchLinkPatchable(stub_entry); | 1150 __ BranchLinkPatchable(stub_entry); |
1151 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1151 AddCurrentDescriptor(kind, deopt_id, token_pos); |
1152 RecordSafepoint(locs); | 1152 RecordSafepoint(locs); |
1153 // Marks either the continuation point in unoptimized code or the | 1153 // Marks either the continuation point in unoptimized code or the |
1154 // deoptimization point in optimized code, after call. | 1154 // deoptimization point in optimized code, after call. |
1155 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); | 1155 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); |
1156 if (is_optimizing()) { | 1156 if (is_optimizing()) { |
1157 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1157 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1158 } else { | 1158 } else { |
1159 // Add deoptimization continuation point after the call and before the | 1159 // Add deoptimization continuation point after the call and before the |
1160 // arguments are removed. | 1160 // arguments are removed. |
1161 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1161 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1162 } | 1162 } |
1163 } | 1163 } |
1164 | 1164 |
1165 | 1165 |
1166 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, | 1166 void FlowGraphCompiler::GenerateRuntimeCall(TokenPosition token_pos, |
1167 intptr_t deopt_id, | 1167 intptr_t deopt_id, |
1168 const RuntimeEntry& entry, | 1168 const RuntimeEntry& entry, |
1169 intptr_t argument_count, | 1169 intptr_t argument_count, |
1170 LocationSummary* locs) { | 1170 LocationSummary* locs) { |
1171 __ CallRuntime(entry, argument_count); | 1171 __ CallRuntime(entry, argument_count); |
1172 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); | 1172 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); |
1173 RecordSafepoint(locs); | 1173 RecordSafepoint(locs); |
1174 if (deopt_id != Thread::kNoDeoptId) { | 1174 if (deopt_id != Thread::kNoDeoptId) { |
1175 // Marks either the continuation point in unoptimized code or the | 1175 // Marks either the continuation point in unoptimized code or the |
1176 // deoptimization point in optimized code, after call. | 1176 // deoptimization point in optimized code, after call. |
(...skipping 23 matching lines...) Expand all Loading... |
1200 __ add(TMP, TMP, Operand(Smi::RawValue(1))); | 1200 __ add(TMP, TMP, Operand(Smi::RawValue(1))); |
1201 __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id)); | 1201 __ StoreFieldToOffset(TMP, R0, Array::element_offset(edge_id)); |
1202 } | 1202 } |
1203 | 1203 |
1204 | 1204 |
1205 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 1205 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
1206 const StubEntry& stub_entry, | 1206 const StubEntry& stub_entry, |
1207 const ICData& ic_data, | 1207 const ICData& ic_data, |
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 TokenPosition token_pos, |
1211 LocationSummary* locs) { | 1211 LocationSummary* locs) { |
1212 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); | 1212 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); |
1213 // Each ICData propagated from unoptimized to optimized code contains the | 1213 // Each ICData propagated from unoptimized to optimized code contains the |
1214 // function that corresponds to the Dart function of that IC call. Due | 1214 // function that corresponds to the Dart function of that IC call. Due |
1215 // to inlining in optimized code, that function may not correspond to the | 1215 // to inlining in optimized code, that function may not correspond to the |
1216 // top-level function (parsed_function().function()) which could be | 1216 // top-level function (parsed_function().function()) which could be |
1217 // reoptimized and which counter needs to be incremented. | 1217 // reoptimized and which counter needs to be incremented. |
1218 // Pass the function explicitly, it is used in IC stub. | 1218 // Pass the function explicitly, it is used in IC stub. |
1219 | 1219 |
1220 __ LoadObject(R6, parsed_function().function()); | 1220 __ LoadObject(R6, parsed_function().function()); |
1221 __ LoadUniqueObject(R5, ic_data); | 1221 __ LoadUniqueObject(R5, ic_data); |
1222 GenerateDartCall(deopt_id, | 1222 GenerateDartCall(deopt_id, |
1223 token_pos, | 1223 token_pos, |
1224 stub_entry, | 1224 stub_entry, |
1225 RawPcDescriptors::kIcCall, | 1225 RawPcDescriptors::kIcCall, |
1226 locs); | 1226 locs); |
1227 __ Drop(argument_count); | 1227 __ Drop(argument_count); |
1228 } | 1228 } |
1229 | 1229 |
1230 | 1230 |
1231 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, | 1231 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, |
1232 const ICData& ic_data, | 1232 const ICData& ic_data, |
1233 intptr_t argument_count, | 1233 intptr_t argument_count, |
1234 intptr_t deopt_id, | 1234 intptr_t deopt_id, |
1235 intptr_t token_pos, | 1235 TokenPosition token_pos, |
1236 LocationSummary* locs) { | 1236 LocationSummary* locs) { |
1237 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); | 1237 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); |
1238 __ LoadUniqueObject(R5, ic_data); | 1238 __ LoadUniqueObject(R5, ic_data); |
1239 GenerateDartCall(deopt_id, | 1239 GenerateDartCall(deopt_id, |
1240 token_pos, | 1240 token_pos, |
1241 stub_entry, | 1241 stub_entry, |
1242 RawPcDescriptors::kIcCall, | 1242 RawPcDescriptors::kIcCall, |
1243 locs); | 1243 locs); |
1244 __ Drop(argument_count); | 1244 __ Drop(argument_count); |
1245 } | 1245 } |
1246 | 1246 |
1247 | 1247 |
1248 void FlowGraphCompiler::EmitMegamorphicInstanceCall( | 1248 void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
1249 const ICData& ic_data, | 1249 const ICData& ic_data, |
1250 intptr_t argument_count, | 1250 intptr_t argument_count, |
1251 intptr_t deopt_id, | 1251 intptr_t deopt_id, |
1252 intptr_t token_pos, | 1252 TokenPosition token_pos, |
1253 LocationSummary* locs, | 1253 LocationSummary* locs, |
1254 intptr_t try_index) { | 1254 intptr_t try_index) { |
1255 const String& name = String::Handle(zone(), ic_data.target_name()); | 1255 const String& name = String::Handle(zone(), ic_data.target_name()); |
1256 const Array& arguments_descriptor = | 1256 const Array& arguments_descriptor = |
1257 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1257 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
1258 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1258 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
1259 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), | 1259 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), |
1260 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); | 1260 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); |
1261 | 1261 |
1262 __ Comment("MegamorphicCall"); | 1262 __ Comment("MegamorphicCall"); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1294 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1294 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1295 } | 1295 } |
1296 __ Drop(argument_count); | 1296 __ Drop(argument_count); |
1297 } | 1297 } |
1298 | 1298 |
1299 | 1299 |
1300 void FlowGraphCompiler::EmitSwitchableInstanceCall( | 1300 void FlowGraphCompiler::EmitSwitchableInstanceCall( |
1301 const ICData& ic_data, | 1301 const ICData& ic_data, |
1302 intptr_t argument_count, | 1302 intptr_t argument_count, |
1303 intptr_t deopt_id, | 1303 intptr_t deopt_id, |
1304 intptr_t token_pos, | 1304 TokenPosition token_pos, |
1305 LocationSummary* locs) { | 1305 LocationSummary* locs) { |
1306 __ Comment("SwitchableCall"); | 1306 __ Comment("SwitchableCall"); |
1307 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); | 1307 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); |
1308 if (ic_data.NumArgsTested() == 1) { | 1308 if (ic_data.NumArgsTested() == 1) { |
1309 __ LoadUniqueObject(R5, ic_data); | 1309 __ LoadUniqueObject(R5, ic_data); |
1310 __ BranchLinkPatchable(*StubCode::ICLookup_entry()); | 1310 __ BranchLinkPatchable(*StubCode::ICLookup_entry()); |
1311 } else { | 1311 } else { |
1312 const String& name = String::Handle(zone(), ic_data.target_name()); | 1312 const String& name = String::Handle(zone(), ic_data.target_name()); |
1313 const Array& arguments_descriptor = | 1313 const Array& arguments_descriptor = |
1314 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1314 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
(...skipping 18 matching lines...) Expand all Loading... |
1333 // arguments are removed. | 1333 // arguments are removed. |
1334 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1334 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1335 } | 1335 } |
1336 __ Drop(argument_count); | 1336 __ Drop(argument_count); |
1337 } | 1337 } |
1338 | 1338 |
1339 | 1339 |
1340 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1340 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1341 intptr_t argument_count, | 1341 intptr_t argument_count, |
1342 intptr_t deopt_id, | 1342 intptr_t deopt_id, |
1343 intptr_t token_pos, | 1343 TokenPosition token_pos, |
1344 LocationSummary* locs, | 1344 LocationSummary* locs, |
1345 const ICData& ic_data) { | 1345 const ICData& ic_data) { |
1346 const StubEntry* stub_entry = | 1346 const StubEntry* stub_entry = |
1347 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); | 1347 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); |
1348 __ LoadObject(R5, ic_data); | 1348 __ LoadObject(R5, ic_data); |
1349 GenerateDartCall(deopt_id, | 1349 GenerateDartCall(deopt_id, |
1350 token_pos, | 1350 token_pos, |
1351 *stub_entry, | 1351 *stub_entry, |
1352 RawPcDescriptors::kUnoptStaticCall, | 1352 RawPcDescriptors::kUnoptStaticCall, |
1353 locs); | 1353 locs); |
1354 __ Drop(argument_count); | 1354 __ Drop(argument_count); |
1355 } | 1355 } |
1356 | 1356 |
1357 | 1357 |
1358 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1358 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1359 const Function& function, | 1359 const Function& function, |
1360 const Array& arguments_descriptor, | 1360 const Array& arguments_descriptor, |
1361 intptr_t argument_count, | 1361 intptr_t argument_count, |
1362 intptr_t deopt_id, | 1362 intptr_t deopt_id, |
1363 intptr_t token_pos, | 1363 TokenPosition token_pos, |
1364 LocationSummary* locs) { | 1364 LocationSummary* locs) { |
1365 __ LoadObject(R4, arguments_descriptor); | 1365 __ LoadObject(R4, arguments_descriptor); |
1366 // Do not use the code from the function, but let the code be patched so that | 1366 // Do not use the code from the function, but let the code be patched so that |
1367 // we can record the outgoing edges to other code. | 1367 // we can record the outgoing edges to other code. |
1368 GenerateDartCall(deopt_id, | 1368 GenerateDartCall(deopt_id, |
1369 token_pos, | 1369 token_pos, |
1370 *StubCode::CallStaticFunction_entry(), | 1370 *StubCode::CallStaticFunction_entry(), |
1371 RawPcDescriptors::kOther, | 1371 RawPcDescriptors::kOther, |
1372 locs); | 1372 locs); |
1373 AddStaticCallTarget(function); | 1373 AddStaticCallTarget(function); |
1374 __ Drop(argument_count); | 1374 __ Drop(argument_count); |
1375 } | 1375 } |
1376 | 1376 |
1377 | 1377 |
1378 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1378 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1379 Register reg, | 1379 Register reg, |
1380 const Object& obj, | 1380 const Object& obj, |
1381 bool needs_number_check, | 1381 bool needs_number_check, |
1382 intptr_t token_pos) { | 1382 TokenPosition token_pos) { |
1383 if (needs_number_check) { | 1383 if (needs_number_check) { |
1384 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1384 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1385 __ Push(reg); | 1385 __ Push(reg); |
1386 __ PushObject(obj); | 1386 __ PushObject(obj); |
1387 if (is_optimizing()) { | 1387 if (is_optimizing()) { |
1388 __ BranchLinkPatchable( | 1388 __ BranchLinkPatchable( |
1389 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); | 1389 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1390 } else { | 1390 } else { |
1391 __ BranchLinkPatchable( | 1391 __ BranchLinkPatchable( |
1392 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); | 1392 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1393 } | 1393 } |
1394 if (token_pos >= 0) { | 1394 if (token_pos.IsReal()) { |
1395 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1395 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1396 Thread::kNoDeoptId, | 1396 Thread::kNoDeoptId, |
1397 token_pos); | 1397 token_pos); |
1398 } | 1398 } |
1399 // Stub returns result in flags (result of a cmp, we need Z computed). | 1399 // Stub returns result in flags (result of a cmp, we need Z computed). |
1400 __ Drop(1); // Discard constant. | 1400 __ Drop(1); // Discard constant. |
1401 __ Pop(reg); // Restore 'reg'. | 1401 __ Pop(reg); // Restore 'reg'. |
1402 } else { | 1402 } else { |
1403 __ CompareObject(reg, obj); | 1403 __ CompareObject(reg, obj); |
1404 } | 1404 } |
1405 return EQ; | 1405 return EQ; |
1406 } | 1406 } |
1407 | 1407 |
1408 | 1408 |
1409 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1409 Condition FlowGraphCompiler::EmitEqualityRegRegCompare( |
1410 Register right, | 1410 Register left, |
1411 bool needs_number_check, | 1411 Register right, |
1412 intptr_t token_pos) { | 1412 bool needs_number_check, |
| 1413 TokenPosition token_pos) { |
1413 if (needs_number_check) { | 1414 if (needs_number_check) { |
1414 __ Push(left); | 1415 __ Push(left); |
1415 __ Push(right); | 1416 __ Push(right); |
1416 if (is_optimizing()) { | 1417 if (is_optimizing()) { |
1417 __ BranchLinkPatchable( | 1418 __ BranchLinkPatchable( |
1418 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); | 1419 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1419 } else { | 1420 } else { |
1420 __ BranchLinkPatchable( | 1421 __ BranchLinkPatchable( |
1421 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); | 1422 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1422 } | 1423 } |
1423 if (token_pos >= 0) { | 1424 if (token_pos.IsReal()) { |
1424 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1425 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1425 Thread::kNoDeoptId, | 1426 Thread::kNoDeoptId, |
1426 token_pos); | 1427 token_pos); |
1427 } | 1428 } |
1428 // Stub returns result in flags (result of a cmp, we need Z computed). | 1429 // Stub returns result in flags (result of a cmp, we need Z computed). |
1429 __ Pop(right); | 1430 __ Pop(right); |
1430 __ Pop(left); | 1431 __ Pop(left); |
1431 } else { | 1432 } else { |
1432 __ CompareRegisters(left, right); | 1433 __ CompareRegisters(left, right); |
1433 } | 1434 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1502 } | 1503 } |
1503 #endif | 1504 #endif |
1504 | 1505 |
1505 | 1506 |
1506 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1507 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
1507 intptr_t argument_count, | 1508 intptr_t argument_count, |
1508 const Array& argument_names, | 1509 const Array& argument_names, |
1509 Label* failed, | 1510 Label* failed, |
1510 Label* match_found, | 1511 Label* match_found, |
1511 intptr_t deopt_id, | 1512 intptr_t deopt_id, |
1512 intptr_t token_index, | 1513 TokenPosition token_index, |
1513 LocationSummary* locs) { | 1514 LocationSummary* locs) { |
1514 ASSERT(is_optimizing()); | 1515 ASSERT(is_optimizing()); |
1515 | 1516 |
1516 __ Comment("EmitTestAndCall"); | 1517 __ Comment("EmitTestAndCall"); |
1517 const Array& arguments_descriptor = | 1518 const Array& arguments_descriptor = |
1518 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, | 1519 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, |
1519 argument_names)); | 1520 argument_names)); |
1520 | 1521 |
1521 // Load receiver into R0. | 1522 // Load receiver into R0. |
1522 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); | 1523 __ LoadFromOffset(R0, SP, (argument_count - 1) * kWordSize); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1873 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1874 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
1874 __ PopDouble(reg); | 1875 __ PopDouble(reg); |
1875 } | 1876 } |
1876 | 1877 |
1877 | 1878 |
1878 #undef __ | 1879 #undef __ |
1879 | 1880 |
1880 } // namespace dart | 1881 } // namespace dart |
1881 | 1882 |
1882 #endif // defined TARGET_ARCH_ARM64 | 1883 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |