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