Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(292)

Side by Side Diff: runtime/vm/flow_graph_compiler_arm64.cc

Issue 2799373002: Pass a second type argument vector to all type instantiation calls in the VM. (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 __ b(&fall_through, EQ); 195 __ b(&fall_through, EQ);
196 __ CompareObject(bool_register, Bool::True()); 196 __ CompareObject(bool_register, Bool::True());
197 __ b(is_true, EQ); 197 __ b(is_true, EQ);
198 __ b(is_false); 198 __ b(is_false);
199 __ Bind(&fall_through); 199 __ Bind(&fall_through);
200 } 200 }
201 201
202 202
203 // R0: instance (must be preserved). 203 // R0: instance (must be preserved).
204 // R1: instantiator type arguments (if used). 204 // R1: instantiator type arguments (if used).
205 // R2: function type arguments (if used).
205 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( 206 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
206 TypeTestStubKind test_kind, 207 TypeTestStubKind test_kind,
207 Register instance_reg, 208 Register instance_reg,
208 Register type_arguments_reg, 209 Register instantiator_type_arguments_reg,
210 Register function_type_arguments_reg,
209 Register temp_reg, 211 Register temp_reg,
210 Label* is_instance_lbl, 212 Label* is_instance_lbl,
211 Label* is_not_instance_lbl) { 213 Label* is_not_instance_lbl) {
212 ASSERT(instance_reg == R0); 214 ASSERT(instance_reg == R0);
213 ASSERT(temp_reg == kNoRegister); // Unused on ARM. 215 ASSERT(temp_reg == kNoRegister); // Unused on ARM64.
214 const SubtypeTestCache& type_test_cache = 216 const SubtypeTestCache& type_test_cache =
215 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New()); 217 SubtypeTestCache::ZoneHandle(zone(), SubtypeTestCache::New());
216 __ LoadUniqueObject(R2, type_test_cache); 218 __ LoadUniqueObject(R3, type_test_cache);
217 if (test_kind == kTestTypeOneArg) { 219 if (test_kind == kTestTypeOneArg) {
218 ASSERT(type_arguments_reg == kNoRegister); 220 ASSERT(instantiator_type_arguments_reg == kNoRegister);
219 __ LoadObject(R1, Object::null_object()); 221 ASSERT(function_type_arguments_reg == kNoRegister);
220 __ BranchLink(*StubCode::Subtype1TestCache_entry()); 222 __ BranchLink(*StubCode::Subtype1TestCache_entry());
221 } else if (test_kind == kTestTypeTwoArgs) { 223 } else if (test_kind == kTestTypeTwoArgs) {
222 ASSERT(type_arguments_reg == kNoRegister); 224 ASSERT(instantiator_type_arguments_reg == kNoRegister);
223 __ LoadObject(R1, Object::null_object()); 225 ASSERT(function_type_arguments_reg == kNoRegister);
224 __ BranchLink(*StubCode::Subtype2TestCache_entry()); 226 __ BranchLink(*StubCode::Subtype2TestCache_entry());
225 } else if (test_kind == kTestTypeThreeArgs) { 227 } else if (test_kind == kTestTypeFourArgs) {
226 ASSERT(type_arguments_reg == R1); 228 ASSERT(instantiator_type_arguments_reg == R1);
227 __ BranchLink(*StubCode::Subtype3TestCache_entry()); 229 ASSERT(function_type_arguments_reg == R2);
230 __ BranchLink(*StubCode::Subtype4TestCache_entry());
228 } else { 231 } else {
229 UNREACHABLE(); 232 UNREACHABLE();
230 } 233 }
231 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. 234 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False.
232 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); 235 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl);
233 return type_test_cache.raw(); 236 return type_test_cache.raw();
234 } 237 }
235 238
236 239
237 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if 240 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
238 // type test is conclusive, otherwise fallthrough if a type test could not 241 // type test is conclusive, otherwise fallthrough if a type test could not
239 // be completed. 242 // be completed.
240 // R0: instance being type checked (preserved). 243 // R0: instance being type checked (preserved).
241 // Clobbers R2. 244 // Clobbers R1, R2.
242 RawSubtypeTestCache* 245 RawSubtypeTestCache*
243 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 246 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
244 TokenPosition token_pos, 247 TokenPosition token_pos,
245 const AbstractType& type, 248 const AbstractType& type,
246 Label* is_instance_lbl, 249 Label* is_instance_lbl,
247 Label* is_not_instance_lbl) { 250 Label* is_not_instance_lbl) {
248 __ Comment("InstantiatedTypeWithArgumentsTest"); 251 __ Comment("InstantiatedTypeWithArgumentsTest");
249 ASSERT(type.IsInstantiated()); 252 ASSERT(type.IsInstantiated());
250 const Class& type_class = Class::ZoneHandle(zone(), type.type_class()); 253 const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
251 ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0)); 254 ASSERT(type.IsFunctionType() || (type_class.NumTypeArguments() > 0));
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 const Type& object_type = Type::Handle(zone(), Type::ObjectType()); 298 const Type& object_type = Type::Handle(zone(), Type::ObjectType());
296 if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) { 299 if (object_type.IsSubtypeOf(tp_argument, NULL, NULL, Heap::kOld)) {
297 // Instance class test only necessary. 300 // Instance class test only necessary.
298 return GenerateSubtype1TestCacheLookup( 301 return GenerateSubtype1TestCacheLookup(
299 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); 302 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
300 } 303 }
301 } 304 }
302 } 305 }
303 } 306 }
304 // Regular subtype test cache involving instance's type arguments. 307 // Regular subtype test cache involving instance's type arguments.
305 const Register kTypeArgumentsReg = kNoRegister; 308 const Register kInstantiatorTypeArgumentsReg = kNoRegister;
309 const Register kFunctionTypeArgumentsReg = kNoRegister;
306 const Register kTempReg = kNoRegister; 310 const Register kTempReg = kNoRegister;
307 // R0: instance (must be preserved). 311 // R0: instance (must be preserved).
308 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg, 312 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
309 kTypeArgumentsReg, kTempReg, 313 kInstantiatorTypeArgumentsReg,
314 kFunctionTypeArgumentsReg, kTempReg,
310 is_instance_lbl, is_not_instance_lbl); 315 is_instance_lbl, is_not_instance_lbl);
311 } 316 }
312 317
313 318
314 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, 319 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
315 const GrowableArray<intptr_t>& class_ids, 320 const GrowableArray<intptr_t>& class_ids,
316 Label* is_equal_lbl, 321 Label* is_equal_lbl,
317 Label* is_not_equal_lbl) { 322 Label* is_not_equal_lbl) {
318 for (intptr_t i = 0; i < class_ids.length(); i++) { 323 for (intptr_t i = 0; i < class_ids.length(); i++) {
319 __ CompareImmediate(class_id_reg, class_ids[i]); 324 __ CompareImmediate(class_id_reg, class_ids[i]);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 __ Comment("Subtype1TestCacheLookup"); 411 __ Comment("Subtype1TestCacheLookup");
407 const Register kInstanceReg = R0; 412 const Register kInstanceReg = R0;
408 __ LoadClass(R1, kInstanceReg); 413 __ LoadClass(R1, kInstanceReg);
409 // R1: instance class. 414 // R1: instance class.
410 // Check immediate superclass equality. 415 // Check immediate superclass equality.
411 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset()); 416 __ LoadFieldFromOffset(R2, R1, Class::super_type_offset());
412 __ LoadFieldFromOffset(R2, R2, Type::type_class_id_offset()); 417 __ LoadFieldFromOffset(R2, R2, Type::type_class_id_offset());
413 __ CompareImmediate(R2, Smi::RawValue(type_class.id())); 418 __ CompareImmediate(R2, Smi::RawValue(type_class.id()));
414 __ b(is_instance_lbl, EQ); 419 __ b(is_instance_lbl, EQ);
415 420
416 const Register kTypeArgumentsReg = kNoRegister; 421 const Register kInstantiatorTypeArgumentsReg = kNoRegister;
422 const Register kFunctionTypeArgumentsReg = kNoRegister;
417 const Register kTempReg = kNoRegister; 423 const Register kTempReg = kNoRegister;
418 return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg, 424 return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
419 kTypeArgumentsReg, kTempReg, 425 kInstantiatorTypeArgumentsReg,
426 kFunctionTypeArgumentsReg, kTempReg,
420 is_instance_lbl, is_not_instance_lbl); 427 is_instance_lbl, is_not_instance_lbl);
421 } 428 }
422 429
423 430
424 // Generates inlined check if 'type' is a type parameter or type itself 431 // Generates inlined check if 'type' is a type parameter or type itself
425 // R0: instance (preserved). 432 // R0: instance (preserved).
426 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 433 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
427 TokenPosition token_pos, 434 TokenPosition token_pos,
428 const AbstractType& type, 435 const AbstractType& type,
429 Label* is_instance_lbl, 436 Label* is_instance_lbl,
430 Label* is_not_instance_lbl) { 437 Label* is_not_instance_lbl) {
431 __ Comment("UninstantiatedTypeTest"); 438 __ Comment("UninstantiatedTypeTest");
432 ASSERT(!type.IsInstantiated()); 439 ASSERT(!type.IsInstantiated());
433 // Skip check if destination is a dynamic type. 440 // Skip check if destination is a dynamic type.
434 if (type.IsTypeParameter()) { 441 if (type.IsTypeParameter()) {
435 const TypeParameter& type_param = TypeParameter::Cast(type); 442 const TypeParameter& type_param = TypeParameter::Cast(type);
436 // Load instantiator type arguments on stack. 443 __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args.
zra 2017/04/07 17:36:30 ldp to load a pair.
regis 2017/04/11 04:23:07 Done.
437 __ ldr(R1, Address(SP)); // Get instantiator type arguments. 444 __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args.
438 // R1: instantiator type arguments. 445 // R1: instantiator type arguments.
446 // R2: function type arguments.
447 const Register kTypeArgumentsReg =
448 type_param.IsClassTypeParameter() ? R1 : R2;
439 // Check if type arguments are null, i.e. equivalent to vector of dynamic. 449 // Check if type arguments are null, i.e. equivalent to vector of dynamic.
440 __ CompareObject(R1, Object::null_object()); 450 __ CompareObject(kTypeArgumentsReg, Object::null_object());
441 __ b(is_instance_lbl, EQ); 451 __ b(is_instance_lbl, EQ);
442 __ LoadFieldFromOffset(R2, R1, 452 __ LoadFieldFromOffset(R3, kTypeArgumentsReg,
443 TypeArguments::type_at_offset(type_param.index())); 453 TypeArguments::type_at_offset(type_param.index()));
444 // R2: concrete type of type. 454 // R3: concrete type of type.
445 // Check if type argument is dynamic. 455 // Check if type argument is dynamic.
446 __ CompareObject(R2, Object::dynamic_type()); 456 __ CompareObject(R3, Object::dynamic_type());
447 __ b(is_instance_lbl, EQ); 457 __ b(is_instance_lbl, EQ);
448 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::ObjectType())); 458 __ CompareObject(R3, Type::ZoneHandle(zone(), Type::ObjectType()));
449 __ b(is_instance_lbl, EQ); 459 __ b(is_instance_lbl, EQ);
460 // TODO(regis): Optimize void type as well once allowed as type argument.
450 461
451 // For Smi check quickly against int and num interfaces. 462 // For Smi check quickly against int and num interfaces.
452 Label not_smi; 463 Label not_smi;
453 __ tsti(R0, Immediate(kSmiTagMask)); // Value is Smi? 464 __ tsti(R0, Immediate(kSmiTagMask)); // Value is Smi?
454 __ b(&not_smi, NE); 465 __ b(&not_smi, NE);
455 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::IntType())); 466 __ CompareObject(R3, Type::ZoneHandle(zone(), Type::IntType()));
456 __ b(is_instance_lbl, EQ); 467 __ b(is_instance_lbl, EQ);
457 __ CompareObject(R2, Type::ZoneHandle(zone(), Type::Number())); 468 __ CompareObject(R3, Type::ZoneHandle(zone(), Type::Number()));
458 __ b(is_instance_lbl, EQ); 469 __ b(is_instance_lbl, EQ);
459 // Smi must be handled in runtime. 470 // Smi must be handled in runtime.
460 Label fall_through; 471 Label fall_through;
461 __ b(&fall_through); 472 __ b(&fall_through);
462 473
463 __ Bind(&not_smi); 474 __ Bind(&not_smi);
464 // R1: instantiator type arguments. 475 // R1: instantiator type arguments.
476 // R2: function type arguments.
465 // R0: instance. 477 // R0: instance.
466 const Register kInstanceReg = R0; 478 const Register kInstanceReg = R0;
467 const Register kTypeArgumentsReg = R1; 479 const Register kInstantiatorTypeArgumentsReg = R1;
480 const Register kFunctionTypeArgumentsReg = R2;
468 const Register kTempReg = kNoRegister; 481 const Register kTempReg = kNoRegister;
469 const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle( 482 const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
470 zone(), GenerateCallSubtypeTestStub( 483 zone(), GenerateCallSubtypeTestStub(
471 kTestTypeThreeArgs, kInstanceReg, kTypeArgumentsReg, 484 kTestTypeFourArgs, kInstanceReg,
485 kInstantiatorTypeArgumentsReg, kFunctionTypeArgumentsReg,
472 kTempReg, is_instance_lbl, is_not_instance_lbl)); 486 kTempReg, is_instance_lbl, is_not_instance_lbl));
473 __ Bind(&fall_through); 487 __ Bind(&fall_through);
474 return type_test_cache.raw(); 488 return type_test_cache.raw();
475 } 489 }
476 if (type.IsType()) { 490 if (type.IsType()) {
477 const Register kInstanceReg = R0; 491 const Register kInstanceReg = R0;
478 const Register kTypeArgumentsReg = R1; 492 const Register kInstantiatorTypeArgumentsReg = R1;
493 const Register kFunctionTypeArgumentsReg = R2;
479 __ tsti(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi? 494 __ tsti(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
480 __ b(is_not_instance_lbl, EQ); 495 __ b(is_not_instance_lbl, EQ);
481 __ ldr(kTypeArgumentsReg, Address(SP)); // Instantiator type args. 496 __ ldr(kInstantiatorTypeArgumentsReg, Address(SP, 1 * kWordSize));
zra 2017/04/07 17:36:30 ditto
regis 2017/04/11 04:23:08 Done.
497 __ ldr(kFunctionTypeArgumentsReg, Address(SP, 0 * kWordSize));
482 // Uninstantiated type class is known at compile time, but the type 498 // Uninstantiated type class is known at compile time, but the type
483 // arguments are determined at runtime by the instantiator. 499 // arguments are determined at runtime by the instantiator.
484 const Register kTempReg = kNoRegister; 500 const Register kTempReg = kNoRegister;
485 return GenerateCallSubtypeTestStub(kTestTypeThreeArgs, kInstanceReg, 501 return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
486 kTypeArgumentsReg, kTempReg, 502 kInstantiatorTypeArgumentsReg,
503 kFunctionTypeArgumentsReg, kTempReg,
487 is_instance_lbl, is_not_instance_lbl); 504 is_instance_lbl, is_not_instance_lbl);
488 } 505 }
489 return SubtypeTestCache::null(); 506 return SubtypeTestCache::null();
490 } 507 }
491 508
492 509
493 // Inputs: 510 // Inputs:
494 // - R0: instance being type checked (preserved). 511 // - R0: instance being type checked (preserved).
495 // - R1: optional instantiator type arguments (preserved). 512 // - R1: optional instantiator type arguments (preserved).
496 // Clobbers R2, R3. 513 // - R2: optional function type arguments (preserved).
514 // Clobbers R3, R4, R8, R9.
497 // Returns: 515 // Returns:
498 // - preserved instance in R0 and optional instantiator type arguments in R1. 516 // - preserved instance in R0, optional instantiator type arguments in R1, and
517 // optional function type arguments in R2.
499 // Note that this inlined code must be followed by the runtime_call code, as it 518 // Note that this inlined code must be followed by the runtime_call code, as it
500 // may fall through to it. Otherwise, this inline code will jump to the label 519 // may fall through to it. Otherwise, this inline code will jump to the label
501 // is_instance or to the label is_not_instance. 520 // is_instance or to the label is_not_instance.
502 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( 521 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
503 TokenPosition token_pos, 522 TokenPosition token_pos,
504 const AbstractType& type, 523 const AbstractType& type,
505 Label* is_instance_lbl, 524 Label* is_instance_lbl,
506 Label* is_not_instance_lbl) { 525 Label* is_not_instance_lbl) {
507 __ Comment("InlineInstanceof"); 526 __ Comment("InlineInstanceof");
508 if (type.IsVoidType()) { 527 if (type.IsVoidType()) {
(...skipping 28 matching lines...) Expand all
537 556
538 557
539 // If instanceof type test cannot be performed successfully at compile time and 558 // If instanceof type test cannot be performed successfully at compile time and
540 // therefore eliminated, optimize it by adding inlined tests for: 559 // therefore eliminated, optimize it by adding inlined tests for:
541 // - NULL -> return type == Null (type is not Object or dynamic). 560 // - NULL -> return type == Null (type is not Object or dynamic).
542 // - Smi -> compile time subtype check (only if dst class is not parameterized). 561 // - Smi -> compile time subtype check (only if dst class is not parameterized).
543 // - Class equality (only if class is not parameterized). 562 // - Class equality (only if class is not parameterized).
544 // Inputs: 563 // Inputs:
545 // - R0: object. 564 // - R0: object.
546 // - R1: instantiator type arguments or raw_null. 565 // - R1: instantiator type arguments or raw_null.
566 // - R2: function type arguments or raw_null.
547 // Returns: 567 // Returns:
548 // - true or false in R0. 568 // - true or false in R0.
549 void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos, 569 void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
550 intptr_t deopt_id, 570 intptr_t deopt_id,
551 const AbstractType& type, 571 const AbstractType& type,
552 LocationSummary* locs) { 572 LocationSummary* locs) {
553 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded()); 573 ASSERT(type.IsFinalized() && !type.IsMalformed() && !type.IsMalbounded());
554 ASSERT(!type.IsObjectType() && !type.IsDynamicType()); 574 ASSERT(!type.IsObjectType() && !type.IsDynamicType());
555 575
556 // Preserve instantiator type arguments (R1). 576 __ Push(R1); // Store instantiator type arguments.
zra 2017/04/07 17:36:30 PushPair
regis 2017/04/11 04:23:08 Done. However, the argument names 'first' and 'se
557 __ Push(R1); 577 __ Push(R2); // Store function type arguments.
558 578
559 Label is_instance, is_not_instance; 579 Label is_instance, is_not_instance;
560 // If type is instantiated and non-parameterized, we can inline code 580 // If type is instantiated and non-parameterized, we can inline code
561 // checking whether the tested instance is a Smi. 581 // checking whether the tested instance is a Smi.
562 if (type.IsInstantiated()) { 582 if (type.IsInstantiated()) {
563 // A null object is only an instance of Null, Object, and dynamic. 583 // A null object is only an instance of Null, Object, and dynamic.
564 // Object and dynamic have already been checked above (if the type is 584 // Object and dynamic have already been checked above (if the type is
565 // instantiated). So we can return false here if the instance is null, 585 // instantiated). So we can return false here if the instance is null,
566 // unless the type is Null (and if the type is instantiated). 586 // unless the type is Null (and if the type is instantiated).
567 // We can only inline this null check if the type is instantiated at compile 587 // We can only inline this null check if the type is instantiated at compile
568 // time, since an uninstantiated type at compile time could be Null, Object, 588 // time, since an uninstantiated type at compile time could be Null, Object,
569 // or dynamic at run time. 589 // or dynamic at run time.
570 __ CompareObject(R0, Object::null_object()); 590 __ CompareObject(R0, Object::null_object());
571 __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ); 591 __ b(type.IsNullType() ? &is_instance : &is_not_instance, EQ);
572 } 592 }
573 593
574 // Generate inline instanceof test. 594 // Generate inline instanceof test.
575 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 595 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
576 test_cache = 596 test_cache =
577 GenerateInlineInstanceof(token_pos, type, &is_instance, &is_not_instance); 597 GenerateInlineInstanceof(token_pos, type, &is_instance, &is_not_instance);
578 598
579 // test_cache is null if there is no fall-through. 599 // test_cache is null if there is no fall-through.
580 Label done; 600 Label done;
581 if (!test_cache.IsNull()) { 601 if (!test_cache.IsNull()) {
582 // Generate runtime call. 602 // Generate runtime call.
583 // Load instantiator (R2) and its type arguments (R1). 603 // Load instantiator (R2) and its type arguments (R1).
584 __ ldr(R1, Address(SP, 0 * kWordSize)); 604 __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args.
zra 2017/04/07 17:36:30 ldp
regis 2017/04/11 04:23:08 Done.
585 __ PushObject(Object::null_object()); // Make room for the result. 605 __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args.
586 __ Push(R0); // Push the instance. 606 __ PushObject(Object::null_object()); // Make room for the result.
587 __ PushObject(type); // Push the type. 607 __ Push(R0); // Push the instance.
588 __ Push(R1); // Push instantiator type arguments (R1). 608 __ PushObject(type); // Push the type.
609 __ Push(R1); // Instantiator type arguments.
zra 2017/04/07 17:36:30 PushPair
regis 2017/04/11 04:23:08 Done.
610 __ Push(R2); // Function type arguments.
589 __ LoadUniqueObject(R0, test_cache); 611 __ LoadUniqueObject(R0, test_cache);
590 __ Push(R0); 612 __ Push(R0);
591 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 4, locs); 613 GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
592 // Pop the parameters supplied to the runtime entry. The result of the 614 // Pop the parameters supplied to the runtime entry. The result of the
593 // instanceof runtime call will be left as the result of the operation. 615 // instanceof runtime call will be left as the result of the operation.
594 __ Drop(4); 616 __ Drop(5);
595 __ Pop(R0); 617 __ Pop(R0);
596 __ b(&done); 618 __ b(&done);
597 } 619 }
598 __ Bind(&is_not_instance); 620 __ Bind(&is_not_instance);
599 __ LoadObject(R0, Bool::Get(false)); 621 __ LoadObject(R0, Bool::Get(false));
600 __ b(&done); 622 __ b(&done);
601 623
602 __ Bind(&is_instance); 624 __ Bind(&is_instance);
603 __ LoadObject(R0, Bool::Get(true)); 625 __ LoadObject(R0, Bool::Get(true));
604 __ Bind(&done); 626 __ Bind(&done);
605 // Remove instantiator type arguments (R1). 627 // Remove instantiator type arguments and function type arguments.
606 __ Drop(1); 628 __ Drop(2);
607 } 629 }
608 630
609 631
610 // Optimize assignable type check by adding inlined tests for: 632 // Optimize assignable type check by adding inlined tests for:
611 // - NULL -> return NULL. 633 // - NULL -> return NULL.
612 // - Smi -> compile time subtype check (only if dst class is not parameterized). 634 // - Smi -> compile time subtype check (only if dst class is not parameterized).
613 // - Class equality (only if class is not parameterized). 635 // - Class equality (only if class is not parameterized).
614 // Inputs: 636 // Inputs:
615 // - R0: instance being type checked. 637 // - R0: instance being type checked.
616 // - R1: instantiator type arguments or raw_null. 638 // - R1: instantiator type arguments or raw_null.
639 // - R2: function type arguments or raw_null.
617 // Returns: 640 // Returns:
618 // - object in R0 for successful assignable check (or throws TypeError). 641 // - object in R0 for successful assignable check (or throws TypeError).
619 // Performance notes: positive checks must be quick, negative checks can be slow 642 // Performance notes: positive checks must be quick, negative checks can be slow
620 // as they throw an exception. 643 // as they throw an exception.
621 void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos, 644 void FlowGraphCompiler::GenerateAssertAssignable(TokenPosition token_pos,
622 intptr_t deopt_id, 645 intptr_t deopt_id,
623 const AbstractType& dst_type, 646 const AbstractType& dst_type,
624 const String& dst_name, 647 const String& dst_name,
625 LocationSummary* locs) { 648 LocationSummary* locs) {
626 ASSERT(!TokenPosition(token_pos).IsClassifying()); 649 ASSERT(!TokenPosition(token_pos).IsClassifying());
627 ASSERT(!dst_type.IsNull()); 650 ASSERT(!dst_type.IsNull());
628 ASSERT(dst_type.IsFinalized()); 651 ASSERT(dst_type.IsFinalized());
629 // Assignable check is skipped in FlowGraphBuilder, not here. 652 // Assignable check is skipped in FlowGraphBuilder, not here.
630 ASSERT(dst_type.IsMalformedOrMalbounded() || 653 ASSERT(dst_type.IsMalformedOrMalbounded() ||
631 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 654 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
632 // Preserve instantiator type arguments (R1). 655 __ Push(R1); // Store instantiator type arguments.
zra 2017/04/07 17:36:30 PushPair
regis 2017/04/11 04:23:08 Done.
633 __ Push(R1); 656 __ Push(R2); // Store function type arguments.
634 // A null object is always assignable and is returned as result. 657 // A null object is always assignable and is returned as result.
635 Label is_assignable, runtime_call; 658 Label is_assignable, runtime_call;
636 __ CompareObject(R0, Object::null_object()); 659 __ CompareObject(R0, Object::null_object());
637 __ b(&is_assignable, EQ); 660 __ b(&is_assignable, EQ);
638 661
639 // Generate throw new TypeError() if the type is malformed or malbounded. 662 // Generate throw new TypeError() if the type is malformed or malbounded.
640 if (dst_type.IsMalformedOrMalbounded()) { 663 if (dst_type.IsMalformedOrMalbounded()) {
641 __ PushObject(Object::null_object()); // Make room for the result. 664 __ PushObject(Object::null_object()); // Make room for the result.
642 __ Push(R0); // Push the source object. 665 __ Push(R0); // Push the source object.
643 __ PushObject(dst_name); // Push the name of the destination. 666 __ PushObject(dst_name); // Push the name of the destination.
644 __ PushObject(dst_type); // Push the type of the destination. 667 __ PushObject(dst_type); // Push the type of the destination.
645 GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3, 668 GenerateRuntimeCall(token_pos, deopt_id, kBadTypeErrorRuntimeEntry, 3,
646 locs); 669 locs);
647 // We should never return here. 670 // We should never return here.
648 __ brk(0); 671 __ brk(0);
649 672
650 __ Bind(&is_assignable); // For a null object. 673 __ Bind(&is_assignable); // For a null object.
651 // Restore instantiator type arguments (R1). 674 __ Pop(R2); // Remove pushed function type arguments.
zra 2017/04/07 17:36:30 PopPair
regis 2017/04/11 04:23:08 Done.
652 __ Pop(R1); 675 __ Pop(R1); // Remove pushed instantiator type arguments.
653 return; 676 return;
654 } 677 }
655 678
656 // Generate inline type check, linking to runtime call if not assignable. 679 // Generate inline type check, linking to runtime call if not assignable.
657 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone()); 680 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
658 test_cache = GenerateInlineInstanceof(token_pos, dst_type, &is_assignable, 681 test_cache = GenerateInlineInstanceof(token_pos, dst_type, &is_assignable,
659 &runtime_call); 682 &runtime_call);
660 683
661 __ Bind(&runtime_call); 684 __ Bind(&runtime_call);
662 __ ldr(R1, Address(SP)); // Load instantiator type arguments (R1). 685 __ ldr(R1, Address(SP, 1 * kWordSize)); // Get instantiator type args.
zra 2017/04/07 17:36:30 ldp
regis 2017/04/11 04:23:07 Done.
663 __ PushObject(Object::null_object()); // Make room for the result. 686 __ ldr(R2, Address(SP, 0 * kWordSize)); // Get function type args.
664 __ Push(R0); // Push the source object. 687 __ PushObject(Object::null_object()); // Make room for the result.
665 __ PushObject(dst_type); // Push the type of the destination. 688 __ Push(R0); // Push the source object.
666 __ Push(R1); // Push instantiator type arguments (R1). 689 __ PushObject(dst_type); // Push the type of the destination.
667 __ PushObject(dst_name); // Push the name of the destination. 690 __ Push(R1); // Instantiator type arguments.
zra 2017/04/07 17:36:30 PushPair
regis 2017/04/11 04:23:07 Done.
691 __ Push(R2); // Function type arguments.
692 __ PushObject(dst_name); // Push the name of the destination.
668 __ LoadUniqueObject(R0, test_cache); 693 __ LoadUniqueObject(R0, test_cache);
669 __ Push(R0); 694 __ Push(R0);
670 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 5, locs); 695 GenerateRuntimeCall(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs);
671 // Pop the parameters supplied to the runtime entry. The result of the 696 // Pop the parameters supplied to the runtime entry. The result of the
672 // type check runtime call is the checked value. 697 // type check runtime call is the checked value.
673 __ Drop(5); 698 __ Drop(6);
674 __ Pop(R0); 699 __ Pop(R0);
675 700
676 __ Bind(&is_assignable); 701 __ Bind(&is_assignable);
677 // Restore instantiator type arguments (R1). 702 __ Pop(R2); // Remove pushed function type arguments.
zra 2017/04/07 17:36:30 PopPair
regis 2017/04/11 04:23:08 Done.
678 __ Pop(R1); 703 __ Pop(R1); // Remove pushed instantiator type arguments.
679 } 704 }
680 705
681 706
682 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) { 707 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
683 if (is_optimizing()) { 708 if (is_optimizing()) {
684 return; 709 return;
685 } 710 }
686 Definition* defn = instr->AsDefinition(); 711 Definition* defn = instr->AsDefinition();
687 if ((defn != NULL) && defn->HasTemp()) { 712 if ((defn != NULL) && defn->HasTemp()) {
688 __ Push(defn->locs()->out(0).reg()); 713 __ Push(defn->locs()->out(0).reg());
(...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after
1833 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { 1858 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) {
1834 __ PopDouble(reg); 1859 __ PopDouble(reg);
1835 } 1860 }
1836 1861
1837 1862
1838 #undef __ 1863 #undef __
1839 1864
1840 } // namespace dart 1865 } // namespace dart
1841 1866
1842 #endif // defined TARGET_ARCH_ARM64 1867 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698