| 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 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |