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

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

Issue 8999031: More optimizations. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 12 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 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 if (node->info() != NULL) { 556 if (node->info() != NULL) {
557 const Class* cls = NULL; 557 const Class* cls = NULL;
558 classes_for_locals_->GetLocalClass(node->local(), &cls); 558 classes_for_locals_->GetLocalClass(node->local(), &cls);
559 if (cls != NULL) { 559 if (cls != NULL) {
560 node->info()->set_is_class(cls); 560 node->info()->set_is_class(cls);
561 } 561 }
562 } 562 }
563 } 563 }
564 564
565 565
566 void OptimizingCodeGenerator::HandleResult(AstNode* node, Register result_reg) {
567 if (CodeGenerator::IsResultNeeded(node)) {
568 if (IsResultInEaxRequested(node)) {
569 if (result_reg != EAX) {
570 __ movl(EAX, result_reg);
571 }
572 node->info()->set_result_returned_in_eax(true);
573 } else {
574 __ pushl(result_reg);
575 }
576 }
577 }
578
579
566 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { 580 void OptimizingCodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) {
567 if (FLAG_enable_type_checks) { 581 if (FLAG_enable_type_checks) {
568 CodeGenerator::VisitStoreLocalNode(node); 582 CodeGenerator::VisitStoreLocalNode(node);
569 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); 583 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle());
570 return; 584 return;
571 } 585 }
572 CodeGenInfo value_info(node->value()); 586 CodeGenInfo value_info(node->value());
573 value_info.set_request_result_in_eax(true); 587 value_info.set_request_result_in_eax(true);
574 node->value()->Visit(this); 588 node->value()->Visit(this);
575 if (value_info.is_temp()) { 589 if (value_info.is_temp()) {
(...skipping 12 matching lines...) Expand all
588 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX); 602 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
589 } else { 603 } else {
590 UNIMPLEMENTED(); // Cannot handle other temporary types yet. 604 UNIMPLEMENTED(); // Cannot handle other temporary types yet.
591 } 605 }
592 } else { 606 } else {
593 if (!value_info.result_returned_in_eax()) { 607 if (!value_info.result_returned_in_eax()) {
594 __ popl(EAX); 608 __ popl(EAX);
595 } 609 }
596 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX); 610 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
597 } 611 }
598 if (IsResultNeeded(node)) { 612 HandleResult(node, EAX);
599 __ pushl(EAX);
600 }
601 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class()); 613 classes_for_locals_->SetLocalType(node->local(), *value_info.is_class());
602 } 614 }
603 615
604 616
605 static bool NodeHasBothReceiverClasses(AstNode* node, 617 static bool NodeHasBothReceiverClasses(AstNode* node,
606 const Class& cls1, 618 const Class& cls1,
607 const Class& cls2) { 619 const Class& cls2) {
608 ASSERT(node != NULL); 620 ASSERT(node != NULL);
609 ASSERT(!cls1.IsNull() && !cls2.IsNull()); 621 ASSERT(!cls1.IsNull() && !cls2.IsNull());
610 const ICData& ic_data = node->ICDataAtId(node->id()); 622 const ICData& ic_data = node->ICDataAtId(node->id());
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 __ testl(EAX, Immediate(kSmiTagMask)); 814 __ testl(EAX, Immediate(kSmiTagMask));
803 __ j(NOT_ZERO, deopt_blob->label()); 815 __ j(NOT_ZERO, deopt_blob->label());
804 if (node->kind() == Token::kSUB) { 816 if (node->kind() == Token::kSUB) {
805 __ negl(EAX); 817 __ negl(EAX);
806 __ j(OVERFLOW, deopt_blob->label()); 818 __ j(OVERFLOW, deopt_blob->label());
807 } else { 819 } else {
808 ASSERT(node->kind() == Token::kBIT_NOT); 820 ASSERT(node->kind() == Token::kBIT_NOT);
809 __ notl(EAX); 821 __ notl(EAX);
810 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 822 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
811 } 823 }
812 if (CodeGenerator::IsResultNeeded(node)) { 824 HandleResult(node, EAX);
813 if (IsResultInEaxRequested(node)) {
814 node->info()->set_result_returned_in_eax(true);
815 } else {
816 __ pushl(EAX);
817 }
818 }
819 } 825 }
820 826
821 827
822 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) { 828 void OptimizingCodeGenerator::GenerateDoubleUnaryOp(UnaryOpNode* node) {
823 const Register kOperandRegister = ECX; 829 const Register kOperandRegister = ECX;
824 const Register kTempRegister = EBX; 830 const Register kTempRegister = EBX;
825 const Register kResultRegister = EAX; 831 const Register kResultRegister = EAX;
826 const ICData& ic_data = node->ICDataAtId(node->id()); 832 const ICData& ic_data = node->ICDataAtId(node->id());
827 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? 833 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ?
828 kDeoptNoTypeFeedback : kDeoptUnaryOp; 834 kDeoptNoTypeFeedback : kDeoptUnaryOp;
(...skipping 22 matching lines...) Expand all
851 __ popl(kOperandRegister); 857 __ popl(kOperandRegister);
852 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); 858 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset()));
853 __ xorps(XMM1, XMM1); // 0.0 -> XMM1. 859 __ xorps(XMM1, XMM1); // 0.0 -> XMM1.
854 __ subsd(XMM1, XMM0); 860 __ subsd(XMM1, XMM0);
855 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1); 861 __ movsd(FieldAddress(kResultRegister, Double::value_offset()), XMM1);
856 if (CodeGenerator::IsResultNeeded(node)) { 862 if (CodeGenerator::IsResultNeeded(node)) {
857 if (node->info() != NULL) { 863 if (node->info() != NULL) {
858 node->info()->set_is_temp(true); 864 node->info()->set_is_temp(true);
859 node->info()->set_is_class(&double_class_); 865 node->info()->set_is_class(&double_class_);
860 } 866 }
861 if (IsResultInEaxRequested(node)) { 867 HandleResult(node, kResultRegister);
862 ASSERT(kResultRegister == EAX);
863 node->info()->set_result_returned_in_eax(true);
864 } else {
865 __ pushl(kResultRegister);
866 }
867 } 868 }
868 } 869 }
869 870
870 871
871 // Handles only Smi & Smi. 872 // Handles only Smi & Smi.
872 // TODO(srdjan): Certain operations always overflow, and thus cause 873 // TODO(srdjan): Certain operations always overflow, and thus cause
873 // deoptimization. We need to mark those places and handle them. 874 // deoptimization. We need to mark those places and handle them.
874 void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) { 875 void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) {
875 const char* kOptMessage = "Inlines BinaryOp for Smi"; 876 const char* kOptMessage = "Inlines BinaryOp for Smi";
876 Label done; 877 Label done;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } else { 983 } else {
983 // Unhandled node kind. 984 // Unhandled node kind.
984 TraceNotOpt(node, kOptMessage); 985 TraceNotOpt(node, kOptMessage);
985 node->left()->Visit(this); 986 node->left()->Visit(this);
986 node->right()->Visit(this); 987 node->right()->Visit(this);
987 CodeGenerator::GenerateBinaryOperatorCall(node->id(), 988 CodeGenerator::GenerateBinaryOperatorCall(node->id(),
988 node->token_index(), 989 node->token_index(),
989 node->Name()); 990 node->Name());
990 } 991 }
991 __ Bind(&done); 992 __ Bind(&done);
992 if (CodeGenerator::IsResultNeeded(node)) { 993 HandleResult(node, EAX);
993 if (IsResultInEaxRequested(node)) {
994 node->info()->set_result_returned_in_eax(true);
995 } else {
996 __ pushl(EAX);
997 }
998 }
999 } 994 }
1000 995
1001 996
1002 // Supports some mixed Smi/Mint operations. 997 // Supports some mixed Smi/Mint operations.
1003 // For BIT_AND operation with one operand being Smi, we can throw away 998 // For BIT_AND operation with one operand being Smi, we can throw away
1004 // any Mint bits above the Smi range. 999 // any Mint bits above the Smi range.
1005 // 'allow_smi' is true if Smi and Mint classes have been encountered. 1000 // 'allow_smi' is true if Smi and Mint classes have been encountered.
1006 void OptimizingCodeGenerator::GenerateMintBinaryOp(BinaryOpNode* node, 1001 void OptimizingCodeGenerator::GenerateMintBinaryOp(BinaryOpNode* node,
1007 bool allow_smi) { 1002 bool allow_smi) {
1008 const char* kOptMessage = "Inline Mint binop."; 1003 const char* kOptMessage = "Inline Mint binop.";
(...skipping 28 matching lines...) Expand all
1037 __ pushl(EDX); 1032 __ pushl(EDX);
1038 const int number_of_arguments = 2; 1033 const int number_of_arguments = 2;
1039 const Array& no_optional_argument_names = Array::Handle(); 1034 const Array& no_optional_argument_names = Array::Handle();
1040 GenerateCheckedInstanceCalls(node, 1035 GenerateCheckedInstanceCalls(node,
1041 node->left(), 1036 node->left(),
1042 node->id(), 1037 node->id(),
1043 node->token_index(), 1038 node->token_index(),
1044 number_of_arguments, 1039 number_of_arguments,
1045 no_optional_argument_names); 1040 no_optional_argument_names);
1046 __ Bind(&done); 1041 __ Bind(&done);
1047 if (CodeGenerator::IsResultNeeded(node)) { 1042 HandleResult(node, EAX);
1048 __ pushl(EAX);
1049 }
1050 return; 1043 return;
1051 } 1044 }
1052 if ((kind == Token::kSHL) && allow_smi) { 1045 if ((kind == Token::kSHL) && allow_smi) {
1053 GenerateSmiShiftBinaryOp(node); 1046 GenerateSmiShiftBinaryOp(node);
1054 if (CodeGenerator::IsResultNeeded(node)) { 1047 HandleResult(node, EAX);
1055 __ pushl(EAX);
1056 }
1057 return; 1048 return;
1058 } 1049 }
1059 TraceNotOpt(node, kOptMessage); 1050 TraceNotOpt(node, kOptMessage);
1060 CodeGenerator::VisitBinaryOpNode(node); 1051 CodeGenerator::VisitBinaryOpNode(node);
1061 } 1052 }
1062 1053
1063 1054
1064 // Conservative approach: 1055 // Conservative approach:
1065 // - true if both nodes are LoadLocalNodes with the same index. 1056 // - true if both nodes are LoadLocalNodes with the same index.
1066 static bool AreNodesOfSameType(AstNode* a, AstNode* b) { 1057 static bool AreNodesOfSameType(AstNode* a, AstNode* b) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 case Token::kMUL: __ mulsd(XMM0, XMM1); break; 1185 case Token::kMUL: __ mulsd(XMM0, XMM1); break;
1195 case Token::kDIV: __ divsd(XMM0, XMM1); break; 1186 case Token::kDIV: __ divsd(XMM0, XMM1); break;
1196 default: UNREACHABLE(); 1187 default: UNREACHABLE();
1197 } 1188 }
1198 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); 1189 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0);
1199 if (CodeGenerator::IsResultNeeded(node)) { 1190 if (CodeGenerator::IsResultNeeded(node)) {
1200 if (node->info() != NULL) { 1191 if (node->info() != NULL) {
1201 node->info()->set_is_temp(true); 1192 node->info()->set_is_temp(true);
1202 node->info()->set_is_class(&double_class_); 1193 node->info()->set_is_class(&double_class_);
1203 } 1194 }
1204 if (IsResultInEaxRequested(node)) { 1195 HandleResult(node, result_register);
1205 __ movl(EAX, result_register);
1206 node->info()->set_result_returned_in_eax(true);
1207 } else {
1208 __ pushl(result_register);
1209 }
1210 } 1196 }
1211 return; 1197 return;
1212 } 1198 }
1213 1199
1214 TraceNotOpt(node, kOptMessage); 1200 TraceNotOpt(node, kOptMessage);
1215 CodeGenerator::VisitBinaryOpNode(node); 1201 CodeGenerator::VisitBinaryOpNode(node);
1216 } 1202 }
1217 1203
1218 1204
1219 static bool NodeInfoHasLabels(AstNode* node) { 1205 static bool NodeInfoHasLabels(AstNode* node) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1282 if (NodeInfoHasLabels(node)) { 1268 if (NodeInfoHasLabels(node)) {
1283 node->info()->set_labels_used(true); 1269 node->info()->set_labels_used(true);
1284 } else { 1270 } else {
1285 Label done; 1271 Label done;
1286 __ Bind(&return_true_object); 1272 __ Bind(&return_true_object);
1287 __ LoadObject(EAX, bool_true); 1273 __ LoadObject(EAX, bool_true);
1288 __ jmp(&done, Assembler::kNearJump); 1274 __ jmp(&done, Assembler::kNearJump);
1289 __ Bind(&return_false_object); 1275 __ Bind(&return_false_object);
1290 __ LoadObject(EAX, bool_false); 1276 __ LoadObject(EAX, bool_false);
1291 __ Bind(&done); 1277 __ Bind(&done);
1292 if (IsResultNeeded(node)) { 1278 HandleResult(node, EAX);
1293 __ pushl(EAX);
1294 }
1295 } 1279 }
1296 } 1280 }
1297 1281
1298 1282
1299 void OptimizingCodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) { 1283 void OptimizingCodeGenerator::VisitBinaryOpNode(BinaryOpNode* node) {
1300 // Operators "&&" and "||" cannot be overloaded, therefore inline them 1284 // Operators "&&" and "||" cannot be overloaded, therefore inline them
1301 // instead of calling the operator. 1285 // instead of calling the operator.
1302 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { 1286 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
1303 if (FLAG_enable_type_checks) { 1287 if (FLAG_enable_type_checks) {
1304 CodeGenerator::VisitBinaryOpNode(node); 1288 CodeGenerator::VisitBinaryOpNode(node);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 node->left()->Visit(this); 1337 node->left()->Visit(this);
1354 node->right()->Visit(this); 1338 node->right()->Visit(this);
1355 const int number_of_arguments = 2; 1339 const int number_of_arguments = 2;
1356 const Array& no_optional_argument_names = Array::Handle(); 1340 const Array& no_optional_argument_names = Array::Handle();
1357 GenerateCheckedInstanceCalls(node, 1341 GenerateCheckedInstanceCalls(node,
1358 node->left(), 1342 node->left(),
1359 node->id(), 1343 node->id(),
1360 node->token_index(), 1344 node->token_index(),
1361 number_of_arguments, 1345 number_of_arguments,
1362 no_optional_argument_names); 1346 no_optional_argument_names);
1363 if (IsResultNeeded(node)) { 1347 HandleResult(node, EAX);
1364 __ pushl(EAX);
1365 }
1366 return; 1348 return;
1367 } 1349 }
1368 1350
1369 1351
1370 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { 1352 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
1371 if (FLAG_enable_type_checks) { 1353 if (FLAG_enable_type_checks) {
1372 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); 1354 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle());
1373 CodeGenerator::VisitIncrOpLocalNode(node); 1355 CodeGenerator::VisitIncrOpLocalNode(node);
1374 return; 1356 return;
1375 } 1357 }
(...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after
1732 return; 1714 return;
1733 } 1715 }
1734 1716
1735 VisitLoadOne(node->receiver(), EBX); 1717 VisitLoadOne(node->receiver(), EBX);
1736 InlineInstanceGetter(node, 1718 InlineInstanceGetter(node,
1737 node->id(), 1719 node->id(),
1738 node->receiver(), 1720 node->receiver(),
1739 node->field_name(), 1721 node->field_name(),
1740 EBX); 1722 EBX);
1741 // Result is in EAX. 1723 // Result is in EAX.
1742 if (CodeGenerator::IsResultNeeded(node)) { 1724 HandleResult(node, EAX);
1743 __ pushl(EAX);
1744 }
1745 } 1725 }
1746 1726
1747 1727
1748 // Helper struct to pass arguments to 'GenerateInstanceSetter'. 1728 // Helper struct to pass arguments to 'GenerateInstanceSetter'.
1749 struct InstanceSetterArgs { 1729 struct InstanceSetterArgs {
1750 const Class* cls; 1730 const Class* cls;
1751 const Function* target; 1731 const Function* target;
1752 const String* field_name; 1732 const String* field_name;
1753 Register recv_reg; 1733 Register recv_reg;
1754 Register value_reg; 1734 Register value_reg;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1879 return; 1859 return;
1880 } 1860 }
1881 // Value in EAX survives and will be stored on stack if result is needed. 1861 // Value in EAX survives and will be stored on stack if result is needed.
1882 InlineInstanceSetter(node, 1862 InlineInstanceSetter(node,
1883 node->id(), 1863 node->id(),
1884 node->receiver(), 1864 node->receiver(),
1885 node->field_name(), 1865 node->field_name(),
1886 EDX, 1866 EDX,
1887 EAX); 1867 EAX);
1888 1868
1889 if (CodeGenerator::IsResultNeeded(node)) { 1869 HandleResult(node, EAX);
1890 __ pushl(EAX);
1891 }
1892 } 1870 }
1893 1871
1894 1872
1895 // Return false if condition is not supported. 1873 // Return false if condition is not supported.
1896 static bool SupportedTokenKindToSmiCondition(Token::Kind kind, 1874 static bool SupportedTokenKindToSmiCondition(Token::Kind kind,
1897 Condition* condition) { 1875 Condition* condition) {
1898 switch (kind) { 1876 switch (kind) {
1899 case Token::kEQ: 1877 case Token::kEQ:
1900 *condition = EQUAL; 1878 *condition = EQUAL;
1901 return true; 1879 return true;
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 2344
2367 // Type check of index. 2345 // Type check of index.
2368 __ testl(EDX, Immediate(kSmiTagMask)); 2346 __ testl(EDX, Immediate(kSmiTagMask));
2369 __ j(NOT_ZERO, deopt_blob->label()); 2347 __ j(NOT_ZERO, deopt_blob->label());
2370 // Range check. 2348 // Range check.
2371 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); 2349 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset()));
2372 __ j(ABOVE_EQUAL, deopt_blob->label()); 2350 __ j(ABOVE_EQUAL, deopt_blob->label());
2373 // Note that EDX is Smi, i.e, times 2. 2351 // Note that EDX is Smi, i.e, times 2.
2374 ASSERT(kSmiTagShift == 1); 2352 ASSERT(kSmiTagShift == 1);
2375 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); 2353 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray)));
2376 if (CodeGenerator::IsResultNeeded(node)) { 2354 HandleResult(node, EAX);
2377 __ pushl(EAX);
2378 }
2379 TraceOpt(node, kMessage); 2355 TraceOpt(node, kMessage);
2380 return; 2356 return;
2381 } 2357 }
2382 2358
2383 const String& growable_object_array_class_name = String::Handle( 2359 const String& growable_object_array_class_name = String::Handle(
2384 String::NewSymbol(kGrowableArrayClassName)); 2360 String::NewSymbol(kGrowableArrayClassName));
2385 const Class& growable_array_class = Class::ZoneHandle( 2361 const Class& growable_array_class = Class::ZoneHandle(
2386 Library::Handle(Library::CoreImplLibrary()). 2362 Library::Handle(Library::CoreImplLibrary()).
2387 LookupClass(growable_object_array_class_name)); 2363 LookupClass(growable_object_array_class_name));
2388 ASSERT(!growable_array_class.IsNull()); 2364 ASSERT(!growable_array_class.IsNull());
(...skipping 18 matching lines...) Expand all
2407 __ movl(EBX, FieldAddress(EDX, Object::class_offset())); 2383 __ movl(EBX, FieldAddress(EDX, Object::class_offset()));
2408 __ CompareObject(EBX, growable_array_class); 2384 __ CompareObject(EBX, growable_array_class);
2409 __ j(NOT_EQUAL, deopt_blob->label()); // Array is not GrowableObjectArray. 2385 __ j(NOT_EQUAL, deopt_blob->label()); // Array is not GrowableObjectArray.
2410 // Range check: deoptimize if out of bounds. 2386 // Range check: deoptimize if out of bounds.
2411 __ cmpl(EAX, FieldAddress(EDX, length_offset)); 2387 __ cmpl(EAX, FieldAddress(EDX, length_offset));
2412 __ j(ABOVE_EQUAL, deopt_blob->label()); 2388 __ j(ABOVE_EQUAL, deopt_blob->label());
2413 __ movl(EDX, FieldAddress(EDX, array_offset)); // backingArray. 2389 __ movl(EDX, FieldAddress(EDX, array_offset)); // backingArray.
2414 // Note that EAX is Smi, i.e, times 2. 2390 // Note that EAX is Smi, i.e, times 2.
2415 ASSERT(kSmiTagShift == 1); 2391 ASSERT(kSmiTagShift == 1);
2416 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); 2392 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray)));
2417 if (CodeGenerator::IsResultNeeded(node)) { 2393 HandleResult(node, EAX);
2418 __ pushl(EAX);
2419 }
2420 return; 2394 return;
2421 } else { 2395 } else {
2422 // E.g., HashMap. 2396 // E.g., HashMap.
2423 TraceNotOpt(node, kMessage); 2397 TraceNotOpt(node, kMessage);
2424 } 2398 }
2425 CodeGenerator::VisitLoadIndexedNode(node); 2399 CodeGenerator::VisitLoadIndexedNode(node);
2426 } 2400 }
2427 2401
2428 2402
2429 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { 2403 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) {
(...skipping 30 matching lines...) Expand all
2460 // Check class of index. 2434 // Check class of index.
2461 __ testl(EBX, Immediate(kSmiTagMask)); 2435 __ testl(EBX, Immediate(kSmiTagMask));
2462 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. 2436 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt.
2463 // Range check. 2437 // Range check.
2464 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); 2438 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset()));
2465 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. 2439 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt.
2466 ASSERT(kSmiTagShift == 1); 2440 ASSERT(kSmiTagShift == 1);
2467 __ StoreIntoObject(EAX, 2441 __ StoreIntoObject(EAX,
2468 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), 2442 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)),
2469 ECX); 2443 ECX);
2470 if (CodeGenerator::IsResultNeeded(node)) { 2444 HandleResult(node, ECX);
2471 __ pushl(ECX);
2472 }
2473 return; 2445 return;
2474 } 2446 }
2475 2447
2476 const String& growable_object_array_class_name = String::Handle( 2448 const String& growable_object_array_class_name = String::Handle(
2477 String::NewSymbol(kGrowableArrayClassName)); 2449 String::NewSymbol(kGrowableArrayClassName));
2478 const Class& growable_array_class = Class::ZoneHandle( 2450 const Class& growable_array_class = Class::ZoneHandle(
2479 Library::Handle(Library::CoreImplLibrary()). 2451 Library::Handle(Library::CoreImplLibrary()).
2480 LookupClass(growable_object_array_class_name)); 2452 LookupClass(growable_object_array_class_name));
2481 ASSERT(!growable_array_class.IsNull()); 2453 ASSERT(!growable_array_class.IsNull());
2482 if (AtIdNodeHasReceiverClass(node, node->id(), growable_array_class)) { 2454 if (AtIdNodeHasReceiverClass(node, node->id(), growable_array_class)) {
(...skipping 21 matching lines...) Expand all
2504 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. 2476 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt.
2505 // Range check: deoptimize if out of bounds. 2477 // Range check: deoptimize if out of bounds.
2506 __ cmpl(EBX, FieldAddress(EAX, length_offset)); 2478 __ cmpl(EBX, FieldAddress(EAX, length_offset));
2507 __ j(ABOVE_EQUAL, deopt_blob->label()); 2479 __ j(ABOVE_EQUAL, deopt_blob->label());
2508 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray. 2480 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray.
2509 // Note that EAX is Smi, i.e, times 2. 2481 // Note that EAX is Smi, i.e, times 2.
2510 ASSERT(kSmiTagShift == 1); 2482 ASSERT(kSmiTagShift == 1);
2511 __ StoreIntoObject(EDX, 2483 __ StoreIntoObject(EDX,
2512 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)), 2484 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)),
2513 ECX); 2485 ECX);
2514 if (CodeGenerator::IsResultNeeded(node)) { 2486 HandleResult(node, ECX);
2515 __ pushl(ECX);
2516 }
2517 return; 2487 return;
2518 } 2488 }
2519 node->index_expr()->Visit(this); 2489 node->index_expr()->Visit(this);
2520 node->value()->Visit(this); 2490 node->value()->Visit(this);
2521 GenerateStoreIndexed(node->id(), node->token_index(), IsResultNeeded(node)); 2491 GenerateStoreIndexed(node->id(), node->token_index(), IsResultNeeded(node));
2522 } 2492 }
2523 2493
2524 2494
2525 void OptimizingCodeGenerator::VisitForNode(ForNode* node) { 2495 void OptimizingCodeGenerator::VisitForNode(ForNode* node) {
2526 if (FLAG_enable_type_checks) { 2496 if (FLAG_enable_type_checks) {
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
2849 // Instance call is inlined. 2819 // Instance call is inlined.
2850 } else { 2820 } else {
2851 GenerateCheckedInstanceCalls(node, 2821 GenerateCheckedInstanceCalls(node,
2852 node->receiver(), 2822 node->receiver(),
2853 node->id(), 2823 node->id(),
2854 node->token_index(), 2824 node->token_index(),
2855 number_of_arguments, 2825 number_of_arguments,
2856 node->arguments()->names()); 2826 node->arguments()->names());
2857 } 2827 }
2858 // Result is in EAX. 2828 // Result is in EAX.
2859 if (IsResultNeeded(node)) { 2829 HandleResult(node, EAX);
2860 __ pushl(EAX);
2861 }
2862 } 2830 }
2863 2831
2864 2832
2865 // Returns true if an instance call was replaced with its intrinsic. 2833 // Returns true if an instance call was replaced with its intrinsic.
2866 // Returns result in EAX. 2834 // Returns result in EAX.
2867 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) { 2835 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) {
2868 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node); 2836 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
2869 if ((classes != NULL) && (classes->length() == 1)) { 2837 if ((classes != NULL) && (classes->length() == 1)) {
2870 const int num_arguments = node->arguments()->length() + 1; 2838 const int num_arguments = node->arguments()->length() + 1;
2871 const int num_named_arguments = node->arguments()->names().IsNull() ? 2839 const int num_named_arguments = node->arguments()->names().IsNull() ?
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
2949 if (TryInlineStaticCall(node)) { 2917 if (TryInlineStaticCall(node)) {
2950 // Static method is inlined, result is in EAX. 2918 // Static method is inlined, result is in EAX.
2951 } else { 2919 } else {
2952 __ LoadObject(ECX, node->function()); 2920 __ LoadObject(ECX, node->function());
2953 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), 2921 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(),
2954 node->arguments()->names())); 2922 node->arguments()->names()));
2955 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel()); 2923 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel());
2956 } 2924 }
2957 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); 2925 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize));
2958 // Result is in EAX. 2926 // Result is in EAX.
2959 if (IsResultNeeded(node)) { 2927 HandleResult(node, EAX);
2960 __ pushl(EAX);
2961 }
2962 } 2928 }
2963 2929
2964 2930
2965 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) { 2931 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) {
2966 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) { 2932 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) {
2967 CodeGenerator::VisitReturnNode(node); 2933 CodeGenerator::VisitReturnNode(node);
2968 return; 2934 return;
2969 } 2935 }
2970 ASSERT(!IsResultNeeded(node)); 2936 ASSERT(!IsResultNeeded(node));
2971 ASSERT(node->value() != NULL); 2937 ASSERT(node->value() != NULL);
(...skipping 29 matching lines...) Expand all
3001 2967
3002 2968
3003 void OptimizingCodeGenerator::VisitStoreInstanceFieldNode( 2969 void OptimizingCodeGenerator::VisitStoreInstanceFieldNode(
3004 StoreInstanceFieldNode* node) { 2970 StoreInstanceFieldNode* node) {
3005 if (FLAG_enable_type_checks) { 2971 if (FLAG_enable_type_checks) {
3006 CodeGenerator::VisitStoreInstanceFieldNode(node); 2972 CodeGenerator::VisitStoreInstanceFieldNode(node);
3007 return; 2973 return;
3008 } 2974 }
3009 VisitLoadTwo(node->instance(), node->value(), EDX, EAX); 2975 VisitLoadTwo(node->instance(), node->value(), EDX, EAX);
3010 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); 2976 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX);
3011 if (IsResultNeeded(node)) { 2977 // The result is the input value.
3012 // The result is the input value. 2978 HandleResult(node, EAX);
3013 __ pushl(EAX);
3014 }
3015 } 2979 }
3016 2980
3017 2981
3018 void OptimizingCodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) { 2982 void OptimizingCodeGenerator::VisitCatchClauseNode(CatchClauseNode* node) {
3019 // TODO(srdjan): Set classes for locals. 2983 // TODO(srdjan): Set classes for locals.
3020 classes_for_locals_->Clear(); 2984 classes_for_locals_->Clear();
3021 CodeGenerator::VisitCatchClauseNode(node); 2985 CodeGenerator::VisitCatchClauseNode(node);
3022 } 2986 }
3023 2987
3024 2988
(...skipping 13 matching lines...) Expand all
3038 if (node->kind() == Token::kNOT) { 3002 if (node->kind() == Token::kNOT) {
3039 // Only a true bool returns false, everything else is true. 3003 // Only a true bool returns false, everything else is true.
3040 CodeGenInfo info(node->operand()); 3004 CodeGenInfo info(node->operand());
3041 VisitLoadOne(node->operand(), EDX); 3005 VisitLoadOne(node->operand(), EDX);
3042 Label done; 3006 Label done;
3043 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True())); 3007 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True()));
3044 __ cmpl(EDX, EAX); 3008 __ cmpl(EDX, EAX);
3045 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 3009 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
3046 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); 3010 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False()));
3047 __ Bind(&done); 3011 __ Bind(&done);
3048 if (CodeGenerator::IsResultNeeded(node)) { 3012 HandleResult(node, EAX);
3049 if (IsResultInEaxRequested(node)) {
3050 node->info()->set_result_returned_in_eax(true);
3051 } else {
3052 __ pushl(EAX);
3053 }
3054 }
3055 return; 3013 return;
3056 } 3014 }
3057 3015
3058 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) { 3016 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) {
3059 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 3017 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
3060 const ICData& ic_data = node->ICDataAtId(node->id()); 3018 const ICData& ic_data = node->ICDataAtId(node->id());
3061 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); 3019 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
3062 GenerateSmiUnaryOp(node); 3020 GenerateSmiUnaryOp(node);
3063 return; 3021 return;
3064 } 3022 }
3065 } 3023 }
3066 if (node->kind() == Token::kSUB) { 3024 if (node->kind() == Token::kSUB) {
3067 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 3025 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) {
3068 const ICData& ic_data = node->ICDataAtId(node->id()); 3026 const ICData& ic_data = node->ICDataAtId(node->id());
3069 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); 3027 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
3070 GenerateDoubleUnaryOp(node); 3028 GenerateDoubleUnaryOp(node);
3071 return; 3029 return;
3072 } 3030 }
3073 } 3031 }
3074 // TODO(srdjan): Implement unary kSUB (negate) Mint. 3032 // TODO(srdjan): Implement unary kSUB (negate) Mint.
3075 CodeGenerator::VisitUnaryOpNode(node); 3033 CodeGenerator::VisitUnaryOpNode(node);
3076 } 3034 }
3077 3035
3078 3036
3079 } // namespace dart 3037 } // namespace dart
3080 3038
3081 #endif // defined TARGET_ARCH_IA32 3039 #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