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

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

Issue 8972002: Use deopt on some instructions that have not collected type feedback when optimizing compierl kic... (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/code_generator.h ('k') | tests/language/src/BitOperationsTest.dart » ('j') | 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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.h ('k') | tests/language/src/BitOperationsTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698