| 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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 | 317 |
| 318 | 318 |
| 319 static const ZoneGrowableArray<const Class*>* | 319 static const ZoneGrowableArray<const Class*>* |
| 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->ICDataAtId(node->id()); | 323 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 324 if (ic_data.NumberOfChecks() == 0) { | 324 if (ic_data.NumberOfChecks() == 0) { |
| 325 return result; | 325 return result; |
| 326 } | 326 } |
| 327 ASSERT(ic_data.NumberOfArgumentsChecked() == 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 Class& cls = Class::ZoneHandle(); |
| 331 ic_data.GetOneClassCheckAt(i, &cls, &target); | 331 ic_data.GetOneClassCheckAt(i, &cls, &target); |
| 332 result->Add(&cls); | 332 result->Add(&cls); |
| 333 } | 333 } |
| 334 return result; | 334 return result; |
| 335 } | 335 } |
| 336 | 336 |
| 337 | 337 |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 static bool AtIdNodeHasClassAt(AstNode* node, | 630 static bool AtIdNodeHasClassAt(AstNode* node, |
| 631 intptr_t id, | 631 intptr_t id, |
| 632 const Class& cls, | 632 const Class& cls, |
| 633 intptr_t arg_index) { | 633 intptr_t arg_index) { |
| 634 ASSERT(node != NULL); | 634 ASSERT(node != NULL); |
| 635 ASSERT(!cls.IsNull()); | 635 ASSERT(!cls.IsNull()); |
| 636 const ICData& ic_data = node->ICDataAtId(id); | 636 const ICData& ic_data = node->ICDataAtId(id); |
| 637 if (ic_data.NumberOfChecks() == 0) { | 637 if (ic_data.NumberOfChecks() == 0) { |
| 638 return false; | 638 return false; |
| 639 } | 639 } |
| 640 ASSERT(ic_data.NumberOfArgumentsChecked() > arg_index); | 640 ASSERT(ic_data.num_args_tested() > arg_index); |
| 641 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 641 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 642 GrowableArray<const Class*> classes; | 642 GrowableArray<const Class*> classes; |
| 643 Function& target = Function::Handle(); | 643 Function& target = Function::Handle(); |
| 644 ic_data.GetCheckAt(i, &classes, &target); | 644 ic_data.GetCheckAt(i, &classes, &target); |
| 645 if (classes.is_empty()) { | 645 if (classes.is_empty()) { |
| 646 return false; | 646 return false; |
| 647 } | 647 } |
| 648 if (classes[arg_index]->raw() != cls.raw()) { | 648 if (classes[arg_index]->raw() != cls.raw()) { |
| 649 return false; | 649 return false; |
| 650 } | 650 } |
| 651 } | 651 } |
| 652 return true; | 652 return true; |
| 653 } | 653 } |
| 654 | 654 |
| 655 | 655 |
| 656 // IC data may have only one check, and it has to contain the two classes in | 656 // IC data may have only one check, and it has to contain the two classes in |
| 657 // specified order. | 657 // specified order. |
| 658 static bool AtIdNodeHasTwoClasses(AstNode* node, | 658 static bool AtIdNodeHasTwoClasses(AstNode* node, |
| 659 intptr_t id, | 659 intptr_t id, |
| 660 const Class& cls0, | 660 const Class& cls0, |
| 661 const Class& cls1) { | 661 const Class& cls1) { |
| 662 ASSERT(node != NULL); | 662 ASSERT(node != NULL); |
| 663 ASSERT(!cls0.IsNull() && !cls1.IsNull()); | 663 ASSERT(!cls0.IsNull() && !cls1.IsNull()); |
| 664 const ICData& ic_data = node->ICDataAtId(id); | 664 const ICData& ic_data = node->ICDataAtId(id); |
| 665 ASSERT(ic_data.NumberOfArgumentsChecked() == 2); | 665 ASSERT(ic_data.num_args_tested() == 2); |
| 666 if (ic_data.NumberOfChecks() != 1) { | 666 if (ic_data.NumberOfChecks() != 1) { |
| 667 return false; | 667 return false; |
| 668 } | 668 } |
| 669 Function& target = Function::Handle(); | 669 Function& target = Function::Handle(); |
| 670 GrowableArray<const Class*> classes; | 670 GrowableArray<const Class*> classes; |
| 671 ic_data.GetCheckAt(0, &classes, &target); | 671 ic_data.GetCheckAt(0, &classes, &target); |
| 672 if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) { | 672 if ((cls0.raw() == classes[0]->raw()) && (cls1.raw() == classes[1]->raw())) { |
| 673 return true; | 673 return true; |
| 674 } | 674 } |
| 675 return false; | 675 return false; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 node->token_index(), | 789 node->token_index(), |
| 790 number_of_arguments, | 790 number_of_arguments, |
| 791 no_optional_argument_names); | 791 no_optional_argument_names); |
| 792 __ Bind(&done); | 792 __ Bind(&done); |
| 793 } | 793 } |
| 794 | 794 |
| 795 | 795 |
| 796 // Implement Token::kSUB and Token::kBIT_NOT. | 796 // Implement Token::kSUB and Token::kBIT_NOT. |
| 797 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) { | 797 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) { |
| 798 const ICData& ic_data = node->ICDataAtId(node->id()); | 798 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 799 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); | 799 ASSERT(ic_data.num_args_tested() == 1); |
| 800 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? | 800 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ? |
| 801 kDeoptNoTypeFeedback : kDeoptUnaryOp; | 801 kDeoptNoTypeFeedback : kDeoptUnaryOp; |
| 802 DeoptimizationBlob* deopt_blob = | 802 DeoptimizationBlob* deopt_blob = |
| 803 AddDeoptimizationBlob(node, EAX, deopt_reason_id); | 803 AddDeoptimizationBlob(node, EAX, deopt_reason_id); |
| 804 CodeGenInfo info(node->operand()); | 804 CodeGenInfo info(node->operand()); |
| 805 VisitLoadOne(node->operand(), EAX); | 805 VisitLoadOne(node->operand(), EAX); |
| 806 if (ic_data.NumberOfChecks() == 0) { | 806 if (ic_data.NumberOfChecks() == 0) { |
| 807 // No type feedback. | 807 // No type feedback. |
| 808 __ jmp(deopt_blob->label()); | 808 __ jmp(deopt_blob->label()); |
| 809 return; | 809 return; |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 893 if ((kind == Token::kADD) || | 893 if ((kind == Token::kADD) || |
| 894 (kind == Token::kSUB) || | 894 (kind == Token::kSUB) || |
| 895 (kind == Token::kMUL) || | 895 (kind == Token::kMUL) || |
| 896 (kind == Token::kTRUNCDIV) || | 896 (kind == Token::kTRUNCDIV) || |
| 897 (kind == Token::kBIT_AND) || | 897 (kind == Token::kBIT_AND) || |
| 898 (kind == Token::kBIT_OR) || | 898 (kind == Token::kBIT_OR) || |
| 899 (kind == Token::kBIT_XOR)) { | 899 (kind == Token::kBIT_XOR)) { |
| 900 TraceOpt(node, kOptMessage); | 900 TraceOpt(node, kOptMessage); |
| 901 // Check if both arguments are expected to be Smi. | 901 // Check if both arguments are expected to be Smi. |
| 902 const ICData& ic_data = node->ICDataAtId(node->id()); | 902 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 903 ASSERT(ic_data.NumberOfArgumentsChecked() == 2); | 903 ASSERT(ic_data.num_args_tested() == 2); |
| 904 ASSERT(ic_data.NumberOfChecks() > 0); | 904 ASSERT(ic_data.NumberOfChecks() > 0); |
| 905 Function& target = Function::Handle(); | 905 Function& target = Function::Handle(); |
| 906 GrowableArray<const Class*> classes; | 906 GrowableArray<const Class*> classes; |
| 907 ic_data.GetCheckAt(0, &classes, &target); | 907 ic_data.GetCheckAt(0, &classes, &target); |
| 908 ASSERT(ic_data.NumberOfChecks() == 1); | 908 ASSERT(ic_data.NumberOfChecks() == 1); |
| 909 ASSERT((classes[0]->raw() == smi_class_.raw()) && | 909 ASSERT((classes[0]->raw() == smi_class_.raw()) && |
| 910 (classes[1]->raw() == smi_class_.raw())); | 910 (classes[1]->raw() == smi_class_.raw())); |
| 911 CodeGenInfo left_info(node->left()); | 911 CodeGenInfo left_info(node->left()); |
| 912 CodeGenInfo right_info(node->right()); | 912 CodeGenInfo right_info(node->right()); |
| 913 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 913 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 | 1351 |
| 1352 const ICData& ic_data = node->ICDataAtId(node->id()); | 1352 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 1353 if (ic_data.NumberOfChecks() == 0) { | 1353 if (ic_data.NumberOfChecks() == 0) { |
| 1354 VisitLoadTwo(node->left(), node->right(), EAX, EDX); | 1354 VisitLoadTwo(node->left(), node->right(), EAX, EDX); |
| 1355 DeoptimizationBlob* deopt_blob = | 1355 DeoptimizationBlob* deopt_blob = |
| 1356 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback); | 1356 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback); |
| 1357 __ jmp(deopt_blob->label()); | 1357 __ jmp(deopt_blob->label()); |
| 1358 return; | 1358 return; |
| 1359 } | 1359 } |
| 1360 | 1360 |
| 1361 ASSERT(ic_data.NumberOfArgumentsChecked() == 2); | 1361 ASSERT(ic_data.num_args_tested() == 2); |
| 1362 | 1362 |
| 1363 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) { | 1363 if (AtIdNodeHasTwoClasses(node, node->id(), smi_class_, smi_class_)) { |
| 1364 GenerateSmiBinaryOp(node); | 1364 GenerateSmiBinaryOp(node); |
| 1365 return; | 1365 return; |
| 1366 } | 1366 } |
| 1367 | 1367 |
| 1368 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { | 1368 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { |
| 1369 const bool receiver_can_be_smi = false; | 1369 const bool receiver_can_be_smi = false; |
| 1370 GenerateDoubleBinaryOp(node, receiver_can_be_smi); | 1370 GenerateDoubleBinaryOp(node, receiver_can_be_smi); |
| 1371 return; | 1371 return; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 | 1460 |
| 1461 | 1461 |
| 1462 // Debugging helper method, used in assert only. | 1462 // Debugging helper method, used in assert only. |
| 1463 static bool HaveSameClassesInICData(const ICData& a, const ICData& b) { | 1463 static bool HaveSameClassesInICData(const ICData& a, const ICData& b) { |
| 1464 if (a.NumberOfChecks() != b.NumberOfChecks()) { | 1464 if (a.NumberOfChecks() != b.NumberOfChecks()) { |
| 1465 return false; | 1465 return false; |
| 1466 } | 1466 } |
| 1467 if (a.NumberOfChecks() == 0) { | 1467 if (a.NumberOfChecks() == 0) { |
| 1468 return true; | 1468 return true; |
| 1469 } | 1469 } |
| 1470 if (a.NumberOfArgumentsChecked() != b.NumberOfArgumentsChecked()) { | 1470 if (a.num_args_tested() != b.num_args_tested()) { |
| 1471 return false; | 1471 return false; |
| 1472 } | 1472 } |
| 1473 // Only one-argument checks implemented. | 1473 // Only one-argument checks implemented. |
| 1474 ASSERT(a.NumberOfArgumentsChecked() == 1); | 1474 ASSERT(a.num_args_tested() == 1); |
| 1475 Function& a_target = Function::Handle(); | 1475 Function& a_target = Function::Handle(); |
| 1476 Function& b_target = Function::Handle(); | 1476 Function& b_target = Function::Handle(); |
| 1477 Class& a_class = Class::Handle(); | 1477 Class& a_class = Class::Handle(); |
| 1478 Class& b_class = Class::Handle(); | 1478 Class& b_class = Class::Handle(); |
| 1479 for (intptr_t i = 0; i < a.NumberOfChecks(); i++) { | 1479 for (intptr_t i = 0; i < a.NumberOfChecks(); i++) { |
| 1480 a.GetOneClassCheckAt(i, &a_class, &a_target); | 1480 a.GetOneClassCheckAt(i, &a_class, &a_target); |
| 1481 bool found = false; | 1481 bool found = false; |
| 1482 for (intptr_t n = 0; n < b.NumberOfChecks(); n++) { | 1482 for (intptr_t n = 0; n < b.NumberOfChecks(); n++) { |
| 1483 b.GetOneClassCheckAt(n, &b_class, &b_target); | 1483 b.GetOneClassCheckAt(n, &b_class, &b_target); |
| 1484 if ((a_class.raw() == b_class.raw())) { | 1484 if ((a_class.raw() == b_class.raw())) { |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1828 Register recv_reg, | 1828 Register recv_reg, |
| 1829 Register value_reg) { | 1829 Register value_reg) { |
| 1830 // EBX is used as temporary register for class. | 1830 // EBX is used as temporary register for class. |
| 1831 ASSERT((recv_reg != EBX) && (value_reg != EBX)); | 1831 ASSERT((recv_reg != EBX) && (value_reg != EBX)); |
| 1832 GrowableArray<Class*> classes; | 1832 GrowableArray<Class*> classes; |
| 1833 GrowableArray<Function*> targets; | 1833 GrowableArray<Function*> targets; |
| 1834 bool unique_target = true; | 1834 bool unique_target = true; |
| 1835 { | 1835 { |
| 1836 const ICData& ic_data = node->ICDataAtId(id); | 1836 const ICData& ic_data = node->ICDataAtId(id); |
| 1837 ASSERT(ic_data.NumberOfChecks() > 0); | 1837 ASSERT(ic_data.NumberOfChecks() > 0); |
| 1838 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); | 1838 ASSERT(ic_data.num_args_tested() == 1); |
| 1839 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | 1839 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { |
| 1840 Class& cls = Class::ZoneHandle(); | 1840 Class& cls = Class::ZoneHandle(); |
| 1841 Function& target = Function::ZoneHandle(); | 1841 Function& target = Function::ZoneHandle(); |
| 1842 ic_data.GetOneClassCheckAt(i, &cls, &target); | 1842 ic_data.GetOneClassCheckAt(i, &cls, &target); |
| 1843 classes.Add(&cls); | 1843 classes.Add(&cls); |
| 1844 targets.Add(&target); | 1844 targets.Add(&target); |
| 1845 } | 1845 } |
| 1846 for (intptr_t i = 1; i < targets.length(); i++) { | 1846 for (intptr_t i = 1; i < targets.length(); i++) { |
| 1847 if (targets[i - 1]->raw() != targets[i]->raw()) { | 1847 if (targets[i - 1]->raw() != targets[i]->raw()) { |
| 1848 unique_target = false; | 1848 unique_target = false; |
| (...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2752 // provided. | 2752 // provided. |
| 2753 // TODO(srdjan): Recompilation framework should recognize active IC calls | 2753 // TODO(srdjan): Recompilation framework should recognize active IC calls |
| 2754 // in optimized code and mark them for reoptimization since type feedback was | 2754 // in optimized code and mark them for reoptimization since type feedback was |
| 2755 // collected in the meantime. | 2755 // collected in the meantime. |
| 2756 void OptimizingCodeGenerator::GenerateInlineCacheCall( | 2756 void OptimizingCodeGenerator::GenerateInlineCacheCall( |
| 2757 intptr_t node_id, | 2757 intptr_t node_id, |
| 2758 intptr_t token_index, | 2758 intptr_t token_index, |
| 2759 const ICData& ic_data, | 2759 const ICData& ic_data, |
| 2760 intptr_t num_args, | 2760 intptr_t num_args, |
| 2761 const Array& optional_arguments_names) { | 2761 const Array& optional_arguments_names) { |
| 2762 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); | 2762 __ LoadObject(ECX, ic_data); |
| 2763 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names)); | 2763 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names)); |
| 2764 ExternalLabel target_label( | 2764 ExternalLabel target_label( |
| 2765 "InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint()); | 2765 "InlineCache", StubCode::OneArgCheckInlineCacheEntryPoint()); |
| 2766 | 2766 |
| 2767 __ call(&target_label); | 2767 __ call(&target_label); |
| 2768 AddCurrentDescriptor(PcDescriptors::kIcCall, | 2768 AddCurrentDescriptor(PcDescriptors::kIcCall, |
| 2769 node_id, | 2769 node_id, |
| 2770 token_index); | 2770 token_index); |
| 2771 __ addl(ESP, Immediate(num_args * kWordSize)); | 2771 __ addl(ESP, Immediate(num_args * kWordSize)); |
| 2772 } | 2772 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2812 } | 2812 } |
| 2813 // Do not add a target that has not been compiled yet. | 2813 // Do not add a target that has not been compiled yet. |
| 2814 if (!null_target.IsNull() && null_target.HasCode()) { | 2814 if (!null_target.IsNull() && null_target.HasCode()) { |
| 2815 ASSERT(null_target.IsZoneHandle()); | 2815 ASSERT(null_target.IsZoneHandle()); |
| 2816 classes->Add(&Class::ZoneHandle(Object::null_class())); | 2816 classes->Add(&Class::ZoneHandle(Object::null_class())); |
| 2817 targets->Add(&null_target); | 2817 targets->Add(&null_target); |
| 2818 } | 2818 } |
| 2819 } | 2819 } |
| 2820 | 2820 |
| 2821 | 2821 |
| 2822 // Use ICData in 'node' to issues checks and calls. | 2822 // Use IC data in 'node' to issues checks and calls. |
| 2823 // IC data can contain one or more argument checks. | 2823 // IC data can contain one or more argument checks. |
| 2824 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls( | 2824 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls( |
| 2825 AstNode* node, | 2825 AstNode* node, |
| 2826 AstNode* receiver, | 2826 AstNode* receiver, |
| 2827 intptr_t node_id, | 2827 intptr_t node_id, |
| 2828 intptr_t token_index, | 2828 intptr_t token_index, |
| 2829 intptr_t num_args, | 2829 intptr_t num_args, |
| 2830 const Array& optional_arguments_names) { | 2830 const Array& optional_arguments_names) { |
| 2831 ASSERT(node != NULL); | 2831 ASSERT(node != NULL); |
| 2832 ASSERT(receiver != NULL); | 2832 ASSERT(receiver != NULL); |
| 2833 ASSERT(num_args > 0); | 2833 ASSERT(num_args > 0); |
| 2834 const ICData& ic_data = node->ICDataAtId(node_id); | 2834 const ICData& ic_data = node->ICDataAtId(node_id); |
| 2835 if (ic_data.NumberOfChecks() == 0) { | 2835 if (ic_data.NumberOfChecks() == 0) { |
| 2836 // No type feedback means node was never executed. However that can be | 2836 // No type feedback means node was never executed. However that can be |
| 2837 // a common case especially in case of large switch statements. | 2837 // a common case especially in case of large switch statements. |
| 2838 // Use a special inline cache call which can help us decide when to | 2838 // Use a special inline cache call which can help us decide when to |
| 2839 // re-optimize this optiumized function. | 2839 // re-optimize this optiumized function. |
| 2840 GenerateInlineCacheCall( | 2840 GenerateInlineCacheCall( |
| 2841 node_id, token_index, ic_data, num_args, optional_arguments_names); | 2841 node_id, token_index, ic_data, num_args, optional_arguments_names); |
| 2842 return; | 2842 return; |
| 2843 } | 2843 } |
| 2844 | 2844 |
| 2845 Function& target_for_null = Function::ZoneHandle(); | 2845 Function& target_for_null = Function::ZoneHandle(); |
| 2846 ObjectStore* object_store = Isolate::Current()->object_store(); | 2846 ObjectStore* object_store = Isolate::Current()->object_store(); |
| 2847 int num_optional_args = | 2847 int num_optional_args = |
| 2848 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); | 2848 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); |
| 2849 target_for_null = Resolver::ResolveDynamicForReceiverClass( | 2849 target_for_null = Resolver::ResolveDynamicForReceiverClass( |
| 2850 Class::Handle(object_store->object_class()), | 2850 Class::Handle(object_store->object_class()), |
| 2851 String::Handle(ic_data.FunctionName()), | 2851 String::Handle(ic_data.target_name()), |
| 2852 num_args, | 2852 num_args, |
| 2853 num_optional_args); | 2853 num_optional_args); |
| 2854 GrowableArray<const Class*> classes; | 2854 GrowableArray<const Class*> classes; |
| 2855 GrowableArray<const Function*> targets; | 2855 GrowableArray<const Function*> targets; |
| 2856 // Make Smi class the first one, if it is in the list. | 2856 // Make Smi class the first one, if it is in the list. |
| 2857 NormalizeClassChecks(ic_data, target_for_null, &classes, &targets); | 2857 NormalizeClassChecks(ic_data, target_for_null, &classes, &targets); |
| 2858 ASSERT(!classes.is_empty()); | 2858 ASSERT(!classes.is_empty()); |
| 2859 ASSERT(classes.length() == targets.length()); | 2859 ASSERT(classes.length() == targets.length()); |
| 2860 intptr_t start_ix = 0; | 2860 intptr_t start_ix = 0; |
| 2861 | 2861 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3125 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 3125 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 3126 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); | 3126 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False())); |
| 3127 __ Bind(&done); | 3127 __ Bind(&done); |
| 3128 HandleResult(node, EAX); | 3128 HandleResult(node, EAX); |
| 3129 return; | 3129 return; |
| 3130 } | 3130 } |
| 3131 | 3131 |
| 3132 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) { | 3132 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) { |
| 3133 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) { | 3133 if (AtIdNodeHasClassAt(node, node->id(), smi_class_, 0)) { |
| 3134 const ICData& ic_data = node->ICDataAtId(node->id()); | 3134 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 3135 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); | 3135 ASSERT(ic_data.num_args_tested() == 1); |
| 3136 GenerateSmiUnaryOp(node); | 3136 GenerateSmiUnaryOp(node); |
| 3137 return; | 3137 return; |
| 3138 } | 3138 } |
| 3139 } | 3139 } |
| 3140 if (node->kind() == Token::kSUB) { | 3140 if (node->kind() == Token::kSUB) { |
| 3141 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { | 3141 if (AtIdNodeHasClassAt(node, node->id(), double_class_, 0)) { |
| 3142 const ICData& ic_data = node->ICDataAtId(node->id()); | 3142 const ICData& ic_data = node->ICDataAtId(node->id()); |
| 3143 ASSERT(ic_data.NumberOfArgumentsChecked() == 1); | 3143 ASSERT(ic_data.num_args_tested() == 1); |
| 3144 GenerateDoubleUnaryOp(node); | 3144 GenerateDoubleUnaryOp(node); |
| 3145 return; | 3145 return; |
| 3146 } | 3146 } |
| 3147 } | 3147 } |
| 3148 // TODO(srdjan): Implement unary kSUB (negate) Mint. | 3148 // TODO(srdjan): Implement unary kSUB (negate) Mint. |
| 3149 CodeGenerator::VisitUnaryOpNode(node); | 3149 CodeGenerator::VisitUnaryOpNode(node); |
| 3150 } | 3150 } |
| 3151 | 3151 |
| 3152 | 3152 |
| 3153 } // namespace dart | 3153 } // namespace dart |
| 3154 | 3154 |
| 3155 #endif // defined TARGET_ARCH_IA32 | 3155 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |