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

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

Issue 10477020: Move inlined type checking code to new compiler ia32. Sharing more and more code between ia32/x64 (… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
7 7
8 #include "vm/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
11 #include "vm/ast_printer.h" 11 #include "vm/ast_printer.h"
12 #include "vm/compiler_stats.h" 12 #include "vm/compiler_stats.h"
13 #include "vm/il_printer.h" 13 #include "vm/il_printer.h"
14 #include "vm/locations.h" 14 #include "vm/locations.h"
15 #include "vm/object_store.h"
15 #include "vm/stub_code.h" 16 #include "vm/stub_code.h"
16 17
17 namespace dart { 18 namespace dart {
18 19
19 DECLARE_FLAG(bool, code_comments); 20 DECLARE_FLAG(bool, code_comments);
20 DECLARE_FLAG(bool, compiler_stats); 21 DECLARE_FLAG(bool, compiler_stats);
21 DECLARE_FLAG(bool, enable_type_checks); 22 DECLARE_FLAG(bool, enable_type_checks);
22 DECLARE_FLAG(bool, print_ast); 23 DECLARE_FLAG(bool, print_ast);
23 DECLARE_FLAG(bool, print_scopes); 24 DECLARE_FLAG(bool, print_scopes);
24 DECLARE_FLAG(bool, trace_functions); 25 DECLARE_FLAG(bool, trace_functions);
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 403
403 void FlowGraphCompiler::GenerateCall(intptr_t token_index, 404 void FlowGraphCompiler::GenerateCall(intptr_t token_index,
404 intptr_t try_index, 405 intptr_t try_index,
405 const ExternalLabel* label, 406 const ExternalLabel* label,
406 PcDescriptors::Kind kind) { 407 PcDescriptors::Kind kind) {
407 __ call(label); 408 __ call(label);
408 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); 409 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index);
409 } 410 }
410 411
411 412
413 // Fall through if bool_register contains null.
414 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register,
415 Label* is_true,
416 Label* is_false) {
417 const Immediate raw_null =
418 Immediate(reinterpret_cast<intptr_t>(Object::null()));
419 Label fall_through;
420 __ cmpl(bool_register, raw_null);
421 __ j(EQUAL, &fall_through, Assembler::kNearJump);
422 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
423 __ CompareObject(bool_register, bool_true);
424 __ j(EQUAL, is_true);
425 __ jmp(is_false);
426 __ Bind(&fall_through);
427 }
428
429
430 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 comment that it clobbers ECX?
srdjan 2012/06/05 15:32:20 Done.
431 TypeTestStubKind test_kind,
432 Register instance_reg,
433 Register type_arguments_reg,
434 Register temp_reg,
435 Label* is_instance_lbl,
436 Label* is_not_instance_lbl) {
437 const SubtypeTestCache& type_test_cache =
438 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New());
439 const Immediate raw_null =
440 Immediate(reinterpret_cast<intptr_t>(Object::null()));
441 __ LoadObject(temp_reg, type_test_cache);
442 __ pushl(temp_reg); // Subtype test cache.
443 __ pushl(instance_reg); // Instance.
444 if (test_kind == kTestTypeOneArg) {
445 ASSERT(type_arguments_reg == kNoRegister);
446 __ pushl(raw_null);
447 __ call(&StubCode::Subtype1TestCacheLabel());
448 } else if (test_kind == kTestTypeTwoArgs) {
449 ASSERT(type_arguments_reg == kNoRegister);
450 __ pushl(raw_null);
451 __ call(&StubCode::Subtype2TestCacheLabel());
452 } else if (test_kind == kTestTypeThreeArgs) {
453 __ pushl(type_arguments_reg);
454 __ call(&StubCode::Subtype3TestCacheLabel());
455 } else {
456 UNREACHABLE();
457 }
458 // Result is in ECX: null -> not found, otherwise Bool::True or Bool::False.
459 __ popl(instance_reg); // Discard.
460 __ popl(instance_reg); // Restore receiver.
461 __ popl(temp_reg); // Discard.
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 instance reg and temp_reg should not be ECX. asser
srdjan 2012/06/05 15:32:20 Done.
462 GenerateBoolToJump(ECX, is_instance_lbl, is_not_instance_lbl);
463 return type_test_cache.raw();
464 }
465
466
467 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
468 // type test is conclusive, otherwise fallthrough if a type test could not
469 // be completed.
470 // EAX: instance (must survive), clobbers ECX, EDI
471 RawSubtypeTestCache*
472 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
473 intptr_t cid,
474 intptr_t token_index,
475 const AbstractType& type,
476 Label* is_instance_lbl,
477 Label* is_not_instance_lbl) {
478 ASSERT(type.IsInstantiated());
479 const Class& type_class = Class::ZoneHandle(type.type_class());
480 ASSERT(type_class.HasTypeArguments());
481 const Register kInstanceReg = EAX;
482 // A Smi object cannot be the instance of a parameterized class.
483 __ testl(kInstanceReg, Immediate(kSmiTagMask));
484 __ j(ZERO, is_not_instance_lbl);
485 const AbstractTypeArguments& type_arguments =
486 AbstractTypeArguments::ZoneHandle(type.arguments());
487 const bool is_raw_type = type_arguments.IsNull() ||
488 type_arguments.IsRaw(type_arguments.Length());
489 if (is_raw_type) {
490 const Register kClassIdReg = ECX;
491 // Dynamic type argument, check only classes.
492 __ LoadClassId(kClassIdReg, kInstanceReg);
493 if (!type_class.is_interface()) {
494 __ cmpl(kClassIdReg, Immediate(type_class.id()));
495 __ j(EQUAL, is_instance_lbl);
496 }
497 if (type.IsListInterface()) {
498 GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
499 }
500 return GenerateSubtype1TestCacheLookup(
501 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
502 }
503 // If one type argument only, check if type argument is Object or Dynamic.
504 if (type_arguments.Length() == 1) {
505 const AbstractType& tp_argument = AbstractType::ZoneHandle(
506 type_arguments.TypeAt(0));
507 ASSERT(!tp_argument.IsMalformed());
508 if (tp_argument.IsType()) {
509 ASSERT(tp_argument.HasResolvedTypeClass());
510 // Check if type argument is dynamic or Object.
511 const Type& object_type =
512 Type::Handle(Isolate::Current()->object_store()->object_type());
513 Error& malformed_error = Error::Handle();
514 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
515 // Instance class test only necessary.
516 return GenerateSubtype1TestCacheLookup(
517 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl);
518 }
519 }
520 }
521 // Regular subtype test cache involving instance's type arguments.
522 const Register kTypeArgumentsReg = kNoRegister;
523 const Register kTempReg = EDI;
524 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs,
525 kInstanceReg,
526 kTypeArgumentsReg,
527 kTempReg,
528 is_instance_lbl,
529 is_not_instance_lbl);
530 }
531
532
533 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
534 const GrowableArray<intptr_t>& class_ids,
535 Label* is_equal_lbl,
536 Label* is_not_equal_lbl) {
537 for (intptr_t i = 0; i < class_ids.length(); i++) {
538 __ cmpl(class_id_reg, Immediate(class_ids[i]));
539 __ j(EQUAL, is_equal_lbl);
540 }
541 __ jmp(is_not_equal_lbl);
542 }
543
544
545 // Testing against an instantiated type with no arguments, without
546 // SubtypeTestCache.
547 // EAX: instance to test against (preserved). Clobbers ECX.
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 clobbers ebx as well
srdjan 2012/06/05 15:32:20 Removed LoadClass usage, EBX not clobbered any lon
548 void FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
549 intptr_t cid,
550 intptr_t token_index,
551 const AbstractType& type,
552 Label* is_instance_lbl,
553 Label* is_not_instance_lbl) {
554 ASSERT(type.IsInstantiated());
555 const Class& type_class = Class::Handle(type.type_class());
556 ASSERT(!type_class.HasTypeArguments());
557
558 Label compare_classes;
559 __ testl(EAX, Immediate(kSmiTagMask));
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 declare named constants for registers just like ab
srdjan 2012/06/05 15:32:20 Done.
560 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
561 // Instance is Smi, check directly.
562 const Class& smi_class = Class::Handle(Smi::Class());
563 // TODO(regis): We should introduce a SmiType.
564 Error& malformed_error = Error::Handle();
565 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
566 type_class,
567 TypeArguments::Handle(),
568 &malformed_error)) {
569 __ jmp(is_instance_lbl);
570 } else {
571 __ jmp(is_not_instance_lbl);
572 }
573 // Compare if the classes are equal.
574 __ Bind(&compare_classes);
575 const Register kClassIdReg = ECX;
576 __ LoadClassId(kClassIdReg, EAX);
577 // If type is an interface, we can skip the class equality check.
578 if (!type_class.is_interface()) {
579 __ cmpl(kClassIdReg, Immediate(type_class.id()));
580 __ j(EQUAL, is_instance_lbl);
581 }
582 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces).
583 // Bool interface can be implemented only by core class Bool.
584 if (type.IsBoolInterface()) {
585 __ cmpl(kClassIdReg, Immediate(kBool));
586 __ j(EQUAL, is_instance_lbl);
587 __ jmp(is_not_instance_lbl);
588 return;
589 }
590 if (type.IsFunctionInterface()) {
591 // Check if instance is a closure.
592 const Immediate raw_null =
593 Immediate(reinterpret_cast<intptr_t>(Object::null()));
594 __ LoadClass(ECX, EAX, EBX);
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 on x64 we have LoadClassById (ECX already contains
srdjan 2012/06/05 15:32:20 Added LoadClassById
595 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset()));
596 __ cmpl(ECX, raw_null);
597 __ j(NOT_EQUAL, is_instance_lbl);
598 __ jmp(is_not_instance_lbl);
599 return;
600 }
601 // Custom checking for numbers (Smi, Mint, Bigint and Double).
602 // Note that instance is not Smi(checked above).
603 if (type.IsSubtypeOf(
604 Type::Handle(Type::NumberInterface()), &malformed_error)) {
605 GenerateNumberTypeCheck(
606 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
607 return;
608 }
609 if (type.IsStringInterface()) {
610 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
611 return;
612 }
613 }
614
615
616 // Generates inlined check if 'type' is a type parameter or type itsef
617 // EAX: instance (preserved). Clobbers EDX, EDI, ECX.
618 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
619 intptr_t cid,
620 intptr_t token_index,
621 const AbstractType& type,
622 Label* is_instance_lbl,
623 Label* is_not_instance_lbl) {
624 ASSERT(!type.IsInstantiated());
625 // Skip check if destination is a dynamic type.
626 const Immediate raw_null =
627 Immediate(reinterpret_cast<intptr_t>(Object::null()));
628 if (type.IsTypeParameter()) {
629 // Load instantiator (or null) and instantiator type arguments on stack.
630 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
631 // EDX: instantiator type arguments.
632 // Check if type argument is Dynamic.
633 __ cmpl(EDX, raw_null);
634 __ j(EQUAL, is_instance_lbl);
635 // Can handle only type arguments that are instances of TypeArguments.
636 // (runtime checks canonicalize type arguments).
637 Label fall_through;
638 __ CompareClassId(EDX, kTypeArguments, EDI);
639 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
640
641 __ movl(EDI,
642 FieldAddress(EDX, TypeArguments::type_at_offset(type.Index())));
643 // EDI: concrete type of type.
644 // Check if type argument is dynamic.
645 __ CompareObject(EDI, Type::ZoneHandle(Type::DynamicType()));
646 __ j(EQUAL, is_instance_lbl);
647 __ cmpl(EDI, raw_null);
648 __ j(EQUAL, is_instance_lbl);
649 const Type& object_type =
650 Type::ZoneHandle(Isolate::Current()->object_store()->object_type());
651 __ CompareObject(EDI, object_type);
652 __ j(EQUAL, is_instance_lbl);
653
654 // For Smi check quickly against int and num interfaces.
Vyacheslav Egorov (Google) 2012/06/05 12:52:24 indentation
srdjan 2012/06/05 15:32:20 Done.
655 Label not_smi;
656 __ testl(EAX, Immediate(kSmiTagMask)); // Value is Smi?
657 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
658 __ CompareObject(EDI, Type::ZoneHandle(Type::IntInterface()));
659 __ j(EQUAL, is_instance_lbl);
660 __ CompareObject(EDI, Type::ZoneHandle(Type::NumberInterface()));
661 __ j(EQUAL, is_instance_lbl);
662 // Smi must be handled in runtime.
663 __ jmp(&fall_through);
664
665 __ Bind(&not_smi);
666 // EDX: instantiator type arguments.
667 // EAX: instance.
668 const Register kInstanceReg = EAX;
669 const Register kTypeArgumentsReg = EDX;
670 const Register kTempReg = EDI;
671 const SubtypeTestCache& type_test_cache =
672 SubtypeTestCache::ZoneHandle(
673 GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
674 kInstanceReg,
675 kTypeArgumentsReg,
676 kTempReg,
677 is_instance_lbl,
678 is_not_instance_lbl));
679 __ Bind(&fall_through);
680 return type_test_cache.raw();
681 }
682 if (type.IsType()) {
683 const Register kInstanceReg = EAX;
684 const Register kTypeArgumentsReg = EDX;
685 __ testl(kInstanceReg, Immediate(kSmiTagMask)); // Is instance Smi?
686 __ j(ZERO, is_not_instance_lbl);
687 __ movl(kTypeArgumentsReg, Address(ESP, 0)); // Instantiator type args.
688 // Uninstantiated type class is known at compile time, but the type
689 // arguments are determined at runtime by the instantiator.
690 const Register kTempReg = EDI;
691 return GenerateCallSubtypeTestStub(kTestTypeThreeArgs,
692 kInstanceReg,
693 kTypeArgumentsReg,
694 kTempReg,
695 is_instance_lbl,
696 is_not_instance_lbl);
697 }
698 return SubtypeTestCache::null();
699 }
700
701
702 // Uses SubtypeTestCache to store instance class and result.
703 // EAX: instance to test. Clobbers EDI, ECX.
704 // Immediate class test already done.
705 // TODO(srdjan): Implement a quicker subtype check, as type test
706 // arrays can grow too high, but they may be useful when optimizing
707 // code (type-feedback).
708 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
709 intptr_t cid,
710 intptr_t token_index,
711 const Class& type_class,
712 Label* is_instance_lbl,
713 Label* is_not_instance_lbl) {
714 const Register kInstanceReg = EAX;
715 __ LoadClass(ECX, kInstanceReg, EDI);
716 // ECX: instance class.
717 // Check immediate superclass equality.
718 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
719 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
720 __ CompareObject(EDI, type_class);
721 __ j(EQUAL, is_instance_lbl);
722
723 const Register kTypeArgumentsReg = kNoRegister;
724 const Register kTempReg = EDI;
725 return GenerateCallSubtypeTestStub(kTestTypeOneArg,
726 kInstanceReg,
727 kTypeArgumentsReg,
728 kTempReg,
729 is_instance_lbl,
730 is_not_instance_lbl);
731 }
732
733
734 // Inputs:
735 // - EAX: instance to test against (preserved).
736 // - EDX: optional instantiator type arguments (preserved).
737 // Returns:
738 // - preserved instance in EAX and optional instantiator type arguments in EDX.
739 // Note that this inlined code must be followed by the runtime_call code, as it
740 // may fall through to it. Otherwise, this inline code will jump to the label
741 // is_instance or to the label is_not_instance.
742 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
743 intptr_t cid,
744 intptr_t token_index,
745 const AbstractType& type,
746 Label* is_instance_lbl,
747 Label* is_not_instance_lbl) {
748 if (type.IsInstantiated()) {
749 const Class& type_class = Class::ZoneHandle(type.type_class());
750 // A Smi object cannot be the instance of a parameterized class.
751 // A class equality check is only applicable with a dst type of a
752 // non-parameterized class or with a raw dst type of a parameterized class.
753 if (type_class.HasTypeArguments()) {
754 return GenerateInstantiatedTypeWithArgumentsTest(cid,
755 token_index,
756 type,
757 is_instance_lbl,
758 is_not_instance_lbl);
759 // Fall through to runtime call.
760 } else {
761 GenerateInstantiatedTypeNoArgumentsTest(cid,
762 token_index,
763 type,
764 is_instance_lbl,
765 is_not_instance_lbl);
766 // If test non-conclusive so far, try the inlined type-test cache.
767 // 'type' is known at compile time.
768 return GenerateSubtype1TestCacheLookup(
769 cid, token_index, type_class,
770 is_instance_lbl, is_not_instance_lbl);
771 }
772 } else {
773 return GenerateUninstantiatedTypeTest(cid,
774 token_index,
775 type,
776 is_instance_lbl,
777 is_not_instance_lbl);
778 }
779 return SubtypeTestCache::null();
780 }
781
782
412 // If instanceof type test cannot be performed successfully at compile time and 783 // If instanceof type test cannot be performed successfully at compile time and
413 // therefore eliminated, optimize it by adding inlined tests for: 784 // therefore eliminated, optimize it by adding inlined tests for:
414 // - NULL -> return false. 785 // - NULL -> return false.
415 // - Smi -> compile time subtype check (only if dst class is not parameterized). 786 // - Smi -> compile time subtype check (only if dst class is not parameterized).
416 // - Class equality (only if class is not parameterized). 787 // - Class equality (only if class is not parameterized).
417 // Inputs: 788 // Inputs:
418 // - EAX: object. 789 // - EAX: object.
419 // - EDX: instantiator type arguments or raw_null. 790 // - EDX: instantiator type arguments or raw_null.
420 // - ECX: instantiator or raw_null. 791 // - ECX: instantiator or raw_null.
421 // Returns: 792 // Returns:
(...skipping 21 matching lines...) Expand all
443 // instantiated). 814 // instantiated).
444 // We can only inline this null check if the type is instantiated at compile 815 // We can only inline this null check if the type is instantiated at compile
445 // time, since an uninstantiated type at compile time could be Object or 816 // time, since an uninstantiated type at compile time could be Object or
446 // Dynamic at run time. 817 // Dynamic at run time.
447 __ cmpl(EAX, raw_null); 818 __ cmpl(EAX, raw_null);
448 __ j(EQUAL, &is_not_instance); 819 __ j(EQUAL, &is_not_instance);
449 } 820 }
450 // TODO(srdjan): Enable inlined checks. 821 // TODO(srdjan): Enable inlined checks.
451 // Generate inline instanceof test. 822 // Generate inline instanceof test.
452 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 823 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
453 // test_cache = GenerateInlineInstanceof(cid, token_index, type, 824 test_cache = GenerateInlineInstanceof(cid, token_index, type,
454 // &is_instance, &is_not_instance); 825 &is_instance, &is_not_instance);
455 826
456 // Generate runtime call. 827 // Generate runtime call.
457 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 828 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
458 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 829 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
459 __ PushObject(Object::ZoneHandle()); // Make room for the result. 830 __ PushObject(Object::ZoneHandle()); // Make room for the result.
460 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 831 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
461 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id. 832 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
462 __ pushl(EAX); // Push the instance. 833 __ pushl(EAX); // Push the instance.
463 __ PushObject(type); // Push the type. 834 __ PushObject(type); // Push the type.
464 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null. 835 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 // We should never return here. 915 // We should never return here.
545 __ int3(); 916 __ int3();
546 917
547 __ Bind(&is_assignable); // For a null object. 918 __ Bind(&is_assignable); // For a null object.
548 return; 919 return;
549 } 920 }
550 921
551 // TODO(srdjan): Enable subtype test cache. 922 // TODO(srdjan): Enable subtype test cache.
552 // Generate inline type check, linking to runtime call if not assignable. 923 // Generate inline type check, linking to runtime call if not assignable.
553 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 924 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
554 // test_cache = GenerateInlineInstanceof(cid, token_index, dst_type, 925 test_cache = GenerateInlineInstanceof(cid, token_index, dst_type,
555 // &is_assignable, &runtime_call); 926 &is_assignable, &runtime_call);
556 927
557 __ Bind(&runtime_call); 928 __ Bind(&runtime_call);
558 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 929 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
559 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 930 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
560 __ PushObject(Object::ZoneHandle()); // Make room for the result. 931 __ PushObject(Object::ZoneHandle()); // Make room for the result.
561 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 932 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location.
562 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id. 933 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
563 __ pushl(EAX); // Push the source object. 934 __ pushl(EAX); // Push the source object.
564 __ PushObject(dst_type); // Push the type of the destination. 935 __ PushObject(dst_type); // Push the type of the destination.
565 __ pushl(ECX); // Instantiator. 936 __ pushl(ECX); // Instantiator.
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
642 } 1013 }
643 } 1014 }
644 } 1015 }
645 } 1016 }
646 1017
647 #undef __ 1018 #undef __
648 1019
649 } // namespace dart 1020 } // namespace dart
650 1021
651 #endif // defined TARGET_ARCH_IA32 1022 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698