| 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 result->Add(&cls); | 331 result->Add(&cls); |
| 332 } | 332 } |
| 333 return result; | 333 return result; |
| 334 } | 334 } |
| 335 | 335 |
| 336 | 336 |
| 337 // Debugging helper function. | 337 // Debugging helper function. |
| 338 void OptimizingCodeGenerator::PrintCollectedClassesAtId(AstNode* node, | 338 void OptimizingCodeGenerator::PrintCollectedClassesAtId(AstNode* node, |
| 339 intptr_t id) { | 339 intptr_t id) { |
| 340 const ICData& ic_data = node->ICDataAtId(id); | 340 const ICData& ic_data = node->ICDataAtId(id); |
| 341 OS::Print("Collected classes id %d num: %d\n", id, ic_data.NumberOfChecks()); |
| 341 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 342 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 342 Function& target = Function::Handle(); | 343 Function& target = Function::Handle(); |
| 343 GrowableArray<const Class*> classes; | 344 GrowableArray<const Class*> classes; |
| 344 ic_data.GetCheckAt(i, &classes, &target); | 345 ic_data.GetCheckAt(i, &classes, &target); |
| 345 OS::Print("["); | 346 OS::Print("["); |
| 346 for (intptr_t c = 0; c < classes.length(); c++) { | 347 for (intptr_t c = 0; c < classes.length(); c++) { |
| 347 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString()); | 348 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString()); |
| 348 } | 349 } |
| 349 OS::Print("] -> %s\n", target.ToFullyQualifiedCString()); | 350 OS::Print("] -> %s\n", target.ToFullyQualifiedCString()); |
| 350 } | 351 } |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 return false; | 667 return false; |
| 667 } | 668 } |
| 668 Class& target_cls = Class::Handle(); | 669 Class& target_cls = Class::Handle(); |
| 669 Function& target = Function::Handle(); | 670 Function& target = Function::Handle(); |
| 670 ic_data.GetOneClassCheckAt(0, &target_cls, &target); | 671 ic_data.GetOneClassCheckAt(0, &target_cls, &target); |
| 671 return target_cls.raw() == cls.raw(); | 672 return target_cls.raw() == cls.raw(); |
| 672 } | 673 } |
| 673 | 674 |
| 674 | 675 |
| 675 | 676 |
| 676 // Implement with slow case so that it can work both with Smi and Mint types. | 677 // SHL: Implement with slow case so that it works both with Smi and Mint types. |
| 678 // Result is in EAX. Mangles ECX, EBX, EDX. |
| 677 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { | 679 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { |
| 680 if (node->kind() == Token::kSAR) { |
| 681 // TODO(srdjan): Implement for Mint? |
| 682 DeoptimizationBlob* deopt_blob = |
| 683 AddDeoptimizationBlob(node, EAX, ECX, kDeoptSAR); |
| 684 // EAX: value to shift, ECX: amount to shift. |
| 685 VisitLoadTwo(node->left(), node->right(), EAX, ECX); |
| 686 // Check if both Smi. |
| 687 __ movl(EBX, EAX); |
| 688 __ orl(EBX, ECX); |
| 689 __ testl(EBX, Immediate(kSmiTagMask)); |
| 690 __ j(NOT_ZERO, deopt_blob->label()); |
| 691 Immediate count_limit = Immediate(0x1F); |
| 692 __ SmiUntag(ECX); |
| 693 __ cmpl(ECX, count_limit); |
| 694 Label shift_count_ok; |
| 695 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); |
| 696 __ movl(ECX, count_limit); |
| 697 __ Bind(&shift_count_ok); |
| 698 // Shift amount must be in ECX. |
| 699 __ SmiUntag(EAX); // Value. |
| 700 __ sarl(EAX, ECX); |
| 701 __ SmiTag(EAX); |
| 702 return; |
| 703 } |
| 678 ASSERT(node->kind() == Token::kSHL); | 704 ASSERT(node->kind() == Token::kSHL); |
| 679 Label done; | 705 Label done; |
| 680 bool shift_generated = false; | 706 bool shift_generated = false; |
| 681 if (node->right()->IsLiteralNode() && | 707 if (node->right()->IsLiteralNode() && |
| 682 node->right()->AsLiteralNode()->literal().IsSmi()) { | 708 node->right()->AsLiteralNode()->literal().IsSmi()) { |
| 683 // Shift count is a Smi literal. | 709 // Shift count is a Smi literal. |
| 684 Smi& smi = Smi::Handle(); | 710 Smi& smi = Smi::Handle(); |
| 685 smi ^= node->right()->AsLiteralNode()->literal().raw(); | 711 smi ^= node->right()->AsLiteralNode()->literal().raw(); |
| 686 if (smi.Value() < Smi::kBits) { | 712 if (smi.Value() < Smi::kBits) { |
| 687 Label slow_case; | 713 Label slow_case; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 904 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 879 // case we cannot tag the result. | 905 // case we cannot tag the result. |
| 880 __ cmpl(EAX, Immediate(0x40000000)); | 906 __ cmpl(EAX, Immediate(0x40000000)); |
| 881 __ j(EQUAL, overflow_label); | 907 __ j(EQUAL, overflow_label); |
| 882 __ SmiTag(EAX); | 908 __ SmiTag(EAX); |
| 883 break; | 909 break; |
| 884 } | 910 } |
| 885 default: | 911 default: |
| 886 UNREACHABLE(); | 912 UNREACHABLE(); |
| 887 } | 913 } |
| 888 } else if (kind == Token::kSHL) { | 914 } else if ((kind == Token::kSHL) || (kind == Token::kSAR)) { |
| 889 GenerateSmiShiftBinaryOp(node); | 915 GenerateSmiShiftBinaryOp(node); |
| 890 } else { | 916 } else { |
| 917 // Unhandled node kind. |
| 891 TraceNotOpt(node, kOptMessage); | 918 TraceNotOpt(node, kOptMessage); |
| 892 node->left()->Visit(this); | 919 node->left()->Visit(this); |
| 893 node->right()->Visit(this); | 920 node->right()->Visit(this); |
| 894 CodeGenerator::GenerateBinaryOperatorCall(node->id(), | 921 CodeGenerator::GenerateBinaryOperatorCall(node->id(), |
| 895 node->token_index(), | 922 node->token_index(), |
| 896 node->Name()); | 923 node->Name()); |
| 897 } | 924 } |
| 898 __ Bind(&done); | 925 __ Bind(&done); |
| 899 if (CodeGenerator::IsResultNeeded(node)) { | 926 if (CodeGenerator::IsResultNeeded(node)) { |
| 900 if (IsResultInEaxRequested(node)) { | 927 if (IsResultInEaxRequested(node)) { |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1204 GenerateMintBinaryOp(node, false); | 1231 GenerateMintBinaryOp(node, false); |
| 1205 return; | 1232 return; |
| 1206 } | 1233 } |
| 1207 | 1234 |
| 1208 if (NodeHasBothReceiverClasses(node, | 1235 if (NodeHasBothReceiverClasses(node, |
| 1209 smi_class_, Class::Handle(object_store->mint_class()))) { | 1236 smi_class_, Class::Handle(object_store->mint_class()))) { |
| 1210 GenerateMintBinaryOp(node, true); | 1237 GenerateMintBinaryOp(node, true); |
| 1211 return; | 1238 return; |
| 1212 } | 1239 } |
| 1213 | 1240 |
| 1241 // TODO(srdjan): Handle "+" for strings. |
| 1214 // Type feedback tells this is not a Smi or Double operation. | 1242 // Type feedback tells this is not a Smi or Double operation. |
| 1215 TraceNotOpt(node, | 1243 TraceNotOpt(node, |
| 1216 "BinaryOp: type feedback tells this is not a Smi or Double op"); | 1244 "BinaryOp: type feedback tells this is not a Smi or Double op"); |
| 1217 CodeGenerator::VisitBinaryOpNode(node); | 1245 CodeGenerator::VisitBinaryOpNode(node); |
| 1218 return; | 1246 return; |
| 1219 } | 1247 } |
| 1220 | 1248 |
| 1221 | 1249 |
| 1222 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { | 1250 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { |
| 1223 if (FLAG_enable_type_checks) { | 1251 if (FLAG_enable_type_checks) { |
| 1224 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); | 1252 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); |
| 1225 CodeGenerator::VisitIncrOpLocalNode(node); | 1253 CodeGenerator::VisitIncrOpLocalNode(node); |
| 1226 return; | 1254 return; |
| 1227 } | 1255 } |
| 1256 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 1257 if (ic_data.NumberOfChecks() == 0) { |
| 1258 DeoptimizationBlob* deopt_blob = |
| 1259 AddDeoptimizationBlob(node, kDeoptNoTypeFeedback); |
| 1260 __ jmp(deopt_blob->label()); |
| 1261 return; |
| 1262 } |
| 1228 const char* kOptMessage = "Inlines IncrOpLocal"; | 1263 const char* kOptMessage = "Inlines IncrOpLocal"; |
| 1229 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); | 1264 ASSERT((node->kind() == Token::kINCR) || (node->kind() == Token::kDECR)); |
| 1230 if (!AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { | 1265 if (!AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { |
| 1231 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); | 1266 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); |
| 1232 TraceNotOpt(node, kOptMessage); | 1267 TraceNotOpt(node, kOptMessage); |
| 1233 CodeGenerator::VisitIncrOpLocalNode(node); | 1268 CodeGenerator::VisitIncrOpLocalNode(node); |
| 1234 return; | 1269 return; |
| 1235 } | 1270 } |
| 1236 TraceOpt(node, kOptMessage); | 1271 TraceOpt(node, kOptMessage); |
| 1237 | 1272 |
| (...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2257 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { | 2292 void OptimizingCodeGenerator::VisitStoreIndexedNode(StoreIndexedNode* node) { |
| 2258 if (FLAG_enable_type_checks) { | 2293 if (FLAG_enable_type_checks) { |
| 2259 CodeGenerator::VisitStoreIndexedNode(node); | 2294 CodeGenerator::VisitStoreIndexedNode(node); |
| 2260 return; | 2295 return; |
| 2261 } | 2296 } |
| 2262 node->array()->Visit(this); | 2297 node->array()->Visit(this); |
| 2263 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo). | 2298 // TODO(srdjan): Use VisitLoadTwo and check if index is smi (CodeGenInfo). |
| 2264 ObjectStore* object_store = Isolate::Current()->object_store(); | 2299 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 2265 const Class& object_array_class = | 2300 const Class& object_array_class = |
| 2266 Class::ZoneHandle(object_store->array_class()); | 2301 Class::ZoneHandle(object_store->array_class()); |
| 2302 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 2303 if (ic_data.NumberOfChecks() == 0) { |
| 2304 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); |
| 2305 DeoptimizationBlob* deopt_blob = |
| 2306 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); |
| 2307 __ jmp(deopt_blob->label()); |
| 2308 return; |
| 2309 } |
| 2267 if (AtIdNodeHasOnlyClass(node, node->id(), object_array_class)) { | 2310 if (AtIdNodeHasOnlyClass(node, node->id(), object_array_class)) { |
| 2268 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); | 2311 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); |
| 2269 DeoptimizationBlob* deopt_blob = | 2312 DeoptimizationBlob* deopt_blob = |
| 2270 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); | 2313 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); |
| 2271 __ popl(EAX); // array. | 2314 __ popl(EAX); // array. |
| 2272 // ECX: value, EBX:index, EAX: array. | 2315 // ECX: value, EBX:index, EAX: array. |
| 2273 // Check type of array. | 2316 // Check type of array. |
| 2274 __ testl(EAX, Immediate(kSmiTagMask)); | 2317 __ testl(EAX, Immediate(kSmiTagMask)); |
| 2275 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. | 2318 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. |
| 2276 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); | 2319 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2790 void OptimizingCodeGenerator::VisitTryCatchNode(TryCatchNode* node) { | 2833 void OptimizingCodeGenerator::VisitTryCatchNode(TryCatchNode* node) { |
| 2791 // TODO(srdjan): Set classes for locals. | 2834 // TODO(srdjan): Set classes for locals. |
| 2792 classes_for_locals_->Clear(); | 2835 classes_for_locals_->Clear(); |
| 2793 CodeGenerator::VisitTryCatchNode(node); | 2836 CodeGenerator::VisitTryCatchNode(node); |
| 2794 } | 2837 } |
| 2795 | 2838 |
| 2796 | 2839 |
| 2797 } // namespace dart | 2840 } // namespace dart |
| 2798 | 2841 |
| 2799 #endif // defined TARGET_ARCH_IA32 | 2842 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |