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

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

Issue 10356108: With removal of increment operations, each node has a unique id. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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 | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | 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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/opt_code_generator.h" 8 #include "vm/opt_code_generator.h"
9 9
10 #include "vm/assembler_macros.h" 10 #include "vm/assembler_macros.h"
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 313
314 bool OptimizingCodeGenerator::IsResultInEaxRequested(AstNode* node) const { 314 bool OptimizingCodeGenerator::IsResultInEaxRequested(AstNode* node) const {
315 return (node->info() != NULL) && node->info()->request_result_in_eax(); 315 return (node->info() != NULL) && node->info()->request_result_in_eax();
316 } 316 }
317 317
318 318
319 static const ZoneGrowableArray<const Class*>* 319 static const ZoneGrowableArray<const Class*>*
320 CollectedClassesAtNode(AstNode* node) { 320 CollectedClassesAtNode(AstNode* node) {
321 ZoneGrowableArray<const Class*>* result = 321 ZoneGrowableArray<const Class*>* result =
322 new ZoneGrowableArray<const Class*>(); 322 new ZoneGrowableArray<const Class*>();
323 const ICData& ic_data = node->ICDataAtId(node->id()); 323 const ICData& ic_data = node->ic_data();
324 if (ic_data.NumberOfChecks() == 0) { 324 if (ic_data.NumberOfChecks() == 0) {
325 return result; 325 return result;
326 } 326 }
327 ASSERT(ic_data.num_args_tested() == 1); 327 ASSERT(ic_data.num_args_tested() == 1);
328 Function& target = Function::Handle(); 328 Function& target = Function::Handle();
329 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 329 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
330 Class& cls = Class::ZoneHandle(); 330 Class& cls = Class::ZoneHandle();
331 ic_data.GetOneClassCheckAt(i, &cls, &target); 331 ic_data.GetOneClassCheckAt(i, &cls, &target);
332 result->Add(&cls); 332 result->Add(&cls);
333 } 333 }
334 return result; 334 return result;
335 } 335 }
336 336
337 337
338 // Debugging helper function. 338 // Debugging helper function.
339 void OptimizingCodeGenerator::PrintCollectedClassesAtId(AstNode* node, 339 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) {
340 intptr_t id) { 340 const ICData& ic_data = node->ic_data();
341 const ICData& ic_data = node->ICDataAtId(id); 341 OS::Print("Collected classes id %d num: %d\n",
342 OS::Print("Collected classes id %d num: %d\n", id, ic_data.NumberOfChecks()); 342 node->id(), ic_data.NumberOfChecks());
343 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 343 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
344 Function& target = Function::Handle(); 344 Function& target = Function::Handle();
345 GrowableArray<const Class*> classes; 345 GrowableArray<const Class*> classes;
346 ic_data.GetCheckAt(i, &classes, &target); 346 ic_data.GetCheckAt(i, &classes, &target);
347 OS::Print("["); 347 OS::Print("[");
348 for (intptr_t c = 0; c < classes.length(); c++) { 348 for (intptr_t c = 0; c < classes.length(); c++) {
349 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString()); 349 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString());
350 } 350 }
351 OS::Print("] -> %s\n", target.ToFullyQualifiedCString()); 351 OS::Print("] -> %s\n", target.ToFullyQualifiedCString());
352 } 352 }
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
544 HandleResult(node, EAX); 544 HandleResult(node, EAX);
545 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class()); 545 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class());
546 } 546 }
547 547
548 548
549 static bool NodeHasBothReceiverClasses(AstNode* node, 549 static bool NodeHasBothReceiverClasses(AstNode* node,
550 const Class& cls1, 550 const Class& cls1,
551 const Class& cls2) { 551 const Class& cls2) {
552 ASSERT(node != NULL); 552 ASSERT(node != NULL);
553 ASSERT(!cls1.IsNull() && !cls2.IsNull()); 553 ASSERT(!cls1.IsNull() && !cls2.IsNull());
554 const ICData& ic_data = node->ICDataAtId(node->id()); 554 const ICData& ic_data = node->ic_data();
555 bool cls1_found = false; 555 bool cls1_found = false;
556 bool cls2_found = false; 556 bool cls2_found = false;
557 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 557 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
558 GrowableArray<const Class*> classes; 558 GrowableArray<const Class*> classes;
559 Function& target = Function::Handle(); 559 Function& target = Function::Handle();
560 ic_data.GetCheckAt(i, &classes, &target); 560 ic_data.GetCheckAt(i, &classes, &target);
561 if (!classes.is_empty()) { 561 if (!classes.is_empty()) {
562 if (classes[0]->raw() == cls1.raw()) { 562 if (classes[0]->raw() == cls1.raw()) {
563 cls1_found = true; 563 cls1_found = true;
564 } 564 }
565 if (classes[0]->raw() == cls2.raw()) { 565 if (classes[0]->raw() == cls2.raw()) {
566 cls2_found = true; 566 cls2_found = true;
567 } 567 }
568 if (cls1_found && cls2_found) { 568 if (cls1_found && cls2_found) {
569 return true; 569 return true;
570 } 570 }
571 } 571 }
572 } 572 }
573 return false; 573 return false;
574 } 574 }
575 575
576 576
577 // Look only at the first class in all check groups. Returns true if all 577 // Look only at the first class in all check groups. Returns true if all
578 // receiver classes are 'cls'. 578 // receiver classes are 'cls'.
579 static bool AtIdNodeHasClassAt(AstNode* node, 579 static bool NodeHasClassAt(AstNode* node,
580 intptr_t id, 580 const Class& cls,
581 const Class& cls, 581 intptr_t arg_index) {
582 intptr_t arg_index) {
583 ASSERT(node != NULL); 582 ASSERT(node != NULL);
584 ASSERT(!cls.IsNull()); 583 ASSERT(!cls.IsNull());
585 const ICData& ic_data = node->ICDataAtId(id); 584 const ICData& ic_data = node->ic_data();
586 if (ic_data.NumberOfChecks() == 0) { 585 if (ic_data.NumberOfChecks() == 0) {
587 return false; 586 return false;
588 } 587 }
589 ASSERT(ic_data.num_args_tested() > arg_index); 588 ASSERT(ic_data.num_args_tested() > arg_index);
590 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 589 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
591 GrowableArray<const Class*> classes; 590 GrowableArray<const Class*> classes;
592 Function& target = Function::Handle(); 591 Function& target = Function::Handle();
593 ic_data.GetCheckAt(i, &classes, &target); 592 ic_data.GetCheckAt(i, &classes, &target);
594 if (classes.is_empty()) { 593 if (classes.is_empty()) {
595 return false; 594 return false;
596 } 595 }
597 if (classes[arg_index]->raw() != cls.raw()) { 596 if (classes[arg_index]->raw() != cls.raw()) {
598 return false; 597 return false;
599 } 598 }
600 } 599 }
601 return true; 600 return true;
602 } 601 }
603 602
604 603
605 // IC data may have only one check, and it has to contain the two classes in 604 // IC data may have only one check, and it has to contain the two classes in
606 // specified order. 605 // specified order.
607 static bool AtIdNodeHasTwoClasses(AstNode* node, 606 static bool NodeHasTwoClasses(AstNode* node,
608 intptr_t id, 607 const Class& cls0,
609 const Class& cls0, 608 const Class& cls1) {
610 const Class& cls1) {
611 ASSERT(node != NULL); 609 ASSERT(node != NULL);
612 ASSERT(!cls0.IsNull() && !cls1.IsNull()); 610 ASSERT(!cls0.IsNull() && !cls1.IsNull());
613 const ICData& ic_data = node->ICDataAtId(id); 611 const ICData& ic_data = node->ic_data();
614 ASSERT(ic_data.num_args_tested() == 2); 612 ASSERT(ic_data.num_args_tested() == 2);
615 if (ic_data.NumberOfChecks() != 1) { 613 if (ic_data.NumberOfChecks() != 1) {
616 return false; 614 return false;
617 } 615 }
618 Function& target = Function::Handle(); 616 Function& target = Function::Handle();
619 GrowableArray<const Class*> classes; 617 GrowableArray<const Class*> classes;
620 ic_data.GetCheckAt(0, &classes, &target); 618 ic_data.GetCheckAt(0, &classes, &target);
621 if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) { 619 if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) {
622 return true; 620 return true;
623 } 621 }
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow. 680 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
683 __ shll(EAX, imm); // Shift for result now we know there is no overflow. 681 __ shll(EAX, imm); // Shift for result now we know there is no overflow.
684 __ jmp(&done); 682 __ jmp(&done);
685 __ Bind(&slow_case); 683 __ Bind(&slow_case);
686 __ pushl(EAX); 684 __ pushl(EAX);
687 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw()))); 685 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw())));
688 const int number_of_arguments = 2; 686 const int number_of_arguments = 2;
689 const Array& no_optional_argument_names = Array::Handle(); 687 const Array& no_optional_argument_names = Array::Handle();
690 GenerateCheckedInstanceCalls(node, 688 GenerateCheckedInstanceCalls(node,
691 node->left(), 689 node->left(),
692 node->id(),
693 node->token_index(), 690 node->token_index(),
694 number_of_arguments, 691 number_of_arguments,
695 no_optional_argument_names); 692 no_optional_argument_names);
696 __ Bind(&done); 693 __ Bind(&done);
697 return; 694 return;
698 } 695 }
699 } 696 }
700 697
701 Label slow_case, done; 698 Label slow_case, done;
702 CodeGenInfo left_info(node->left()); 699 CodeGenInfo left_info(node->left());
(...skipping 24 matching lines...) Expand all
727 __ shll(EAX, ECX); // Shift for result now we know there is no overflow. 724 __ shll(EAX, ECX); // Shift for result now we know there is no overflow.
728 // EAX is the correctly tagged Smi. 725 // EAX is the correctly tagged Smi.
729 __ jmp(&done); 726 __ jmp(&done);
730 __ Bind(&slow_case); 727 __ Bind(&slow_case);
731 __ pushl(EAX); 728 __ pushl(EAX);
732 __ pushl(EDX); 729 __ pushl(EDX);
733 const int number_of_arguments = 2; 730 const int number_of_arguments = 2;
734 const Array& no_optional_argument_names = Array::Handle(); 731 const Array& no_optional_argument_names = Array::Handle();
735 GenerateCheckedInstanceCalls(node, 732 GenerateCheckedInstanceCalls(node,
736 node->left(), 733 node->left(),
737 node->id(),
738 node->token_index(), 734 node->token_index(),
739 number_of_arguments, 735 number_of_arguments,
740 no_optional_argument_names); 736 no_optional_argument_names);
741 __ Bind(&done); 737 __ Bind(&done);
742 } 738 }
743 739
744 740
745 // Implement Token::kSUB and Token::kBIT_NOT. 741 // Implement Token::kSUB and Token::kBIT_NOT.
746 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) { 742 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) {
747 const ICData& ic_data = node->ICDataAtId(node->id()); 743 const ICData& ic_data = node->ic_data();
748 ASSERT(ic_data.num_args_tested() == 1); 744 ASSERT(ic_data.num_args_tested() == 1);
749 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? 745 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ?
750 kDeoptNoTypeFeedback : kDeoptUnaryOp; 746 kDeoptNoTypeFeedback : kDeoptUnaryOp;
751 DeoptimizationBlob* deopt_blob = 747 DeoptimizationBlob* deopt_blob =
752 AddDeoptimizationBlob(node, EAX, deopt_reason_id); 748 AddDeoptimizationBlob(node, EAX, deopt_reason_id);
753 CodeGenInfo info(node->operand()); 749 CodeGenInfo info(node->operand());
754 VisitLoadOne(node->operand(), EAX); 750 VisitLoadOne(node->operand(), EAX);
755 if (ic_data.NumberOfChecks() == 0) { 751 if (ic_data.NumberOfChecks() == 0) {
756 // No type feedback. 752 // No type feedback.
757 __ jmp(deopt_blob->label()); 753 __ jmp(deopt_blob->label());
(...skipping 14 matching lines...) Expand all
772 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 768 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
773 } 769 }
774 HandleResult(node, EAX); 770 HandleResult(node, EAX);
775 } 771 }
776 772
777 773
778 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) { 774 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) {
779 const Register kOperandRegister = ECX; 775 const Register kOperandRegister = ECX;
780 const Register kTempRegister = EBX; 776 const Register kTempRegister = EBX;
781 const Register kResultRegister = EAX; 777 const Register kResultRegister = EAX;
782 const ICData& ic_data = node->ICDataAtId(node->id()); 778 const ICData& ic_data = node->ic_data();
783 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? 779 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ?
784 kDeoptNoTypeFeedback : kDeoptUnaryOp; 780 kDeoptNoTypeFeedback : kDeoptUnaryOp;
785 DeoptimizationBlob* deopt_blob = 781 DeoptimizationBlob* deopt_blob =
786 AddDeoptimizationBlob(node, kOperandRegister, deopt_reason_id); 782 AddDeoptimizationBlob(node, kOperandRegister, deopt_reason_id);
787 CodeGenInfo info(node->operand()); 783 CodeGenInfo info(node->operand());
788 info.set_allow_temp(true); 784 info.set_allow_temp(true);
789 VisitLoadOne(node->operand(), kOperandRegister); 785 VisitLoadOne(node->operand(), kOperandRegister);
790 if (ic_data.NumberOfChecks() == 0) { 786 if (ic_data.NumberOfChecks() == 0) {
791 // No type feedback. 787 // No type feedback.
792 __ jmp(deopt_blob->label()); 788 __ jmp(deopt_blob->label());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 const Token::Kind kind = node->kind(); 837 const Token::Kind kind = node->kind();
842 if ((kind == Token::kADD) || 838 if ((kind == Token::kADD) ||
843 (kind == Token::kSUB) || 839 (kind == Token::kSUB) ||
844 (kind == Token::kMUL) || 840 (kind == Token::kMUL) ||
845 (kind == Token::kTRUNCDIV) || 841 (kind == Token::kTRUNCDIV) ||
846 (kind == Token::kBIT_AND) || 842 (kind == Token::kBIT_AND) ||
847 (kind == Token::kBIT_OR) || 843 (kind == Token::kBIT_OR) ||
848 (kind == Token::kBIT_XOR)) { 844 (kind == Token::kBIT_XOR)) {
849 TraceOpt(node, kOptMessage); 845 TraceOpt(node, kOptMessage);
850 // Check if both arguments are expected to be Smi. 846 // Check if both arguments are expected to be Smi.
851 const ICData& ic_data = node->ICDataAtId(node->id()); 847 const ICData& ic_data = node->ic_data();
852 ASSERT(ic_data.num_args_tested() == 2); 848 ASSERT(ic_data.num_args_tested() == 2);
853 ASSERT(ic_data.NumberOfChecks() > 0); 849 ASSERT(ic_data.NumberOfChecks() > 0);
854 Function& target = Function::Handle(); 850 Function& target = Function::Handle();
855 GrowableArray<const Class*> classes; 851 GrowableArray<const Class*> classes;
856 ic_data.GetCheckAt(0, &classes, &target); 852 ic_data.GetCheckAt(0, &classes, &target);
857 ASSERT(ic_data.NumberOfChecks() == 1); 853 ASSERT(ic_data.NumberOfChecks() == 1);
858 ASSERT((classes[0]->raw() == smi_class_.raw()) && 854 ASSERT((classes[0]->raw() == smi_class_.raw()) &&
859 (classes[1]->raw() == smi_class_.raw())); 855 (classes[1]->raw() == smi_class_.raw()));
860 CodeGenInfo left_info(node->left()); 856 CodeGenInfo left_info(node->left());
861 CodeGenInfo right_info(node->right()); 857 CodeGenInfo right_info(node->right());
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 __ Bind(&is_smi); 994 __ Bind(&is_smi);
999 __ andl(EAX, EDX); 995 __ andl(EAX, EDX);
1000 __ jmp(&done); 996 __ jmp(&done);
1001 __ Bind(&slow_case); 997 __ Bind(&slow_case);
1002 __ pushl(EAX); 998 __ pushl(EAX);
1003 __ pushl(EDX); 999 __ pushl(EDX);
1004 const int number_of_arguments = 2; 1000 const int number_of_arguments = 2;
1005 const Array& no_optional_argument_names = Array::Handle(); 1001 const Array& no_optional_argument_names = Array::Handle();
1006 GenerateCheckedInstanceCalls(node, 1002 GenerateCheckedInstanceCalls(node,
1007 node->left(), 1003 node->left(),
1008 node->id(),
1009 node->token_index(), 1004 node->token_index(),
1010 number_of_arguments, 1005 number_of_arguments,
1011 no_optional_argument_names); 1006 no_optional_argument_names);
1012 __ Bind(&done); 1007 __ Bind(&done);
1013 HandleResult(node, EAX); 1008 HandleResult(node, EAX);
1014 return; 1009 return;
1015 } 1010 }
1016 if ((kind == Token::kSHL) && allow_smi) { 1011 if ((kind == Token::kSHL) && allow_smi) {
1017 GenerateSmiShiftBinaryOp(node); 1012 GenerateSmiShiftBinaryOp(node);
1018 HandleResult(node, EAX); 1013 HandleResult(node, EAX);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 __ SmiUntag(kLeftRegister); 1146 __ SmiUntag(kLeftRegister);
1152 __ cvtsi2sd(XMM0, kLeftRegister); 1147 __ cvtsi2sd(XMM0, kLeftRegister);
1153 __ Bind(&done); 1148 __ Bind(&done);
1154 } else { 1149 } else {
1155 CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, deopt_lbl, deopt_lbl); 1150 CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, deopt_lbl, deopt_lbl);
1156 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset())); 1151 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
1157 PropagateBackLocalClass(node->left(), double_class_); 1152 PropagateBackLocalClass(node->left(), double_class_);
1158 } 1153 }
1159 } 1154 }
1160 1155
1161 const bool right_must_be_double = 1156 const bool right_must_be_double = NodeHasClassAt(node, double_class_, 1);
1162 AtIdNodeHasClassAt(node, node->id(), double_class_, 1);
1163 1157
1164 // If arguments are of same type (e.g., same local), then the test of left 1158 // If arguments are of same type (e.g., same local), then the test of left
1165 // argument was sufficient. 1159 // argument was sufficient.
1166 if (right_info.IsClass(double_class_) || args_of_same_type) { 1160 if (right_info.IsClass(double_class_) || args_of_same_type) {
1167 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset())); 1161 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
1168 if (!right_info.IsClass(double_class_)) { 1162 if (!right_info.IsClass(double_class_)) {
1169 PropagateBackLocalClass(node->right(), double_class_); 1163 PropagateBackLocalClass(node->right(), double_class_);
1170 } 1164 }
1171 } else { 1165 } else {
1172 if (right_must_be_double) { 1166 if (right_must_be_double) {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 // TODO(srdjan): Test in checked mode if they are Booleans otherwise 1289 // TODO(srdjan): Test in checked mode if they are Booleans otherwise
1296 // throw exception. 1290 // throw exception.
1297 if (FLAG_enable_type_checks) { 1291 if (FLAG_enable_type_checks) {
1298 CodeGenerator::VisitBinaryOpNode(node); 1292 CodeGenerator::VisitBinaryOpNode(node);
1299 return; 1293 return;
1300 } 1294 }
1301 GenerateLogicalBinaryOp(node); 1295 GenerateLogicalBinaryOp(node);
1302 return; 1296 return;
1303 } 1297 }
1304 1298
1305 const ICData& ic_data = node->ICDataAtId(node->id()); 1299 const ICData& ic_data = node->ic_data();
1306 if (ic_data.NumberOfChecks() == 0) { 1300 if (ic_data.NumberOfChecks() == 0) {
1307 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 1301 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
1308 DeoptimizationBlob* deopt_blob = 1302 DeoptimizationBlob* deopt_blob =
1309 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback); 1303 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback);
1310 __ jmp(deopt_blob->label()); 1304 __ jmp(deopt_blob->label());
1311 return; 1305 return;
1312 } 1306 }
1313 1307
1314 ASSERT(ic_data.num_args_tested() == 2); 1308 ASSERT(ic_data.num_args_tested() == 2);
1315 1309
1316 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) { 1310 if (NodeHasTwoClasses(node, smi_class_, smi_class_)) {
1317 GenerateSmiBinaryOp(node); 1311 GenerateSmiBinaryOp(node);
1318 return; 1312 return;
1319 } 1313 }
1320 1314
1321 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { 1315 if (NodeHasClassAt(node, double_class_, 0)) {
1322 const bool receiver_can_be_smi = false; 1316 const bool receiver_can_be_smi = false;
1323 GenerateDoubleBinaryOp(node, receiver_can_be_smi); 1317 GenerateDoubleBinaryOp(node, receiver_can_be_smi);
1324 return; 1318 return;
1325 } 1319 }
1326 1320
1327 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, double_class_)) { 1321 if (NodeHasTwoClasses(node, smi_class_, double_class_)) {
1328 const bool receiver_can_be_smi = true; 1322 const bool receiver_can_be_smi = true;
1329 GenerateDoubleBinaryOp(node, receiver_can_be_smi); 1323 GenerateDoubleBinaryOp(node, receiver_can_be_smi);
1330 return; 1324 return;
1331 } 1325 }
1332 1326
1333 const Class& mint_class = 1327 const Class& mint_class =
1334 Class::Handle(Isolate::Current()->object_store()->mint_class()); 1328 Class::Handle(Isolate::Current()->object_store()->mint_class());
1335 if (AtIdNodeHasClassAt(node, node->id(), mint_class, 0)) { 1329 if (NodeHasClassAt(node, mint_class, 0)) {
1336 GenerateMintBinaryOp(node, false); 1330 GenerateMintBinaryOp(node, false);
1337 return; 1331 return;
1338 } 1332 }
1339 1333
1340 if (NodeHasBothReceiverClasses(node, smi_class_, mint_class)) { 1334 if (NodeHasBothReceiverClasses(node, smi_class_, mint_class)) {
1341 GenerateMintBinaryOp(node, true); 1335 GenerateMintBinaryOp(node, true);
1342 return; 1336 return;
1343 } 1337 }
1344 1338
1345 // TODO(srdjan): Implement "+" for Strings. 1339 // TODO(srdjan): Implement "+" for Strings.
1346 // Type feedback tells this is not a Smi or Double operation. 1340 // Type feedback tells this is not a Smi or Double operation.
1347 TraceNotOpt(node, 1341 TraceNotOpt(node,
1348 "BinaryOp: type feedback tells this is not a Smi, Mint or Double op"); 1342 "BinaryOp: type feedback tells this is not a Smi, Mint or Double op");
1349 node->left()->Visit(this); 1343 node->left()->Visit(this);
1350 node->right()->Visit(this); 1344 node->right()->Visit(this);
1351 const int number_of_arguments = 2; 1345 const int number_of_arguments = 2;
1352 const Array& no_optional_argument_names = Array::Handle(); 1346 const Array& no_optional_argument_names = Array::Handle();
1353 GenerateCheckedInstanceCalls(node, 1347 GenerateCheckedInstanceCalls(node,
1354 node->left(), 1348 node->left(),
1355 node->id(),
1356 node->token_index(), 1349 node->token_index(),
1357 number_of_arguments, 1350 number_of_arguments,
1358 no_optional_argument_names); 1351 no_optional_argument_names);
1359 HandleResult(node, EAX); 1352 HandleResult(node, EAX);
1360 return; 1353 return;
1361 } 1354 }
1362 1355
1363 1356
1364 // Return offset of a field or -1 if field is not found. 1357 // Return offset of a field or -1 if field is not found.
1365 static intptr_t GetFieldOffset(const Class& field_class, 1358 static intptr_t GetFieldOffset(const Class& field_class,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 return true; 1396 return true;
1404 } 1397 }
1405 1398
1406 1399
1407 // Emits code for an instance getter that has one or more collected classes, 1400 // Emits code for an instance getter that has one or more collected classes,
1408 // all with the same target. Deoptimizes for Smi or unexpected class. 1401 // all with the same target. Deoptimizes for Smi or unexpected class.
1409 // EBX: loaded receiver. 1402 // EBX: loaded receiver.
1410 // Result is returned in EAX. 1403 // Result is returned in EAX.
1411 void OptimizingCodeGenerator::InlineInstanceGettersWithSameTarget( 1404 void OptimizingCodeGenerator::InlineInstanceGettersWithSameTarget(
1412 AstNode* node, 1405 AstNode* node,
1413 intptr_t id,
1414 AstNode* receiver, 1406 AstNode* receiver,
1415 const String& field_name, 1407 const String& field_name,
1416 Register recv_reg) { 1408 Register recv_reg) {
1417 if (recv_reg != EBX) { 1409 if (recv_reg != EBX) {
1418 // TODO(srdjan): Do not hardwire register. 1410 // TODO(srdjan): Do not hardwire register.
1419 UNIMPLEMENTED(); 1411 UNIMPLEMENTED();
1420 } 1412 }
1421 DeoptimizationBlob* deopt_blob = 1413 DeoptimizationBlob* deopt_blob =
1422 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget); 1414 AddDeoptimizationBlob(node, EBX, kDeoptInstanceGetterSameTarget);
1423 if (NodeMayBeSmi(receiver)) { 1415 if (NodeMayBeSmi(receiver)) {
1424 __ testl(EBX, Immediate(kSmiTagMask)); 1416 __ testl(EBX, Immediate(kSmiTagMask));
1425 __ j(ZERO, deopt_blob->label()); 1417 __ j(ZERO, deopt_blob->label());
1426 } 1418 }
1427 1419
1428 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); 1420 __ movl(EAX, FieldAddress(EBX, Object::class_offset()));
1429 const ICData& ic_data = node->ICDataAtId(id); 1421 const ICData& ic_data = node->ic_data();
1430 Function& target = Function::Handle(); 1422 Function& target = Function::Handle();
1431 Label load_field; 1423 Label load_field;
1432 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 1424 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
1433 Class& cls = Class::ZoneHandle(); 1425 Class& cls = Class::ZoneHandle();
1434 ic_data.GetOneClassCheckAt(i, &cls, &target); 1426 ic_data.GetOneClassCheckAt(i, &cls, &target);
1435 __ CompareObject(EAX, cls); 1427 __ CompareObject(EAX, cls);
1436 if (i == (ic_data.NumberOfChecks() - 1)) { 1428 if (i == (ic_data.NumberOfChecks() - 1)) {
1437 __ j(NOT_EQUAL, deopt_blob->label()); 1429 __ j(NOT_EQUAL, deopt_blob->label());
1438 } else { 1430 } else {
1439 __ j(EQUAL, &load_field); 1431 __ j(EQUAL, &load_field);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1509 1501
1510 // Return true if all targets in 'ic_data' point to same 1502 // Return true if all targets in 'ic_data' point to same
1511 // inlineable getter target. 1503 // inlineable getter target.
1512 static bool ICDataToSameInlineableInstanceGetter(const ICData& ic_data) { 1504 static bool ICDataToSameInlineableInstanceGetter(const ICData& ic_data) {
1513 const Function& target = Function::Handle(GetUniqueTarget(ic_data)); 1505 const Function& target = Function::Handle(GetUniqueTarget(ic_data));
1514 return !target.IsNull() && IsInlineableInstanceGetter(target); 1506 return !target.IsNull() && IsInlineableInstanceGetter(target);
1515 } 1507 }
1516 1508
1517 1509
1518 void OptimizingCodeGenerator::InlineInstanceGetter(AstNode* node, 1510 void OptimizingCodeGenerator::InlineInstanceGetter(AstNode* node,
1519 intptr_t id,
1520 AstNode* receiver, 1511 AstNode* receiver,
1521 const String& field_name, 1512 const String& field_name,
1522 Register recv_reg) { 1513 Register recv_reg) {
1523 if (ICDataToSameInlineableInstanceGetter(node->ICDataAtId(id))) { 1514 if (ICDataToSameInlineableInstanceGetter(node->ic_data())) {
1524 InlineInstanceGettersWithSameTarget(node, 1515 InlineInstanceGettersWithSameTarget(node,
1525 id,
1526 receiver, 1516 receiver,
1527 field_name, 1517 field_name,
1528 recv_reg); 1518 recv_reg);
1529 } else { 1519 } else {
1530 // TODO(srdjan): Inline access. 1520 // TODO(srdjan): Inline access.
1531 __ pushl(recv_reg); 1521 __ pushl(recv_reg);
1532 const int kNumberOfArguments = 1; 1522 const int kNumberOfArguments = 1;
1533 const Array& kNoArgumentNames = Array::Handle(); 1523 const Array& kNoArgumentNames = Array::Handle();
1534 GenerateCheckedInstanceCalls(node, 1524 GenerateCheckedInstanceCalls(node,
1535 receiver, 1525 receiver,
1536 id,
1537 node->token_index(), 1526 node->token_index(),
1538 kNumberOfArguments, 1527 kNumberOfArguments,
1539 kNoArgumentNames); 1528 kNoArgumentNames);
1540 } 1529 }
1541 } 1530 }
1542 1531
1543 1532
1544 // TODO(srdjan): Implement for multiple getter targets. 1533 // TODO(srdjan): Implement for multiple getter targets.
1545 // For every class inline its implicit getter, or call the instance getter. 1534 // For every class inline its implicit getter, or call the instance getter.
1546 void OptimizingCodeGenerator::VisitInstanceGetterNode( 1535 void OptimizingCodeGenerator::VisitInstanceGetterNode(
1547 InstanceGetterNode* node) { 1536 InstanceGetterNode* node) {
1548 const ICData& ic_data = node->ICDataAtId(node->id()); 1537 const ICData& ic_data = node->ic_data();
1549 if (ic_data.NumberOfChecks() == 0) { 1538 if (ic_data.NumberOfChecks() == 0) {
1550 // No type feedback collected. 1539 // No type feedback collected.
1551 node->receiver()->Visit(this); 1540 node->receiver()->Visit(this);
1552 DeoptimizationBlob* deopt_blob = 1541 DeoptimizationBlob* deopt_blob =
1553 AddDeoptimizationBlob(node, kDeoptInstanceGetter); 1542 AddDeoptimizationBlob(node, kDeoptInstanceGetter);
1554 __ jmp(deopt_blob->label()); 1543 __ jmp(deopt_blob->label());
1555 return; 1544 return;
1556 } 1545 }
1557 1546
1558 VisitLoadOne(node->receiver(), EBX); 1547 VisitLoadOne(node->receiver(), EBX);
1559 InlineInstanceGetter(node, 1548 InlineInstanceGetter(node,
1560 node->id(),
1561 node->receiver(), 1549 node->receiver(),
1562 node->field_name(), 1550 node->field_name(),
1563 EBX); 1551 EBX);
1564 // Result is in EAX. 1552 // Result is in EAX.
1565 HandleResult(node, EAX); 1553 HandleResult(node, EAX);
1566 } 1554 }
1567 1555
1568 1556
1569 // Helper struct to pass arguments to 'GenerateInstanceSetter'. 1557 // Helper struct to pass arguments to 'GenerateInstanceSetter'.
1570 struct InstanceSetterArgs { 1558 struct InstanceSetterArgs {
(...skipping 26 matching lines...) Expand all
1597 *(args.target), 1585 *(args.target),
1598 2, 1586 2,
1599 no_optional_argument_names); 1587 no_optional_argument_names);
1600 __ popl(args.value_reg); 1588 __ popl(args.value_reg);
1601 } 1589 }
1602 } 1590 }
1603 1591
1604 1592
1605 // Returns value in 'value_reg', clobbers EBX. 1593 // Returns value in 'value_reg', clobbers EBX.
1606 void OptimizingCodeGenerator::InlineInstanceSetter(AstNode* node, 1594 void OptimizingCodeGenerator::InlineInstanceSetter(AstNode* node,
1607 intptr_t id,
1608 AstNode* receiver, 1595 AstNode* receiver,
1609 const String& field_name, 1596 const String& field_name,
1610 Register recv_reg, 1597 Register recv_reg,
1611 Register value_reg) { 1598 Register value_reg) {
1612 // EBX is used as temporary register for class. 1599 // EBX is used as temporary register for class.
1613 ASSERT((recv_reg != EBX) && (value_reg != EBX)); 1600 ASSERT((recv_reg != EBX) && (value_reg != EBX));
1614 GrowableArray<Class*> classes; 1601 GrowableArray<Class*> classes;
1615 GrowableArray<Function*> targets; 1602 GrowableArray<Function*> targets;
1616 bool unique_target = true; 1603 bool unique_target = true;
1617 { 1604 {
1618 const ICData& ic_data = node->ICDataAtId(id); 1605 const ICData& ic_data = node->ic_data();
1619 ASSERT(ic_data.NumberOfChecks() > 0); 1606 ASSERT(ic_data.NumberOfChecks() > 0);
1620 ASSERT(ic_data.num_args_tested() == 1); 1607 ASSERT(ic_data.num_args_tested() == 1);
1621 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 1608 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
1622 Class& cls = Class::ZoneHandle(); 1609 Class& cls = Class::ZoneHandle();
1623 Function& target = Function::ZoneHandle(); 1610 Function& target = Function::ZoneHandle();
1624 ic_data.GetOneClassCheckAt(i, &cls, &target); 1611 ic_data.GetOneClassCheckAt(i, &cls, &target);
1625 classes.Add(&cls); 1612 classes.Add(&cls);
1626 targets.Add(&target); 1613 targets.Add(&target);
1627 } 1614 }
1628 for (intptr_t i = 1; i < targets.length(); i++) { 1615 for (intptr_t i = 1; i < targets.length(); i++) {
1629 if (targets[i - 1]->raw() != targets[i]->raw()) { 1616 if (targets[i - 1]->raw() != targets[i]->raw()) {
1630 unique_target = false; 1617 unique_target = false;
1631 break; 1618 break;
1632 } 1619 }
1633 } 1620 }
1634 } 1621 }
1635 // TODO(srdjan): sort classes/target by their invocation count. 1622 // TODO(srdjan): sort classes/target by their invocation count.
1636 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob( 1623 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(
1637 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); 1624 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget);
1638 // Deoptimize if Smi, since they do not have setters. 1625 // Deoptimize if Smi, since they do not have setters.
1639 if (NodeMayBeSmi(receiver)) { 1626 if (NodeMayBeSmi(receiver)) {
1640 __ testl(recv_reg, Immediate(kSmiTagMask)); 1627 __ testl(recv_reg, Immediate(kSmiTagMask));
1641 __ j(ZERO, deopt_blob->label()); 1628 __ j(ZERO, deopt_blob->label());
1642 } 1629 }
1643 __ movl(EBX, FieldAddress(recv_reg, Object::class_offset())); 1630 __ movl(EBX, FieldAddress(recv_reg, Object::class_offset()));
1644 // Initialize setter arguments, but leave the class and target fields NULL. 1631 // Initialize setter arguments, but leave the class and target fields NULL.
1645 InstanceSetterArgs setter_args = 1632 InstanceSetterArgs setter_args =
1646 {NULL, NULL, &field_name, recv_reg, value_reg, id, node->token_index()}; 1633 {NULL, NULL, &field_name, recv_reg, value_reg,
1634 node->id(), node->token_index()};
1647 1635
1648 if (unique_target) { 1636 if (unique_target) {
1649 Label store_field; 1637 Label store_field;
1650 for (intptr_t i = 0; i < classes.length(); i++) { 1638 for (intptr_t i = 0; i < classes.length(); i++) {
1651 __ CompareObject(EBX, *classes[i]); 1639 __ CompareObject(EBX, *classes[i]);
1652 if (i == (classes.length() - 1)) { 1640 if (i == (classes.length() - 1)) {
1653 __ j(NOT_EQUAL, deopt_blob->label()); 1641 __ j(NOT_EQUAL, deopt_blob->label());
1654 } else { 1642 } else {
1655 __ j(EQUAL, &store_field); 1643 __ j(EQUAL, &store_field);
1656 } 1644 }
(...skipping 28 matching lines...) Expand all
1685 // The call to the instance setter implements the assignment to a field. 1673 // The call to the instance setter implements the assignment to a field.
1686 // The result of the assignment to a field is the value being stored. 1674 // The result of the assignment to a field is the value being stored.
1687 void OptimizingCodeGenerator::VisitInstanceSetterNode( 1675 void OptimizingCodeGenerator::VisitInstanceSetterNode(
1688 InstanceSetterNode* node) { 1676 InstanceSetterNode* node) {
1689 // TODO(srdjan): inline setters to different targets as well. 1677 // TODO(srdjan): inline setters to different targets as well.
1690 if (FLAG_enable_type_checks) { 1678 if (FLAG_enable_type_checks) {
1691 CodeGenerator::VisitInstanceSetterNode(node); 1679 CodeGenerator::VisitInstanceSetterNode(node);
1692 return; 1680 return;
1693 } 1681 }
1694 VisitLoadTwo(node->receiver(), node->value(), EDX, EAX); 1682 VisitLoadTwo(node->receiver(), node->value(), EDX, EAX);
1695 const ICData& ic_data = node->ICDataAtId(node->id()); 1683 const ICData& ic_data = node->ic_data();
1696 if (ic_data.NumberOfChecks() == 0) { 1684 if (ic_data.NumberOfChecks() == 0) {
1697 DeoptimizationBlob* deopt_blob = 1685 DeoptimizationBlob* deopt_blob =
1698 AddDeoptimizationBlob(node, EDX, EAX, kDeoptInstanceSetter); 1686 AddDeoptimizationBlob(node, EDX, EAX, kDeoptInstanceSetter);
1699 __ jmp(deopt_blob->label()); 1687 __ jmp(deopt_blob->label());
1700 return; 1688 return;
1701 } 1689 }
1702 // Value in EAX survives and will be stored on stack if result is needed. 1690 // Value in EAX survives and will be stored on stack if result is needed.
1703 InlineInstanceSetter(node, 1691 InlineInstanceSetter(node,
1704 node->id(),
1705 node->receiver(), 1692 node->receiver(),
1706 node->field_name(), 1693 node->field_name(),
1707 EDX, 1694 EDX,
1708 EAX); 1695 EAX);
1709 1696
1710 HandleResult(node, EAX); 1697 HandleResult(node, EAX);
1711 } 1698 }
1712 1699
1713 1700
1714 // Return false if condition is not supported. 1701 // Return false if condition is not supported.
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 __ jmp(&evaluate_comparison); 1816 __ jmp(&evaluate_comparison);
1830 1817
1831 __ Bind(&call_operator); 1818 __ Bind(&call_operator);
1832 // Left is Smi. 1819 // Left is Smi.
1833 const int kNumberOfArguments = 2; 1820 const int kNumberOfArguments = 2;
1834 const Array& kNoArgumentNames = Array::Handle(); 1821 const Array& kNoArgumentNames = Array::Handle();
1835 __ pushl(EAX); 1822 __ pushl(EAX);
1836 __ pushl(EDX); 1823 __ pushl(EDX);
1837 GenerateCheckedInstanceCalls(node, 1824 GenerateCheckedInstanceCalls(node,
1838 node->left(), 1825 node->left(),
1839 node->id(),
1840 node->token_index(), 1826 node->token_index(),
1841 kNumberOfArguments, 1827 kNumberOfArguments,
1842 kNoArgumentNames); 1828 kNoArgumentNames);
1843 __ CompareObject(EAX, bool_true); 1829 __ CompareObject(EAX, bool_true);
1844 // Fall through to evaluate result. 1830 // Fall through to evaluate result.
1845 } 1831 }
1846 __ Bind(&evaluate_comparison); 1832 __ Bind(&evaluate_comparison);
1847 // Condition is set by a previous comparison operation. 1833 // Condition is set by a previous comparison operation.
1848 Condition condition = OVERFLOW; // Initialize to something. 1834 Condition condition = OVERFLOW; // Initialize to something.
1849 bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition); 1835 bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition);
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 node->token_index(), 2120 node->token_index(),
2135 node->left(), 2121 node->left(),
2136 node->right()->AsTypeNode()->type(), 2122 node->right()->AsTypeNode()->type(),
2137 (node->kind() == Token::kISNOT)); 2123 (node->kind() == Token::kISNOT));
2138 if (!IsResultNeeded(node)) { 2124 if (!IsResultNeeded(node)) {
2139 __ popl(EAX); // Pop the result of the instanceof operation. 2125 __ popl(EAX); // Pop the result of the instanceof operation.
2140 } 2126 }
2141 return; 2127 return;
2142 } 2128 }
2143 2129
2144 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) { 2130 if (NodeHasClassAt(node, smi_class_, 0)) {
2145 if (GenerateSmiComparison(node)) { 2131 if (GenerateSmiComparison(node)) {
2146 // The comparison was handled, code was emitted. 2132 // The comparison was handled, code was emitted.
2147 return; 2133 return;
2148 } 2134 }
2149 // Fall through if condition is not supported. 2135 // Fall through if condition is not supported.
2150 } else if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { 2136 } else if (NodeHasClassAt(node, double_class_, 0)) {
2151 // Double comparison. 2137 // Double comparison.
2152 if (GenerateDoubleComparison(node)) { 2138 if (GenerateDoubleComparison(node)) {
2153 return; 2139 return;
2154 } 2140 }
2155 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { 2141 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
2156 // Equality, not-equality comparison of any other type. 2142 // Equality, not-equality comparison of any other type.
2157 if (GenerateEqualityComparison(node)) { 2143 if (GenerateEqualityComparison(node)) {
2158 return; 2144 return;
2159 } 2145 }
2160 } 2146 }
2161 2147
2162 // Fall through here if a comparison was not implemented. 2148 // Fall through here if a comparison was not implemented.
2163 // TODO(srdjan): Implement for Strings. 2149 // TODO(srdjan): Implement for Strings.
2164 CodeGenerator::VisitComparisonNode(node); 2150 CodeGenerator::VisitComparisonNode(node);
2165 } 2151 }
2166 2152
2167 2153
2168 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { 2154 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) {
2169 const char* kMessage = "Inline indexed access"; 2155 const char* kMessage = "Inline indexed access";
2170 ObjectStore* object_store = Isolate::Current()->object_store(); 2156 ObjectStore* object_store = Isolate::Current()->object_store();
2171 const Class& object_array_class = 2157 const Class& object_array_class =
2172 Class::ZoneHandle(object_store->array_class()); 2158 Class::ZoneHandle(object_store->array_class());
2173 const Class& immutable_object_array_class = 2159 const Class& immutable_object_array_class =
2174 Class::ZoneHandle(object_store->immutable_array_class()); 2160 Class::ZoneHandle(object_store->immutable_array_class());
2175 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) || 2161 if (NodeHasClassAt(node, object_array_class, 0) ||
2176 AtIdNodeHasClassAt(node, node->id(), 2162 NodeHasClassAt(node, immutable_object_array_class, 0)) {
2177 immutable_object_array_class, 0)) {
2178 CodeGenInfo array_info(node->array()); 2163 CodeGenInfo array_info(node->array());
2179 CodeGenInfo index_info(node->index_expr()); 2164 CodeGenInfo index_info(node->index_expr());
2180 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); 2165 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX);
2181 DeoptimizationBlob* deopt_blob = 2166 DeoptimizationBlob* deopt_blob =
2182 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); 2167 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray);
2183 const Class& test_class = 2168 const Class& test_class = NodeHasClassAt(node, object_array_class, 0) ?
2184 AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ? 2169 object_array_class : immutable_object_array_class;
2185 object_array_class : immutable_object_array_class;
2186 // Type checks of array. 2170 // Type checks of array.
2187 if (!array_info.IsClass(test_class)) { 2171 if (!array_info.IsClass(test_class)) {
2188 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. 2172 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi.
2189 __ j(ZERO, deopt_blob->label()); 2173 __ j(ZERO, deopt_blob->label());
2190 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); 2174 __ movl(EAX, FieldAddress(EBX, Object::class_offset()));
2191 __ CompareObject(EAX, test_class); 2175 __ CompareObject(EAX, test_class);
2192 __ j(NOT_EQUAL, deopt_blob->label()); 2176 __ j(NOT_EQUAL, deopt_blob->label());
2193 PropagateBackLocalClass(node->array(), test_class); 2177 PropagateBackLocalClass(node->array(), test_class);
2194 } 2178 }
2195 2179
2196 // Type check of index. 2180 // Type check of index.
2197 if (!index_info.IsClass(smi_class_)) { 2181 if (!index_info.IsClass(smi_class_)) {
2198 __ testl(EDX, Immediate(kSmiTagMask)); 2182 __ testl(EDX, Immediate(kSmiTagMask));
2199 __ j(NOT_ZERO, deopt_blob->label()); 2183 __ j(NOT_ZERO, deopt_blob->label());
2200 PropagateBackLocalClass(node->index_expr(), smi_class_); 2184 PropagateBackLocalClass(node->index_expr(), smi_class_);
2201 } 2185 }
2202 // Range check. 2186 // Range check.
2203 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); 2187 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset()));
2204 __ j(ABOVE_EQUAL, deopt_blob->label()); 2188 __ j(ABOVE_EQUAL, deopt_blob->label());
2205 // Note that EDX is Smi, i.e, times 2. 2189 // Note that EDX is Smi, i.e, times 2.
2206 ASSERT(kSmiTagShift == 1); 2190 ASSERT(kSmiTagShift == 1);
2207 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); 2191 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray)));
2208 HandleResult(node, EAX); 2192 HandleResult(node, EAX);
2209 TraceOpt(node, kMessage); 2193 TraceOpt(node, kMessage);
2210 return; 2194 return;
2211 } 2195 }
2212 2196
2213 if (AtIdNodeHasClassAt(node, node->id(), growable_object_array_class_, 0)) { 2197 if (NodeHasClassAt(node, growable_object_array_class_, 0)) {
2214 CodeGenInfo array_info(node->array()); 2198 CodeGenInfo array_info(node->array());
2215 CodeGenInfo index_info(node->index_expr()); 2199 CodeGenInfo index_info(node->index_expr());
2216 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX); 2200 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX);
2217 DeoptimizationBlob* deopt_blob = 2201 DeoptimizationBlob* deopt_blob =
2218 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); 2202 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray);
2219 // EAX: index, EDX: array. 2203 // EAX: index, EDX: array.
2220 if (!index_info.IsClass(smi_class_)) { 2204 if (!index_info.IsClass(smi_class_)) {
2221 __ testl(EAX, Immediate(kSmiTagMask)); 2205 __ testl(EAX, Immediate(kSmiTagMask));
2222 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. 2206 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index.
2223 PropagateBackLocalClass(node->index_expr(), smi_class_); 2207 PropagateBackLocalClass(node->index_expr(), smi_class_);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2257 // array (e.g. in a[x] += 3). Fixes issue 1570. 2241 // array (e.g. in a[x] += 3). Fixes issue 1570.
2258 { 2242 {
2259 CodeGenInfo array_info(node->array()); 2243 CodeGenInfo array_info(node->array());
2260 node->array()->Visit(this); 2244 node->array()->Visit(this);
2261 class_of_this_array = array_info.is_class()->raw(); 2245 class_of_this_array = array_info.is_class()->raw();
2262 } 2246 }
2263 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo). 2247 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo).
2264 ObjectStore* object_store = Isolate::Current()->object_store(); 2248 ObjectStore* object_store = Isolate::Current()->object_store();
2265 const Class& object_array_class = 2249 const Class& object_array_class =
2266 Class::ZoneHandle(object_store->array_class()); 2250 Class::ZoneHandle(object_store->array_class());
2267 const ICData& ic_data = node->ICDataAtId(node->id()); 2251 const ICData& ic_data = node->ic_data();
2268 if (ic_data.NumberOfChecks() == 0) { 2252 if (ic_data.NumberOfChecks() == 0) {
2269 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2253 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2270 DeoptimizationBlob* deopt_blob = 2254 DeoptimizationBlob* deopt_blob =
2271 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); 2255 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback);
2272 __ jmp(deopt_blob->label()); 2256 __ jmp(deopt_blob->label());
2273 return; 2257 return;
2274 } 2258 }
2275 2259
2276 2260
2277 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) { 2261 if (NodeHasClassAt(node, object_array_class, 0)) {
2278 // Release CodeGenInfo of index quickly as it may be used in the value, 2262 // Release CodeGenInfo of index quickly as it may be used in the value,
2279 // e.g. a[i] += 3. Fixes issue 1570. 2263 // e.g. a[i] += 3. Fixes issue 1570.
2280 bool index_is_smi = false; 2264 bool index_is_smi = false;
2281 { 2265 {
2282 CodeGenInfo index_info(node->index_expr()); 2266 CodeGenInfo index_info(node->index_expr());
2283 node->index_expr()->Visit(this); 2267 node->index_expr()->Visit(this);
2284 index_is_smi = index_info.IsClass(smi_class_); 2268 index_is_smi = index_info.IsClass(smi_class_);
2285 } 2269 }
2286 VisitLoadOne(node->value(), ECX); 2270 VisitLoadOne(node->value(), ECX);
2287 DeoptimizationBlob* deopt_blob = 2271 DeoptimizationBlob* deopt_blob =
(...skipping 20 matching lines...) Expand all
2308 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); 2292 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset()));
2309 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. 2293 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt.
2310 ASSERT(kSmiTagShift == 1); 2294 ASSERT(kSmiTagShift == 1);
2311 __ StoreIntoObject(EAX, 2295 __ StoreIntoObject(EAX,
2312 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), 2296 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)),
2313 ECX); 2297 ECX);
2314 HandleResult(node, ECX); 2298 HandleResult(node, ECX);
2315 return; 2299 return;
2316 } 2300 }
2317 2301
2318 if (AtIdNodeHasClassAt(node, node->id(), growable_object_array_class_, 0)) { 2302 if (NodeHasClassAt(node, growable_object_array_class_, 0)) {
2319 bool index_is_smi = false; 2303 bool index_is_smi = false;
2320 // Release CodeGenInfo of index quickly as it may be used in the value, 2304 // Release CodeGenInfo of index quickly as it may be used in the value,
2321 // e.g. a[i] += 3. Fixes issue 1570. 2305 // e.g. a[i] += 3. Fixes issue 1570.
2322 { 2306 {
2323 CodeGenInfo index_info(node->index_expr()); 2307 CodeGenInfo index_info(node->index_expr());
2324 node->index_expr()->Visit(this); 2308 node->index_expr()->Visit(this);
2325 index_is_smi = index_info.IsClass(smi_class_); 2309 index_is_smi = index_info.IsClass(smi_class_);
2326 } 2310 }
2327 VisitLoadOne(node->value(), ECX); 2311 VisitLoadOne(node->value(), ECX);
2328 DeoptimizationBlob* deopt_blob = 2312 DeoptimizationBlob* deopt_blob =
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
2587 targets->Add(&null_target); 2571 targets->Add(&null_target);
2588 } 2572 }
2589 } 2573 }
2590 2574
2591 2575
2592 // Use IC data in 'node' to issues checks and calls. 2576 // Use IC data in 'node' to issues checks and calls.
2593 // IC data can contain one or more argument checks. 2577 // IC data can contain one or more argument checks.
2594 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls( 2578 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls(
2595 AstNode* node, 2579 AstNode* node,
2596 AstNode* receiver, 2580 AstNode* receiver,
2597 intptr_t node_id,
2598 intptr_t token_index, 2581 intptr_t token_index,
2599 intptr_t num_args, 2582 intptr_t num_args,
2600 const Array& optional_arguments_names) { 2583 const Array& optional_arguments_names) {
2601 ASSERT(node != NULL); 2584 ASSERT(node != NULL);
2602 ASSERT(receiver != NULL); 2585 ASSERT(receiver != NULL);
2603 ASSERT(num_args > 0); 2586 ASSERT(num_args > 0);
2604 const ICData& ic_data = node->ICDataAtId(node_id); 2587 const ICData& ic_data = node->ic_data();
2605 if (ic_data.NumberOfChecks() == 0) { 2588 if (ic_data.NumberOfChecks() == 0) {
2606 // No type feedback means node was never executed. However that can be 2589 // No type feedback means node was never executed. However that can be
2607 // a common case especially in case of large switch statements. 2590 // a common case especially in case of large switch statements.
2608 // Use a special inline cache call which can help us decide when to 2591 // Use a special inline cache call which can help us decide when to
2609 // re-optimize this optiumized function. 2592 // re-optimize this optiumized function.
2610 GenerateInlineCacheCall( 2593 GenerateInlineCacheCall(
2611 node_id, token_index, ic_data, num_args, optional_arguments_names); 2594 node->id(), token_index, ic_data, num_args, optional_arguments_names);
2612 return; 2595 return;
2613 } 2596 }
2614 2597
2615 Function& target_for_null = Function::ZoneHandle(); 2598 Function& target_for_null = Function::ZoneHandle();
2616 ObjectStore* object_store = Isolate::Current()->object_store(); 2599 ObjectStore* object_store = Isolate::Current()->object_store();
2617 int num_optional_args = 2600 int num_optional_args =
2618 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); 2601 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length();
2619 target_for_null = Resolver::ResolveDynamicForReceiverClass( 2602 target_for_null = Resolver::ResolveDynamicForReceiverClass(
2620 Class::Handle(object_store->object_class()), 2603 Class::Handle(object_store->object_class()),
2621 String::Handle(ic_data.target_name()), 2604 String::Handle(ic_data.target_name()),
(...skipping 11 matching lines...) Expand all
2633 __ movl(EAX, Address(ESP, (num_args - 1) * kWordSize)); // Load receiver. 2616 __ movl(EAX, Address(ESP, (num_args - 1) * kWordSize)); // Load receiver.
2634 if (classes[0]->raw() == smi_class_.raw()) { 2617 if (classes[0]->raw() == smi_class_.raw()) {
2635 start_ix++; 2618 start_ix++;
2636 // Smi test is needed. 2619 // Smi test is needed.
2637 __ testl(EAX, Immediate(kSmiTagMask)); 2620 __ testl(EAX, Immediate(kSmiTagMask));
2638 if (classes.length() == 1) { 2621 if (classes.length() == 1) {
2639 // Only Smi test. 2622 // Only Smi test.
2640 DeoptimizationBlob* deopt_blob = 2623 DeoptimizationBlob* deopt_blob =
2641 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiOnly); 2624 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiOnly);
2642 __ j(NOT_ZERO, deopt_blob->label()); 2625 __ j(NOT_ZERO, deopt_blob->label());
2643 GenerateDirectCall(node_id, 2626 GenerateDirectCall(node->id(),
2644 token_index, 2627 token_index,
2645 *targets[0], 2628 *targets[0],
2646 num_args, 2629 num_args,
2647 optional_arguments_names); 2630 optional_arguments_names);
2648 return; 2631 return;
2649 } 2632 }
2650 Label not_smi; 2633 Label not_smi;
2651 __ j(NOT_ZERO, &not_smi); 2634 __ j(NOT_ZERO, &not_smi);
2652 GenerateDirectCall(node_id, 2635 GenerateDirectCall(node->id(),
2653 token_index, 2636 token_index,
2654 *targets[0], 2637 *targets[0],
2655 num_args, 2638 num_args,
2656 optional_arguments_names); 2639 optional_arguments_names);
2657 __ jmp(&done); 2640 __ jmp(&done);
2658 __ Bind(&not_smi); // Continue with other test below. 2641 __ Bind(&not_smi); // Continue with other test below.
2659 } else if (NodeMayBeSmi(receiver)) { 2642 } else if (NodeMayBeSmi(receiver)) {
2660 DeoptimizationBlob* deopt_blob = 2643 DeoptimizationBlob* deopt_blob =
2661 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail); 2644 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallSmiFail);
2662 __ testl(EAX, Immediate(kSmiTagMask)); 2645 __ testl(EAX, Immediate(kSmiTagMask));
2663 __ j(ZERO, deopt_blob->label()); 2646 __ j(ZERO, deopt_blob->label());
2664 } else { 2647 } else {
2665 // Receiver cannot be Smi, no need to test it. 2648 // Receiver cannot be Smi, no need to test it.
2666 } 2649 }
2667 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); // Receiver's class. 2650 __ movl(EAX, FieldAddress(EAX, Object::class_offset())); // Receiver's class.
2668 for (intptr_t i = start_ix; i < classes.length(); i++) { 2651 for (intptr_t i = start_ix; i < classes.length(); i++) {
2669 const Class& cls = *classes[i]; 2652 const Class& cls = *classes[i];
2670 const Function& target = *targets[i]; 2653 const Function& target = *targets[i];
2671 __ CompareObject(EAX, cls); 2654 __ CompareObject(EAX, cls);
2672 if (i == (classes.length() - 1)) { 2655 if (i == (classes.length() - 1)) {
2673 // Last check. 2656 // Last check.
2674 DeoptimizationBlob* deopt_blob = 2657 DeoptimizationBlob* deopt_blob =
2675 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail); 2658 AddDeoptimizationBlob(node, kDeoptCheckedInstanceCallCheckFail);
2676 __ j(NOT_EQUAL, deopt_blob->label()); 2659 __ j(NOT_EQUAL, deopt_blob->label());
2677 GenerateDirectCall(node_id, 2660 GenerateDirectCall(node->id(),
2678 token_index, 2661 token_index,
2679 target, 2662 target,
2680 num_args, 2663 num_args,
2681 optional_arguments_names); 2664 optional_arguments_names);
2682 } else { 2665 } else {
2683 Label next; 2666 Label next;
2684 __ j(NOT_EQUAL, &next); 2667 __ j(NOT_EQUAL, &next);
2685 GenerateDirectCall(node_id, 2668 GenerateDirectCall(node->id(),
2686 token_index, 2669 token_index,
2687 target, 2670 target,
2688 num_args, 2671 num_args,
2689 optional_arguments_names); 2672 optional_arguments_names);
2690 __ jmp(&done); 2673 __ jmp(&done);
2691 __ Bind(&next); 2674 __ Bind(&next);
2692 } 2675 }
2693 } 2676 }
2694 __ Bind(&done); 2677 __ Bind(&done);
2695 } 2678 }
2696 2679
2697 2680
2698 void OptimizingCodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { 2681 void OptimizingCodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) {
2699 const int number_of_arguments = node->arguments()->length() + 1; 2682 const int number_of_arguments = node->arguments()->length() + 1;
2700 // Compute the receiver object and pass it as first argument to call. 2683 // Compute the receiver object and pass it as first argument to call.
2701 node->receiver()->Visit(this); 2684 node->receiver()->Visit(this);
2702 // Now compute rest of the arguments to the call. 2685 // Now compute rest of the arguments to the call.
2703 node->arguments()->Visit(this); 2686 node->arguments()->Visit(this);
2704 if (TryInlineInstanceCall(node)) { 2687 if (TryInlineInstanceCall(node)) {
2705 // Instance call is inlined. 2688 // Instance call is inlined.
2706 } else { 2689 } else {
2707 GenerateCheckedInstanceCalls(node, 2690 GenerateCheckedInstanceCalls(node,
2708 node->receiver(), 2691 node->receiver(),
2709 node->id(),
2710 node->token_index(), 2692 node->token_index(),
2711 number_of_arguments, 2693 number_of_arguments,
2712 node->arguments()->names()); 2694 node->arguments()->names());
2713 } 2695 }
2714 // Result is in EAX. 2696 // Result is in EAX.
2715 HandleResult(node, EAX); 2697 HandleResult(node, EAX);
2716 } 2698 }
2717 2699
2718 2700
2719 // Returns true if an instance call was replaced with its intrinsic. 2701 // Returns true if an instance call was replaced with its intrinsic.
2720 // Returns result in EAX. 2702 // Returns result in EAX.
2721 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) { 2703 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) {
2722 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node); 2704 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
2723 if ((classes != NULL) && (classes->length() == 1)) { 2705 if ((classes != NULL) && (classes->length() == 1)) {
2724 const int num_arguments = node->arguments()->length() + 1; 2706 const int num_arguments = node->arguments()->length() + 1;
2725 const int num_named_arguments = node->arguments()->names().IsNull() ? 2707 const int num_named_arguments = node->arguments()->names().IsNull() ?
2726 0 : node->arguments()->names().Length(); 2708 0 : node->arguments()->names().Length();
2727 const Function& target = Function::ZoneHandle( 2709 const Function& target = Function::ZoneHandle(
2728 Resolver::ResolveDynamicForReceiverClass(*(*classes)[0], 2710 Resolver::ResolveDynamicForReceiverClass(*(*classes)[0],
2729 node->function_name(), 2711 node->function_name(),
2730 num_arguments, 2712 num_arguments,
2731 num_named_arguments)); 2713 num_named_arguments));
2732 Recognizer::Kind recognized = Recognizer::RecognizeKind(target); 2714 Recognizer::Kind recognized = Recognizer::RecognizeKind(target);
2733 if (FLAG_trace_optimization) { 2715 if (FLAG_trace_optimization) {
2734 OS::Print("Monomorphic inline candidate: %s -> %s\n", 2716 OS::Print("Monomorphic inline candidate: %s -> %s\n",
2735 target.ToFullyQualifiedCString(), 2717 target.ToFullyQualifiedCString(),
2736 Recognizer::KindToCString(recognized)); 2718 Recognizer::KindToCString(recognized));
2737 } 2719 }
2738 if ((recognized == Recognizer::kIntegerToDouble) && 2720 if ((recognized == Recognizer::kIntegerToDouble) &&
2739 AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) { 2721 NodeHasClassAt(node, smi_class_, 0)) {
2740 // TODO(srdjan): Check if we could use temporary double instead of 2722 // TODO(srdjan): Check if we could use temporary double instead of
2741 // allocating a new object every time. 2723 // allocating a new object every time.
2742 const Code& stub = 2724 const Code& stub =
2743 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 2725 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
2744 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 2726 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
2745 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); 2727 GenerateCall(node->token_index(), &label, PcDescriptors::kOther);
2746 // EAX is double object. 2728 // EAX is double object.
2747 DeoptimizationBlob* deopt_blob = 2729 DeoptimizationBlob* deopt_blob =
2748 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble); 2730 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble);
2749 __ popl(EBX); // Receiver 2731 __ popl(EBX); // Receiver
2750 __ testl(EBX, Immediate(kSmiTagMask)); 2732 __ testl(EBX, Immediate(kSmiTagMask));
2751 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi. 2733 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi.
2752 __ SmiUntag(EBX); 2734 __ SmiUntag(EBX);
2753 __ cvtsi2sd(XMM0, EBX); 2735 __ cvtsi2sd(XMM0, EBX);
2754 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 2736 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
2755 return true; 2737 return true;
2756 } 2738 }
2757 2739
2758 if ((recognized == Recognizer::kDoubleToDouble) && 2740 if ((recognized == Recognizer::kDoubleToDouble) &&
2759 AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { 2741 NodeHasClassAt(node, double_class_, 0)) {
2760 DeoptimizationBlob* deopt_blob = 2742 DeoptimizationBlob* deopt_blob =
2761 AddDeoptimizationBlob(node, EAX, kDeoptDoubleToDouble); 2743 AddDeoptimizationBlob(node, EAX, kDeoptDoubleToDouble);
2762 __ popl(EAX); 2744 __ popl(EAX);
2763 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label()); 2745 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label());
2764 return true; 2746 return true;
2765 } 2747 }
2766 } 2748 }
2767 return false; 2749 return false;
2768 } 2750 }
2769 2751
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
2896 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True())); 2878 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True()));
2897 __ cmpl(EDX, EAX); 2879 __ cmpl(EDX, EAX);
2898 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 2880 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
2899 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); 2881 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False()));
2900 __ Bind(&done); 2882 __ Bind(&done);
2901 HandleResult(node, EAX); 2883 HandleResult(node, EAX);
2902 return; 2884 return;
2903 } 2885 }
2904 2886
2905 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) { 2887 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) {
2906 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) { 2888 if (NodeHasClassAt(node, smi_class_, 0)) {
2907 const ICData& ic_data = node->ICDataAtId(node->id()); 2889 const ICData& ic_data = node->ic_data();
2908 ASSERT(ic_data.num_args_tested() == 1); 2890 ASSERT(ic_data.num_args_tested() == 1);
2909 GenerateSmiUnaryOp(node); 2891 GenerateSmiUnaryOp(node);
2910 return; 2892 return;
2911 } 2893 }
2912 } 2894 }
2913 if (node->kind() == Token::kSUB) { 2895 if (node->kind() == Token::kSUB) {
2914 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { 2896 if (NodeHasClassAt(node, double_class_, 0)) {
2915 const ICData& ic_data = node->ICDataAtId(node->id()); 2897 const ICData& ic_data = node->ic_data();
2916 ASSERT(ic_data.num_args_tested() == 1); 2898 ASSERT(ic_data.num_args_tested() == 1);
2917 GenerateDoubleUnaryOp(node); 2899 GenerateDoubleUnaryOp(node);
2918 return; 2900 return;
2919 } 2901 }
2920 } 2902 }
2921 // TODO(srdjan): Implement unary kSUB (negate) Mint. 2903 // TODO(srdjan): Implement unary kSUB (negate) Mint.
2922 CodeGenerator::VisitUnaryOpNode(node); 2904 CodeGenerator::VisitUnaryOpNode(node);
2923 } 2905 }
2924 2906
2925 2907
2926 } // namespace dart 2908 } // namespace dart
2927 2909
2928 #endif // defined TARGET_ARCH_IA32 2910 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698