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

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

Issue 9025025: Propagate more local variable types. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years 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 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 return true; 637 return true;
638 } 638 }
639 } 639 }
640 } 640 }
641 return false; 641 return false;
642 } 642 }
643 643
644 644
645 // Look only at the first class in all check groups. Returns true if all 645 // Look only at the first class in all check groups. Returns true if all
646 // receiver classes are 'cls'. 646 // receiver classes are 'cls'.
647 static bool AtIdNodeHasReceiverClass(AstNode* node, 647 static bool AtIdNodeHasClassAt(AstNode* node,
648 intptr_t id, 648 intptr_t id,
649 const Class& cls) { 649 const Class& cls,
650 intptr_t arg_index) {
650 ASSERT(node != NULL); 651 ASSERT(node != NULL);
651 ASSERT(!cls.IsNull()); 652 ASSERT(!cls.IsNull());
652 const ICData& ic_data = node->ICDataAtId(id); 653 const ICData& ic_data = node->ICDataAtId(id);
653 if (ic_data.NumberOfChecks() == 0) { 654 if (ic_data.NumberOfChecks() == 0) {
654 return false; 655 return false;
655 } 656 }
657 ASSERT(ic_data.NumberOfArgumentsChecked() > arg_index);
656 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 658 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
657 GrowableArray<const Class*> classes; 659 GrowableArray<const Class*> classes;
658 Function& target = Function::Handle(); 660 Function& target = Function::Handle();
659 ic_data.GetCheckAt(i, &classes, &target); 661 ic_data.GetCheckAt(i, &classes, &target);
660 if (classes.is_empty()) { 662 if (classes.is_empty()) {
661 return false; 663 return false;
662 } 664 }
663 if (classes[0]->raw() != cls.raw()) { 665 if (classes[arg_index]->raw() != cls.raw()) {
664 return false; 666 return false;
665 } 667 }
666 } 668 }
667 return true; 669 return true;
668 } 670 }
669 671
670 672
671 // IC data may have only one check, and it has to contain the two classes in 673 // IC data may have only one check, and it has to contain the two classes in
672 // specified order. 674 // specified order.
673 static bool AtIdNodeHasTwoClasses(AstNode* node, 675 static bool AtIdNodeHasTwoClasses(AstNode* node,
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 if (ic_data.NumberOfChecks() == 0) { 841 if (ic_data.NumberOfChecks() == 0) {
840 // No type feedback. 842 // No type feedback.
841 __ jmp(deopt_blob->label()); 843 __ jmp(deopt_blob->label());
842 return; 844 return;
843 } 845 }
844 ASSERT(ic_data.NumberOfChecks() == 1); 846 ASSERT(ic_data.NumberOfChecks() == 1);
845 CheckIfDoubleOrSmi(kOperandRegister, 847 CheckIfDoubleOrSmi(kOperandRegister,
846 kTempRegister, 848 kTempRegister,
847 deopt_blob->label(), 849 deopt_blob->label(),
848 deopt_blob->label()); 850 deopt_blob->label());
851 PropagateBackLocalClass(node->operand(), double_class_);
849 // TODO(srdjan): check if we could reuse a temporary object instead of 852 // TODO(srdjan): check if we could reuse a temporary object instead of
850 // allocating a new one. 853 // allocating a new one.
851 const Code& stub = 854 const Code& stub =
852 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 855 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
853 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 856 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
854 __ pushl(kOperandRegister); 857 __ pushl(kOperandRegister);
855 GenerateCall(node->token_index(), &label); 858 GenerateCall(node->token_index(), &label);
856 ASSERT(kResultRegister == EAX); 859 ASSERT(kResultRegister == EAX);
857 __ popl(kOperandRegister); 860 __ popl(kOperandRegister);
858 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); 861 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset()));
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 (classes[1]->raw() == smi_class_.raw())); 899 (classes[1]->raw() == smi_class_.raw()));
897 CodeGenInfo left_info(node->left()); 900 CodeGenInfo left_info(node->left());
898 CodeGenInfo right_info(node->right()); 901 CodeGenInfo right_info(node->right());
899 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 902 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
900 Label two_smis, call_operator; 903 Label two_smis, call_operator;
901 DeoptimizationBlob* deopt_blob = 904 DeoptimizationBlob* deopt_blob =
902 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp); 905 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp);
903 __ movl(ECX, EAX); // Save if overflow (needs original value). 906 __ movl(ECX, EAX); // Save if overflow (needs original value).
904 907
905 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { 908 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) {
906 if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) { 909 if (!left_info.IsClass(smi_class_)) {
907 // One of the type is not known (statically) to be Smi. Check it. 910 __ testl(EAX, Immediate(kSmiTagMask));
908 Register test_reg = left_info.IsClass(smi_class_) ? EDX : EAX;
909 __ testl(test_reg, Immediate(kSmiTagMask));
910 __ j(NOT_ZERO, deopt_blob->label()); 911 __ j(NOT_ZERO, deopt_blob->label());
912 PropagateBackLocalClass(node->left(), smi_class_);
913 }
914 if (!right_info.IsClass(smi_class_)) {
915 __ testl(EDX, Immediate(kSmiTagMask));
916 __ j(NOT_ZERO, deopt_blob->label());
917 PropagateBackLocalClass(node->right(), smi_class_);
911 } 918 }
912 } else { 919 } else {
913 // Type feedback says both types are Smi, but static type analysis 920 // Type feedback says both types are Smi, but static type analysis
914 // does not know if any of them is Smi, therefore check. 921 // does not know if any of them is Smi, therefore check.
915 __ orl(EAX, EDX); 922 __ orl(EAX, EDX);
916 __ testl(EAX, Immediate(kSmiTagMask)); 923 __ testl(EAX, Immediate(kSmiTagMask));
917 __ j(NOT_ZERO, deopt_blob->label()); 924 __ j(NOT_ZERO, deopt_blob->label());
918 __ movl(EAX, ECX); 925 __ movl(EAX, ECX);
926 PropagateBackLocalClass(node->left(), smi_class_);
927 PropagateBackLocalClass(node->right(), smi_class_);
919 } 928 }
920 if (node->info() != NULL) { 929 if (node->info() != NULL) {
921 node->info()->set_is_class(&smi_class_); 930 node->info()->set_is_class(&smi_class_);
922 } 931 }
923 switch (kind) { 932 switch (kind) {
924 case Token::kADD: { 933 case Token::kADD: {
925 __ addl(EAX, EDX); 934 __ addl(EAX, EDX);
926 __ j(OVERFLOW, deopt_blob->label()); 935 __ j(OVERFLOW, deopt_blob->label());
927 break; 936 break;
928 } 937 }
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 // Conservative approach: 1064 // Conservative approach:
1056 // - true if both nodes are LoadLocalNodes with the same index. 1065 // - true if both nodes are LoadLocalNodes with the same index.
1057 static bool AreNodesOfSameType(AstNode* a, AstNode* b) { 1066 static bool AreNodesOfSameType(AstNode* a, AstNode* b) {
1058 ASSERT((a != NULL) && (b != NULL)); 1067 ASSERT((a != NULL) && (b != NULL));
1059 if (a->IsLoadLocalNode() && b->IsLoadLocalNode()) { 1068 if (a->IsLoadLocalNode() && b->IsLoadLocalNode()) {
1060 return a->AsLoadLocalNode()->local().Equals(b->AsLoadLocalNode()->local()); 1069 return a->AsLoadLocalNode()->local().Equals(b->AsLoadLocalNode()->local());
1061 } 1070 }
1062 return false; 1071 return false;
1063 } 1072 }
1064 1073
1074
1075 // If possible propagate node type back to the local.
1076 void OptimizingCodeGenerator::PropagateBackLocalClass(AstNode* node,
1077 const Class& cls) {
1078 if (node->IsLoadLocalNode()) {
1079 LoadLocalNode* local_node = node->AsLoadLocalNode();
1080 classes_for_locals_->SetLocalType(local_node->local(), cls);
1081 }
1082 }
1083
1084
1065 // 'reg' is not modified, 'temp' is trashed. 1085 // 'reg' is not modified, 'temp' is trashed.
1066 // Fall through if double, jump to 'is_smi' if Smi and 1086 // Fall through if double, jump to 'is_smi' if Smi and
1067 // jump to 'not_double_or_smi' if neither double nor Smi. 1087 // jump to 'not_double_or_smi' if neither double nor Smi.
1068 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg, 1088 void OptimizingCodeGenerator::CheckIfDoubleOrSmi(Register reg,
1069 Register temp, 1089 Register temp,
1070 Label* is_smi, 1090 Label* is_smi,
1071 Label* not_double_or_smi) { 1091 Label* not_double_or_smi) {
1072 __ testl(reg, Immediate(kSmiTagMask)); 1092 __ testl(reg, Immediate(kSmiTagMask));
1073 __ j(ZERO, is_smi); 1093 __ j(ZERO, is_smi);
1074 __ movl(temp, FieldAddress(reg, Object::class_offset())); 1094 __ movl(temp, FieldAddress(reg, Object::class_offset()));
(...skipping 17 matching lines...) Expand all
1092 if ((kind == Token::kADD) || 1112 if ((kind == Token::kADD) ||
1093 (kind == Token::kSUB) || 1113 (kind == Token::kSUB) ||
1094 (kind == Token::kMUL) || 1114 (kind == Token::kMUL) ||
1095 (kind == Token::kDIV)) { 1115 (kind == Token::kDIV)) {
1096 TraceOpt(node, kOptMessage); 1116 TraceOpt(node, kOptMessage);
1097 // All four register below must be different. 1117 // All four register below must be different.
1098 const Register kLeftRegister = EAX; 1118 const Register kLeftRegister = EAX;
1099 const Register kRightRegister = EDX; 1119 const Register kRightRegister = EDX;
1100 const Register kAllocatedRegister = ECX; 1120 const Register kAllocatedRegister = ECX;
1101 const Register kTempRegister = EBX; 1121 const Register kTempRegister = EBX;
1102 CodeGenInfo left_info(node->left()); 1122 CodeGenInfo left_info(node->left()); // Receiver.
1103 CodeGenInfo right_info(node->right()); 1123 CodeGenInfo right_info(node->right());
1104 VisitLoadTwo(node->left(), node->right(), kLeftRegister, kRightRegister); 1124 VisitLoadTwo(node->left(), node->right(), kLeftRegister, kRightRegister);
1105 // First allocate result object or specify an existing object as result. 1125 // First allocate result object or specify an existing object as result.
1106 Register result_register = kNoRegister; 1126 Register result_register = kNoRegister;
1107 if (node->info() == NULL) { 1127 if (node->info() == NULL) {
1108 // Parent node cannot handle a temporary double object, allocate one 1128 // Parent node cannot handle a temporary double object, allocate one
1109 // each time. 1129 // each time.
1110 result_register = kAllocatedRegister; 1130 result_register = kAllocatedRegister;
1111 const Code& stub = 1131 const Code& stub =
1112 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 1132 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
(...skipping 29 matching lines...) Expand all
1142 } 1162 }
1143 1163
1144 if (receiver_can_be_smi) { 1164 if (receiver_can_be_smi) {
1145 // Only deoptimize if both argument are Smi. 1165 // Only deoptimize if both argument are Smi.
1146 __ movl(kTempRegister, kLeftRegister); 1166 __ movl(kTempRegister, kLeftRegister);
1147 __ orl(kTempRegister, kRightRegister); 1167 __ orl(kTempRegister, kRightRegister);
1148 __ testl(kTempRegister, Immediate(kSmiTagMask)); 1168 __ testl(kTempRegister, Immediate(kSmiTagMask));
1149 __ j(ZERO, deopt_lbl); 1169 __ j(ZERO, deopt_lbl);
1150 } 1170 }
1151 1171
1152 bool nodes_of_same_type = AreNodesOfSameType(node->left(), node->right()); 1172 bool args_of_same_type = AreNodesOfSameType(node->left(), node->right());
1153 if (!left_info.IsClass(double_class_)) { 1173 if (left_info.IsClass(double_class_)) {
1154 Label is_smi, done;
1155 CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, &is_smi, deopt_lbl);
1156 // Fall through for double. Jump to 'is_smi' if double, jump to
1157 // 'deopt' if neither smi nor double.
1158 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset())); 1174 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
1159 __ jmp(&done);
1160 __ Bind(&is_smi);
1161 __ SmiUntag(kLeftRegister);
1162 __ cvtsi2sd(XMM0, kLeftRegister);
1163 __ Bind(&done);
1164 } else { 1175 } else {
1165 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset())); 1176 if (receiver_can_be_smi) {
1177 Label is_smi, done;
1178 CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, &is_smi, deopt_lbl);
1179 // Fall through for double. Jump to 'is_smi' if double, jump to
1180 // 'deopt' if neither smi nor double.
1181 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
1182 __ jmp(&done);
1183 __ Bind(&is_smi);
1184 __ SmiUntag(kLeftRegister);
1185 __ cvtsi2sd(XMM0, kLeftRegister);
1186 __ Bind(&done);
1187 } else {
1188 CheckIfDoubleOrSmi(kLeftRegister, kTempRegister, deopt_lbl, deopt_lbl);
1189 __ movsd(XMM0, FieldAddress(kLeftRegister, Double::value_offset()));
1190 PropagateBackLocalClass(node->left(), double_class_);
1191 }
1166 } 1192 }
1167 if (!right_info.IsClass(double_class_) && !nodes_of_same_type) { 1193
1168 Label is_smi, done; 1194 const bool right_must_be_double =
1169 CheckIfDoubleOrSmi(kRightRegister, kTempRegister, &is_smi, deopt_lbl); 1195 AtIdNodeHasClassAt(node, node->id(), double_class_, 1);
1170 // Fall through for double. Jump to 'is_smi' if double, jump to 1196
1171 // 'deopt' if neither smi nor double. 1197 // If arguments are of same type (e.g., same local), then the test of left
1198 // argument was sufficient.
1199 if (right_info.IsClass(double_class_) || args_of_same_type) {
1172 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset())); 1200 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
1173 __ jmp(&done); 1201 if (!right_info.IsClass(double_class_)) {
1174 __ Bind(&is_smi); 1202 PropagateBackLocalClass(node->right(), double_class_);
1175 __ SmiUntag(kRightRegister); 1203 }
1176 __ cvtsi2sd(XMM1, kRightRegister);
1177 __ Bind(&done);
1178 } else { 1204 } else {
1179 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset())); 1205 if (right_must_be_double) {
1206 CheckIfDoubleOrSmi(kRightRegister, kTempRegister, deopt_lbl, deopt_lbl);
1207 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
1208 PropagateBackLocalClass(node->right(), double_class_);
1209 } else {
1210 Label is_smi, done;
1211 CheckIfDoubleOrSmi(kRightRegister, kTempRegister, &is_smi, deopt_lbl);
1212 // Fall through for double. Jump to 'is_smi' if double, jump to
1213 // 'deopt' if neither smi nor double.
1214 __ movsd(XMM1, FieldAddress(kRightRegister, Double::value_offset()));
1215 __ jmp(&done);
1216 __ Bind(&is_smi);
1217 __ SmiUntag(kRightRegister);
1218 __ cvtsi2sd(XMM1, kRightRegister);
1219 __ Bind(&done);
1220 }
1180 } 1221 }
1181 1222
1182 switch (kind) { 1223 switch (kind) {
1183 case Token::kADD: __ addsd(XMM0, XMM1); break; 1224 case Token::kADD: __ addsd(XMM0, XMM1); break;
1184 case Token::kSUB: __ subsd(XMM0, XMM1); break; 1225 case Token::kSUB: __ subsd(XMM0, XMM1); break;
1185 case Token::kMUL: __ mulsd(XMM0, XMM1); break; 1226 case Token::kMUL: __ mulsd(XMM0, XMM1); break;
1186 case Token::kDIV: __ divsd(XMM0, XMM1); break; 1227 case Token::kDIV: __ divsd(XMM0, XMM1); break;
1187 default: UNREACHABLE(); 1228 default: UNREACHABLE();
1188 } 1229 }
1189 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0); 1230 __ movsd(FieldAddress(result_register, Double::value_offset()), XMM0);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1294 1335
1295 const ICData& ic_data = node->ICDataAtId(node->id()); 1336 const ICData& ic_data = node->ICDataAtId(node->id());
1296 if (ic_data.NumberOfChecks() == 0) { 1337 if (ic_data.NumberOfChecks() == 0) {
1297 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 1338 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
1298 DeoptimizationBlob* deopt_blob = 1339 DeoptimizationBlob* deopt_blob =
1299 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback); 1340 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback);
1300 __ jmp(deopt_blob->label()); 1341 __ jmp(deopt_blob->label());
1301 return; 1342 return;
1302 } 1343 }
1303 1344
1345 ASSERT(ic_data.NumberOfArgumentsChecked() == 2);
1346
1304 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) { 1347 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) {
1305 GenerateSmiBinaryOp(node); 1348 GenerateSmiBinaryOp(node);
1306 return; 1349 return;
1307 } 1350 }
1308 1351
1309 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 1352 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) {
1310 const bool receiver_can_be_smi = false; 1353 const bool receiver_can_be_smi = false;
1311 GenerateDoubleBinaryOp(node, receiver_can_be_smi); 1354 GenerateDoubleBinaryOp(node, receiver_can_be_smi);
1312 return; 1355 return;
1313 } 1356 }
1314 1357
1315 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, double_class_)) { 1358 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, double_class_)) {
1316 const bool receiver_can_be_smi = true; 1359 const bool receiver_can_be_smi = true;
1317 GenerateDoubleBinaryOp(node, receiver_can_be_smi); 1360 GenerateDoubleBinaryOp(node, receiver_can_be_smi);
1318 return; 1361 return;
1319 } 1362 }
1320 1363
1321 const Class& mint_class = 1364 const Class& mint_class =
1322 Class::Handle(Isolate::Current()->object_store()->mint_class()); 1365 Class::Handle(Isolate::Current()->object_store()->mint_class());
1323 if (AtIdNodeHasReceiverClass(node, node->id(), mint_class)) { 1366 if (AtIdNodeHasClassAt(node, node->id(), mint_class, 0)) {
1324 GenerateMintBinaryOp(node, false); 1367 GenerateMintBinaryOp(node, false);
1325 return; 1368 return;
1326 } 1369 }
1327 1370
1328 if (NodeHasBothReceiverClasses(node, smi_class_, mint_class)) { 1371 if (NodeHasBothReceiverClasses(node, smi_class_, mint_class)) {
1329 GenerateMintBinaryOp(node, true); 1372 GenerateMintBinaryOp(node, true);
1330 return; 1373 return;
1331 } 1374 }
1332 1375
1333 // TODO(srdjan): Implement "+" for Strings. 1376 // TODO(srdjan): Implement "+" for Strings.
(...skipping 23 matching lines...) Expand all
1357 } 1400 }
1358 const ICData& ic_data = node->ICDataAtId(node->id()); 1401 const ICData& ic_data = node->ICDataAtId(node->id());
1359 if (ic_data.NumberOfChecks() == 0) { 1402 if (ic_data.NumberOfChecks() == 0) {
1360 DeoptimizationBlob* deopt_blob = 1403 DeoptimizationBlob* deopt_blob =
1361 AddDeoptimizationBlob(node, kDeoptNoTypeFeedback); 1404 AddDeoptimizationBlob(node, kDeoptNoTypeFeedback);
1362 __ jmp(deopt_blob->label()); 1405 __ jmp(deopt_blob->label());
1363 return; 1406 return;
1364 } 1407 }
1365 const char* kOptMessage = "Inlines IncrOpLocal"; 1408 const char* kOptMessage = "Inlines IncrOpLocal";
1366 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); 1409 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR));
1367 if (!AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 1410 if (!AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) {
1368 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); 1411 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle());
1369 TraceNotOpt(node, kOptMessage); 1412 TraceNotOpt(node, kOptMessage);
1370 CodeGenerator::VisitIncrOpLocalNode(node); 1413 CodeGenerator::VisitIncrOpLocalNode(node);
1371 return; 1414 return;
1372 } 1415 }
1373 TraceOpt(node, kOptMessage); 1416 TraceOpt(node, kOptMessage);
1374 1417
1375 GenerateLoadVariable(EAX, node->local()); 1418 GenerateLoadVariable(EAX, node->local());
1376 if (!node->prefix() && IsResultNeeded(node)) { 1419 if (!node->prefix() && IsResultNeeded(node)) {
1377 // Preserve as result. 1420 // Preserve as result.
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1453 node->getter_id(), 1496 node->getter_id(),
1454 node->receiver(), 1497 node->receiver(),
1455 node->field_name(), 1498 node->field_name(),
1456 EBX); 1499 EBX);
1457 // result is in EAX. 1500 // result is in EAX.
1458 __ popl(EDX); // Get receiver. 1501 __ popl(EDX); // Get receiver.
1459 const bool return_original_value = !node->prefix() && IsResultNeeded(node); 1502 const bool return_original_value = !node->prefix() && IsResultNeeded(node);
1460 const Immediate one_value = Immediate(Smi::RawValue(1)); 1503 const Immediate one_value = Immediate(Smi::RawValue(1));
1461 // EAX: Value. 1504 // EAX: Value.
1462 // EDX: Receiver. 1505 // EDX: Receiver.
1463 if (AtIdNodeHasReceiverClass(node, node->operator_id(), smi_class_)) { 1506 if (AtIdNodeHasClassAt(node, node->operator_id(), smi_class_, 0)) {
1464 // Deoptimization point for this node is after receiver has been 1507 // Deoptimization point for this node is after receiver has been
1465 // pushed twice on stack and before the getter (above) was executed. 1508 // pushed twice on stack and before the getter (above) was executed.
1466 DeoptimizationBlob* deopt_blob = 1509 DeoptimizationBlob* deopt_blob =
1467 AddDeoptimizationBlob(node, EDX, EDX, kDeoptIncrInstanceOneClass); 1510 AddDeoptimizationBlob(node, EDX, EDX, kDeoptIncrInstanceOneClass);
1468 if (return_original_value) { 1511 if (return_original_value) {
1469 // Preserve pre increment result. 1512 // Preserve pre increment result.
1470 __ movl(ECX, EAX); 1513 __ movl(ECX, EAX);
1471 } 1514 }
1472 __ testl(EAX, Immediate(kSmiTagMask)); 1515 __ testl(EAX, Immediate(kSmiTagMask));
1473 __ j(NOT_ZERO, deopt_blob->label()); 1516 __ j(NOT_ZERO, deopt_blob->label());
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
2211 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 2254 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
2212 CodeGenInfo left_info(node->left()); 2255 CodeGenInfo left_info(node->left());
2213 CodeGenInfo right_info(node->right()); 2256 CodeGenInfo right_info(node->right());
2214 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 2257 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
2215 DeoptimizationBlob* deopt_blob = NULL; 2258 DeoptimizationBlob* deopt_blob = NULL;
2216 if (!left_info.IsClass(double_class_) || !right_info.IsClass(double_class_)) { 2259 if (!left_info.IsClass(double_class_) || !right_info.IsClass(double_class_)) {
2217 deopt_blob = AddDeoptimizationBlob(node, EAX, EDX, kDeoptDoubleComparison); 2260 deopt_blob = AddDeoptimizationBlob(node, EAX, EDX, kDeoptDoubleComparison);
2218 } 2261 }
2219 if (!left_info.IsClass(double_class_)) { 2262 if (!left_info.IsClass(double_class_)) {
2220 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label()); 2263 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label());
2264 PropagateBackLocalClass(node->left(), double_class_);
2221 } 2265 }
2222 if (!right_info.IsClass(double_class_)) { 2266 if (!right_info.IsClass(double_class_)) {
2223 CheckIfDoubleOrSmi(EDX, EBX, deopt_blob->label(), deopt_blob->label()); 2267 CheckIfDoubleOrSmi(EDX, EBX, deopt_blob->label(), deopt_blob->label());
2268 PropagateBackLocalClass(node->right(), double_class_);
2224 } 2269 }
2225 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 2270 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
2226 __ movsd(XMM1, FieldAddress(EDX, Double::value_offset())); 2271 __ movsd(XMM1, FieldAddress(EDX, Double::value_offset()));
2227 __ comisd(XMM0, XMM1); 2272 __ comisd(XMM0, XMM1);
2228 if (NodeInfoHasLabels(node)) { 2273 if (NodeInfoHasLabels(node)) {
2229 __ j(PARITY_EVEN, node->info()->false_label()); // NaN -> false; 2274 __ j(PARITY_EVEN, node->info()->false_label()); // NaN -> false;
2230 GenerateConditionalJumps(*(node->info()), true_condition); 2275 GenerateConditionalJumps(*(node->info()), true_condition);
2231 node->info()->set_labels_used(true); 2276 node->info()->set_labels_used(true);
2232 } else { 2277 } else {
2233 Label is_false, is_true, done; 2278 Label is_false, is_true, done;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2288 GenerateInstanceOf(node->id(), 2333 GenerateInstanceOf(node->id(),
2289 node->token_index(), 2334 node->token_index(),
2290 node->right()->AsTypeNode()->type(), 2335 node->right()->AsTypeNode()->type(),
2291 (node->kind() == Token::kISNOT)); 2336 (node->kind() == Token::kISNOT));
2292 if (!IsResultNeeded(node)) { 2337 if (!IsResultNeeded(node)) {
2293 __ popl(EAX); // Pop the result of the instanceof operation. 2338 __ popl(EAX); // Pop the result of the instanceof operation.
2294 } 2339 }
2295 return; 2340 return;
2296 } 2341 }
2297 2342
2298 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 2343 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) {
2299 if (GenerateSmiComparison(node)) { 2344 if (GenerateSmiComparison(node)) {
2300 // The comparison was handled, code was emitted. 2345 // The comparison was handled, code was emitted.
2301 return; 2346 return;
2302 } 2347 }
2303 // Fall through if condition is not supported. 2348 // Fall through if condition is not supported.
2304 } else if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 2349 } else if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) {
2305 // Double comparison 2350 // Double comparison
2306 if (GenerateDoubleComparison(node)) { 2351 if (GenerateDoubleComparison(node)) {
2307 return; 2352 return;
2308 } 2353 }
2309 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { 2354 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
2310 // Equality, not-equality comparison of any other type. 2355 // Equality, not-equality comparison of any other type.
2311 if (GenerateEqualityComparison(node)) { 2356 if (GenerateEqualityComparison(node)) {
2312 return; 2357 return;
2313 } 2358 }
2314 } 2359 }
2315 2360
2316 // Fall through here if a comparison was not implemented. 2361 // Fall through here if a comparison was not implemented.
2317 // TODO(srdjan): Implement for Strings. 2362 // TODO(srdjan): Implement for Strings.
2318 CodeGenerator::VisitComparisonNode(node); 2363 CodeGenerator::VisitComparisonNode(node);
2319 } 2364 }
2320 2365
2321 2366
2322 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { 2367 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) {
2323 const char* kMessage = "Inline indexed access"; 2368 const char* kMessage = "Inline indexed access";
2324 ObjectStore* object_store = Isolate::Current()->object_store(); 2369 ObjectStore* object_store = Isolate::Current()->object_store();
2325 const Class& object_array_class = 2370 const Class& object_array_class =
2326 Class::ZoneHandle(object_store->array_class()); 2371 Class::ZoneHandle(object_store->array_class());
2327 const Class& immutable_object_array_class = 2372 const Class& immutable_object_array_class =
2328 Class::ZoneHandle(object_store->immutable_array_class()); 2373 Class::ZoneHandle(object_store->immutable_array_class());
2329 if (AtIdNodeHasReceiverClass(node, node->id(), object_array_class) || 2374 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ||
2330 AtIdNodeHasReceiverClass(node, node->id(), 2375 AtIdNodeHasClassAt(node, node->id(),
2331 immutable_object_array_class)) { 2376 immutable_object_array_class, 0)) {
2332 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); 2377 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX);
2333 DeoptimizationBlob* deopt_blob = 2378 DeoptimizationBlob* deopt_blob =
2334 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); 2379 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray);
2335 const Class& test_class = 2380 const Class& test_class =
2336 AtIdNodeHasReceiverClass(node, node->id(), object_array_class) ? 2381 AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ?
2337 object_array_class : immutable_object_array_class; 2382 object_array_class : immutable_object_array_class;
2338 // Type checks of array. 2383 // Type checks of array.
2339 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. 2384 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi.
2340 __ j(ZERO, deopt_blob->label()); 2385 __ j(ZERO, deopt_blob->label());
2341 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); 2386 __ movl(EAX, FieldAddress(EBX, Object::class_offset()));
2342 __ CompareObject(EAX, test_class); 2387 __ CompareObject(EAX, test_class);
2343 __ j(NOT_EQUAL, deopt_blob->label()); 2388 __ j(NOT_EQUAL, deopt_blob->label());
2344 2389
2345 // Type check of index. 2390 // Type check of index.
2346 __ testl(EDX, Immediate(kSmiTagMask)); 2391 __ testl(EDX, Immediate(kSmiTagMask));
2347 __ j(NOT_ZERO, deopt_blob->label()); 2392 __ j(NOT_ZERO, deopt_blob->label());
2348 // Range check. 2393 // Range check.
2349 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); 2394 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset()));
2350 __ j(ABOVE_EQUAL, deopt_blob->label()); 2395 __ j(ABOVE_EQUAL, deopt_blob->label());
2351 // Note that EDX is Smi, i.e, times 2. 2396 // Note that EDX is Smi, i.e, times 2.
2352 ASSERT(kSmiTagShift == 1); 2397 ASSERT(kSmiTagShift == 1);
2353 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); 2398 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray)));
2354 HandleResult(node, EAX); 2399 HandleResult(node, EAX);
2355 TraceOpt(node, kMessage); 2400 TraceOpt(node, kMessage);
2356 return; 2401 return;
2357 } 2402 }
2358 2403
2359 const String& growable_object_array_class_name = String::Handle( 2404 const String& growable_object_array_class_name = String::Handle(
2360 String::NewSymbol(kGrowableArrayClassName)); 2405 String::NewSymbol(kGrowableArrayClassName));
2361 const Class& growable_array_class = Class::ZoneHandle( 2406 const Class& growable_array_class = Class::ZoneHandle(
2362 Library::Handle(Library::CoreImplLibrary()). 2407 Library::Handle(Library::CoreImplLibrary()).
2363 LookupClass(growable_object_array_class_name)); 2408 LookupClass(growable_object_array_class_name));
2364 ASSERT(!growable_array_class.IsNull()); 2409 ASSERT(!growable_array_class.IsNull());
2365 if (AtIdNodeHasReceiverClass(node, node->id(), growable_array_class)) { 2410 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) {
2366 const String& growable_array_length_field_name = 2411 const String& growable_array_length_field_name =
2367 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); 2412 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName));
2368 const String& growable_array_array_field_name = 2413 const String& growable_array_array_field_name =
2369 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); 2414 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName));
2370 intptr_t length_offset = GetFieldOffset(growable_array_class, 2415 intptr_t length_offset = GetFieldOffset(growable_array_class,
2371 growable_array_length_field_name); 2416 growable_array_length_field_name);
2372 intptr_t array_offset = GetFieldOffset(growable_array_class, 2417 intptr_t array_offset = GetFieldOffset(growable_array_class,
2373 growable_array_array_field_name); 2418 growable_array_array_field_name);
2374 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX); 2419 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX);
2375 DeoptimizationBlob* deopt_blob = 2420 DeoptimizationBlob* deopt_blob =
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2412 Class::ZoneHandle(object_store->array_class()); 2457 Class::ZoneHandle(object_store->array_class());
2413 const ICData& ic_data = node->ICDataAtId(node->id()); 2458 const ICData& ic_data = node->ICDataAtId(node->id());
2414 if (ic_data.NumberOfChecks() == 0) { 2459 if (ic_data.NumberOfChecks() == 0) {
2415 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2460 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2416 DeoptimizationBlob* deopt_blob = 2461 DeoptimizationBlob* deopt_blob =
2417 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); 2462 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback);
2418 __ jmp(deopt_blob->label()); 2463 __ jmp(deopt_blob->label());
2419 return; 2464 return;
2420 } 2465 }
2421 2466
2422 if (AtIdNodeHasReceiverClass(node, node->id(), object_array_class)) { 2467 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) {
2423 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2468 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2424 DeoptimizationBlob* deopt_blob = 2469 DeoptimizationBlob* deopt_blob =
2425 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); 2470 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed);
2426 __ popl(EAX); // array. 2471 __ popl(EAX); // array.
2427 // ECX: value, EBX:index, EAX: array. 2472 // ECX: value, EBX:index, EAX: array.
2428 // Check class of array. 2473 // Check class of array.
2429 __ testl(EAX, Immediate(kSmiTagMask)); 2474 __ testl(EAX, Immediate(kSmiTagMask));
2430 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. 2475 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt.
2431 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); 2476 __ movl(EDX, FieldAddress(EAX, Object::class_offset()));
2432 __ CompareObject(EDX, object_array_class); 2477 __ CompareObject(EDX, object_array_class);
(...skipping 11 matching lines...) Expand all
2444 HandleResult(node, ECX); 2489 HandleResult(node, ECX);
2445 return; 2490 return;
2446 } 2491 }
2447 2492
2448 const String& growable_object_array_class_name = String::Handle( 2493 const String& growable_object_array_class_name = String::Handle(
2449 String::NewSymbol(kGrowableArrayClassName)); 2494 String::NewSymbol(kGrowableArrayClassName));
2450 const Class& growable_array_class = Class::ZoneHandle( 2495 const Class& growable_array_class = Class::ZoneHandle(
2451 Library::Handle(Library::CoreImplLibrary()). 2496 Library::Handle(Library::CoreImplLibrary()).
2452 LookupClass(growable_object_array_class_name)); 2497 LookupClass(growable_object_array_class_name));
2453 ASSERT(!growable_array_class.IsNull()); 2498 ASSERT(!growable_array_class.IsNull());
2454 if (AtIdNodeHasReceiverClass(node, node->id(), growable_array_class)) { 2499 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) {
2455 const String& growable_array_length_field_name = 2500 const String& growable_array_length_field_name =
2456 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); 2501 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName));
2457 const String& growable_array_array_field_name = 2502 const String& growable_array_array_field_name =
2458 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); 2503 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName));
2459 intptr_t length_offset = GetFieldOffset(growable_array_class, 2504 intptr_t length_offset = GetFieldOffset(growable_array_class,
2460 growable_array_length_field_name); 2505 growable_array_length_field_name);
2461 intptr_t array_offset = GetFieldOffset(growable_array_class, 2506 intptr_t array_offset = GetFieldOffset(growable_array_class,
2462 growable_array_array_field_name); 2507 growable_array_array_field_name);
2463 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2508 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2464 DeoptimizationBlob* deopt_blob = 2509 DeoptimizationBlob* deopt_blob =
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
2843 node->function_name(), 2888 node->function_name(),
2844 num_arguments, 2889 num_arguments,
2845 num_named_arguments)); 2890 num_named_arguments));
2846 Recognizer::Kind recognized = Recognizer::RecognizeKind(target); 2891 Recognizer::Kind recognized = Recognizer::RecognizeKind(target);
2847 if (FLAG_trace_optimization) { 2892 if (FLAG_trace_optimization) {
2848 OS::Print("Monomorphic inline candidate: %s -> %s\n", 2893 OS::Print("Monomorphic inline candidate: %s -> %s\n",
2849 target.ToFullyQualifiedCString(), 2894 target.ToFullyQualifiedCString(),
2850 Recognizer::KindToCString(recognized)); 2895 Recognizer::KindToCString(recognized));
2851 } 2896 }
2852 if ((recognized == Recognizer::kIntegerToDouble) && 2897 if ((recognized == Recognizer::kIntegerToDouble) &&
2853 AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 2898 AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) {
2854 // TODO(srdjan): Check if we could use temporary double instead of 2899 // TODO(srdjan): Check if we could use temporary double instead of
2855 // allocating a new object every time. 2900 // allocating a new object every time.
2856 const Code& stub = 2901 const Code& stub =
2857 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 2902 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
2858 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 2903 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
2859 GenerateCall(node->token_index(), &label); 2904 GenerateCall(node->token_index(), &label);
2860 // EAX is double object. 2905 // EAX is double object.
2861 DeoptimizationBlob* deopt_blob = 2906 DeoptimizationBlob* deopt_blob =
2862 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble); 2907 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble);
2863 __ popl(EBX); // Receiver 2908 __ popl(EBX); // Receiver
2864 __ testl(EBX, Immediate(kSmiTagMask)); 2909 __ testl(EBX, Immediate(kSmiTagMask));
2865 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi. 2910 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi.
2866 __ SmiUntag(EBX); 2911 __ SmiUntag(EBX);
2867 __ cvtsi2sd(XMM0, EBX); 2912 __ cvtsi2sd(XMM0, EBX);
2868 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 2913 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
2869 return true; 2914 return true;
2870 } 2915 }
2871 2916
2872 if ((recognized == Recognizer::kDoubleToDouble) && 2917 if ((recognized == Recognizer::kDoubleToDouble) &&
2873 AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 2918 AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) {
2874 DeoptimizationBlob* deopt_blob = 2919 DeoptimizationBlob* deopt_blob =
2875 AddDeoptimizationBlob(node, EAX, kDeoptDoubleToDouble); 2920 AddDeoptimizationBlob(node, EAX, kDeoptDoubleToDouble);
2876 __ popl(EAX); 2921 __ popl(EAX);
2877 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label()); 2922 CheckIfDoubleOrSmi(EAX, EBX, deopt_blob->label(), deopt_blob->label());
2878 return true; 2923 return true;
2879 } 2924 }
2880 } 2925 }
2881 return false; 2926 return false;
2882 } 2927 }
2883 2928
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
3007 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True())); 3052 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True()));
3008 __ cmpl(EDX, EAX); 3053 __ cmpl(EDX, EAX);
3009 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 3054 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
3010 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); 3055 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False()));
3011 __ Bind(&done); 3056 __ Bind(&done);
3012 HandleResult(node, EAX); 3057 HandleResult(node, EAX);
3013 return; 3058 return;
3014 } 3059 }
3015 3060
3016 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) { 3061 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) {
3017 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 3062 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) {
3018 const ICData& ic_data = node->ICDataAtId(node->id()); 3063 const ICData& ic_data = node->ICDataAtId(node->id());
3019 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); 3064 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
3020 GenerateSmiUnaryOp(node); 3065 GenerateSmiUnaryOp(node);
3021 return; 3066 return;
3022 } 3067 }
3023 } 3068 }
3024 if (node->kind() == Token::kSUB) { 3069 if (node->kind() == Token::kSUB) {
3025 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 3070 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) {
3026 const ICData& ic_data = node->ICDataAtId(node->id()); 3071 const ICData& ic_data = node->ICDataAtId(node->id());
3027 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); 3072 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
3028 GenerateDoubleUnaryOp(node); 3073 GenerateDoubleUnaryOp(node);
3029 return; 3074 return;
3030 } 3075 }
3031 } 3076 }
3032 // TODO(srdjan): Implement unary kSUB (negate) Mint. 3077 // TODO(srdjan): Implement unary kSUB (negate) Mint.
3033 CodeGenerator::VisitUnaryOpNode(node); 3078 CodeGenerator::VisitUnaryOpNode(node);
3034 } 3079 }
3035 3080
3036 3081
3037 } // namespace dart 3082 } // namespace dart
3038 3083
3039 #endif // defined TARGET_ARCH_IA32 3084 #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