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

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

Issue 8394061: Store IC data instead of array of classes in AST node, so that we can easier access targets and f... (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 1 month 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 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 deoptimization_blobs_[i]->Generate(this); 261 deoptimization_blobs_[i]->Generate(this);
262 } 262 }
263 } 263 }
264 264
265 265
266 bool OptimizingCodeGenerator::IsResultInEaxRequested(AstNode* node) const { 266 bool OptimizingCodeGenerator::IsResultInEaxRequested(AstNode* node) const {
267 return (node->info() != NULL) && node->info()->request_result_in_eax(); 267 return (node->info() != NULL) && node->info()->request_result_in_eax();
268 } 268 }
269 269
270 270
271 static const ZoneGrowableArray<const Class*>*
272 CollectedClassesAtNode(AstNode* node) {
273 ZoneGrowableArray<const Class*>* result =
274 new ZoneGrowableArray<const Class*>();
275 const ICData& ic_data = node->ICDataAtId(node->id());
276 if (ic_data.NumberOfChecks() == 0) {
277 return result;
278 }
279 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
280 Function& target = Function::Handle();
281 GrowableArray<const Class*> classes;
282 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
283 ic_data.GetCheckAt(i, &classes, &target);
284 ASSERT(classes.length() == 1);
285 result->Add(classes[0]);
286 }
287 return result;
288 }
289
290
271 // Debugging helper function. 291 // Debugging helper function.
272 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) { 292 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) {
273 const ZoneGrowableArray<const Class*>* classes = 293 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
274 node->CollectedClassesAtId(node->id());
275 for (intptr_t i = 0; i < classes->length(); i++) { 294 for (intptr_t i = 0; i < classes->length(); i++) {
276 OS::Print("- %s\n", (*classes)[i]->ToCString()); 295 OS::Print("- %s\n", (*classes)[i]->ToCString());
277 } 296 }
278 } 297 }
279 298
280 299
281 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { 300 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) {
282 if (FLAG_trace_optimization) { 301 if (FLAG_trace_optimization) {
283 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); 302 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message);
284 } 303 }
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 if (!value_info.result_returned_in_eax()) { 526 if (!value_info.result_returned_in_eax()) {
508 __ popl(EAX); 527 __ popl(EAX);
509 } 528 }
510 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX); 529 CodeGenerator::GenerateStoreVariable(node->local(), EAX, EDX);
511 } 530 }
512 if (IsResultNeeded(node)) { 531 if (IsResultNeeded(node)) {
513 __ pushl(EAX); 532 __ pushl(EAX);
514 } 533 }
515 } 534 }
516 535
536
517 static bool NodeHasBothClasses(AstNode* node, 537 static bool NodeHasBothClasses(AstNode* node,
518 const Class& cls1, 538 const Class& cls1,
519 const Class& cls2) { 539 const Class& cls2) {
520 ASSERT(node != NULL); 540 ASSERT(node != NULL);
521 ASSERT(!cls1.IsNull() && !cls2.IsNull()); 541 ASSERT(!cls1.IsNull() && !cls2.IsNull());
522 const ZoneGrowableArray<const Class*>* classes = 542
523 node->CollectedClassesAtId(node->id()); 543 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
524 if ((classes == NULL) || (classes->length() != 2)) { 544 if ((classes == NULL) || (classes->length() != 2)) {
525 return false; 545 return false;
526 } 546 }
527 if ((cls1.raw() != (*classes)[0]->raw()) && 547 if ((cls1.raw() != (*classes)[0]->raw()) &&
528 (cls1.raw() != (*classes)[1]->raw())) { 548 (cls1.raw() != (*classes)[1]->raw())) {
529 return false; 549 return false;
530 } 550 }
531 if ((cls2.raw() != (*classes)[0]->raw()) && 551 if ((cls2.raw() != (*classes)[0]->raw()) &&
532 (cls2.raw() != (*classes)[1]->raw())) { 552 (cls2.raw() != (*classes)[1]->raw())) {
533 return false; 553 return false;
534 } 554 }
535 return true; 555 return true;
536 } 556 }
537 557
538 558
539 static bool NodeHasOnlyClass(AstNode* node, const Class& cls) { 559 static bool NodeHasOnlyClass(AstNode* node, const Class& cls) {
540 ASSERT(node != NULL); 560 ASSERT(node != NULL);
541 ASSERT(!cls.IsNull()); 561 ASSERT(!cls.IsNull());
542 const ZoneGrowableArray<const Class*>* classes = 562 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
543 node->CollectedClassesAtId(node->id());
544 return (classes != NULL) && 563 return (classes != NULL) &&
545 (classes->length() == 1) && 564 (classes->length() == 1) &&
546 ((*classes)[0]->raw() == cls.raw()); 565 ((*classes)[0]->raw() == cls.raw());
547 } 566 }
548 567
549 568
550 // Implement with slow case so that it can work both with Smi and Mint types. 569 // Implement with slow case so that it can work both with Smi and Mint types.
551 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { 570 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) {
552 ASSERT(node->kind() == Token::kSHL); 571 ASSERT(node->kind() == Token::kSHL);
553 Label done; 572 Label done;
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 } 1138 }
1120 } 1139 }
1121 return true; 1140 return true;
1122 } 1141 }
1123 1142
1124 1143
1125 // Emits code for an instance getter that has one or more collected classes, 1144 // Emits code for an instance getter that has one or more collected classes,
1126 // all with the same target. 1145 // all with the same target.
1127 void OptimizingCodeGenerator::InlineInstanceGettersWithSameTarget( 1146 void OptimizingCodeGenerator::InlineInstanceGettersWithSameTarget(
1128 InstanceGetterNode* node, const Function& target) { 1147 InstanceGetterNode* node, const Function& target) {
1129 const ZoneGrowableArray<const Class*>* classes = 1148 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1130 node->CollectedClassesAtId(node->id());
1131 ASSERT(classes->length() > 0); 1149 ASSERT(classes->length() > 0);
1132 Label load_field; 1150 Label load_field;
1133 VisitLoadOne(node->receiver(), EBX); 1151 VisitLoadOne(node->receiver(), EBX);
1134 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EBX); 1152 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node, EBX);
1135 if (NodeMayBeSmi(node->receiver())) { 1153 if (NodeMayBeSmi(node->receiver())) {
1136 __ testl(EBX, Immediate(kSmiTagMask)); 1154 __ testl(EBX, Immediate(kSmiTagMask));
1137 __ j(ZERO, deopt_blob->label()); 1155 __ j(ZERO, deopt_blob->label());
1138 } 1156 }
1139 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); 1157 __ movl(EAX, FieldAddress(EBX, Object::class_offset()));
1140 const int num_classes = classes->length(); 1158 const int num_classes = classes->length();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 } 1210 }
1193 return false; 1211 return false;
1194 } 1212 }
1195 1213
1196 1214
1197 // TODO(srdjan): Implement for multiple getter targets. 1215 // TODO(srdjan): Implement for multiple getter targets.
1198 // For every class inline its implicit getter, or call the instance getter. 1216 // For every class inline its implicit getter, or call the instance getter.
1199 void OptimizingCodeGenerator::VisitInstanceGetterNode( 1217 void OptimizingCodeGenerator::VisitInstanceGetterNode(
1200 InstanceGetterNode* node) { 1218 InstanceGetterNode* node) {
1201 const char* kMessage = "Inline instance getter"; 1219 const char* kMessage = "Inline instance getter";
1202 const ZoneGrowableArray<const Class*>* classes = 1220 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1203 node->CollectedClassesAtId(node->id());
1204 const String& getter_name = 1221 const String& getter_name =
1205 String::Handle(Field::GetterName(node->field_name())); 1222 String::Handle(Field::GetterName(node->field_name()));
1206 if (FLAG_trace_optimization) { 1223 if (FLAG_trace_optimization) {
1207 OS::Print("Getter %s ", getter_name.ToCString()); 1224 OS::Print("Getter %s ", getter_name.ToCString());
1208 } 1225 }
1209 if ((classes == NULL) || classes->is_empty()) { 1226 if ((classes == NULL) || classes->is_empty()) {
1210 TraceNotOpt(node, kMessage); 1227 TraceNotOpt(node, kMessage);
1211 CodeGenerator::VisitInstanceGetterNode(node); 1228 CodeGenerator::VisitInstanceGetterNode(node);
1212 return; 1229 return;
1213 } 1230 }
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1253 1270
1254 // The call to the instance setter implements the assignment to a field. 1271 // The call to the instance setter implements the assignment to a field.
1255 // The result of the assignment to a field is the value being stored. 1272 // The result of the assignment to a field is the value being stored.
1256 void OptimizingCodeGenerator::VisitInstanceSetterNode( 1273 void OptimizingCodeGenerator::VisitInstanceSetterNode(
1257 InstanceSetterNode* node) { 1274 InstanceSetterNode* node) {
1258 if (FLAG_enable_type_checks) { 1275 if (FLAG_enable_type_checks) {
1259 CodeGenerator::VisitInstanceSetterNode(node); 1276 CodeGenerator::VisitInstanceSetterNode(node);
1260 return; 1277 return;
1261 } 1278 }
1262 const char* kMessage = "Inline instance setter"; 1279 const char* kMessage = "Inline instance setter";
1263 const ZoneGrowableArray<const Class*>* classes = 1280 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1264 node->CollectedClassesAtId(node->id());
1265 if ((classes == NULL) || classes->is_empty()) { 1281 if ((classes == NULL) || classes->is_empty()) {
1266 // Type feedback not yet collected. 1282 // Type feedback not yet collected.
1267 TraceNotOpt(node, kMessage); 1283 TraceNotOpt(node, kMessage);
1268 CodeGenerator::VisitInstanceSetterNode(node); 1284 CodeGenerator::VisitInstanceSetterNode(node);
1269 return; 1285 return;
1270 } 1286 }
1271 const int num_classes = classes->length(); 1287 const int num_classes = classes->length();
1272 bool all_inlineable = true; 1288 bool all_inlineable = true;
1273 const String& setter_name = 1289 const String& setter_name =
1274 String::Handle(Field::SetterName(node->field_name())); 1290 String::Handle(Field::SetterName(node->field_name()));
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1474 1490
1475 1491
1476 // Checks if an inlined equality/non-equality operation can be emitted: 1492 // Checks if an inlined equality/non-equality operation can be emitted:
1477 // - type feedback must exist. 1493 // - type feedback must exist.
1478 // - no class in type feedback list overrides '=='. 1494 // - no class in type feedback list overrides '=='.
1479 // - no Smi class in type feedback class list. 1495 // - no Smi class in type feedback class list.
1480 bool OptimizingCodeGenerator::GenerateEqualityComparison(ComparisonNode* node) { 1496 bool OptimizingCodeGenerator::GenerateEqualityComparison(ComparisonNode* node) {
1481 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)); 1497 ASSERT((node->kind() == Token::kEQ) || (node->kind() == Token::kNE));
1482 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1498 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1483 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1499 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1484 const ZoneGrowableArray<const Class*>* classes = 1500 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1485 node->CollectedClassesAtId(node->id());
1486 if (classes == NULL) { 1501 if (classes == NULL) {
1487 return false; 1502 return false;
1488 } 1503 }
1489 const int num_classes = classes->length(); 1504 const int num_classes = classes->length();
1490 // 'num_classes' can be 0 if the receiver was always null. 1505 // 'num_classes' can be 0 if the receiver was always null.
1491 const String& operator_name = String::Handle(String::NewSymbol("==")); 1506 const String& operator_name = String::Handle(String::NewSymbol("=="));
1492 // Check that all classes resolve to Object.==. Object.!= is not overridable 1507 // Check that all classes resolve to Object.==. Object.!= is not overridable
1493 // and is based on Object.==. 1508 // and is based on Object.==.
1494 ObjectStore* object_store = Isolate::Current()->object_store(); 1509 ObjectStore* object_store = Isolate::Current()->object_store();
1495 Function& function = Function::Handle(); 1510 Function& function = Function::Handle();
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
1957 __ addl(ESP, Immediate(arg_count * kWordSize)); 1972 __ addl(ESP, Immediate(arg_count * kWordSize));
1958 } 1973 }
1959 1974
1960 1975
1961 // Using collected type feedback, inline class checks and call the targets 1976 // Using collected type feedback, inline class checks and call the targets
1962 // directly instead of via inline cache stub. TODO(srdjan): Use type propagation 1977 // directly instead of via inline cache stub. TODO(srdjan): Use type propagation
1963 // and CHA to eliminate checks. 1978 // and CHA to eliminate checks.
1964 // Return false if no code was generated (because no type feedback was found). 1979 // Return false if no code was generated (because no type feedback was found).
1965 bool OptimizingCodeGenerator::GenerateCheckedInstanceCalls( 1980 bool OptimizingCodeGenerator::GenerateCheckedInstanceCalls(
1966 InstanceCallNode* node) { 1981 InstanceCallNode* node) {
1967 const ZoneGrowableArray<const Class*>* classes = 1982 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
1968 node->CollectedClassesAtId(node->id());
1969 if ((classes == NULL) || classes->is_empty()) { 1983 if ((classes == NULL) || classes->is_empty()) {
1970 return false; 1984 return false;
1971 } 1985 }
1972 1986
1973 const int arg_count = node->arguments()->length() + 1; // With receiver. 1987 const int arg_count = node->arguments()->length() + 1; // With receiver.
1974 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node); 1988 DeoptimizationBlob* deopt_blob = AddDeoptimizationBlob(node);
1975 ASSERT(arg_count > 0); 1989 ASSERT(arg_count > 0);
1976 __ movl(EAX, Address(ESP, (arg_count - 1) * kWordSize)); // Load receiver. 1990 __ movl(EAX, Address(ESP, (arg_count - 1) * kWordSize)); // Load receiver.
1977 1991
1978 Label done; 1992 Label done;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2049 // Result is in EAX. 2063 // Result is in EAX.
2050 if (IsResultNeeded(node)) { 2064 if (IsResultNeeded(node)) {
2051 __ pushl(EAX); 2065 __ pushl(EAX);
2052 } 2066 }
2053 } 2067 }
2054 2068
2055 2069
2056 // Returns true if an instance call was replaced with its intrinsic. 2070 // Returns true if an instance call was replaced with its intrinsic.
2057 // Returns result in EAX. 2071 // Returns result in EAX.
2058 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) { 2072 bool OptimizingCodeGenerator::TryInlineInstanceCall(InstanceCallNode* node) {
2059 const ZoneGrowableArray<const Class*>* classes = 2073 const ZoneGrowableArray<const Class*>* classes = CollectedClassesAtNode(node);
2060 node->CollectedClassesAtId(node->id());
2061 if ((classes != NULL) && (classes->length() == 1)) { 2074 if ((classes != NULL) && (classes->length() == 1)) {
2062 const int num_arguments = node->arguments()->length() + 1; 2075 const int num_arguments = node->arguments()->length() + 1;
2063 const int num_named_arguments = node->arguments()->names().IsNull() ? 2076 const int num_named_arguments = node->arguments()->names().IsNull() ?
2064 0 : node->arguments()->names().Length(); 2077 0 : node->arguments()->names().Length();
2065 const Function& target = Function::ZoneHandle( 2078 const Function& target = Function::ZoneHandle(
2066 Resolver::ResolveDynamicForReceiverClass(*(*classes)[0], 2079 Resolver::ResolveDynamicForReceiverClass(*(*classes)[0],
2067 node->function_name(), 2080 node->function_name(),
2068 num_arguments, 2081 num_arguments,
2069 num_named_arguments)); 2082 num_named_arguments));
2070 Recognizer::Kind recognized = Recognizer::RecognizeKind(target); 2083 Recognizer::Kind recognized = Recognizer::RecognizeKind(target);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2147 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); 2160 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize));
2148 // Result is in EAX. 2161 // Result is in EAX.
2149 if (IsResultNeeded(node)) { 2162 if (IsResultNeeded(node)) {
2150 __ pushl(EAX); 2163 __ pushl(EAX);
2151 } 2164 }
2152 } 2165 }
2153 2166
2154 } // namespace dart 2167 } // namespace dart
2155 2168
2156 #endif // defined TARGET_ARCH_IA32 2169 #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