Chromium Code Reviews| 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 CollectedClassesAtNode(AstNode* node) { | 320 CollectedClassesAtNode(AstNode* node) { |
| 321 ZoneGrowableArray<const Class*>* result = | 321 ZoneGrowableArray<const Class*>* result = |
| 322 new ZoneGrowableArray<const Class*>(); | 322 new ZoneGrowableArray<const Class*>(); |
| 323 const ICData& ic_data = node->ic_data(); | 323 const ICData& ic_data = node->ic_data(); |
| 324 if (ic_data.NumberOfChecks() == 0) { | 324 if (ic_data.NumberOfChecks() == 0) { |
| 325 return result; | 325 return result; |
| 326 } | 326 } |
| 327 ASSERT(ic_data.num_args_tested() == 1); | 327 ASSERT(ic_data.num_args_tested() == 1); |
| 328 Function& target = Function::Handle(); | 328 Function& target = Function::Handle(); |
| 329 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 329 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 330 Class& cls = Class::ZoneHandle(); | 330 intptr_t class_id; |
| 331 ic_data.GetOneClassCheckAt(i, &cls, &target); | 331 ic_data.GetOneClassCheckAt(i, &class_id, &target); |
| 332 result->Add(&cls); | 332 result->Add(&Class::ZoneHandle( |
| 333 Isolate::Current()->class_table()->At(class_id))); | |
| 333 } | 334 } |
| 334 return result; | 335 return result; |
| 335 } | 336 } |
| 336 | 337 |
| 337 | 338 |
| 338 // Debugging helper function. | 339 // Debugging helper function. TODO(srdjan): Remove |
| 339 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) { | 340 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) { |
| 340 const ICData& ic_data = node->ic_data(); | 341 const ICData& ic_data = node->ic_data(); |
| 341 OS::Print("Collected classes id %d num: %d\n", | 342 OS::Print("Collected classes id %d num: %d\n", |
| 342 node->id(), ic_data.NumberOfChecks()); | 343 node->id(), ic_data.NumberOfChecks()); |
| 343 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | |
| 344 Function& target = Function::Handle(); | |
| 345 GrowableArray<const Class*> classes; | |
| 346 ic_data.GetCheckAt(i, &classes, &target); | |
| 347 OS::Print("["); | |
| 348 for (intptr_t c = 0; c < classes.length(); c++) { | |
| 349 OS::Print("%s%s", (c > 0) ? ", " : "", classes[c]->ToCString()); | |
| 350 } | |
| 351 OS::Print("] -> %s\n", target.ToFullyQualifiedCString()); | |
| 352 } | |
| 353 } | 344 } |
| 354 | 345 |
| 355 | 346 |
| 356 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { | 347 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { |
| 357 if (FLAG_trace_optimization) { | 348 if (FLAG_trace_optimization) { |
| 358 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); | 349 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); |
| 359 } | 350 } |
| 360 } | 351 } |
| 361 | 352 |
| 362 | 353 |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 540 | 531 |
| 541 static bool NodeHasBothReceiverClasses(AstNode* node, | 532 static bool NodeHasBothReceiverClasses(AstNode* node, |
| 542 const Class& cls1, | 533 const Class& cls1, |
| 543 const Class& cls2) { | 534 const Class& cls2) { |
| 544 ASSERT(node != NULL); | 535 ASSERT(node != NULL); |
| 545 ASSERT(!cls1.IsNull() && !cls2.IsNull()); | 536 ASSERT(!cls1.IsNull() && !cls2.IsNull()); |
| 546 const ICData& ic_data = node->ic_data(); | 537 const ICData& ic_data = node->ic_data(); |
| 547 bool cls1_found = false; | 538 bool cls1_found = false; |
| 548 bool cls2_found = false; | 539 bool cls2_found = false; |
| 549 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 540 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 550 GrowableArray<const Class*> classes; | 541 GrowableArray<intptr_t> class_ids; |
| 551 Function& target = Function::Handle(); | 542 Function& target = Function::Handle(); |
| 552 ic_data.GetCheckAt(i, &classes, &target); | 543 ic_data.GetCheckAt(i, &class_ids, &target); |
| 553 if (!classes.is_empty()) { | 544 if (!class_ids.is_empty()) { |
| 554 if (classes[0]->raw() == cls1.raw()) { | 545 if (class_ids[0] == cls1.id()) { |
| 555 cls1_found = true; | 546 cls1_found = true; |
| 556 } | 547 } |
| 557 if (classes[0]->raw() == cls2.raw()) { | 548 if (class_ids[0] == cls2.id()) { |
| 558 cls2_found = true; | 549 cls2_found = true; |
| 559 } | 550 } |
| 560 if (cls1_found && cls2_found) { | 551 if (cls1_found && cls2_found) { |
| 561 return true; | 552 return true; |
| 562 } | 553 } |
| 563 } | 554 } |
| 564 } | 555 } |
| 565 return false; | 556 return false; |
| 566 } | 557 } |
| 567 | 558 |
| 568 | 559 |
| 569 // Look only at the first class in all check groups. Returns true if all | 560 // Look only at the first class in all check groups. Returns true if all |
| 570 // receiver classes are 'cls'. | 561 // receiver classes are 'cls'. |
| 571 static bool NodeHasClassAt(AstNode* node, | 562 static bool NodeHasClassAt(AstNode* node, |
| 572 const Class& cls, | 563 const Class& cls, |
| 573 intptr_t arg_index) { | 564 intptr_t arg_index) { |
| 574 ASSERT(node != NULL); | 565 ASSERT(node != NULL); |
| 575 ASSERT(!cls.IsNull()); | 566 ASSERT(!cls.IsNull()); |
| 576 const ICData& ic_data = node->ic_data(); | 567 const ICData& ic_data = node->ic_data(); |
| 577 if (ic_data.NumberOfChecks() == 0) { | 568 if (ic_data.NumberOfChecks() == 0) { |
| 578 return false; | 569 return false; |
| 579 } | 570 } |
| 580 ASSERT(ic_data.num_args_tested() > arg_index); | 571 ASSERT(ic_data.num_args_tested() > arg_index); |
| 581 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 572 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 582 GrowableArray<const Class*> classes; | 573 GrowableArray<intptr_t> class_ids; |
| 583 Function& target = Function::Handle(); | 574 Function& target = Function::Handle(); |
| 584 ic_data.GetCheckAt(i, &classes, &target); | 575 ic_data.GetCheckAt(i, &class_ids, &target); |
| 585 if (classes.is_empty()) { | 576 if (class_ids.is_empty()) { |
| 586 return false; | 577 return false; |
| 587 } | 578 } |
| 588 if (classes[arg_index]->raw() != cls.raw()) { | 579 if (class_ids[arg_index] != cls.id()) { |
| 589 return false; | 580 return false; |
| 590 } | 581 } |
| 591 } | 582 } |
| 592 return true; | 583 return true; |
| 593 } | 584 } |
| 594 | 585 |
| 595 | 586 |
| 596 // IC data may have only one check, and it has to contain the two classes in | 587 // IC data may have only one check, and it has to contain the two classes in |
| 597 // specified order. | 588 // specified order. |
| 598 static bool NodeHasTwoClasses(AstNode* node, | 589 static bool NodeHasTwoClasses(AstNode* node, |
| 599 const Class& cls0, | 590 const Class& cls0, |
| 600 const Class& cls1) { | 591 const Class& cls1) { |
| 601 ASSERT(node != NULL); | 592 ASSERT(node != NULL); |
| 602 ASSERT(!cls0.IsNull() && !cls1.IsNull()); | 593 ASSERT(!cls0.IsNull() && !cls1.IsNull()); |
| 603 const ICData& ic_data = node->ic_data(); | 594 const ICData& ic_data = node->ic_data(); |
| 604 ASSERT(ic_data.num_args_tested() == 2); | 595 ASSERT(ic_data.num_args_tested() == 2); |
| 605 if (ic_data.NumberOfChecks() != 1) { | 596 if (ic_data.NumberOfChecks() != 1) { |
| 606 return false; | 597 return false; |
| 607 } | 598 } |
| 608 Function& target = Function::Handle(); | 599 Function& target = Function::Handle(); |
| 609 GrowableArray<const Class*> classes; | 600 GrowableArray<intptr_t> class_ids; |
| 610 ic_data.GetCheckAt(0, &classes, &target); | 601 ic_data.GetCheckAt(0, &class_ids, &target); |
| 611 if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) { | 602 if ((cls0.id() == class_ids[0]) && (cls1.id() == class_ids[1])) { |
| 612 return true; | 603 return true; |
| 613 } | 604 } |
| 614 return false; | 605 return false; |
| 615 } | 606 } |
| 616 | 607 |
| 617 | 608 |
| 618 // SHL: Implement with slow case so that it works both with Smi and Mint types. | 609 // SHL: Implement with slow case so that it works both with Smi and Mint types. |
| 619 // Result is in EAX. Mangles ECX, EBX, EDX. | 610 // Result is in EAX. Mangles ECX, EBX, EDX. |
| 620 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { | 611 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { |
| 621 if (node->kind() == Token::kSHR) { | 612 if (node->kind() == Token::kSHR) { |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 835 (kind == Token::kTRUNCDIV) || | 826 (kind == Token::kTRUNCDIV) || |
| 836 (kind == Token::kBIT_AND) || | 827 (kind == Token::kBIT_AND) || |
| 837 (kind == Token::kBIT_OR) || | 828 (kind == Token::kBIT_OR) || |
| 838 (kind == Token::kBIT_XOR)) { | 829 (kind == Token::kBIT_XOR)) { |
| 839 TraceOpt(node, kOptMessage); | 830 TraceOpt(node, kOptMessage); |
| 840 // Check if both arguments are expected to be Smi. | 831 // Check if both arguments are expected to be Smi. |
| 841 const ICData& ic_data = node->ic_data(); | 832 const ICData& ic_data = node->ic_data(); |
| 842 ASSERT(ic_data.num_args_tested() == 2); | 833 ASSERT(ic_data.num_args_tested() == 2); |
| 843 ASSERT(ic_data.NumberOfChecks() > 0); | 834 ASSERT(ic_data.NumberOfChecks() > 0); |
| 844 Function& target = Function::Handle(); | 835 Function& target = Function::Handle(); |
| 845 GrowableArray<const Class*> classes; | 836 GrowableArray<intptr_t> class_ids; |
| 846 ic_data.GetCheckAt(0, &classes, &target); | 837 ic_data.GetCheckAt(0, &class_ids, &target); |
| 847 ASSERT(ic_data.NumberOfChecks() == 1); | 838 ASSERT(ic_data.NumberOfChecks() == 1); |
| 848 ASSERT((classes[0]->raw() == smi_class_.raw()) && | 839 ASSERT((class_ids[0] == kSmi) && (class_ids[1] == kSmi)); |
| 849 (classes[1]->raw() == smi_class_.raw())); | |
| 850 CodeGenInfo left_info(node->left()); | 840 CodeGenInfo left_info(node->left()); |
| 851 CodeGenInfo right_info(node->right()); | 841 CodeGenInfo right_info(node->right()); |
| 852 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 842 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 853 Label two_smis, call_operator; | 843 Label two_smis, call_operator; |
| 854 DeoptimizationBlob* deopt_blob = | 844 DeoptimizationBlob* deopt_blob = |
| 855 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp); | 845 AddDeoptimizationBlob(node, ECX, EDX, kDeoptSmiBinaryOp); |
| 856 __ movl(ECX, EAX); // Save if overflow (needs original value). | 846 __ movl(ECX, EAX); // Save if overflow (needs original value). |
| 857 | 847 |
| 858 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { | 848 if (left_info.IsClass(smi_class_) || right_info.IsClass(smi_class_)) { |
| 859 if (!left_info.IsClass(smi_class_)) { | 849 if (!left_info.IsClass(smi_class_)) { |
| (...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1406 if (NodeMayBeSmi(receiver)) { | 1396 if (NodeMayBeSmi(receiver)) { |
| 1407 __ testl(EBX, Immediate(kSmiTagMask)); | 1397 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1408 __ j(ZERO, deopt_blob->label()); | 1398 __ j(ZERO, deopt_blob->label()); |
| 1409 } | 1399 } |
| 1410 | 1400 |
| 1411 __ LoadClassId(EAX, EBX); | 1401 __ LoadClassId(EAX, EBX); |
| 1412 const ICData& ic_data = node->ic_data(); | 1402 const ICData& ic_data = node->ic_data(); |
| 1413 Function& target = Function::Handle(); | 1403 Function& target = Function::Handle(); |
| 1414 Label load_field; | 1404 Label load_field; |
| 1415 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1405 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1416 Class& cls = Class::Handle(); | 1406 intptr_t class_id = -1; |
|
Vyacheslav Egorov (Google)
2012/06/19 12:01:06
kIllegalObjectKind instead of -1?
srdjan
2012/06/19 15:19:16
Done.
| |
| 1417 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1407 ic_data.GetOneClassCheckAt(i, &class_id, &target); |
| 1418 __ cmpl(EAX, Immediate(cls.id())); | 1408 __ cmpl(EAX, Immediate(class_id)); |
| 1419 if (i == (ic_data.NumberOfChecks() - 1)) { | 1409 if (i == (ic_data.NumberOfChecks() - 1)) { |
| 1420 __ j(NOT_EQUAL, deopt_blob->label()); | 1410 __ j(NOT_EQUAL, deopt_blob->label()); |
| 1421 } else { | 1411 } else { |
| 1422 __ j(EQUAL, &load_field); | 1412 __ j(EQUAL, &load_field); |
| 1423 } | 1413 } |
| 1424 } | 1414 } |
| 1425 Class& cls = Class::Handle(); | 1415 intptr_t class_id = -1; |
| 1426 ic_data.GetOneClassCheckAt(0, &cls, &target); | 1416 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 1427 | 1417 |
| 1428 __ Bind(&load_field); | 1418 __ Bind(&load_field); |
| 1429 // EBX: receiver. | 1419 // EBX: receiver. |
| 1430 if (target.kind() == RawFunction::kImplicitGetter) { | 1420 if (target.kind() == RawFunction::kImplicitGetter) { |
| 1431 TraceOpt(node, "Inlines instance getter with same target"); | 1421 TraceOpt(node, "Inlines instance getter with same target"); |
| 1422 const Class& cls = | |
| 1423 Class::Handle(Isolate::Current()->class_table()->At(class_id)); | |
| 1432 intptr_t field_offset = GetFieldOffset(cls, field_name); | 1424 intptr_t field_offset = GetFieldOffset(cls, field_name); |
| 1433 ASSERT(field_offset >= 0); | 1425 ASSERT(field_offset >= 0); |
| 1434 __ movl(EAX, FieldAddress(EBX, field_offset)); | 1426 __ movl(EAX, FieldAddress(EBX, field_offset)); |
| 1435 return; | 1427 return; |
| 1436 } | 1428 } |
| 1437 | 1429 |
| 1438 Recognizer::Kind recognized_kind = Recognizer::RecognizeKind(target); | 1430 Recognizer::Kind recognized_kind = Recognizer::RecognizeKind(target); |
| 1439 switch (recognized_kind) { | 1431 switch (recognized_kind) { |
| 1440 case Recognizer::kObjectArrayLength: { | 1432 case Recognizer::kObjectArrayLength: { |
| 1441 TraceOpt(node, "Inlines ObjectArray.length"); | 1433 TraceOpt(node, "Inlines ObjectArray.length"); |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 1470 return true; | 1462 return true; |
| 1471 } | 1463 } |
| 1472 return false; | 1464 return false; |
| 1473 } | 1465 } |
| 1474 | 1466 |
| 1475 | 1467 |
| 1476 // Return the unique target of all checks or null. | 1468 // Return the unique target of all checks or null. |
| 1477 static RawFunction* GetUniqueTarget(const ICData& ic_data) { | 1469 static RawFunction* GetUniqueTarget(const ICData& ic_data) { |
| 1478 Function& prev_target = Function::Handle(); | 1470 Function& prev_target = Function::Handle(); |
| 1479 Function& target = Function::Handle(); | 1471 Function& target = Function::Handle(); |
| 1480 Class& cls = Class::Handle(); | |
| 1481 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1472 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1482 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1473 intptr_t class_id; |
| 1474 ic_data.GetOneClassCheckAt(i, &class_id, &target); | |
| 1483 ASSERT(!target.IsNull()); | 1475 ASSERT(!target.IsNull()); |
| 1484 if (!prev_target.IsNull() && (prev_target.raw() != target.raw())) { | 1476 if (!prev_target.IsNull() && (prev_target.raw() != target.raw())) { |
| 1485 return Function::null(); | 1477 return Function::null(); |
| 1486 } | 1478 } |
| 1487 prev_target = target.raw(); | 1479 prev_target = target.raw(); |
| 1488 } | 1480 } |
| 1489 return target.raw(); | 1481 return target.raw(); |
| 1490 } | 1482 } |
| 1491 | 1483 |
| 1492 | 1484 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1590 // EBX is used as temporary register for class. | 1582 // EBX is used as temporary register for class. |
| 1591 ASSERT((recv_reg != EBX) && (value_reg != EBX)); | 1583 ASSERT((recv_reg != EBX) && (value_reg != EBX)); |
| 1592 GrowableArray<Class*> classes; | 1584 GrowableArray<Class*> classes; |
| 1593 GrowableArray<Function*> targets; | 1585 GrowableArray<Function*> targets; |
| 1594 bool unique_target = true; | 1586 bool unique_target = true; |
| 1595 { | 1587 { |
| 1596 const ICData& ic_data = node->ic_data(); | 1588 const ICData& ic_data = node->ic_data(); |
| 1597 ASSERT(ic_data.NumberOfChecks() > 0); | 1589 ASSERT(ic_data.NumberOfChecks() > 0); |
| 1598 ASSERT(ic_data.num_args_tested() == 1); | 1590 ASSERT(ic_data.num_args_tested() == 1); |
| 1599 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1591 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1600 Class& cls = Class::ZoneHandle(); | |
| 1601 Function& target = Function::ZoneHandle(); | 1592 Function& target = Function::ZoneHandle(); |
| 1602 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1593 intptr_t class_id; |
| 1594 ic_data.GetOneClassCheckAt(i, &class_id, &target); | |
| 1595 Class& cls = | |
| 1596 Class::ZoneHandle(Isolate::Current()->class_table()->At(class_id)); | |
| 1603 classes.Add(&cls); | 1597 classes.Add(&cls); |
| 1604 targets.Add(&target); | 1598 targets.Add(&target); |
| 1605 } | 1599 } |
| 1606 for (intptr_t i = 1; i < targets.length(); i++) { | 1600 for (intptr_t i = 1; i < targets.length(); i++) { |
| 1607 if (targets[i - 1]->raw() != targets[i]->raw()) { | 1601 if (targets[i - 1]->raw() != targets[i]->raw()) { |
| 1608 unique_target = false; | 1602 unique_target = false; |
| 1609 break; | 1603 break; |
| 1610 } | 1604 } |
| 1611 } | 1605 } |
| 1612 } | 1606 } |
| (...skipping 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2517 // - If Smi class exists, make it the first one. | 2511 // - If Smi class exists, make it the first one. |
| 2518 // - If 'null_target' not null, append null-class/'null_target' | 2512 // - If 'null_target' not null, append null-class/'null_target' |
| 2519 void OptimizingCodeGenerator::NormalizeClassChecks( | 2513 void OptimizingCodeGenerator::NormalizeClassChecks( |
| 2520 const ICData& ic_data, | 2514 const ICData& ic_data, |
| 2521 const Function& null_target, | 2515 const Function& null_target, |
| 2522 GrowableArray<const Class*>* classes, | 2516 GrowableArray<const Class*>* classes, |
| 2523 GrowableArray<const Function*>* targets) { | 2517 GrowableArray<const Function*>* targets) { |
| 2524 ASSERT(classes != NULL); | 2518 ASSERT(classes != NULL); |
| 2525 ASSERT(targets != NULL); | 2519 ASSERT(targets != NULL); |
| 2526 // Check if we can add Smi class in front. | 2520 // Check if we can add Smi class in front. |
| 2527 Class& smi_test_class = Class::Handle(); | |
| 2528 Function& smi_target = Function::ZoneHandle(); | 2521 Function& smi_target = Function::ZoneHandle(); |
| 2529 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 2522 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 2530 GrowableArray<const Class*> test_classes; | 2523 GrowableArray<intptr_t> test_class_ids; |
| 2531 ic_data.GetCheckAt(i, &test_classes, &smi_target); | 2524 ic_data.GetCheckAt(i, &test_class_ids, &smi_target); |
| 2532 smi_test_class = test_classes[0]->raw(); | 2525 if (test_class_ids[0] == kSmi) { |
| 2533 if (smi_test_class.raw() == smi_class_.raw()) { | |
| 2534 classes->Add(&Class::ZoneHandle(smi_class_.raw())); | 2526 classes->Add(&Class::ZoneHandle(smi_class_.raw())); |
| 2535 targets->Add(&Function::ZoneHandle(smi_target.raw())); | 2527 targets->Add(&Function::ZoneHandle(smi_target.raw())); |
| 2536 break; | 2528 break; |
| 2537 } | 2529 } |
| 2538 } | 2530 } |
| 2539 // Add all classes except Smi. | 2531 // Add all classes except Smi. |
| 2540 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 2532 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 2541 Function& target = Function::ZoneHandle(); | 2533 Function& target = Function::ZoneHandle(); |
| 2542 Class& cls = Class::ZoneHandle(); | 2534 GrowableArray<intptr_t> test_class_ids; |
| 2543 GrowableArray<const Class*> test_classes; | 2535 ic_data.GetCheckAt(i, &test_class_ids, &target); |
| 2544 ic_data.GetCheckAt(i, &test_classes, &target); | 2536 ASSERT(test_class_ids[0] != kNullClassId); |
| 2545 cls = test_classes[0]->raw(); | 2537 if (test_class_ids[0] != kSmi) { |
| 2546 ASSERT(!cls.IsNullClass()); | 2538 const Class& cls = |
| 2547 if (cls.raw() != smi_class_.raw()) { | 2539 Class::Handle(Isolate::Current()->class_table()->At( |
| 2540 test_class_ids[0])); | |
| 2548 ASSERT(!cls.IsNull()); | 2541 ASSERT(!cls.IsNull()); |
| 2549 ASSERT(!target.IsNull()); | 2542 ASSERT(!target.IsNull()); |
| 2550 classes->Add(&cls); | 2543 classes->Add(&cls); |
| 2551 targets->Add(&target); | 2544 targets->Add(&target); |
| 2552 } | 2545 } |
| 2553 } | 2546 } |
| 2554 // Do not add a target that has not been compiled yet. | 2547 // Do not add a target that has not been compiled yet. |
| 2555 if (!null_target.IsNull() && null_target.HasCode()) { | 2548 if (!null_target.IsNull() && null_target.HasCode()) { |
| 2556 ASSERT(null_target.IsZoneHandle()); | 2549 ASSERT(null_target.IsZoneHandle()); |
| 2557 classes->Add(&Class::ZoneHandle(Object::null_class())); | 2550 classes->Add(&Class::ZoneHandle(Object::null_class())); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2887 } | 2880 } |
| 2888 } | 2881 } |
| 2889 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 2882 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 2890 CodeGenerator::VisitUnaryOpNode(node); | 2883 CodeGenerator::VisitUnaryOpNode(node); |
| 2891 } | 2884 } |
| 2892 | 2885 |
| 2893 | 2886 |
| 2894 } // namespace dart | 2887 } // namespace dart |
| 2895 | 2888 |
| 2896 #endif // defined TARGET_ARCH_IA32 | 2889 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |