| OLD | NEW |
| 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 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 result->Add(&cls); | 298 result->Add(&cls); |
| 299 } | 299 } |
| 300 return result; | 300 return result; |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 // Debugging helper function. | 304 // Debugging helper function. |
| 305 void OptimizingCodeGenerator::PrintCollectedClassesAtId(AstNode* node, | 305 void OptimizingCodeGenerator::PrintCollectedClassesAtId(AstNode* node, |
| 306 intptr_t id) { | 306 intptr_t id) { |
| 307 const ICData& ic_data = node->ICDataAtId(id); | 307 const ICData& ic_data = node->ICDataAtId(id); |
| 308 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); | |
| 309 Function& target = Function::Handle(); | |
| 310 Class& cls = Class::Handle(); | |
| 311 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 308 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 312 ic_data.GetOneClassCheckAt(i, &cls, &target); | 309 Function& target = Function::Handle(); |
| 313 OS::Print("- %s -> %s\n", cls.ToCString(), | 310 GrowableArray<const Class*> classes; |
| 314 target.ToFullyQualifiedCString()); | 311 ic_data.GetCheckAt(i, &classes, &target); |
| 312 OS::Print("["); |
| 313 for (intptr_t c = 0; c < classes.length(); c++) { |
| 314 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString()); |
| 315 } |
| 316 OS::Print("] -> %s\n", target.ToFullyQualifiedCString()); |
| 315 } | 317 } |
| 316 } | 318 } |
| 317 | 319 |
| 318 | 320 |
| 319 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { | 321 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { |
| 320 if (FLAG_trace_optimization) { | 322 if (FLAG_trace_optimization) { |
| 321 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); | 323 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); |
| 322 } | 324 } |
| 323 } | 325 } |
| 324 | 326 |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 __ popl(EAX); | 548 __ popl(EAX); |
| 547 } | 549 } |
| 548 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX); | 550 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX); |
| 549 } | 551 } |
| 550 if (IsResultNeeded(node)) { | 552 if (IsResultNeeded(node)) { |
| 551 __ pushl(EAX); | 553 __ pushl(EAX); |
| 552 } | 554 } |
| 553 } | 555 } |
| 554 | 556 |
| 555 | 557 |
| 556 static bool NodeHasBothClasses(AstNode* node, | 558 static bool NodeHasBothReceiverClasses(AstNode* node, |
| 557 const Class& cls1, | 559 const Class& cls1, |
| 558 const Class& cls2) { | 560 const Class& cls2) { |
| 559 ASSERT(node != NULL); | 561 ASSERT(node != NULL); |
| 560 ASSERT(!cls1.IsNull() && !cls2.IsNull()); | 562 ASSERT(!cls1.IsNull() && !cls2.IsNull()); |
| 563 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 564 bool cls1_found = false; |
| 565 bool cls2_found = false; |
| 566 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 567 GrowableArray<const Class*> classes; |
| 568 Function& target = Function::Handle(); |
| 569 ic_data.GetCheckAt(i, &classes, &target); |
| 570 if (!classes.is_empty()) { |
| 571 if (classes[0]->raw() == cls1.raw()) { |
| 572 cls1_found = true; |
| 573 } |
| 574 if (classes[0]->raw() == cls2.raw()) { |
| 575 cls2_found = true; |
| 576 } |
| 577 if (cls1_found && cls2_found) { |
| 578 return true; |
| 579 } |
| 580 } |
| 581 } |
| 582 return false; |
| 583 } |
| 561 | 584 |
| 562 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node); | 585 |
| 563 if ((classes == NULL) || (classes->length() != 2)) { | 586 // Look only at the first class in all check groups. |
| 587 static bool AtIdNodeHasReceiverClass(AstNode* node, |
| 588 intptr_t id, |
| 589 const Class& cls) { |
| 590 ASSERT(node != NULL); |
| 591 ASSERT(!cls.IsNull()); |
| 592 const ICData& ic_data = node->ICDataAtId(id); |
| 593 if (ic_data.NumberOfChecks() == 0) { |
| 564 return false; | 594 return false; |
| 565 } | 595 } |
| 566 if ((cls1.raw() != (*classes)[0]->raw()) && | 596 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 567 (cls1.raw() != (*classes)[1]->raw())) { | 597 GrowableArray<const Class*> classes; |
| 568 return false; | 598 Function& target = Function::Handle(); |
| 569 } | 599 ic_data.GetCheckAt(i, &classes, &target); |
| 570 if ((cls2.raw() != (*classes)[0]->raw()) && | 600 if (classes.is_empty()) { |
| 571 (cls2.raw() != (*classes)[1]->raw())) { | 601 return false; |
| 572 return false; | 602 } |
| 603 if (classes[0]->raw() != cls.raw()) { |
| 604 return false; |
| 605 } |
| 573 } | 606 } |
| 574 return true; | 607 return true; |
| 575 } | 608 } |
| 576 | 609 |
| 577 | 610 |
| 578 static bool AtIdNodeHasOnlyClass(AstNode* node, intptr_t id, const Class& cls) { | 611 static bool AtIdNodeHasOnlyClass(AstNode* node, intptr_t id, const Class& cls) { |
| 579 ASSERT(node != NULL); | 612 ASSERT(node != NULL); |
| 580 ASSERT(!cls.IsNull()); | 613 ASSERT(!cls.IsNull()); |
| 581 const ICData& ic_data = node->ICDataAtId(id); | 614 const ICData& ic_data = node->ICDataAtId(id); |
| 582 if ((ic_data.NumberOfArgumentsChecked() != 1) || | 615 if ((ic_data.NumberOfArgumentsChecked() != 1) || |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 670 const char* kOptMessage = "Inlines BinaryOp for Smi"; | 703 const char* kOptMessage = "Inlines BinaryOp for Smi"; |
| 671 Label done; | 704 Label done; |
| 672 const Token::Kind kind = node->kind(); | 705 const Token::Kind kind = node->kind(); |
| 673 if ((kind == Token::kADD) || | 706 if ((kind == Token::kADD) || |
| 674 (kind == Token::kSUB) || | 707 (kind == Token::kSUB) || |
| 675 (kind == Token::kMUL) || | 708 (kind == Token::kMUL) || |
| 676 (kind == Token::kBIT_AND) || | 709 (kind == Token::kBIT_AND) || |
| 677 (kind == Token::kBIT_OR) || | 710 (kind == Token::kBIT_OR) || |
| 678 (kind == Token::kBIT_XOR)) { | 711 (kind == Token::kBIT_XOR)) { |
| 679 TraceOpt(node, kOptMessage); | 712 TraceOpt(node, kOptMessage); |
| 713 // Check if both arguments are expected to be Smi. |
| 714 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 715 ASSERT(ic_data.NumberOfArgumentsChecked() == 2); |
| 716 ASSERT(ic_data.NumberOfChecks() > 0); |
| 717 Function& target = Function::Handle(); |
| 718 GrowableArray<const Class*> classes; |
| 719 ic_data.GetCheckAt(0, &classes, &target); |
| 720 const bool both_args_expected_smi = |
| 721 (ic_data.NumberOfChecks() == 1) && |
| 722 (classes[0]->raw() == smi_class_.raw()) && |
| 723 (classes[1]->raw() == smi_class_.raw()); |
| 724 |
| 680 CodeGenInfo left_info(node->left()); | 725 CodeGenInfo left_info(node->left()); |
| 681 CodeGenInfo right_info(node->right()); | 726 CodeGenInfo right_info(node->right()); |
| 682 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 727 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 683 Label* overflow_label = NULL; | 728 Label* overflow_label = NULL; |
| 684 Label two_smis, call_operator; | 729 Label two_smis, call_operator; |
| 685 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { | 730 if (both_args_expected_smi) { |
| 686 DeoptimizationBlob* deopt_blob = | 731 DeoptimizationBlob* deopt_blob = |
| 687 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp); | 732 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp); |
| 688 overflow_label = deopt_blob->label(); | 733 overflow_label = deopt_blob->label(); |
| 689 __ movl(ECX, EAX); // Save if overflow (needs original value). | 734 __ movl(ECX, EAX); // Save if overflow (needs original value). |
| 690 if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) { | 735 |
| 691 Register test_reg = left_info.IsClass(smi_class_) ? EDX : EAX; | 736 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { |
| 692 __ testl(test_reg, Immediate(kSmiTagMask)); | 737 if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) { |
| 738 // One of the type is not known (statically) to be Smi. Check it. |
| 739 Register test_reg = left_info.IsClass(smi_class_) ? EDX : EAX; |
| 740 __ testl(test_reg, Immediate(kSmiTagMask)); |
| 741 __ j(NOT_ZERO, deopt_blob->label()); |
| 742 } |
| 743 } else { |
| 744 // Type feedback says both types are Smi, but static type analysis |
| 745 // does not know if any of them is Smi, therefore check. |
| 746 __ orl(EAX, EDX); |
| 747 __ testl(EAX, Immediate(kSmiTagMask)); |
| 693 __ j(NOT_ZERO, deopt_blob->label()); | 748 __ j(NOT_ZERO, deopt_blob->label()); |
| 749 __ movl(EAX, ECX); |
| 694 } | 750 } |
| 695 if (node->info() != NULL) { | 751 if (node->info() != NULL) { |
| 696 node->info()->set_is_class(&smi_class_); | 752 node->info()->set_is_class(&smi_class_); |
| 697 } | 753 } |
| 698 } else { | 754 } else { |
| 699 overflow_label = &call_operator; | 755 overflow_label = &call_operator; |
| 700 __ movl(ECX, EAX); | 756 __ movl(ECX, EAX); |
| 701 __ orl(EAX, EDX); | 757 __ orl(EAX, EDX); |
| 702 __ testl(EAX, Immediate(kSmiTagMask)); | 758 __ testl(EAX, Immediate(kSmiTagMask)); |
| 703 __ j(ZERO, &two_smis, Assembler::kNearJump); | 759 __ j(ZERO, &two_smis, Assembler::kNearJump); |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1053 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { | 1109 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { |
| 1054 if (FLAG_enable_type_checks) { | 1110 if (FLAG_enable_type_checks) { |
| 1055 CodeGenerator::VisitBinaryOpNode(node); | 1111 CodeGenerator::VisitBinaryOpNode(node); |
| 1056 return; | 1112 return; |
| 1057 } | 1113 } |
| 1058 GenerateLogicalBinaryOp(node); | 1114 GenerateLogicalBinaryOp(node); |
| 1059 return; | 1115 return; |
| 1060 } | 1116 } |
| 1061 | 1117 |
| 1062 ObjectStore* object_store = Isolate::Current()->object_store(); | 1118 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 1063 if (AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) { | 1119 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { |
| 1064 GenerateSmiBinaryOp(node); | 1120 GenerateSmiBinaryOp(node); |
| 1065 return; | 1121 return; |
| 1066 } | 1122 } |
| 1067 | 1123 |
| 1068 if (AtIdNodeHasOnlyClass(node, node->id(), double_class_)) { | 1124 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { |
| 1069 GenerateDoubleBinaryOp(node); | 1125 GenerateDoubleBinaryOp(node); |
| 1070 return; | 1126 return; |
| 1071 } | 1127 } |
| 1072 | 1128 |
| 1073 if (AtIdNodeHasOnlyClass(node, | 1129 if (AtIdNodeHasReceiverClass(node, |
| 1074 node->id(), | 1130 node->id(), |
| 1075 Class::Handle(object_store->mint_class()))) { | 1131 Class::Handle(object_store->mint_class()))) { |
| 1076 GenerateMintBinaryOp(node, false); | 1132 GenerateMintBinaryOp(node, false); |
| 1077 return; | 1133 return; |
| 1078 } | 1134 } |
| 1079 | 1135 |
| 1080 if (NodeHasBothClasses(node, | 1136 if (NodeHasBothReceiverClasses(node, |
| 1081 smi_class_, Class::Handle(object_store->mint_class()))) { | 1137 smi_class_, Class::Handle(object_store->mint_class()))) { |
| 1082 GenerateMintBinaryOp(node, true); | 1138 GenerateMintBinaryOp(node, true); |
| 1083 return; | 1139 return; |
| 1084 } | 1140 } |
| 1085 | 1141 |
| 1086 // Type feedback tells this is not a Smi or Double operation. | 1142 // Type feedback tells this is not a Smi or Double operation. |
| 1087 TraceNotOpt(node, | 1143 TraceNotOpt(node, |
| 1088 "BinaryOp: type feedback tells this is not a Smi or Double op"); | 1144 "BinaryOp: type feedback tells this is not a Smi or Double op"); |
| 1089 CodeGenerator::VisitBinaryOpNode(node); | 1145 CodeGenerator::VisitBinaryOpNode(node); |
| 1090 return; | 1146 return; |
| 1091 } | 1147 } |
| 1092 | 1148 |
| 1093 | 1149 |
| 1094 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { | 1150 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
| 1095 if (FLAG_enable_type_checks) { | 1151 if (FLAG_enable_type_checks) { |
| 1096 CodeGenerator::VisitIncrOpLocalNode(node); | 1152 CodeGenerator::VisitIncrOpLocalNode(node); |
| 1097 return; | 1153 return; |
| 1098 } | 1154 } |
| 1099 const char* kOptMessage = "Inlines IncrOpLocal"; | 1155 const char* kOptMessage = "Inlines IncrOpLocal"; |
| 1100 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | 1156 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); |
| 1101 if (!AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) { | 1157 if (!AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { |
| 1102 TraceNotOpt(node, kOptMessage); | 1158 TraceNotOpt(node, kOptMessage); |
| 1103 CodeGenerator::VisitIncrOpLocalNode(node); | 1159 CodeGenerator::VisitIncrOpLocalNode(node); |
| 1104 return; | 1160 return; |
| 1105 } | 1161 } |
| 1106 TraceOpt(node, kOptMessage); | 1162 TraceOpt(node, kOptMessage); |
| 1107 | 1163 |
| 1108 GenerateLoadVariable(EAX, node->local()); | 1164 GenerateLoadVariable(EAX, node->local()); |
| 1109 if (!node->prefix() && IsResultNeeded(node)) { | 1165 if (!node->prefix() && IsResultNeeded(node)) { |
| 1110 // Preserve as result. | 1166 // Preserve as result. |
| 1111 __ movl(ECX, EAX); | 1167 __ movl(ECX, EAX); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1185 node->getter_id(), | 1241 node->getter_id(), |
| 1186 node->receiver(), | 1242 node->receiver(), |
| 1187 node->field_name(), | 1243 node->field_name(), |
| 1188 EBX); | 1244 EBX); |
| 1189 // result is in EAX. | 1245 // result is in EAX. |
| 1190 __ popl(EDX); // Get receiver. | 1246 __ popl(EDX); // Get receiver. |
| 1191 const bool return_original_value = !node->prefix() && IsResultNeeded(node); | 1247 const bool return_original_value = !node->prefix() && IsResultNeeded(node); |
| 1192 const Immediate one_value = Immediate(Smi::RawValue(1)); | 1248 const Immediate one_value = Immediate(Smi::RawValue(1)); |
| 1193 // EAX: Value. | 1249 // EAX: Value. |
| 1194 // EDX: Receiver. | 1250 // EDX: Receiver. |
| 1195 if (AtIdNodeHasOnlyClass(node, node->operator_id(), smi_class_)) { | 1251 if (AtIdNodeHasReceiverClass(node, node->operator_id(), smi_class_)) { |
| 1196 // Deoptimization point for this node is after receiver has been | 1252 // Deoptimization point for this node is after receiver has been |
| 1197 // pushed twice on stack and before the getter (above) was executed. | 1253 // pushed twice on stack and before the getter (above) was executed. |
| 1198 DeoptimizationBlob* deopt_blob = | 1254 DeoptimizationBlob* deopt_blob = |
| 1199 AddDeoptimizationBlob(node, EDX, EDX, kDeoptIncrInstanceOneClass); | 1255 AddDeoptimizationBlob(node, EDX, EDX, kDeoptIncrInstanceOneClass); |
| 1200 if (return_original_value) { | 1256 if (return_original_value) { |
| 1201 // Preserve pre increment result. | 1257 // Preserve pre increment result. |
| 1202 __ movl(ECX, EAX); | 1258 __ movl(ECX, EAX); |
| 1203 } | 1259 } |
| 1204 __ testl(EAX, Immediate(kSmiTagMask)); | 1260 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1205 __ j(NOT_ZERO, deopt_blob->label()); | 1261 __ j(NOT_ZERO, deopt_blob->label()); |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1964 __ j(condition, &is_true); | 2020 __ j(condition, &is_true); |
| 1965 __ PushObject(bool_false); | 2021 __ PushObject(bool_false); |
| 1966 __ jmp(&done); | 2022 __ jmp(&done); |
| 1967 __ Bind(&is_true); | 2023 __ Bind(&is_true); |
| 1968 __ PushObject(bool_true); | 2024 __ PushObject(bool_true); |
| 1969 __ Bind(&done); | 2025 __ Bind(&done); |
| 1970 } | 2026 } |
| 1971 return; | 2027 return; |
| 1972 } | 2028 } |
| 1973 | 2029 |
| 1974 if (AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) { | 2030 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { |
| 1975 if (GenerateSmiComparison(node)) { | 2031 if (GenerateSmiComparison(node)) { |
| 1976 return; | 2032 return; |
| 1977 } | 2033 } |
| 1978 // Fall through if condition is not supported. | 2034 // Fall through if condition is not supported. |
| 1979 } else if (AtIdNodeHasOnlyClass(node, node->id(), double_class_)) { | 2035 } else if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { |
| 1980 // Double comparison | 2036 // Double comparison |
| 1981 if (GenerateDoubleComparison(node)) { | 2037 if (GenerateDoubleComparison(node)) { |
| 1982 return; | 2038 return; |
| 1983 } | 2039 } |
| 1984 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { | 2040 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { |
| 1985 // Equality, not-equality comparison of any other type. | 2041 // Equality, not-equality comparison of any other type. |
| 1986 if (GenerateEqualityComparison(node)) { | 2042 if (GenerateEqualityComparison(node)) { |
| 1987 return; | 2043 return; |
| 1988 } | 2044 } |
| 1989 } | 2045 } |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2266 // collected in the meantime. | 2322 // collected in the meantime. |
| 2267 void OptimizingCodeGenerator::GenerateInlineCacheCall( | 2323 void OptimizingCodeGenerator::GenerateInlineCacheCall( |
| 2268 intptr_t node_id, | 2324 intptr_t node_id, |
| 2269 intptr_t token_index, | 2325 intptr_t token_index, |
| 2270 const ICData& ic_data, | 2326 const ICData& ic_data, |
| 2271 intptr_t num_args, | 2327 intptr_t num_args, |
| 2272 const Array& optional_arguments_names) { | 2328 const Array& optional_arguments_names) { |
| 2273 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); | 2329 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); |
| 2274 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names)); | 2330 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names)); |
| 2275 ExternalLabel target_label( | 2331 ExternalLabel target_label( |
| 2276 "InlineCache", StubCode::InlineCacheEntryPoint()); | 2332 "InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint()); |
| 2277 | 2333 |
| 2278 __ call(&target_label); | 2334 __ call(&target_label); |
| 2279 AddCurrentDescriptor(PcDescriptors::kIcCall, | 2335 AddCurrentDescriptor(PcDescriptors::kIcCall, |
| 2280 node_id, | 2336 node_id, |
| 2281 token_index); | 2337 token_index); |
| 2282 __ addl(ESP, Immediate(num_args * kWordSize)); | 2338 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2283 } | 2339 } |
| 2284 | 2340 |
| 2285 | 2341 |
| 2286 // Normalizes the ic_data class/target pairs: | 2342 // Normalizes the ic_data class/target pairs: |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 if (IsResultNeeded(node)) { | 2651 if (IsResultNeeded(node)) { |
| 2596 // The result is the input value. | 2652 // The result is the input value. |
| 2597 __ pushl(EAX); | 2653 __ pushl(EAX); |
| 2598 } | 2654 } |
| 2599 } | 2655 } |
| 2600 | 2656 |
| 2601 | 2657 |
| 2602 } // namespace dart | 2658 } // namespace dart |
| 2603 | 2659 |
| 2604 #endif // defined TARGET_ARCH_IA32 | 2660 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |