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