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

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

Issue 8972005: More optimizations cleanup. (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/opt_code_generator_ia32.h ('k') | runtime/vm/stub_code_ia32.cc » ('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 741 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 __ sarl(EBX, ECX); 752 __ sarl(EBX, ECX);
753 __ cmpl(EAX, EBX); 753 __ cmpl(EAX, EBX);
754 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow. 754 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
755 755
756 __ shll(EAX, ECX); // Shift for result now we know there is no overflow. 756 __ shll(EAX, ECX); // Shift for result now we know there is no overflow.
757 // EAX is the correctly tagged Smi. 757 // EAX is the correctly tagged Smi.
758 __ jmp(&done); 758 __ jmp(&done);
759 __ Bind(&slow_case); 759 __ Bind(&slow_case);
760 __ pushl(EAX); 760 __ pushl(EAX);
761 __ pushl(EDX); 761 __ pushl(EDX);
762 CodeGenerator::GenerateBinaryOperatorCall(node->id(), 762 const int number_of_arguments = 2;
763 node->token_index(), 763 const Array& no_optional_argument_names = Array::Handle();
764 node->Name()); 764 GenerateCheckedInstanceCalls(node,
765 node->left(),
766 node->id(),
767 node->token_index(),
768 number_of_arguments,
769 no_optional_argument_names);
765 shift_generated = true; 770 shift_generated = true;
766 } 771 }
767 __ Bind(&done); 772 __ Bind(&done);
768 } 773 }
769 774
770 775
776 // Implement Token::kSUB and Token::kBIT_NOT.
777 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) {
778 const ICData& ic_data = node->ICDataAtId(node->id());
779 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
780 DeoptReasonId deopt_reason_id = ic_data.NumberOfChecks() == 0 ?
781 kDeoptNoTypeFeedback : kDeoptUnaryOp;
782 DeoptimizationBlob* deopt_blob =
783 AddDeoptimizationBlob(node, EAX, deopt_reason_id);
784 CodeGenInfo info(node->operand());
785 VisitLoadOne(node->operand(), EAX);
786 if (ic_data.NumberOfChecks() == 0) {
787 // No type feedback.
788 __ jmp(deopt_blob->label());
789 return;
790 }
791 ASSERT(ic_data.NumberOfChecks() == 1);
792 __ testl(EAX, Immediate(kSmiTagMask));
793 __ j(NOT_ZERO, deopt_blob->label());
794 if (node->kind() == Token::kSUB) {
795 __ negl(EAX);
796 __ j(OVERFLOW, deopt_blob->label());
797 } else {
798 ASSERT(node->kind() == Token::kBIT_NOT);
799 __ notl(EAX);
800 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
801 }
802 if (CodeGenerator::IsResultNeeded(node)) {
803 if (IsResultInEaxRequested(node)) {
804 node->info()->set_result_returned_in_eax(true);
805 } else {
806 __ pushl(EAX);
807 }
808 }
809 }
810
811
771 // TODO(srdjan): Expand inline caches to detect Smi/double operations, so that 812 // TODO(srdjan): Expand inline caches to detect Smi/double operations, so that
772 // we do not have to call the instance method, and therefore could guarantee 813 // we do not have to call the instance method, and therefore could guarantee
773 // that the result is a Smi at the end. 814 // that the result is a Smi at the end.
774 void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) { 815 void OptimizingCodeGenerator::GenerateSmiBinaryOp(BinaryOpNode* node) {
775 const char* kOptMessage = "Inlines BinaryOp for Smi"; 816 const char* kOptMessage = "Inlines BinaryOp for Smi";
776 Label done; 817 Label done;
777 const Token::Kind kind = node->kind(); 818 const Token::Kind kind = node->kind();
778 if ((kind == Token::kADD) || 819 if ((kind == Token::kADD) ||
779 (kind == Token::kSUB) || 820 (kind == Token::kSUB) ||
780 (kind == Token::kMUL) || 821 (kind == Token::kMUL) ||
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
1204 // instead of calling the operator. 1245 // instead of calling the operator.
1205 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) { 1246 if ((node->kind() == Token::kAND) || (node->kind() == Token::kOR)) {
1206 if (FLAG_enable_type_checks) { 1247 if (FLAG_enable_type_checks) {
1207 CodeGenerator::VisitBinaryOpNode(node); 1248 CodeGenerator::VisitBinaryOpNode(node);
1208 return; 1249 return;
1209 } 1250 }
1210 GenerateLogicalBinaryOp(node); 1251 GenerateLogicalBinaryOp(node);
1211 return; 1252 return;
1212 } 1253 }
1213 1254
1214 ObjectStore* object_store = Isolate::Current()->object_store(); 1255 const ICData& ic_data = node->ICDataAtId(node->id());
1256 if (ic_data.NumberOfChecks() == 0) {
1257 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
1258 DeoptimizationBlob* deopt_blob =
1259 AddDeoptimizationBlob(node, EAX, EDX, kDeoptNoTypeFeedback);
1260 __ jmp(deopt_blob->label());
1261 return;
1262 }
1263
1215 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 1264 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
1216 GenerateSmiBinaryOp(node); 1265 GenerateSmiBinaryOp(node);
1217 return; 1266 return;
1218 } 1267 }
1219 1268
1220 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 1269 if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) {
1221 GenerateDoubleBinaryOp(node); 1270 GenerateDoubleBinaryOp(node);
1222 return; 1271 return;
1223 } 1272 }
1224 1273
1225 if (AtIdNodeHasReceiverClass(node, 1274 const Class& mint_class =
1226 node->id(), 1275 Class::Handle(Isolate::Current()->object_store()->mint_class());
1227 Class::Handle(object_store->mint_class()))) { 1276 if (AtIdNodeHasReceiverClass(node, node->id(), mint_class)) {
1228 GenerateMintBinaryOp(node, false); 1277 GenerateMintBinaryOp(node, false);
1229 return; 1278 return;
1230 } 1279 }
1231 1280
1232 if (NodeHasBothReceiverClasses(node, 1281 if (NodeHasBothReceiverClasses(node, smi_class_, mint_class)) {
1233 smi_class_, Class::Handle(object_store->mint_class()))) {
1234 GenerateMintBinaryOp(node, true); 1282 GenerateMintBinaryOp(node, true);
1235 return; 1283 return;
1236 } 1284 }
1237 1285
1238 // TODO(srdjan): Handle "+" for strings. 1286 // TODO(srdjan): Implement "+" for Strings.
1239 // Type feedback tells this is not a Smi or Double operation. 1287 // Type feedback tells this is not a Smi or Double operation.
1240 TraceNotOpt(node, 1288 TraceNotOpt(node,
1241 "BinaryOp: type feedback tells this is not a Smi or Double op"); 1289 "BinaryOp: type feedback tells this is not a Smi, Mint or Double op");
1242 CodeGenerator::VisitBinaryOpNode(node); 1290 node->left()->Visit(this);
1291 node->right()->Visit(this);
1292 const int number_of_arguments = 2;
1293 const Array& no_optional_argument_names = Array::Handle();
1294 GenerateCheckedInstanceCalls(node,
1295 node->left(),
1296 node->id(),
1297 node->token_index(),
1298 number_of_arguments,
1299 no_optional_argument_names);
1300 if (IsResultNeeded(node)) {
1301 __ pushl(EAX);
1302 }
1243 return; 1303 return;
1244 } 1304 }
1245 1305
1246 1306
1247 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) { 1307 void OptimizingCodeGenerator::VisitIncrOpLocalNode(IncrOpLocalNode* node) {
1248 if (FLAG_enable_type_checks) { 1308 if (FLAG_enable_type_checks) {
1249 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle()); 1309 classes_for_locals_->SetLocalType(node->local(), Class::ZoneHandle());
1250 CodeGenerator::VisitIncrOpLocalNode(node); 1310 CodeGenerator::VisitIncrOpLocalNode(node);
1251 return; 1311 return;
1252 } 1312 }
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after
2174 __ j(condition, &is_true); 2234 __ j(condition, &is_true);
2175 __ PushObject(bool_false); 2235 __ PushObject(bool_false);
2176 __ jmp(&done); 2236 __ jmp(&done);
2177 __ Bind(&is_true); 2237 __ Bind(&is_true);
2178 __ PushObject(bool_true); 2238 __ PushObject(bool_true);
2179 __ Bind(&done); 2239 __ Bind(&done);
2180 } 2240 }
2181 return; 2241 return;
2182 } 2242 }
2183 2243
2244 if (Token::IsInstanceofOperator(node->kind())) {
2245 VisitLoadOne(node->left(), EAX);
2246 ASSERT(node->right()->IsTypeNode());
2247 GenerateInstanceOf(node->id(),
2248 node->token_index(),
2249 node->right()->AsTypeNode()->type(),
2250 (node->kind() == Token::kISNOT));
2251 if (!IsResultNeeded(node)) {
2252 __ popl(EAX); // Pop the result of the instanceof operation.
2253 }
2254 return;
2255 }
2256
2184 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) { 2257 if (AtIdNodeHasReceiverClass(node, node->id(), smi_class_)) {
2185 if (GenerateSmiComparison(node)) { 2258 if (GenerateSmiComparison(node)) {
2259 // The comparison was handled, code was emitted.
2186 return; 2260 return;
2187 } 2261 }
2188 // Fall through if condition is not supported. 2262 // Fall through if condition is not supported.
2189 } else if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) { 2263 } else if (AtIdNodeHasReceiverClass(node, node->id(), double_class_)) {
2190 // Double comparison 2264 // Double comparison
2191 if (GenerateDoubleComparison(node)) { 2265 if (GenerateDoubleComparison(node)) {
2192 return; 2266 return;
2193 } 2267 }
2194 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) { 2268 } else if ((node->kind() == Token::kEQ) || (node->kind() == Token::kNE)) {
2195 // Equality, not-equality comparison of any other type. 2269 // Equality, not-equality comparison of any other type.
2196 if (GenerateEqualityComparison(node)) { 2270 if (GenerateEqualityComparison(node)) {
2197 return; 2271 return;
2198 } 2272 }
2199 } 2273 }
2200 2274
2201 // Fall through here if a comparison was not implemented. 2275 // Fall through here if a comparison was not implemented.
2276 // TODO(srdjan): Implement for Strings.
2202 CodeGenerator::VisitComparisonNode(node); 2277 CodeGenerator::VisitComparisonNode(node);
2203 } 2278 }
2204 2279
2205 2280
2206 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { 2281 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) {
2207 const char* kMessage = "Inline indexed access"; 2282 const char* kMessage = "Inline indexed access";
2208 ObjectStore* object_store = Isolate::Current()->object_store(); 2283 ObjectStore* object_store = Isolate::Current()->object_store();
2209 const Class& object_array_class = 2284 const Class& object_array_class =
2210 Class::ZoneHandle(object_store->array_class()); 2285 Class::ZoneHandle(object_store->array_class());
2211 const Class& immutable_object_array_class = 2286 const Class& immutable_object_array_class =
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
2508 const ICData& ic_data, 2583 const ICData& ic_data,
2509 const Function& null_target, 2584 const Function& null_target,
2510 GrowableArray<const Class*>* classes, 2585 GrowableArray<const Class*>* classes,
2511 GrowableArray<const Function*>* targets) { 2586 GrowableArray<const Function*>* targets) {
2512 ASSERT(classes != NULL); 2587 ASSERT(classes != NULL);
2513 ASSERT(targets != NULL); 2588 ASSERT(targets != NULL);
2514 // Check if we can add Smi class in front. 2589 // Check if we can add Smi class in front.
2515 Class& smi_test_class = Class::Handle(); 2590 Class& smi_test_class = Class::Handle();
2516 Function& smi_target = Function::ZoneHandle(); 2591 Function& smi_target = Function::ZoneHandle();
2517 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 2592 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
2518 ic_data.GetOneClassCheckAt(i, &smi_test_class, &smi_target); 2593 GrowableArray<const Class*> test_classes;
2594 ic_data.GetCheckAt(i, &test_classes, &smi_target);
2595 smi_test_class = test_classes[0]->raw();
2519 if (smi_test_class.raw() == smi_class_.raw()) { 2596 if (smi_test_class.raw() == smi_class_.raw()) {
2520 classes->Add(&Class::ZoneHandle(smi_class_.raw())); 2597 classes->Add(&Class::ZoneHandle(smi_class_.raw()));
2521 targets->Add(&Function::ZoneHandle(smi_target.raw())); 2598 targets->Add(&Function::ZoneHandle(smi_target.raw()));
2522 break; 2599 break;
2523 } 2600 }
2524 } 2601 }
2525 // Add all classes except Smi. 2602 // Add all classes except Smi.
2526 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { 2603 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
2527 Function& target = Function::ZoneHandle(); 2604 Function& target = Function::ZoneHandle();
2528 Class& cls = Class::ZoneHandle(); 2605 Class& cls = Class::ZoneHandle();
2529 ic_data.GetOneClassCheckAt(i, &cls, &target); 2606 GrowableArray<const Class*> test_classes;
2607 ic_data.GetCheckAt(i, &test_classes, &target);
2608 cls = test_classes[0]->raw();
2530 ASSERT(!cls.IsNullClass()); 2609 ASSERT(!cls.IsNullClass());
2531 if (cls.raw() != smi_class_.raw()) { 2610 if (cls.raw() != smi_class_.raw()) {
2532 ASSERT(!cls.IsNull()); 2611 ASSERT(!cls.IsNull());
2533 ASSERT(!target.IsNull()); 2612 ASSERT(!target.IsNull());
2534 classes->Add(&cls); 2613 classes->Add(&cls);
2535 targets->Add(&target); 2614 targets->Add(&target);
2536 } 2615 }
2537 } 2616 }
2538 // Do not add a target that has not been compiled yet. 2617 // Do not add a target that has not been compiled yet.
2539 if (!null_target.IsNull() && null_target.HasCode()) { 2618 if (!null_target.IsNull() && null_target.HasCode()) {
2540 ASSERT(null_target.IsZoneHandle()); 2619 ASSERT(null_target.IsZoneHandle());
2541 classes->Add(&Class::ZoneHandle(Object::null_class())); 2620 classes->Add(&Class::ZoneHandle(Object::null_class()));
2542 targets->Add(&null_target); 2621 targets->Add(&null_target);
2543 } 2622 }
2544 } 2623 }
2545 2624
2546 2625
2547 // Use ICData in 'node' to issues checks and calls. 2626 // Use ICData in 'node' to issues checks and calls.
2627 // IC data can contain one or more argument checks.
2548 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls( 2628 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls(
2549 AstNode* node, 2629 AstNode* node,
2550 AstNode* receiver, 2630 AstNode* receiver,
2551 intptr_t node_id, 2631 intptr_t node_id,
2552 intptr_t token_index, 2632 intptr_t token_index,
2553 intptr_t num_args, 2633 intptr_t num_args,
2554 const Array& optional_arguments_names) { 2634 const Array& optional_arguments_names) {
2555 ASSERT(node != NULL); 2635 ASSERT(node != NULL);
2556 ASSERT(receiver != NULL); 2636 ASSERT(receiver != NULL);
2557 ASSERT(num_args > 0); 2637 ASSERT(num_args > 0);
2558 const ICData& ic_data = node->ICDataAtId(node_id); 2638 const ICData& ic_data = node->ICDataAtId(node_id);
2559 if (ic_data.NumberOfChecks() == 0) { 2639 if (ic_data.NumberOfChecks() == 0) {
2560 // No type feedback means node was never executed. However that can be 2640 // No type feedback means node was never executed. However that can be
2561 // a common case especially in case of large switch statements. 2641 // a common case especially in case of large switch statements.
2562 // Use a special inline cache call which can help us decide when to 2642 // Use a special inline cache call which can help us decide when to
2563 // re-optimize this optiumized function. 2643 // re-optimize this optiumized function.
2564 GenerateInlineCacheCall( 2644 GenerateInlineCacheCall(
2565 node_id, token_index, ic_data, num_args, optional_arguments_names); 2645 node_id, token_index, ic_data, num_args, optional_arguments_names);
2566 return; 2646 return;
2567 } 2647 }
2568 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
2569 2648
2570 Function& target_for_null = Function::ZoneHandle(); 2649 Function& target_for_null = Function::ZoneHandle();
2571 ObjectStore* object_store = Isolate::Current()->object_store(); 2650 ObjectStore* object_store = Isolate::Current()->object_store();
2572 int num_optional_args = 2651 int num_optional_args =
2573 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); 2652 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length();
2574 target_for_null = Resolver::ResolveDynamicForReceiverClass( 2653 target_for_null = Resolver::ResolveDynamicForReceiverClass(
2575 Class::Handle(object_store->object_class()), 2654 Class::Handle(object_store->object_class()),
2576 String::Handle(ic_data.FunctionName()), 2655 String::Handle(ic_data.FunctionName()),
2577 num_args, 2656 num_args,
2578 num_optional_args); 2657 num_optional_args);
2579 GrowableArray<const Class*> classes; 2658 GrowableArray<const Class*> classes;
2580 GrowableArray<const Function*> targets; 2659 GrowableArray<const Function*> targets;
2660 // Make Smi class the first one, if it is in the list.
2581 NormalizeClassChecks(ic_data, target_for_null, &classes, &targets); 2661 NormalizeClassChecks(ic_data, target_for_null, &classes, &targets);
2582 ASSERT(!classes.is_empty()); 2662 ASSERT(!classes.is_empty());
2583 ASSERT(classes.length() == targets.length()); 2663 ASSERT(classes.length() == targets.length());
2584 intptr_t start_ix = 0; 2664 intptr_t start_ix = 0;
2585 2665
2586 Label done; 2666 Label done;
2587 __ movl(EAX, Address(ESP, (num_args - 1) * kWordSize)); // Load receiver. 2667 __ movl(EAX, Address(ESP, (num_args - 1) * kWordSize)); // Load receiver.
2588 if (classes[0]->raw() == smi_class_.raw()) { 2668 if (classes[0]->raw() == smi_class_.raw()) {
2589 start_ix++; 2669 start_ix++;
2590 // Smi test is needed. 2670 // Smi test is needed.
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
2772 } 2852 }
2773 2853
2774 2854
2775 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) { 2855 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) {
2776 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) { 2856 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) {
2777 CodeGenerator::VisitReturnNode(node); 2857 CodeGenerator::VisitReturnNode(node);
2778 return; 2858 return;
2779 } 2859 }
2780 ASSERT(!IsResultNeeded(node)); 2860 ASSERT(!IsResultNeeded(node));
2781 ASSERT(node->value() != NULL); 2861 ASSERT(node->value() != NULL);
2782 VisitLoadOne(node->value(), EAX); 2862 CodeGenInfo value_info(node->value());
2863 value_info.set_request_result_in_eax(true);
2864 node->value()->Visit(this);
2865 if (!value_info.result_returned_in_eax()) {
2866 __ popl(EAX);
2867 }
2783 GenerateReturnEpilog(); 2868 GenerateReturnEpilog();
2784 } 2869 }
2785 2870
2786 2871
2787 void OptimizingCodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) { 2872 void OptimizingCodeGenerator::VisitSequenceNode(SequenceNode* node_sequence) {
2788 // TODO(srdjan): Allow limited forwarding of types across sequence nodes. 2873 // TODO(srdjan): Allow limited forwarding of types across sequence nodes.
2789 classes_for_locals_->Clear(); 2874 classes_for_locals_->Clear();
2790 const intptr_t num_context_variables = (node_sequence->scope() != NULL) ? 2875 const intptr_t num_context_variables = (node_sequence->scope() != NULL) ?
2791 node_sequence->scope()->num_context_variables() : 0; 2876 node_sequence->scope()->num_context_variables() : 0;
2792 if (FLAG_enable_type_checks || (num_context_variables > 0)) { 2877 if (FLAG_enable_type_checks || (num_context_variables > 0)) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2827 } 2912 }
2828 2913
2829 2914
2830 void OptimizingCodeGenerator::VisitTryCatchNode(TryCatchNode* node) { 2915 void OptimizingCodeGenerator::VisitTryCatchNode(TryCatchNode* node) {
2831 // TODO(srdjan): Set classes for locals. 2916 // TODO(srdjan): Set classes for locals.
2832 classes_for_locals_->Clear(); 2917 classes_for_locals_->Clear();
2833 CodeGenerator::VisitTryCatchNode(node); 2918 CodeGenerator::VisitTryCatchNode(node);
2834 } 2919 }
2835 2920
2836 2921
2922 void OptimizingCodeGenerator::VisitUnaryOpNode(UnaryOpNode* node) {
2923 if (FLAG_enable_type_checks) {
2924 CodeGenerator::VisitUnaryOpNode(node);
2925 return;
2926 }
2927 // TODO(srdjan): Jump directly to labels instead of returning a boolean.
2928 if (node->kind() == Token::kNOT) {
2929 // Only a true bool returns false, everything else is true.
2930 CodeGenInfo info(node->operand());
2931 VisitLoadOne(node->operand(), EDX);
2932 Label done;
2933 __ LoadObject(EAX, Bool::ZoneHandle(Bool::True()));
2934 __ cmpl(EDX, EAX);
2935 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
2936 __ LoadObject(EAX, Bool::ZoneHandle(Bool::False()));
2937 __ Bind(&done);
2938 if (CodeGenerator::IsResultNeeded(node)) {
2939 if (IsResultInEaxRequested(node)) {
2940 node->info()->set_result_returned_in_eax(true);
2941 } else {
2942 __ pushl(EAX);
2943 }
2944 }
2945 return;
2946 }
2947
2948 if ((node->kind() == Token::kSUB) || (node->kind() == Token::kBIT_NOT)) {
2949 if (AtIdNodeHasOnlyClass(node, node->id(), smi_class_)) {
2950 const ICData& ic_data = node->ICDataAtId(node->id());
2951 ASSERT(ic_data.NumberOfArgumentsChecked() == 1);
2952 GenerateSmiUnaryOp(node);
2953 return;
2954 }
2955 }
2956 // TODO(srdjan): Implement unary kSUB (negate) for doubles and Mint.
2957 CodeGenerator::VisitUnaryOpNode(node);
2958 }
2959
2960
2837 } // namespace dart 2961 } // namespace dart
2838 2962
2839 #endif // defined TARGET_ARCH_IA32 2963 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/opt_code_generator_ia32.h ('k') | runtime/vm/stub_code_ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698