OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
9 | 9 |
10 #include "vm/ast_printer.h" | 10 #include "vm/ast_printer.h" |
(...skipping 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 // A0: instance being type checked (preserved). | 257 // A0: instance being type checked (preserved). |
258 // Clobbers T0. | 258 // Clobbers T0. |
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 = A0; | 269 const Register kInstanceReg = A0; |
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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 __ b(is_not_equal_lbl); | 340 __ b(is_not_equal_lbl); |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 // Testing against an instantiated type with no arguments, without | 344 // Testing against an instantiated type with no arguments, without |
345 // SubtypeTestCache. | 345 // SubtypeTestCache. |
346 // A0: instance being type checked (preserved). | 346 // A0: instance being type checked (preserved). |
347 // Clobbers: T0, T1, T2 | 347 // Clobbers: T0, T1, T2 |
348 // Returns true if there is a fallthrough. | 348 // Returns true if there is a fallthrough. |
349 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( | 349 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( |
350 intptr_t token_pos, | 350 TokenDescriptor token_pos, |
351 const AbstractType& type, | 351 const AbstractType& type, |
352 Label* is_instance_lbl, | 352 Label* is_instance_lbl, |
353 Label* is_not_instance_lbl) { | 353 Label* is_not_instance_lbl) { |
354 __ Comment("InstantiatedTypeNoArgumentsTest"); | 354 __ Comment("InstantiatedTypeNoArgumentsTest"); |
355 ASSERT(type.IsInstantiated()); | 355 ASSERT(type.IsInstantiated()); |
356 if (type.IsFunctionType()) { | 356 if (type.IsFunctionType()) { |
357 // Fallthrough. | 357 // Fallthrough. |
358 return true; | 358 return true; |
359 } | 359 } |
360 const Class& type_class = Class::Handle(zone(), type.type_class()); | 360 const Class& type_class = Class::Handle(zone(), type.type_class()); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
408 | 408 |
409 | 409 |
410 // Uses SubtypeTestCache to store instance class and result. | 410 // Uses SubtypeTestCache to store instance class and result. |
411 // A0: instance to test. | 411 // A0: instance to test. |
412 // Clobbers A1, A2, T0-T3. | 412 // Clobbers A1, A2, T0-T3. |
413 // Immediate class test already done. | 413 // Immediate class test already done. |
414 // TODO(srdjan): Implement a quicker subtype check, as type test | 414 // TODO(srdjan): Implement a quicker subtype check, as type test |
415 // arrays can grow too high, but they may be useful when optimizing | 415 // arrays can grow too high, but they may be useful when optimizing |
416 // code (type-feedback). | 416 // code (type-feedback). |
417 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 417 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
418 intptr_t token_pos, | 418 TokenDescriptor token_pos, |
419 const Class& type_class, | 419 const Class& type_class, |
420 Label* is_instance_lbl, | 420 Label* is_instance_lbl, |
421 Label* is_not_instance_lbl) { | 421 Label* is_not_instance_lbl) { |
422 __ Comment("Subtype1TestCacheLookup"); | 422 __ Comment("Subtype1TestCacheLookup"); |
423 const Register kInstanceReg = A0; | 423 const Register kInstanceReg = A0; |
424 __ LoadClass(T0, kInstanceReg); | 424 __ LoadClass(T0, kInstanceReg); |
425 // T0: instance class. | 425 // T0: instance class. |
426 // Check immediate superclass equality. | 426 // Check immediate superclass equality. |
427 __ lw(T0, FieldAddress(T0, Class::super_type_offset())); | 427 __ lw(T0, FieldAddress(T0, Class::super_type_offset())); |
428 __ lw(T0, FieldAddress(T0, Type::type_class_offset())); | 428 __ lw(T0, FieldAddress(T0, Type::type_class_offset())); |
429 __ BranchEqual(T0, type_class, is_instance_lbl); | 429 __ BranchEqual(T0, type_class, is_instance_lbl); |
430 | 430 |
431 const Register kTypeArgumentsReg = kNoRegister; | 431 const Register kTypeArgumentsReg = kNoRegister; |
432 const Register kTempReg = kNoRegister; | 432 const Register kTempReg = kNoRegister; |
433 return GenerateCallSubtypeTestStub(kTestTypeOneArg, | 433 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
434 kInstanceReg, | 434 kInstanceReg, |
435 kTypeArgumentsReg, | 435 kTypeArgumentsReg, |
436 kTempReg, | 436 kTempReg, |
437 is_instance_lbl, | 437 is_instance_lbl, |
438 is_not_instance_lbl); | 438 is_not_instance_lbl); |
439 } | 439 } |
440 | 440 |
441 | 441 |
442 // Generates inlined check if 'type' is a type parameter or type itself | 442 // Generates inlined check if 'type' is a type parameter or type itself |
443 // A0: instance (preserved). | 443 // A0: instance (preserved). |
444 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 444 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
445 intptr_t token_pos, | 445 TokenDescriptor token_pos, |
446 const AbstractType& type, | 446 const AbstractType& type, |
447 Label* is_instance_lbl, | 447 Label* is_instance_lbl, |
448 Label* is_not_instance_lbl) { | 448 Label* is_not_instance_lbl) { |
449 __ Comment("UninstantiatedTypeTest"); | 449 __ Comment("UninstantiatedTypeTest"); |
450 ASSERT(!type.IsInstantiated()); | 450 ASSERT(!type.IsInstantiated()); |
451 // Skip check if destination is a dynamic type. | 451 // Skip check if destination is a dynamic type. |
452 if (type.IsTypeParameter()) { | 452 if (type.IsTypeParameter()) { |
453 const TypeParameter& type_param = TypeParameter::Cast(type); | 453 const TypeParameter& type_param = TypeParameter::Cast(type); |
454 // Load instantiator type arguments on stack. | 454 // Load instantiator type arguments on stack. |
455 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. | 455 __ lw(A1, Address(SP, 0)); // Get instantiator type arguments. |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 // Inputs: | 518 // Inputs: |
519 // - A0: instance being type checked (preserved). | 519 // - A0: instance being type checked (preserved). |
520 // - A1: optional instantiator type arguments (preserved). | 520 // - A1: optional instantiator type arguments (preserved). |
521 // Returns: | 521 // Returns: |
522 // - preserved instance in A0 and optional instantiator type arguments in A1. | 522 // - preserved instance in A0 and optional instantiator type arguments in A1. |
523 // Clobbers: T0, T1, T2 | 523 // Clobbers: T0, T1, T2 |
524 // Note that this inlined code must be followed by the runtime_call code, as it | 524 // Note that this inlined code must be followed by the runtime_call code, as it |
525 // may fall through to it. Otherwise, this inline code will jump to the label | 525 // may fall through to it. Otherwise, this inline code will jump to the label |
526 // is_instance or to the label is_not_instance. | 526 // is_instance or to the label is_not_instance. |
527 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( | 527 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( |
528 intptr_t token_pos, | 528 TokenDescriptor token_pos, |
529 const AbstractType& type, | 529 const AbstractType& type, |
530 Label* is_instance_lbl, | 530 Label* is_instance_lbl, |
531 Label* is_not_instance_lbl) { | 531 Label* is_not_instance_lbl) { |
532 __ Comment("InlineInstanceof"); | 532 __ Comment("InlineInstanceof"); |
533 if (type.IsVoidType()) { | 533 if (type.IsVoidType()) { |
534 // A non-null value is returned from a void function, which will result in a | 534 // A non-null value is returned from a void function, which will result in a |
535 // type error. A null value is handled prior to executing this inline code. | 535 // type error. A null value is handled prior to executing this inline code. |
536 return SubtypeTestCache::null(); | 536 return SubtypeTestCache::null(); |
537 } | 537 } |
538 if (type.IsInstantiated()) { | 538 if (type.IsInstantiated()) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
571 // If instanceof type test cannot be performed successfully at compile time and | 571 // If instanceof type test cannot be performed successfully at compile time and |
572 // therefore eliminated, optimize it by adding inlined tests for: | 572 // therefore eliminated, optimize it by adding inlined tests for: |
573 // - NULL -> return false. | 573 // - NULL -> return false. |
574 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 574 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
575 // - Class equality (only if class is not parameterized). | 575 // - Class equality (only if class is not parameterized). |
576 // Inputs: | 576 // Inputs: |
577 // - A0: object. | 577 // - A0: object. |
578 // - A1: instantiator type arguments or raw_null. | 578 // - A1: instantiator type arguments or raw_null. |
579 // Returns: | 579 // Returns: |
580 // - true or false in V0. | 580 // - true or false in V0. |
581 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, | 581 void FlowGraphCompiler::GenerateInstanceOf(TokenDescriptor token_pos, |
582 intptr_t deopt_id, | 582 intptr_t deopt_id, |
583 const AbstractType& type, | 583 const AbstractType& type, |
584 bool negate_result, | 584 bool negate_result, |
585 LocationSummary* locs) { | 585 LocationSummary* locs) { |
586 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); | 586 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); |
587 | 587 |
588 // Preserve instantiator type arguments (A1). | 588 // Preserve instantiator type arguments (A1). |
589 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 589 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
590 __ sw(A1, Address(SP, 0 * kWordSize)); | 590 __ sw(A1, Address(SP, 0 * kWordSize)); |
591 | 591 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 // - A0: instance being type checked. | 659 // - A0: instance being type checked. |
660 // - A1: instantiator type arguments or raw_null. | 660 // - A1: instantiator type arguments or raw_null. |
661 // Returns: | 661 // Returns: |
662 // - object in A0 for successful assignable check (or throws TypeError). | 662 // - object in A0 for successful assignable check (or throws TypeError). |
663 // Clobbers: T0, T1, T2 | 663 // Clobbers: T0, T1, T2 |
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(TokenDescriptor 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 __ Comment("AssertAssignable"); | 671 __ Comment("AssertAssignable"); |
672 ASSERT(!Token::IsClassifying(token_pos)); | 672 ASSERT(!TokenDescriptor(token_pos).IsClassifying()); |
673 ASSERT(!dst_type.IsNull()); | 673 ASSERT(!dst_type.IsNull()); |
674 ASSERT(dst_type.IsFinalized()); | 674 ASSERT(dst_type.IsFinalized()); |
675 // Assignable check is skipped in FlowGraphBuilder, not here. | 675 // Assignable check is skipped in FlowGraphBuilder, not here. |
676 ASSERT(dst_type.IsMalformedOrMalbounded() || | 676 ASSERT(dst_type.IsMalformedOrMalbounded() || |
677 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); | 677 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); |
678 // Preserve instantiator type arguments. | 678 // Preserve instantiator type arguments. |
679 __ addiu(SP, SP, Immediate(-1 * kWordSize)); | 679 __ addiu(SP, SP, Immediate(-1 * kWordSize)); |
680 __ sw(A1, Address(SP, 0 * kWordSize)); | 680 __ sw(A1, Address(SP, 0 * kWordSize)); |
681 | 681 |
682 // A null object is always assignable and is returned as result. | 682 // A null object is always assignable and is returned as result. |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 i < CallPattern::kDeoptCallLengthInInstructions; | 1144 i < CallPattern::kDeoptCallLengthInInstructions; |
1145 ++i) { | 1145 ++i) { |
1146 __ nop(); | 1146 __ nop(); |
1147 } | 1147 } |
1148 lazy_deopt_pc_offset_ = assembler()->CodeSize(); | 1148 lazy_deopt_pc_offset_ = assembler()->CodeSize(); |
1149 __ Branch(*StubCode::DeoptimizeLazy_entry()); | 1149 __ Branch(*StubCode::DeoptimizeLazy_entry()); |
1150 } | 1150 } |
1151 } | 1151 } |
1152 | 1152 |
1153 | 1153 |
1154 void FlowGraphCompiler::GenerateCall(intptr_t token_pos, | 1154 void FlowGraphCompiler::GenerateCall(TokenDescriptor token_pos, |
1155 const StubEntry& stub_entry, | 1155 const StubEntry& stub_entry, |
1156 RawPcDescriptors::Kind kind, | 1156 RawPcDescriptors::Kind kind, |
1157 LocationSummary* locs) { | 1157 LocationSummary* locs) { |
1158 __ BranchLinkPatchable(stub_entry); | 1158 __ BranchLinkPatchable(stub_entry); |
1159 AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos); | 1159 AddCurrentDescriptor(kind, Thread::kNoDeoptId, token_pos); |
1160 RecordSafepoint(locs); | 1160 RecordSafepoint(locs); |
1161 } | 1161 } |
1162 | 1162 |
1163 | 1163 |
1164 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, | 1164 void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id, |
1165 intptr_t token_pos, | 1165 TokenDescriptor token_pos, |
1166 const StubEntry& stub_entry, | 1166 const StubEntry& stub_entry, |
1167 RawPcDescriptors::Kind kind, | 1167 RawPcDescriptors::Kind kind, |
1168 LocationSummary* locs) { | 1168 LocationSummary* locs) { |
1169 __ BranchLinkPatchable(stub_entry); | 1169 __ BranchLinkPatchable(stub_entry); |
1170 AddCurrentDescriptor(kind, deopt_id, token_pos); | 1170 AddCurrentDescriptor(kind, deopt_id, token_pos); |
1171 RecordSafepoint(locs); | 1171 RecordSafepoint(locs); |
1172 // Marks either the continuation point in unoptimized code or the | 1172 // Marks either the continuation point in unoptimized code or the |
1173 // deoptimization point in optimized code, after call. | 1173 // deoptimization point in optimized code, after call. |
1174 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); | 1174 const intptr_t deopt_id_after = Thread::ToDeoptAfter(deopt_id); |
1175 if (is_optimizing()) { | 1175 if (is_optimizing()) { |
1176 AddDeoptIndexAtCall(deopt_id_after, token_pos); | 1176 AddDeoptIndexAtCall(deopt_id_after, token_pos); |
1177 } else { | 1177 } else { |
1178 // Add deoptimization continuation point after the call and before the | 1178 // Add deoptimization continuation point after the call and before the |
1179 // arguments are removed. | 1179 // arguments are removed. |
1180 AddCurrentDescriptor(RawPcDescriptors::kDeopt, | 1180 AddCurrentDescriptor(RawPcDescriptors::kDeopt, |
1181 deopt_id_after, | 1181 deopt_id_after, |
1182 token_pos); | 1182 token_pos); |
1183 } | 1183 } |
1184 } | 1184 } |
1185 | 1185 |
1186 | 1186 |
1187 void FlowGraphCompiler::GenerateRuntimeCall(intptr_t token_pos, | 1187 void FlowGraphCompiler::GenerateRuntimeCall(TokenDescriptor token_pos, |
1188 intptr_t deopt_id, | 1188 intptr_t deopt_id, |
1189 const RuntimeEntry& entry, | 1189 const RuntimeEntry& entry, |
1190 intptr_t argument_count, | 1190 intptr_t argument_count, |
1191 LocationSummary* locs) { | 1191 LocationSummary* locs) { |
1192 __ CallRuntime(entry, argument_count); | 1192 __ CallRuntime(entry, argument_count); |
1193 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); | 1193 AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id, token_pos); |
1194 RecordSafepoint(locs); | 1194 RecordSafepoint(locs); |
1195 if (deopt_id != Thread::kNoDeoptId) { | 1195 if (deopt_id != Thread::kNoDeoptId) { |
1196 // Marks either the continuation point in unoptimized code or the | 1196 // Marks either the continuation point in unoptimized code or the |
1197 // deoptimization point in optimized code, after call. | 1197 // deoptimization point in optimized code, after call. |
(...skipping 24 matching lines...) Expand all Loading... |
1222 __ AddImmediate(T1, T1, Smi::RawValue(1)); | 1222 __ AddImmediate(T1, T1, Smi::RawValue(1)); |
1223 __ StoreFieldToOffset(T1, T0, Array::element_offset(edge_id)); | 1223 __ StoreFieldToOffset(T1, T0, Array::element_offset(edge_id)); |
1224 } | 1224 } |
1225 | 1225 |
1226 | 1226 |
1227 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 1227 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
1228 const StubEntry& stub_entry, | 1228 const StubEntry& stub_entry, |
1229 const ICData& ic_data, | 1229 const ICData& ic_data, |
1230 intptr_t argument_count, | 1230 intptr_t argument_count, |
1231 intptr_t deopt_id, | 1231 intptr_t deopt_id, |
1232 intptr_t token_pos, | 1232 TokenDescriptor token_pos, |
1233 LocationSummary* locs) { | 1233 LocationSummary* locs) { |
1234 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); | 1234 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); |
1235 // Each ICData propagated from unoptimized to optimized code contains the | 1235 // Each ICData propagated from unoptimized to optimized code contains the |
1236 // function that corresponds to the Dart function of that IC call. Due | 1236 // function that corresponds to the Dart function of that IC call. Due |
1237 // to inlining in optimized code, that function may not correspond to the | 1237 // to inlining in optimized code, that function may not correspond to the |
1238 // top-level function (parsed_function().function()) which could be | 1238 // top-level function (parsed_function().function()) which could be |
1239 // reoptimized and which counter needs to be incremented. | 1239 // reoptimized and which counter needs to be incremented. |
1240 // Pass the function explicitly, it is used in IC stub. | 1240 // Pass the function explicitly, it is used in IC stub. |
1241 __ Comment("OptimizedInstanceCall"); | 1241 __ Comment("OptimizedInstanceCall"); |
1242 __ LoadObject(T0, parsed_function().function()); | 1242 __ LoadObject(T0, parsed_function().function()); |
1243 __ LoadUniqueObject(S5, ic_data); | 1243 __ LoadUniqueObject(S5, ic_data); |
1244 GenerateDartCall(deopt_id, | 1244 GenerateDartCall(deopt_id, |
1245 token_pos, | 1245 token_pos, |
1246 stub_entry, | 1246 stub_entry, |
1247 RawPcDescriptors::kIcCall, | 1247 RawPcDescriptors::kIcCall, |
1248 locs); | 1248 locs); |
1249 __ Drop(argument_count); | 1249 __ Drop(argument_count); |
1250 } | 1250 } |
1251 | 1251 |
1252 | 1252 |
1253 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, | 1253 void FlowGraphCompiler::EmitInstanceCall(const StubEntry& stub_entry, |
1254 const ICData& ic_data, | 1254 const ICData& ic_data, |
1255 intptr_t argument_count, | 1255 intptr_t argument_count, |
1256 intptr_t deopt_id, | 1256 intptr_t deopt_id, |
1257 intptr_t token_pos, | 1257 TokenDescriptor token_pos, |
1258 LocationSummary* locs) { | 1258 LocationSummary* locs) { |
1259 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); | 1259 ASSERT(Array::Handle(zone(), ic_data.arguments_descriptor()).Length() > 0); |
1260 __ Comment("InstanceCall"); | 1260 __ Comment("InstanceCall"); |
1261 __ LoadUniqueObject(S5, ic_data); | 1261 __ LoadUniqueObject(S5, ic_data); |
1262 GenerateDartCall(deopt_id, | 1262 GenerateDartCall(deopt_id, |
1263 token_pos, | 1263 token_pos, |
1264 stub_entry, | 1264 stub_entry, |
1265 RawPcDescriptors::kIcCall, | 1265 RawPcDescriptors::kIcCall, |
1266 locs); | 1266 locs); |
1267 __ Comment("InstanceCall return"); | 1267 __ Comment("InstanceCall return"); |
1268 __ Drop(argument_count); | 1268 __ Drop(argument_count); |
1269 } | 1269 } |
1270 | 1270 |
1271 | 1271 |
1272 void FlowGraphCompiler::EmitMegamorphicInstanceCall( | 1272 void FlowGraphCompiler::EmitMegamorphicInstanceCall( |
1273 const ICData& ic_data, | 1273 const ICData& ic_data, |
1274 intptr_t argument_count, | 1274 intptr_t argument_count, |
1275 intptr_t deopt_id, | 1275 intptr_t deopt_id, |
1276 intptr_t token_pos, | 1276 TokenDescriptor token_pos, |
1277 LocationSummary* locs, | 1277 LocationSummary* locs, |
1278 intptr_t try_index) { | 1278 intptr_t try_index) { |
1279 const String& name = String::Handle(zone(), ic_data.target_name()); | 1279 const String& name = String::Handle(zone(), ic_data.target_name()); |
1280 const Array& arguments_descriptor = | 1280 const Array& arguments_descriptor = |
1281 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1281 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
1282 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); | 1282 ASSERT(!arguments_descriptor.IsNull() && (arguments_descriptor.Length() > 0)); |
1283 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), | 1283 const MegamorphicCache& cache = MegamorphicCache::ZoneHandle(zone(), |
1284 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); | 1284 MegamorphicCacheTable::Lookup(isolate(), name, arguments_descriptor)); |
1285 | 1285 |
1286 __ Comment("MegamorphicCall"); | 1286 __ Comment("MegamorphicCall"); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1318 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1318 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1319 } | 1319 } |
1320 __ Drop(argument_count); | 1320 __ Drop(argument_count); |
1321 } | 1321 } |
1322 | 1322 |
1323 | 1323 |
1324 void FlowGraphCompiler::EmitSwitchableInstanceCall( | 1324 void FlowGraphCompiler::EmitSwitchableInstanceCall( |
1325 const ICData& ic_data, | 1325 const ICData& ic_data, |
1326 intptr_t argument_count, | 1326 intptr_t argument_count, |
1327 intptr_t deopt_id, | 1327 intptr_t deopt_id, |
1328 intptr_t token_pos, | 1328 TokenDescriptor token_pos, |
1329 LocationSummary* locs) { | 1329 LocationSummary* locs) { |
1330 __ Comment("SwitchableCall"); | 1330 __ Comment("SwitchableCall"); |
1331 __ lw(T0, Address(SP, (argument_count - 1) * kWordSize)); | 1331 __ lw(T0, Address(SP, (argument_count - 1) * kWordSize)); |
1332 if (ic_data.NumArgsTested() == 1) { | 1332 if (ic_data.NumArgsTested() == 1) { |
1333 __ LoadUniqueObject(S5, ic_data); | 1333 __ LoadUniqueObject(S5, ic_data); |
1334 __ BranchLinkPatchable(*StubCode::ICLookup_entry()); | 1334 __ BranchLinkPatchable(*StubCode::ICLookup_entry()); |
1335 } else { | 1335 } else { |
1336 const String& name = String::Handle(zone(), ic_data.target_name()); | 1336 const String& name = String::Handle(zone(), ic_data.target_name()); |
1337 const Array& arguments_descriptor = | 1337 const Array& arguments_descriptor = |
1338 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); | 1338 Array::ZoneHandle(zone(), ic_data.arguments_descriptor()); |
(...skipping 18 matching lines...) Expand all Loading... |
1357 // arguments are removed. | 1357 // arguments are removed. |
1358 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); | 1358 AddCurrentDescriptor(RawPcDescriptors::kDeopt, deopt_id_after, token_pos); |
1359 } | 1359 } |
1360 __ Drop(argument_count); | 1360 __ Drop(argument_count); |
1361 } | 1361 } |
1362 | 1362 |
1363 | 1363 |
1364 void FlowGraphCompiler::EmitUnoptimizedStaticCall( | 1364 void FlowGraphCompiler::EmitUnoptimizedStaticCall( |
1365 intptr_t argument_count, | 1365 intptr_t argument_count, |
1366 intptr_t deopt_id, | 1366 intptr_t deopt_id, |
1367 intptr_t token_pos, | 1367 TokenDescriptor token_pos, |
1368 LocationSummary* locs, | 1368 LocationSummary* locs, |
1369 const ICData& ic_data) { | 1369 const ICData& ic_data) { |
1370 const StubEntry* stub_entry = | 1370 const StubEntry* stub_entry = |
1371 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); | 1371 StubCode::UnoptimizedStaticCallEntry(ic_data.NumArgsTested()); |
1372 __ LoadObject(S5, ic_data); | 1372 __ LoadObject(S5, ic_data); |
1373 GenerateDartCall(deopt_id, | 1373 GenerateDartCall(deopt_id, |
1374 token_pos, | 1374 token_pos, |
1375 *stub_entry, | 1375 *stub_entry, |
1376 RawPcDescriptors::kUnoptStaticCall, | 1376 RawPcDescriptors::kUnoptStaticCall, |
1377 locs); | 1377 locs); |
1378 __ Drop(argument_count); | 1378 __ Drop(argument_count); |
1379 } | 1379 } |
1380 | 1380 |
1381 | 1381 |
1382 void FlowGraphCompiler::EmitOptimizedStaticCall( | 1382 void FlowGraphCompiler::EmitOptimizedStaticCall( |
1383 const Function& function, | 1383 const Function& function, |
1384 const Array& arguments_descriptor, | 1384 const Array& arguments_descriptor, |
1385 intptr_t argument_count, | 1385 intptr_t argument_count, |
1386 intptr_t deopt_id, | 1386 intptr_t deopt_id, |
1387 intptr_t token_pos, | 1387 TokenDescriptor token_pos, |
1388 LocationSummary* locs) { | 1388 LocationSummary* locs) { |
1389 __ Comment("StaticCall"); | 1389 __ Comment("StaticCall"); |
1390 __ LoadObject(S4, arguments_descriptor); | 1390 __ LoadObject(S4, arguments_descriptor); |
1391 // Do not use the code from the function, but let the code be patched so that | 1391 // Do not use the code from the function, but let the code be patched so that |
1392 // we can record the outgoing edges to other code. | 1392 // we can record the outgoing edges to other code. |
1393 GenerateDartCall(deopt_id, | 1393 GenerateDartCall(deopt_id, |
1394 token_pos, | 1394 token_pos, |
1395 *StubCode::CallStaticFunction_entry(), | 1395 *StubCode::CallStaticFunction_entry(), |
1396 RawPcDescriptors::kOther, | 1396 RawPcDescriptors::kOther, |
1397 locs); | 1397 locs); |
1398 AddStaticCallTarget(function); | 1398 AddStaticCallTarget(function); |
1399 __ Drop(argument_count); | 1399 __ Drop(argument_count); |
1400 } | 1400 } |
1401 | 1401 |
1402 | 1402 |
1403 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( | 1403 Condition FlowGraphCompiler::EmitEqualityRegConstCompare( |
1404 Register reg, | 1404 Register reg, |
1405 const Object& obj, | 1405 const Object& obj, |
1406 bool needs_number_check, | 1406 bool needs_number_check, |
1407 intptr_t token_pos) { | 1407 TokenDescriptor token_pos) { |
1408 __ Comment("EqualityRegConstCompare"); | 1408 __ Comment("EqualityRegConstCompare"); |
1409 ASSERT(!needs_number_check || | 1409 ASSERT(!needs_number_check || |
1410 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); | 1410 (!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint())); |
1411 if (needs_number_check) { | 1411 if (needs_number_check) { |
1412 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); | 1412 ASSERT(!obj.IsMint() && !obj.IsDouble() && !obj.IsBigint()); |
1413 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1413 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1414 __ sw(reg, Address(SP, 1 * kWordSize)); | 1414 __ sw(reg, Address(SP, 1 * kWordSize)); |
1415 __ LoadObject(TMP, obj); | 1415 __ LoadObject(TMP, obj); |
1416 __ sw(TMP, Address(SP, 0 * kWordSize)); | 1416 __ sw(TMP, Address(SP, 0 * kWordSize)); |
1417 if (is_optimizing()) { | 1417 if (is_optimizing()) { |
1418 __ BranchLinkPatchable( | 1418 __ BranchLinkPatchable( |
1419 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); | 1419 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1420 } else { | 1420 } else { |
1421 __ BranchLinkPatchable( | 1421 __ BranchLinkPatchable( |
1422 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); | 1422 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1423 } | 1423 } |
1424 if (token_pos >= 0) { | 1424 if (token_pos.IsReal()) { |
1425 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1425 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1426 Thread::kNoDeoptId, | 1426 Thread::kNoDeoptId, |
1427 token_pos); | 1427 token_pos); |
1428 } | 1428 } |
1429 __ Comment("EqualityRegConstCompare return"); | 1429 __ Comment("EqualityRegConstCompare return"); |
1430 // Stub returns result in CMPRES1 (if it is 0, then reg and obj are equal). | 1430 // Stub returns result in CMPRES1 (if it is 0, then reg and obj are equal). |
1431 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. | 1431 __ lw(reg, Address(SP, 1 * kWordSize)); // Restore 'reg'. |
1432 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. | 1432 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Discard constant. |
1433 return Condition(CMPRES1, ZR, EQ); | 1433 return Condition(CMPRES1, ZR, EQ); |
1434 } else { | 1434 } else { |
1435 int16_t imm = 0; | 1435 int16_t imm = 0; |
1436 const Register obj_reg = __ LoadConditionOperand(CMPRES1, obj, &imm); | 1436 const Register obj_reg = __ LoadConditionOperand(CMPRES1, obj, &imm); |
1437 return Condition(reg, obj_reg, EQ, imm); | 1437 return Condition(reg, obj_reg, EQ, imm); |
1438 } | 1438 } |
1439 } | 1439 } |
1440 | 1440 |
1441 | 1441 |
1442 Condition FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 1442 Condition FlowGraphCompiler::EmitEqualityRegRegCompare( |
1443 Register right, | 1443 Register left, |
1444 bool needs_number_check, | 1444 Register right, |
1445 intptr_t token_pos) { | 1445 bool needs_number_check, |
| 1446 TokenDescriptor token_pos) { |
1446 __ Comment("EqualityRegRegCompare"); | 1447 __ Comment("EqualityRegRegCompare"); |
1447 if (needs_number_check) { | 1448 if (needs_number_check) { |
1448 __ addiu(SP, SP, Immediate(-2 * kWordSize)); | 1449 __ addiu(SP, SP, Immediate(-2 * kWordSize)); |
1449 __ sw(left, Address(SP, 1 * kWordSize)); | 1450 __ sw(left, Address(SP, 1 * kWordSize)); |
1450 __ sw(right, Address(SP, 0 * kWordSize)); | 1451 __ sw(right, Address(SP, 0 * kWordSize)); |
1451 if (is_optimizing()) { | 1452 if (is_optimizing()) { |
1452 __ BranchLinkPatchable( | 1453 __ BranchLinkPatchable( |
1453 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); | 1454 *StubCode::OptimizedIdenticalWithNumberCheck_entry()); |
1454 } else { | 1455 } else { |
1455 __ BranchLinkPatchable( | 1456 __ BranchLinkPatchable( |
1456 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); | 1457 *StubCode::UnoptimizedIdenticalWithNumberCheck_entry()); |
1457 } | 1458 } |
1458 if (token_pos >= 0) { | 1459 if (token_pos.IsReal()) { |
1459 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, | 1460 AddCurrentDescriptor(RawPcDescriptors::kRuntimeCall, |
1460 Thread::kNoDeoptId, | 1461 Thread::kNoDeoptId, |
1461 token_pos); | 1462 token_pos); |
1462 } | 1463 } |
1463 __ Comment("EqualityRegRegCompare return"); | 1464 __ Comment("EqualityRegRegCompare return"); |
1464 // Stub returns result in CMPRES1 (if it is 0, then left and right are | 1465 // Stub returns result in CMPRES1 (if it is 0, then left and right are |
1465 // equal). | 1466 // equal). |
1466 __ lw(right, Address(SP, 0 * kWordSize)); | 1467 __ lw(right, Address(SP, 0 * kWordSize)); |
1467 __ lw(left, Address(SP, 1 * kWordSize)); | 1468 __ lw(left, Address(SP, 1 * kWordSize)); |
1468 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1469 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1568 } | 1569 } |
1569 #endif | 1570 #endif |
1570 | 1571 |
1571 | 1572 |
1572 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, | 1573 void FlowGraphCompiler::EmitTestAndCall(const ICData& ic_data, |
1573 intptr_t argument_count, | 1574 intptr_t argument_count, |
1574 const Array& argument_names, | 1575 const Array& argument_names, |
1575 Label* failed, | 1576 Label* failed, |
1576 Label* match_found, | 1577 Label* match_found, |
1577 intptr_t deopt_id, | 1578 intptr_t deopt_id, |
1578 intptr_t token_index, | 1579 TokenDescriptor token_index, |
1579 LocationSummary* locs) { | 1580 LocationSummary* locs) { |
1580 ASSERT(is_optimizing()); | 1581 ASSERT(is_optimizing()); |
1581 __ Comment("EmitTestAndCall"); | 1582 __ Comment("EmitTestAndCall"); |
1582 const Array& arguments_descriptor = | 1583 const Array& arguments_descriptor = |
1583 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, | 1584 Array::ZoneHandle(zone(), ArgumentsDescriptor::New(argument_count, |
1584 argument_names)); | 1585 argument_names)); |
1585 | 1586 |
1586 // Load receiver into T0. | 1587 // Load receiver into T0. |
1587 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); | 1588 __ LoadFromOffset(T0, SP, (argument_count - 1) * kWordSize); |
1588 __ LoadObject(S4, arguments_descriptor); | 1589 __ LoadObject(S4, arguments_descriptor); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 __ AddImmediate(SP, kDoubleSize); | 1899 __ AddImmediate(SP, kDoubleSize); |
1899 } | 1900 } |
1900 | 1901 |
1901 | 1902 |
1902 #undef __ | 1903 #undef __ |
1903 | 1904 |
1904 | 1905 |
1905 } // namespace dart | 1906 } // namespace dart |
1906 | 1907 |
1907 #endif // defined TARGET_ARCH_MIPS | 1908 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |