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

Side by Side Diff: vm/flow_graph_compiler_ia32.cc

Issue 10632009: Make the parser agnostic to the TokenStream implementation. This is the first step towards compacti… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
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
« no previous file with comments | « vm/flow_graph_compiler_ia32.h ('k') | vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 20 matching lines...) Expand all
31 __ Bind(entry_label()); 31 __ Bind(entry_label());
32 for (intptr_t i = 0; i < registers_.length(); i++) { 32 for (intptr_t i = 0; i < registers_.length(); i++) {
33 if (registers_[i] != kNoRegister) { 33 if (registers_[i] != kNoRegister) {
34 __ pushl(registers_[i]); 34 __ pushl(registers_[i]);
35 } 35 }
36 } 36 }
37 __ movl(EAX, Immediate(Smi::RawValue(reason_))); 37 __ movl(EAX, Immediate(Smi::RawValue(reason_)));
38 __ call(&StubCode::DeoptimizeLabel()); 38 __ call(&StubCode::DeoptimizeLabel());
39 compiler->AddCurrentDescriptor(PcDescriptors::kOther, 39 compiler->AddCurrentDescriptor(PcDescriptors::kOther,
40 deopt_id_, 40 deopt_id_,
41 deopt_token_index_, 41 deopt_token_pos_,
42 try_index_); 42 try_index_);
43 #undef __ 43 #undef __
44 } 44 }
45 45
46 46
47 47
48 #define __ assembler()-> 48 #define __ assembler()->
49 49
50 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) { 50 void FlowGraphCompiler::GenerateInlinedGetter(intptr_t offset) {
51 // TOS: return address. 51 // TOS: return address.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 __ Drop(1); 89 __ Drop(1);
90 __ jmp(done); 90 __ jmp(done);
91 __ Bind(&smi_to_double); 91 __ Bind(&smi_to_double);
92 __ SmiUntag(EAX); 92 __ SmiUntag(EAX);
93 __ cvtsi2sd(XMM1, EAX); 93 __ cvtsi2sd(XMM1, EAX);
94 __ jmp(&double_op); 94 __ jmp(&double_op);
95 __ Bind(&call_method); 95 __ Bind(&call_method);
96 } 96 }
97 97
98 98
99 void FlowGraphCompiler::GenerateCall(intptr_t token_index, 99 void FlowGraphCompiler::GenerateCall(intptr_t token_pos,
100 intptr_t try_index, 100 intptr_t try_index,
101 const ExternalLabel* label, 101 const ExternalLabel* label,
102 PcDescriptors::Kind kind) { 102 PcDescriptors::Kind kind) {
103 ASSERT(frame_register_allocator()->IsSpilled()); 103 ASSERT(frame_register_allocator()->IsSpilled());
104 __ call(label); 104 __ call(label);
105 AddCurrentDescriptor(kind, AstNode::kNoId, token_index, try_index); 105 AddCurrentDescriptor(kind, AstNode::kNoId, token_pos, try_index);
106 } 106 }
107 107
108 108
109 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid, 109 void FlowGraphCompiler::GenerateCallRuntime(intptr_t cid,
110 intptr_t token_index, 110 intptr_t token_pos,
111 intptr_t try_index, 111 intptr_t try_index,
112 const RuntimeEntry& entry) { 112 const RuntimeEntry& entry) {
113 ASSERT(frame_register_allocator()->IsSpilled()); 113 ASSERT(frame_register_allocator()->IsSpilled());
114 __ CallRuntime(entry); 114 __ CallRuntime(entry);
115 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_index, try_index); 115 AddCurrentDescriptor(PcDescriptors::kOther, cid, token_pos, try_index);
116 } 116 }
117 117
118 118
119 void FlowGraphCompiler::CopyParameters() { 119 void FlowGraphCompiler::CopyParameters() {
120 const Function& function = parsed_function().function(); 120 const Function& function = parsed_function().function();
121 const bool is_native_instance_closure = 121 const bool is_native_instance_closure =
122 function.is_native() && function.IsImplicitInstanceClosureFunction(); 122 function.is_native() && function.IsImplicitInstanceClosureFunction();
123 LocalScope* scope = parsed_function().node_sequence()->scope(); 123 LocalScope* scope = parsed_function().node_sequence()->scope();
124 const int num_fixed_params = function.num_fixed_parameters(); 124 const int num_fixed_params = function.num_fixed_parameters();
125 const int num_opt_params = function.num_optional_parameters(); 125 const int num_opt_params = function.num_optional_parameters();
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 #endif 349 #endif
350 if (check_arguments) { 350 if (check_arguments) {
351 // Check that num_fixed <= argc <= num_params. 351 // Check that num_fixed <= argc <= num_params.
352 Label argc_in_range; 352 Label argc_in_range;
353 // Total number of args is the first Smi in args descriptor array (EDX). 353 // Total number of args is the first Smi in args descriptor array (EDX).
354 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 354 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
355 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); 355 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count)));
356 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 356 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
357 if (function.IsClosureFunction()) { 357 if (function.IsClosureFunction()) {
358 GenerateCallRuntime(AstNode::kNoId, 358 GenerateCallRuntime(AstNode::kNoId,
359 function.token_index(), 359 function.token_pos(),
360 CatchClauseNode::kInvalidTryIndex, 360 CatchClauseNode::kInvalidTryIndex,
361 kClosureArgumentMismatchRuntimeEntry); 361 kClosureArgumentMismatchRuntimeEntry);
362 } else { 362 } else {
363 __ Stop("Wrong number of arguments"); 363 __ Stop("Wrong number of arguments");
364 } 364 }
365 __ Bind(&argc_in_range); 365 __ Bind(&argc_in_range);
366 } 366 }
367 } else { 367 } else {
368 CopyParameters(); 368 CopyParameters();
369 } 369 }
370 // Initialize (non-argument) stack allocated locals to null. 370 // Initialize (non-argument) stack allocated locals to null.
371 if (local_count > 0) { 371 if (local_count > 0) {
372 const Immediate raw_null = 372 const Immediate raw_null =
373 Immediate(reinterpret_cast<intptr_t>(Object::null())); 373 Immediate(reinterpret_cast<intptr_t>(Object::null()));
374 __ movl(EAX, raw_null); 374 __ movl(EAX, raw_null);
375 const int base = parsed_function().first_stack_local_index(); 375 const int base = parsed_function().first_stack_local_index();
376 for (int i = 0; i < local_count; ++i) { 376 for (int i = 0; i < local_count; ++i) {
377 // Subtract index i (locals lie at lower addresses than EBP). 377 // Subtract index i (locals lie at lower addresses than EBP).
378 __ movl(Address(EBP, (base - i) * kWordSize), EAX); 378 __ movl(Address(EBP, (base - i) * kWordSize), EAX);
379 } 379 }
380 } 380 }
381 381
382 // Generate stack overflow check. 382 // Generate stack overflow check.
383 __ cmpl(ESP, 383 __ cmpl(ESP,
384 Address::Absolute(Isolate::Current()->stack_limit_address())); 384 Address::Absolute(Isolate::Current()->stack_limit_address()));
385 Label no_stack_overflow; 385 Label no_stack_overflow;
386 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump); 386 __ j(ABOVE, &no_stack_overflow, Assembler::kNearJump);
387 GenerateCallRuntime(AstNode::kNoId, 387 GenerateCallRuntime(AstNode::kNoId,
388 function.token_index(), 388 function.token_pos(),
389 CatchClauseNode::kInvalidTryIndex, 389 CatchClauseNode::kInvalidTryIndex,
390 kStackOverflowRuntimeEntry); 390 kStackOverflowRuntimeEntry);
391 __ Bind(&no_stack_overflow); 391 __ Bind(&no_stack_overflow);
392 392
393 if (FLAG_print_scopes) { 393 if (FLAG_print_scopes) {
394 // Print the function scope (again) after generating the prologue in order 394 // Print the function scope (again) after generating the prologue in order
395 // to see annotations such as allocation indices of locals. 395 // to see annotations such as allocation indices of locals.
396 if (FLAG_print_ast) { 396 if (FLAG_print_ast) {
397 // Second printing. 397 // Second printing.
398 OS::Print("Annotated "); 398 OS::Print("Annotated ");
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 } 497 }
498 498
499 499
500 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if 500 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if
501 // type test is conclusive, otherwise fallthrough if a type test could not 501 // type test is conclusive, otherwise fallthrough if a type test could not
502 // be completed. 502 // be completed.
503 // EAX: instance (must survive), clobbers ECX, EDI 503 // EAX: instance (must survive), clobbers ECX, EDI
504 RawSubtypeTestCache* 504 RawSubtypeTestCache*
505 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( 505 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest(
506 intptr_t cid, 506 intptr_t cid,
507 intptr_t token_index, 507 intptr_t token_pos,
508 const AbstractType& type, 508 const AbstractType& type,
509 Label* is_instance_lbl, 509 Label* is_instance_lbl,
510 Label* is_not_instance_lbl) { 510 Label* is_not_instance_lbl) {
511 ASSERT(type.IsInstantiated()); 511 ASSERT(type.IsInstantiated());
512 const Class& type_class = Class::ZoneHandle(type.type_class()); 512 const Class& type_class = Class::ZoneHandle(type.type_class());
513 ASSERT(type_class.HasTypeArguments()); 513 ASSERT(type_class.HasTypeArguments());
514 const Register kInstanceReg = EAX; 514 const Register kInstanceReg = EAX;
515 // A Smi object cannot be the instance of a parameterized class. 515 // A Smi object cannot be the instance of a parameterized class.
516 __ testl(kInstanceReg, Immediate(kSmiTagMask)); 516 __ testl(kInstanceReg, Immediate(kSmiTagMask));
517 __ j(ZERO, is_not_instance_lbl); 517 __ j(ZERO, is_not_instance_lbl);
518 const AbstractTypeArguments& type_arguments = 518 const AbstractTypeArguments& type_arguments =
519 AbstractTypeArguments::ZoneHandle(type.arguments()); 519 AbstractTypeArguments::ZoneHandle(type.arguments());
520 const bool is_raw_type = type_arguments.IsNull() || 520 const bool is_raw_type = type_arguments.IsNull() ||
521 type_arguments.IsRaw(type_arguments.Length()); 521 type_arguments.IsRaw(type_arguments.Length());
522 if (is_raw_type) { 522 if (is_raw_type) {
523 const Register kClassIdReg = ECX; 523 const Register kClassIdReg = ECX;
524 // Dynamic type argument, check only classes. 524 // Dynamic type argument, check only classes.
525 __ LoadClassId(kClassIdReg, kInstanceReg); 525 __ LoadClassId(kClassIdReg, kInstanceReg);
526 if (!type_class.is_interface()) { 526 if (!type_class.is_interface()) {
527 __ cmpl(kClassIdReg, Immediate(type_class.id())); 527 __ cmpl(kClassIdReg, Immediate(type_class.id()));
528 __ j(EQUAL, is_instance_lbl); 528 __ j(EQUAL, is_instance_lbl);
529 } 529 }
530 if (type.IsListInterface()) { 530 if (type.IsListInterface()) {
531 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); 531 GenerateListTypeCheck(kClassIdReg, is_instance_lbl);
532 } 532 }
533 return GenerateSubtype1TestCacheLookup( 533 return GenerateSubtype1TestCacheLookup(
534 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); 534 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
535 } 535 }
536 // If one type argument only, check if type argument is Object or Dynamic. 536 // If one type argument only, check if type argument is Object or Dynamic.
537 if (type_arguments.Length() == 1) { 537 if (type_arguments.Length() == 1) {
538 const AbstractType& tp_argument = AbstractType::ZoneHandle( 538 const AbstractType& tp_argument = AbstractType::ZoneHandle(
539 type_arguments.TypeAt(0)); 539 type_arguments.TypeAt(0));
540 ASSERT(!tp_argument.IsMalformed()); 540 ASSERT(!tp_argument.IsMalformed());
541 if (tp_argument.IsType()) { 541 if (tp_argument.IsType()) {
542 ASSERT(tp_argument.HasResolvedTypeClass()); 542 ASSERT(tp_argument.HasResolvedTypeClass());
543 // Check if type argument is dynamic or Object. 543 // Check if type argument is dynamic or Object.
544 const Type& object_type = 544 const Type& object_type =
545 Type::Handle(Isolate::Current()->object_store()->object_type()); 545 Type::Handle(Isolate::Current()->object_store()->object_type());
546 Error& malformed_error = Error::Handle(); 546 Error& malformed_error = Error::Handle();
547 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) { 547 if (object_type.IsSubtypeOf(tp_argument, &malformed_error)) {
548 // Instance class test only necessary. 548 // Instance class test only necessary.
549 return GenerateSubtype1TestCacheLookup( 549 return GenerateSubtype1TestCacheLookup(
550 cid, token_index, type_class, is_instance_lbl, is_not_instance_lbl); 550 cid, token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
551 } 551 }
552 } 552 }
553 } 553 }
554 // Regular subtype test cache involving instance's type arguments. 554 // Regular subtype test cache involving instance's type arguments.
555 const Register kTypeArgumentsReg = kNoRegister; 555 const Register kTypeArgumentsReg = kNoRegister;
556 const Register kTempReg = EDI; 556 const Register kTempReg = EDI;
557 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, 557 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs,
558 kInstanceReg, 558 kInstanceReg,
559 kTypeArgumentsReg, 559 kTypeArgumentsReg,
560 kTempReg, 560 kTempReg,
(...skipping 12 matching lines...) Expand all
573 } 573 }
574 __ jmp(is_not_equal_lbl); 574 __ jmp(is_not_equal_lbl);
575 } 575 }
576 576
577 577
578 // Testing against an instantiated type with no arguments, without 578 // Testing against an instantiated type with no arguments, without
579 // SubtypeTestCache. 579 // SubtypeTestCache.
580 // EAX: instance to test against (preserved). Clobbers ECX, EDI. 580 // EAX: instance to test against (preserved). Clobbers ECX, EDI.
581 void FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 581 void FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
582 intptr_t cid, 582 intptr_t cid,
583 intptr_t token_index, 583 intptr_t token_pos,
584 const AbstractType& type, 584 const AbstractType& type,
585 Label* is_instance_lbl, 585 Label* is_instance_lbl,
586 Label* is_not_instance_lbl) { 586 Label* is_not_instance_lbl) {
587 ASSERT(type.IsInstantiated()); 587 ASSERT(type.IsInstantiated());
588 const Class& type_class = Class::Handle(type.type_class()); 588 const Class& type_class = Class::Handle(type.type_class());
589 ASSERT(!type_class.HasTypeArguments()); 589 ASSERT(!type_class.HasTypeArguments());
590 590
591 const Register kInstanceReg = EAX; 591 const Register kInstanceReg = EAX;
592 Label compare_classes; 592 Label compare_classes;
593 __ testl(kInstanceReg, Immediate(kSmiTagMask)); 593 __ testl(kInstanceReg, Immediate(kSmiTagMask));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 644 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
645 return; 645 return;
646 } 646 }
647 } 647 }
648 648
649 649
650 // Generates inlined check if 'type' is a type parameter or type itsef 650 // Generates inlined check if 'type' is a type parameter or type itsef
651 // EAX: instance (preserved). Clobbers EDX, EDI, ECX. 651 // EAX: instance (preserved). Clobbers EDX, EDI, ECX.
652 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 652 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
653 intptr_t cid, 653 intptr_t cid,
654 intptr_t token_index, 654 intptr_t token_pos,
655 const AbstractType& type, 655 const AbstractType& type,
656 Label* is_instance_lbl, 656 Label* is_instance_lbl,
657 Label* is_not_instance_lbl) { 657 Label* is_not_instance_lbl) {
658 ASSERT(!type.IsInstantiated()); 658 ASSERT(!type.IsInstantiated());
659 // Skip check if destination is a dynamic type. 659 // Skip check if destination is a dynamic type.
660 const Immediate raw_null = 660 const Immediate raw_null =
661 Immediate(reinterpret_cast<intptr_t>(Object::null())); 661 Immediate(reinterpret_cast<intptr_t>(Object::null()));
662 if (type.IsTypeParameter()) { 662 if (type.IsTypeParameter()) {
663 // Load instantiator (or null) and instantiator type arguments on stack. 663 // Load instantiator (or null) and instantiator type arguments on stack.
664 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 664 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 734
735 735
736 // Uses SubtypeTestCache to store instance class and result. 736 // Uses SubtypeTestCache to store instance class and result.
737 // EAX: instance to test. Clobbers EDI, ECX. 737 // EAX: instance to test. Clobbers EDI, ECX.
738 // Immediate class test already done. 738 // Immediate class test already done.
739 // TODO(srdjan): Implement a quicker subtype check, as type test 739 // TODO(srdjan): Implement a quicker subtype check, as type test
740 // arrays can grow too high, but they may be useful when optimizing 740 // arrays can grow too high, but they may be useful when optimizing
741 // code (type-feedback). 741 // code (type-feedback).
742 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 742 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
743 intptr_t cid, 743 intptr_t cid,
744 intptr_t token_index, 744 intptr_t token_pos,
745 const Class& type_class, 745 const Class& type_class,
746 Label* is_instance_lbl, 746 Label* is_instance_lbl,
747 Label* is_not_instance_lbl) { 747 Label* is_not_instance_lbl) {
748 const Register kInstanceReg = EAX; 748 const Register kInstanceReg = EAX;
749 __ LoadClass(ECX, kInstanceReg, EDI); 749 __ LoadClass(ECX, kInstanceReg, EDI);
750 // ECX: instance class. 750 // ECX: instance class.
751 // Check immediate superclass equality. 751 // Check immediate superclass equality.
752 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset())); 752 __ movl(EDI, FieldAddress(ECX, Class::super_type_offset()));
753 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset())); 753 __ movl(EDI, FieldAddress(EDI, Type::type_class_offset()));
754 __ CompareObject(EDI, type_class); 754 __ CompareObject(EDI, type_class);
(...skipping 13 matching lines...) Expand all
768 // Inputs: 768 // Inputs:
769 // - EAX: instance to test against (preserved). 769 // - EAX: instance to test against (preserved).
770 // - EDX: optional instantiator type arguments (preserved). 770 // - EDX: optional instantiator type arguments (preserved).
771 // Returns: 771 // Returns:
772 // - preserved instance in EAX and optional instantiator type arguments in EDX. 772 // - preserved instance in EAX and optional instantiator type arguments in EDX.
773 // Note that this inlined code must be followed by the runtime_call code, as it 773 // Note that this inlined code must be followed by the runtime_call code, as it
774 // may fall through to it. Otherwise, this inline code will jump to the label 774 // may fall through to it. Otherwise, this inline code will jump to the label
775 // is_instance or to the label is_not_instance. 775 // is_instance or to the label is_not_instance.
776 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( 776 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
777 intptr_t cid, 777 intptr_t cid,
778 intptr_t token_index, 778 intptr_t token_pos,
779 const AbstractType& type, 779 const AbstractType& type,
780 Label* is_instance_lbl, 780 Label* is_instance_lbl,
781 Label* is_not_instance_lbl) { 781 Label* is_not_instance_lbl) {
782 if (type.IsInstantiated()) { 782 if (type.IsInstantiated()) {
783 const Class& type_class = Class::ZoneHandle(type.type_class()); 783 const Class& type_class = Class::ZoneHandle(type.type_class());
784 // A Smi object cannot be the instance of a parameterized class. 784 // A Smi object cannot be the instance of a parameterized class.
785 // A class equality check is only applicable with a dst type of a 785 // A class equality check is only applicable with a dst type of a
786 // non-parameterized class or with a raw dst type of a parameterized class. 786 // non-parameterized class or with a raw dst type of a parameterized class.
787 if (type_class.HasTypeArguments()) { 787 if (type_class.HasTypeArguments()) {
788 return GenerateInstantiatedTypeWithArgumentsTest(cid, 788 return GenerateInstantiatedTypeWithArgumentsTest(cid,
789 token_index, 789 token_pos,
790 type, 790 type,
791 is_instance_lbl, 791 is_instance_lbl,
792 is_not_instance_lbl); 792 is_not_instance_lbl);
793 // Fall through to runtime call. 793 // Fall through to runtime call.
794 } else { 794 } else {
795 GenerateInstantiatedTypeNoArgumentsTest(cid, 795 GenerateInstantiatedTypeNoArgumentsTest(cid,
796 token_index, 796 token_pos,
797 type, 797 type,
798 is_instance_lbl, 798 is_instance_lbl,
799 is_not_instance_lbl); 799 is_not_instance_lbl);
800 // If test non-conclusive so far, try the inlined type-test cache. 800 // If test non-conclusive so far, try the inlined type-test cache.
801 // 'type' is known at compile time. 801 // 'type' is known at compile time.
802 return GenerateSubtype1TestCacheLookup( 802 return GenerateSubtype1TestCacheLookup(
803 cid, token_index, type_class, 803 cid, token_pos, type_class,
804 is_instance_lbl, is_not_instance_lbl); 804 is_instance_lbl, is_not_instance_lbl);
805 } 805 }
806 } else { 806 } else {
807 return GenerateUninstantiatedTypeTest(cid, 807 return GenerateUninstantiatedTypeTest(cid,
808 token_index, 808 token_pos,
809 type, 809 type,
810 is_instance_lbl, 810 is_instance_lbl,
811 is_not_instance_lbl); 811 is_not_instance_lbl);
812 } 812 }
813 return SubtypeTestCache::null(); 813 return SubtypeTestCache::null();
814 } 814 }
815 815
816 816
817 // If instanceof type test cannot be performed successfully at compile time and 817 // If instanceof type test cannot be performed successfully at compile time and
818 // therefore eliminated, optimize it by adding inlined tests for: 818 // therefore eliminated, optimize it by adding inlined tests for:
819 // - NULL -> return false. 819 // - NULL -> return false.
820 // - Smi -> compile time subtype check (only if dst class is not parameterized). 820 // - Smi -> compile time subtype check (only if dst class is not parameterized).
821 // - Class equality (only if class is not parameterized). 821 // - Class equality (only if class is not parameterized).
822 // Inputs: 822 // Inputs:
823 // - EAX: object. 823 // - EAX: object.
824 // - EDX: instantiator type arguments or raw_null. 824 // - EDX: instantiator type arguments or raw_null.
825 // - ECX: instantiator or raw_null. 825 // - ECX: instantiator or raw_null.
826 // Returns: 826 // Returns:
827 // - true or false in EAX. 827 // - true or false in EAX.
828 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid, 828 void FlowGraphCompiler::GenerateInstanceOf(intptr_t cid,
829 intptr_t token_index, 829 intptr_t token_pos,
830 intptr_t try_index, 830 intptr_t try_index,
831 const AbstractType& type, 831 const AbstractType& type,
832 bool negate_result) { 832 bool negate_result) {
833 ASSERT(type.IsFinalized() && !type.IsMalformed()); 833 ASSERT(type.IsFinalized() && !type.IsMalformed());
834 834
835 const Immediate raw_null = 835 const Immediate raw_null =
836 Immediate(reinterpret_cast<intptr_t>(Object::null())); 836 Immediate(reinterpret_cast<intptr_t>(Object::null()));
837 Label is_instance, is_not_instance; 837 Label is_instance, is_not_instance;
838 __ pushl(ECX); // Store instantiator on stack. 838 __ pushl(ECX); // Store instantiator on stack.
839 __ pushl(EDX); // Store instantiator type arguments. 839 __ pushl(EDX); // Store instantiator type arguments.
840 // If type is instantiated and non-parameterized, we can inline code 840 // If type is instantiated and non-parameterized, we can inline code
841 // checking whether the tested instance is a Smi. 841 // checking whether the tested instance is a Smi.
842 if (type.IsInstantiated()) { 842 if (type.IsInstantiated()) {
843 // A null object is only an instance of Object and Dynamic, which has 843 // A null object is only an instance of Object and Dynamic, which has
844 // already been checked above (if the type is instantiated). So we can 844 // already been checked above (if the type is instantiated). So we can
845 // return false here if the instance is null (and if the type is 845 // return false here if the instance is null (and if the type is
846 // instantiated). 846 // instantiated).
847 // We can only inline this null check if the type is instantiated at compile 847 // We can only inline this null check if the type is instantiated at compile
848 // time, since an uninstantiated type at compile time could be Object or 848 // time, since an uninstantiated type at compile time could be Object or
849 // Dynamic at run time. 849 // Dynamic at run time.
850 __ cmpl(EAX, raw_null); 850 __ cmpl(EAX, raw_null);
851 __ j(EQUAL, &is_not_instance); 851 __ j(EQUAL, &is_not_instance);
852 } 852 }
853 // TODO(srdjan): Enable inlined checks. 853 // TODO(srdjan): Enable inlined checks.
854 // Generate inline instanceof test. 854 // Generate inline instanceof test.
855 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 855 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
856 test_cache = GenerateInlineInstanceof(cid, token_index, type, 856 test_cache = GenerateInlineInstanceof(cid, token_pos, type,
857 &is_instance, &is_not_instance); 857 &is_instance, &is_not_instance);
858 858
859 // Generate runtime call. 859 // Generate runtime call.
860 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 860 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
861 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 861 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
862 __ PushObject(Object::ZoneHandle()); // Make room for the result. 862 __ PushObject(Object::ZoneHandle()); // Make room for the result.
863 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 863 __ pushl(Immediate(Smi::RawValue(token_pos))); // Source location.
864 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id. 864 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
865 __ pushl(EAX); // Push the instance. 865 __ pushl(EAX); // Push the instance.
866 __ PushObject(type); // Push the type. 866 __ PushObject(type); // Push the type.
867 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null. 867 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
868 __ pushl(EDX); // Instantiator type arguments. 868 __ pushl(EDX); // Instantiator type arguments.
869 __ LoadObject(EAX, test_cache); 869 __ LoadObject(EAX, test_cache);
870 __ pushl(EAX); 870 __ pushl(EAX);
871 GenerateCallRuntime(cid, token_index, try_index, kInstanceofRuntimeEntry); 871 GenerateCallRuntime(cid, token_pos, try_index, kInstanceofRuntimeEntry);
872 // Pop the two parameters supplied to the runtime entry. The result of the 872 // Pop the two parameters supplied to the runtime entry. The result of the
873 // instanceof runtime call will be left as the result of the operation. 873 // instanceof runtime call will be left as the result of the operation.
874 __ Drop(7); 874 __ Drop(7);
875 Label done; 875 Label done;
876 if (negate_result) { 876 if (negate_result) {
877 __ popl(EDX); 877 __ popl(EDX);
878 __ LoadObject(EAX, bool_true()); 878 __ LoadObject(EAX, bool_true());
879 __ cmpl(EDX, EAX); 879 __ cmpl(EDX, EAX);
880 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 880 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
881 __ LoadObject(EAX, bool_false()); 881 __ LoadObject(EAX, bool_false());
(...skipping 20 matching lines...) Expand all
902 // - Class equality (only if class is not parameterized). 902 // - Class equality (only if class is not parameterized).
903 // Inputs: 903 // Inputs:
904 // - EAX: object. 904 // - EAX: object.
905 // - EDX: instantiator type arguments or raw_null. 905 // - EDX: instantiator type arguments or raw_null.
906 // - ECX: instantiator or raw_null. 906 // - ECX: instantiator or raw_null.
907 // Returns: 907 // Returns:
908 // - object in EAX for successful assignable check (or throws TypeError). 908 // - object in EAX for successful assignable check (or throws TypeError).
909 // Performance notes: positive checks must be quick, negative checks can be slow 909 // Performance notes: positive checks must be quick, negative checks can be slow
910 // as they throw an exception. 910 // as they throw an exception.
911 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid, 911 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t cid,
912 intptr_t token_index, 912 intptr_t token_pos,
913 intptr_t try_index, 913 intptr_t try_index,
914 const AbstractType& dst_type, 914 const AbstractType& dst_type,
915 const String& dst_name) { 915 const String& dst_name) {
916 ASSERT(FLAG_enable_type_checks); 916 ASSERT(FLAG_enable_type_checks);
917 ASSERT(token_index >= 0); 917 ASSERT(token_pos >= 0);
918 ASSERT(!dst_type.IsNull()); 918 ASSERT(!dst_type.IsNull());
919 ASSERT(dst_type.IsFinalized()); 919 ASSERT(dst_type.IsFinalized());
920 // Assignable check is skipped in FlowGraphBuilder, not here. 920 // Assignable check is skipped in FlowGraphBuilder, not here.
921 ASSERT(dst_type.IsMalformed() || 921 ASSERT(dst_type.IsMalformed() ||
922 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 922 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
923 ASSERT(!dst_type.IsVoidType()); 923 ASSERT(!dst_type.IsVoidType());
924 __ pushl(ECX); // Store instantiator. 924 __ pushl(ECX); // Store instantiator.
925 __ pushl(EDX); // Store instantiator type arguments. 925 __ pushl(EDX); // Store instantiator type arguments.
926 // A null object is always assignable and is returned as result. 926 // A null object is always assignable and is returned as result.
927 const Immediate raw_null = 927 const Immediate raw_null =
928 Immediate(reinterpret_cast<intptr_t>(Object::null())); 928 Immediate(reinterpret_cast<intptr_t>(Object::null()));
929 Label is_assignable, runtime_call; 929 Label is_assignable, runtime_call;
930 __ cmpl(EAX, raw_null); 930 __ cmpl(EAX, raw_null);
931 __ j(EQUAL, &is_assignable); 931 __ j(EQUAL, &is_assignable);
932 932
933 // Generate throw new TypeError() if the type is malformed. 933 // Generate throw new TypeError() if the type is malformed.
934 if (dst_type.IsMalformed()) { 934 if (dst_type.IsMalformed()) {
935 const Error& error = Error::Handle(dst_type.malformed_error()); 935 const Error& error = Error::Handle(dst_type.malformed_error());
936 const String& error_message = String::ZoneHandle( 936 const String& error_message = String::ZoneHandle(
937 String::NewSymbol(error.ToErrorCString())); 937 String::NewSymbol(error.ToErrorCString()));
938 __ PushObject(Object::ZoneHandle()); // Make room for the result. 938 __ PushObject(Object::ZoneHandle()); // Make room for the result.
939 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 939 __ pushl(Immediate(Smi::RawValue(token_pos))); // Source location.
940 __ pushl(EAX); // Push the source object. 940 __ pushl(EAX); // Push the source object.
941 __ PushObject(dst_name); // Push the name of the destination. 941 __ PushObject(dst_name); // Push the name of the destination.
942 __ PushObject(error_message); 942 __ PushObject(error_message);
943 GenerateCallRuntime(cid, 943 GenerateCallRuntime(cid,
944 token_index, 944 token_pos,
945 try_index, 945 try_index,
946 kMalformedTypeErrorRuntimeEntry); 946 kMalformedTypeErrorRuntimeEntry);
947 // We should never return here. 947 // We should never return here.
948 __ int3(); 948 __ int3();
949 949
950 __ Bind(&is_assignable); // For a null object. 950 __ Bind(&is_assignable); // For a null object.
951 return; 951 return;
952 } 952 }
953 953
954 // TODO(srdjan): Enable subtype test cache. 954 // TODO(srdjan): Enable subtype test cache.
955 // Generate inline type check, linking to runtime call if not assignable. 955 // Generate inline type check, linking to runtime call if not assignable.
956 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 956 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
957 test_cache = GenerateInlineInstanceof(cid, token_index, dst_type, 957 test_cache = GenerateInlineInstanceof(cid, token_pos, dst_type,
958 &is_assignable, &runtime_call); 958 &is_assignable, &runtime_call);
959 959
960 __ Bind(&runtime_call); 960 __ Bind(&runtime_call);
961 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 961 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
962 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 962 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
963 __ PushObject(Object::ZoneHandle()); // Make room for the result. 963 __ PushObject(Object::ZoneHandle()); // Make room for the result.
964 __ pushl(Immediate(Smi::RawValue(token_index))); // Source location. 964 __ pushl(Immediate(Smi::RawValue(token_pos))); // Source location.
965 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id. 965 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
966 __ pushl(EAX); // Push the source object. 966 __ pushl(EAX); // Push the source object.
967 __ PushObject(dst_type); // Push the type of the destination. 967 __ PushObject(dst_type); // Push the type of the destination.
968 __ pushl(ECX); // Instantiator. 968 __ pushl(ECX); // Instantiator.
969 __ pushl(EDX); // Instantiator type arguments. 969 __ pushl(EDX); // Instantiator type arguments.
970 __ PushObject(dst_name); // Push the name of the destination. 970 __ PushObject(dst_name); // Push the name of the destination.
971 __ LoadObject(EAX, test_cache); 971 __ LoadObject(EAX, test_cache);
972 __ pushl(EAX); 972 __ pushl(EAX);
973 GenerateCallRuntime(cid, 973 GenerateCallRuntime(cid,
974 token_index, 974 token_pos,
975 try_index, 975 try_index,
976 kTypeCheckRuntimeEntry); 976 kTypeCheckRuntimeEntry);
977 // Pop the parameters supplied to the runtime entry. The result of the 977 // Pop the parameters supplied to the runtime entry. The result of the
978 // type check runtime call is the checked value. 978 // type check runtime call is the checked value.
979 __ Drop(8); 979 __ Drop(8);
980 __ popl(EAX); 980 __ popl(EAX);
981 981
982 __ Bind(&is_assignable); 982 __ Bind(&is_assignable);
983 __ popl(EDX); // Remove pushed instantiator type arguments.. 983 __ popl(EDX); // Remove pushed instantiator type arguments..
984 __ popl(ECX); // Remove pushed instantiator. 984 __ popl(ECX); // Remove pushed instantiator.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1046 __ cvtsi2sd(result, temp); 1046 __ cvtsi2sd(result, temp);
1047 __ Bind(&done); 1047 __ Bind(&done);
1048 } 1048 }
1049 1049
1050 1050
1051 #undef __ 1051 #undef __
1052 1052
1053 } // namespace dart 1053 } // namespace dart
1054 1054
1055 #endif // defined TARGET_ARCH_IA32 1055 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/flow_graph_compiler_ia32.h ('k') | vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698