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

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

Issue 9022019: Do back propagation of types(classes) for checks in load and store indexed. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 12 months 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 | « no previous file | 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 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 } 693 }
694 694
695 695
696 // SHL: Implement with slow case so that it works both with Smi and Mint types. 696 // SHL: Implement with slow case so that it works both with Smi and Mint types.
697 // Result is in EAX. Mangles ECX, EBX, EDX. 697 // Result is in EAX. Mangles ECX, EBX, EDX.
698 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) { 698 void OptimizingCodeGenerator::GenerateSmiShiftBinaryOp(BinaryOpNode* node) {
699 if (node->kind() == Token::kSAR) { 699 if (node->kind() == Token::kSAR) {
700 // TODO(srdjan): Implement for Mint? 700 // TODO(srdjan): Implement for Mint?
701 DeoptimizationBlob* deopt_blob = 701 DeoptimizationBlob* deopt_blob =
702 AddDeoptimizationBlob(node, EAX, ECX, kDeoptSAR); 702 AddDeoptimizationBlob(node, EAX, ECX, kDeoptSAR);
703 CodeGenInfo left_info(node->left());
704 CodeGenInfo right_info(node->right());
703 // EAX: value to shift, ECX: amount to shift. 705 // EAX: value to shift, ECX: amount to shift.
704 VisitLoadTwo(node->left(), node->right(), EAX, ECX); 706 VisitLoadTwo(node->left(), node->right(), EAX, ECX);
705 // Check if both Smi. 707 if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) {
706 __ movl(EBX, EAX); 708 // Check if both Smi.
707 __ orl(EBX, ECX); 709 __ movl(EBX, EAX);
708 __ testl(EBX, Immediate(kSmiTagMask)); 710 __ orl(EBX, ECX);
709 __ j(NOT_ZERO, deopt_blob->label()); 711 __ testl(EBX, Immediate(kSmiTagMask));
712 __ j(NOT_ZERO, deopt_blob->label());
713 PropagateBackLocalClass(node->left(), smi_class_);
714 PropagateBackLocalClass(node->right(), smi_class_);
715 }
710 Immediate count_limit = Immediate(0x1F); 716 Immediate count_limit = Immediate(0x1F);
711 __ SmiUntag(ECX); 717 __ SmiUntag(ECX);
712 __ cmpl(ECX, count_limit); 718 __ cmpl(ECX, count_limit);
713 Label shift_count_ok; 719 Label shift_count_ok;
714 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); 720 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
715 __ movl(ECX, count_limit); 721 __ movl(ECX, count_limit);
716 __ Bind(&shift_count_ok); 722 __ Bind(&shift_count_ok);
717 // Shift amount must be in ECX. 723 // Shift amount must be in ECX.
718 __ SmiUntag(EAX); // Value. 724 __ SmiUntag(EAX); // Value.
719 __ sarl(EAX, ECX); 725 __ sarl(EAX, ECX);
720 __ SmiTag(EAX); 726 __ SmiTag(EAX);
721 return; 727 return;
722 } 728 }
723 ASSERT(node->kind() == Token::kSHL); 729 ASSERT(node->kind() == Token::kSHL);
724 if (node->right()->IsLiteralNode() && 730 if (node->right()->IsLiteralNode() &&
725 node->right()->AsLiteralNode()->literal().IsSmi()) { 731 node->right()->AsLiteralNode()->literal().IsSmi()) {
726 Label done; 732 Label done;
727 // Shift count is a Smi literal. 733 // Shift count is a Smi literal.
728 Smi& smi = Smi::Handle(); 734 Smi& smi = Smi::Handle();
729 smi ^= node->right()->AsLiteralNode()->literal().raw(); 735 smi ^= node->right()->AsLiteralNode()->literal().raw();
730 if (smi.Value() < Smi::kBits) { 736 if (smi.Value() < Smi::kBits) {
731 Label slow_case; 737 Label slow_case;
738 CodeGenInfo left_info(node->left());
732 VisitLoadOne(node->left(), EAX); 739 VisitLoadOne(node->left(), EAX);
733 __ testl(EAX, Immediate(kSmiTagMask)); 740 if (!left_info.IsClass(smi_class_)) {
734 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); // left not smi 741 __ testl(EAX, Immediate(kSmiTagMask));
742 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); // left not smi
743 }
735 // Overflow test. 744 // Overflow test.
736 __ movl(EBX, EAX); 745 __ movl(EBX, EAX);
737 Immediate imm(smi.Value()); 746 Immediate imm(smi.Value());
738 __ shll(EBX, imm); 747 __ shll(EBX, imm);
739 __ sarl(EBX, imm); 748 __ sarl(EBX, imm);
740 __ cmpl(EAX, EBX); 749 __ cmpl(EAX, EBX);
741 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow. 750 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
742 __ shll(EAX, imm); // Shift for result now we know there is no overflow. 751 __ shll(EAX, imm); // Shift for result now we know there is no overflow.
743 __ jmp(&done); 752 __ jmp(&done);
744 __ Bind(&slow_case); 753 __ Bind(&slow_case);
745 __ pushl(EAX); 754 __ pushl(EAX);
746 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw()))); 755 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw())));
747 const int number_of_arguments = 2; 756 const int number_of_arguments = 2;
748 const Array& no_optional_argument_names = Array::Handle(); 757 const Array& no_optional_argument_names = Array::Handle();
749 GenerateCheckedInstanceCalls(node, 758 GenerateCheckedInstanceCalls(node,
750 node->left(), 759 node->left(),
751 node->id(), 760 node->id(),
752 node->token_index(), 761 node->token_index(),
753 number_of_arguments, 762 number_of_arguments,
754 no_optional_argument_names); 763 no_optional_argument_names);
755 __ Bind(&done); 764 __ Bind(&done);
756 return; 765 return;
757 } 766 }
758 } 767 }
759 768
760 Label slow_case, done; 769 Label slow_case, done;
770 CodeGenInfo left_info(node->left());
771 CodeGenInfo right_info(node->right());
761 VisitLoadTwo(node->left(), node->right(), EAX, EDX); 772 VisitLoadTwo(node->left(), node->right(), EAX, EDX);
762 // TODO(srdjan): Better code for count being a Smi literal. 773 // TODO(srdjan): Better code for count being a Smi literal.
763 // EAX: value, EDX: shift amount. Preserve them for slow case. 774 // EAX: value, EDX: shift amount. Preserve them for slow case.
764 // Fast case only if both ar Smi. 775 // Fast case only if both ar Smi.
765 __ movl(EBX, EAX); 776 if (!left_info.IsClass(smi_class_) || !right_info.IsClass(smi_class_)) {
766 __ orl(EBX, EDX); 777 __ movl(EBX, EAX);
767 __ testl(EBX, Immediate(kSmiTagMask)); 778 __ orl(EBX, EDX);
768 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); 779 __ testl(EBX, Immediate(kSmiTagMask));
780 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump);
781 }
769 // Check if count too large for handling it inlined. 782 // Check if count too large for handling it inlined.
770 __ cmpl(EDX, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits)))); 783 __ cmpl(EDX, Immediate(reinterpret_cast<int32_t>(Smi::New(Smi::kBits))));
771 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); 784 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump);
772 // Shift amount must be in ECX. 785 // Shift amount must be in ECX.
773 __ movl(ECX, EDX); 786 __ movl(ECX, EDX);
774 __ movl(EBX, EAX); 787 __ movl(EBX, EAX);
775 __ SmiUntag(ECX); 788 __ SmiUntag(ECX);
776 // Overflow test. 789 // Overflow test.
777 __ shll(EBX, ECX); 790 __ shll(EBX, ECX);
778 __ sarl(EBX, ECX); 791 __ sarl(EBX, ECX);
(...skipping 27 matching lines...) Expand all
806 DeoptimizationBlob* deopt_blob = 819 DeoptimizationBlob* deopt_blob =
807 AddDeoptimizationBlob(node, EAX, deopt_reason_id); 820 AddDeoptimizationBlob(node, EAX, deopt_reason_id);
808 CodeGenInfo info(node->operand()); 821 CodeGenInfo info(node->operand());
809 VisitLoadOne(node->operand(), EAX); 822 VisitLoadOne(node->operand(), EAX);
810 if (ic_data.NumberOfChecks() == 0) { 823 if (ic_data.NumberOfChecks() == 0) {
811 // No type feedback. 824 // No type feedback.
812 __ jmp(deopt_blob->label()); 825 __ jmp(deopt_blob->label());
813 return; 826 return;
814 } 827 }
815 ASSERT(ic_data.NumberOfChecks() == 1); 828 ASSERT(ic_data.NumberOfChecks() == 1);
816 __ testl(EAX, Immediate(kSmiTagMask)); 829 if (!info.IsClass(smi_class_)) {
817 __ j(NOT_ZERO, deopt_blob->label()); 830 __ testl(EAX, Immediate(kSmiTagMask));
831 __ j(NOT_ZERO, deopt_blob->label());
832 PropagateBackLocalClass(node->operand(), smi_class_);
833 }
818 if (node->kind() == Token::kSUB) { 834 if (node->kind() == Token::kSUB) {
819 __ negl(EAX); 835 __ negl(EAX);
820 __ j(OVERFLOW, deopt_blob->label()); 836 __ j(OVERFLOW, deopt_blob->label());
821 } else { 837 } else {
822 ASSERT(node->kind() == Token::kBIT_NOT); 838 ASSERT(node->kind() == Token::kBIT_NOT);
823 __ notl(EAX); 839 __ notl(EAX);
824 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 840 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
825 } 841 }
826 HandleResult(node, EAX); 842 HandleResult(node, EAX);
827 } 843 }
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after
2367 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) { 2383 void OptimizingCodeGenerator::VisitLoadIndexedNode(LoadIndexedNode* node) {
2368 const char* kMessage = "Inline indexed access"; 2384 const char* kMessage = "Inline indexed access";
2369 ObjectStore* object_store = Isolate::Current()->object_store(); 2385 ObjectStore* object_store = Isolate::Current()->object_store();
2370 const Class& object_array_class = 2386 const Class& object_array_class =
2371 Class::ZoneHandle(object_store->array_class()); 2387 Class::ZoneHandle(object_store->array_class());
2372 const Class& immutable_object_array_class = 2388 const Class& immutable_object_array_class =
2373 Class::ZoneHandle(object_store->immutable_array_class()); 2389 Class::ZoneHandle(object_store->immutable_array_class());
2374 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) || 2390 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ||
2375 AtIdNodeHasClassAt(node, node->id(), 2391 AtIdNodeHasClassAt(node, node->id(),
2376 immutable_object_array_class, 0)) { 2392 immutable_object_array_class, 0)) {
2393 CodeGenInfo array_info(node->array());
2394 CodeGenInfo index_info(node->index_expr());
2377 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX); 2395 VisitLoadTwo(node->array(), node->index_expr(), EBX, EDX);
2378 DeoptimizationBlob* deopt_blob = 2396 DeoptimizationBlob* deopt_blob =
2379 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray); 2397 AddDeoptimizationBlob(node, EBX, EDX, kDeoptLoadIndexedFixedArray);
2380 const Class& test_class = 2398 const Class& test_class =
2381 AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ? 2399 AtIdNodeHasClassAt(node, node->id(), object_array_class, 0) ?
2382 object_array_class : immutable_object_array_class; 2400 object_array_class : immutable_object_array_class;
2383 // Type checks of array. 2401 // Type checks of array.
2384 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi. 2402 if (!array_info.IsClass(test_class)) {
2385 __ j(ZERO, deopt_blob->label()); 2403 __ testl(EBX, Immediate(kSmiTagMask)); // Deoptimize if Smi.
2386 __ movl(EAX, FieldAddress(EBX, Object::class_offset())); 2404 __ j(ZERO, deopt_blob->label());
2387 __ CompareObject(EAX, test_class); 2405 __ movl(EAX, FieldAddress(EBX, Object::class_offset()));
2388 __ j(NOT_EQUAL, deopt_blob->label()); 2406 __ CompareObject(EAX, test_class);
2407 __ j(NOT_EQUAL, deopt_blob->label());
2408 PropagateBackLocalClass(node->array(), test_class);
2409 }
2389 2410
2390 // Type check of index. 2411 // Type check of index.
2391 __ testl(EDX, Immediate(kSmiTagMask)); 2412 if (!index_info.IsClass(smi_class_)) {
2392 __ j(NOT_ZERO, deopt_blob->label()); 2413 __ testl(EDX, Immediate(kSmiTagMask));
2414 __ j(NOT_ZERO, deopt_blob->label());
2415 PropagateBackLocalClass(node->index_expr(), smi_class_);
2416 }
2393 // Range check. 2417 // Range check.
2394 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset())); 2418 __ cmpl(EDX, FieldAddress(EBX, Array::length_offset()));
2395 __ j(ABOVE_EQUAL, deopt_blob->label()); 2419 __ j(ABOVE_EQUAL, deopt_blob->label());
2396 // Note that EDX is Smi, i.e, times 2. 2420 // Note that EDX is Smi, i.e, times 2.
2397 ASSERT(kSmiTagShift == 1); 2421 ASSERT(kSmiTagShift == 1);
2398 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray))); 2422 __ movl(EAX, FieldAddress(EBX, EDX, TIMES_2, sizeof(RawArray)));
2399 HandleResult(node, EAX); 2423 HandleResult(node, EAX);
2400 TraceOpt(node, kMessage); 2424 TraceOpt(node, kMessage);
2401 return; 2425 return;
2402 } 2426 }
2403 2427
2404 const String& growable_object_array_class_name = String::Handle( 2428 const String& growable_object_array_class_name = String::Handle(
2405 String::NewSymbol(kGrowableArrayClassName)); 2429 String::NewSymbol(kGrowableArrayClassName));
2406 const Class& growable_array_class = Class::ZoneHandle( 2430 const Class& growable_array_class = Class::ZoneHandle(
2407 Library::Handle(Library::CoreImplLibrary()). 2431 Library::Handle(Library::CoreImplLibrary()).
2408 LookupClass(growable_object_array_class_name)); 2432 LookupClass(growable_object_array_class_name));
2409 ASSERT(!growable_array_class.IsNull()); 2433 ASSERT(!growable_array_class.IsNull());
2410 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) { 2434 if (AtIdNodeHasClassAt(node, node->id(), growable_array_class, 0)) {
2411 const String& growable_array_length_field_name = 2435 const String& growable_array_length_field_name =
2412 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName)); 2436 String::Handle(String::NewSymbol(kGrowableArrayLengthFieldName));
2413 const String& growable_array_array_field_name = 2437 const String& growable_array_array_field_name =
2414 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName)); 2438 String::Handle(String::NewSymbol(kGrowableArrayArrayFieldName));
2415 intptr_t length_offset = GetFieldOffset(growable_array_class, 2439 intptr_t length_offset = GetFieldOffset(growable_array_class,
2416 growable_array_length_field_name); 2440 growable_array_length_field_name);
2417 intptr_t array_offset = GetFieldOffset(growable_array_class, 2441 intptr_t array_offset = GetFieldOffset(growable_array_class,
2418 growable_array_array_field_name); 2442 growable_array_array_field_name);
2443 CodeGenInfo array_info(node->array());
2444 CodeGenInfo index_info(node->index_expr());
2419 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX); 2445 VisitLoadTwo(node->array(), node->index_expr(), EDX, EAX);
2420 DeoptimizationBlob* deopt_blob = 2446 DeoptimizationBlob* deopt_blob =
2421 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray); 2447 AddDeoptimizationBlob(node, EDX, EAX, kDeoptLoadIndexedGrowableArray);
2422 // TODO(srdjan): Use CodeGenInfo to eliminate Smi test if possible.
2423 // EAX: index, EDX: array. 2448 // EAX: index, EDX: array.
2424 __ testl(EAX, Immediate(kSmiTagMask)); 2449 if (!index_info.IsClass(smi_class_)) {
2425 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index. 2450 __ testl(EAX, Immediate(kSmiTagMask));
2426 __ testl(EDX, Immediate(kSmiTagMask)); 2451 __ j(NOT_ZERO, deopt_blob->label()); // Not Smi index.
2427 __ j(ZERO, deopt_blob->label()); // Array is Smi. 2452 PropagateBackLocalClass(node->index_expr(), smi_class_);
2428 __ movl(EBX, FieldAddress(EDX, Object::class_offset())); 2453 }
2429 __ CompareObject(EBX, growable_array_class); 2454 if (!array_info.IsClass(growable_array_class)) {
2430 __ j(NOT_EQUAL, deopt_blob->label()); // Array is not GrowableObjectArray. 2455 __ testl(EDX, Immediate(kSmiTagMask));
2456 __ j(ZERO, deopt_blob->label()); // Array is Smi.
2457 __ movl(EBX, FieldAddress(EDX, Object::class_offset()));
2458 __ CompareObject(EBX, growable_array_class);
2459 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray.
2460 PropagateBackLocalClass(node->array(), growable_array_class);
2461 }
2431 // Range check: deoptimize if out of bounds. 2462 // Range check: deoptimize if out of bounds.
2432 __ cmpl(EAX, FieldAddress(EDX, length_offset)); 2463 __ cmpl(EAX, FieldAddress(EDX, length_offset));
2433 __ j(ABOVE_EQUAL, deopt_blob->label()); 2464 __ j(ABOVE_EQUAL, deopt_blob->label());
2434 __ movl(EDX, FieldAddress(EDX, array_offset)); // backingArray. 2465 __ movl(EDX, FieldAddress(EDX, array_offset)); // backingArray.
2435 // Note that EAX is Smi, i.e, times 2. 2466 // Note that EAX is Smi, i.e, times 2.
2436 ASSERT(kSmiTagShift == 1); 2467 ASSERT(kSmiTagShift == 1);
2437 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray))); 2468 __ movl(EAX, FieldAddress(EDX, EAX, TIMES_2, sizeof(RawArray)));
2438 HandleResult(node, EAX); 2469 HandleResult(node, EAX);
2439 return; 2470 return;
2440 } else { 2471 } else {
(...skipping 16 matching lines...) Expand all
2457 Class::ZoneHandle(object_store->array_class()); 2488 Class::ZoneHandle(object_store->array_class());
2458 const ICData& ic_data = node->ICDataAtId(node->id()); 2489 const ICData& ic_data = node->ICDataAtId(node->id());
2459 if (ic_data.NumberOfChecks() == 0) { 2490 if (ic_data.NumberOfChecks() == 0) {
2460 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2491 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2461 DeoptimizationBlob* deopt_blob = 2492 DeoptimizationBlob* deopt_blob =
2462 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback); 2493 AddDeoptimizationBlob(node, EBX, ECX, kDeoptNoTypeFeedback);
2463 __ jmp(deopt_blob->label()); 2494 __ jmp(deopt_blob->label());
2464 return; 2495 return;
2465 } 2496 }
2466 2497
2498 CodeGenInfo array_info(node->array());
2499 CodeGenInfo index_info(node->index_expr());
2500
2467 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) { 2501 if (AtIdNodeHasClassAt(node, node->id(), object_array_class, 0)) {
2468 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2502 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2469 DeoptimizationBlob* deopt_blob = 2503 DeoptimizationBlob* deopt_blob =
2470 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); 2504 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed);
2471 __ popl(EAX); // array. 2505 __ popl(EAX); // array.
2472 // ECX: value, EBX:index, EAX: array. 2506 // ECX: value, EBX:index, EAX: array.
2473 // Check class of array. 2507 // Check class of array.
2474 __ testl(EAX, Immediate(kSmiTagMask)); 2508 if (!array_info.IsClass(object_array_class)) {
2475 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. 2509 __ testl(EAX, Immediate(kSmiTagMask));
2476 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); 2510 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt.
2477 __ CompareObject(EDX, object_array_class); 2511 __ movl(EDX, FieldAddress(EAX, Object::class_offset()));
2478 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt. 2512 __ CompareObject(EDX, object_array_class);
2513 __ j(NOT_EQUAL, deopt_blob->label()); // Not ObjectArray -> deopt.
2514 PropagateBackLocalClass(node->array(), object_array_class);
2515 }
2479 // Check class of index. 2516 // Check class of index.
2480 __ testl(EBX, Immediate(kSmiTagMask)); 2517 if (!index_info.IsClass(smi_class_)) {
2481 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. 2518 __ testl(EBX, Immediate(kSmiTagMask));
2519 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt.
2520 PropagateBackLocalClass(node->index_expr(), smi_class_);
2521 }
2482 // Range check. 2522 // Range check.
2483 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); 2523 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset()));
2484 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt. 2524 __ j(ABOVE_EQUAL, deopt_blob->label()); // Range error -> deopt.
2485 ASSERT(kSmiTagShift == 1); 2525 ASSERT(kSmiTagShift == 1);
2486 __ StoreIntoObject(EAX, 2526 __ StoreIntoObject(EAX,
2487 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)), 2527 FieldAddress(EAX, EBX, TIMES_2, sizeof(RawArray)),
2488 ECX); 2528 ECX);
2489 HandleResult(node, ECX); 2529 HandleResult(node, ECX);
2490 return; 2530 return;
2491 } 2531 }
(...skipping 12 matching lines...) Expand all
2504 intptr_t length_offset = GetFieldOffset(growable_array_class, 2544 intptr_t length_offset = GetFieldOffset(growable_array_class,
2505 growable_array_length_field_name); 2545 growable_array_length_field_name);
2506 intptr_t array_offset = GetFieldOffset(growable_array_class, 2546 intptr_t array_offset = GetFieldOffset(growable_array_class,
2507 growable_array_array_field_name); 2547 growable_array_array_field_name);
2508 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX); 2548 VisitLoadTwo(node->index_expr(), node->value(), EBX, ECX);
2509 DeoptimizationBlob* deopt_blob = 2549 DeoptimizationBlob* deopt_blob =
2510 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed); 2550 AddDeoptimizationBlob(node, EAX, EBX, ECX, kDeoptStoreIndexed);
2511 __ popl(EAX); // Array. 2551 __ popl(EAX); // Array.
2512 // ECX: value, EBX:index, EAX: array, EDX: scratch. 2552 // ECX: value, EBX:index, EAX: array, EDX: scratch.
2513 // Check class of array. 2553 // Check class of array.
2514 __ testl(EAX, Immediate(kSmiTagMask)); 2554 if (!array_info.IsClass(growable_array_class)) {
2515 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt. 2555 __ testl(EAX, Immediate(kSmiTagMask));
2516 __ movl(EDX, FieldAddress(EAX, Object::class_offset())); 2556 __ j(ZERO, deopt_blob->label()); // Array is smi -> deopt.
2517 __ CompareObject(EDX, growable_array_class); 2557 __ movl(EDX, FieldAddress(EAX, Object::class_offset()));
2518 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray -> deopt. 2558 __ CompareObject(EDX, growable_array_class);
2559 __ j(NOT_EQUAL, deopt_blob->label()); // Not GrowableObjectArray.
2560 PropagateBackLocalClass(node->array(), growable_array_class);
2561 }
2519 // Check class of index. 2562 // Check class of index.
2520 __ testl(EBX, Immediate(kSmiTagMask)); 2563 if (!index_info.IsClass(smi_class_)) {
2521 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt. 2564 __ testl(EBX, Immediate(kSmiTagMask));
2565 __ j(NOT_ZERO, deopt_blob->label()); // Index not Smi -> deopt.
2566 PropagateBackLocalClass(node->index_expr(), smi_class_);
2567 }
2522 // Range check: deoptimize if out of bounds. 2568 // Range check: deoptimize if out of bounds.
2523 __ cmpl(EBX, FieldAddress(EAX, length_offset)); 2569 __ cmpl(EBX, FieldAddress(EAX, length_offset));
2524 __ j(ABOVE_EQUAL, deopt_blob->label()); 2570 __ j(ABOVE_EQUAL, deopt_blob->label());
2525 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray. 2571 __ movl(EDX, FieldAddress(EAX, array_offset)); // backingArray.
2526 // Note that EAX is Smi, i.e, times 2. 2572 // Note that EAX is Smi, i.e, times 2.
2527 ASSERT(kSmiTagShift == 1); 2573 ASSERT(kSmiTagShift == 1);
2528 __ StoreIntoObject(EDX, 2574 __ StoreIntoObject(EDX,
2529 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)), 2575 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)),
2530 ECX); 2576 ECX);
2531 HandleResult(node, ECX); 2577 HandleResult(node, ECX);
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
3075 } 3121 }
3076 } 3122 }
3077 // TODO(srdjan): Implement unary kSUB (negate) Mint. 3123 // TODO(srdjan): Implement unary kSUB (negate) Mint.
3078 CodeGenerator::VisitUnaryOpNode(node); 3124 CodeGenerator::VisitUnaryOpNode(node);
3079 } 3125 }
3080 3126
3081 3127
3082 } // namespace dart 3128 } // namespace dart
3083 3129
3084 #endif // defined TARGET_ARCH_IA32 3130 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698