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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 1990012: ia32: Helper function for getting an element of a fixed array from object poi... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 10 years, 7 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 | « src/ia32/codegen-ia32.h ('k') | src/ia32/ic-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4209 matching lines...) Expand 10 before | Expand all | Expand 10 after
4220 // targets only after all the state is pushed on the frame. 4220 // targets only after all the state is pushed on the frame.
4221 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); 4221 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
4222 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); 4222 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
4223 4223
4224 __ mov(eax, frame_->ElementAt(0)); // load the current count 4224 __ mov(eax, frame_->ElementAt(0)); // load the current count
4225 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length 4225 __ cmp(eax, frame_->ElementAt(1)); // compare to the array length
4226 node->break_target()->Branch(above_equal); 4226 node->break_target()->Branch(above_equal);
4227 4227
4228 // Get the i'th entry of the array. 4228 // Get the i'th entry of the array.
4229 __ mov(edx, frame_->ElementAt(2)); 4229 __ mov(edx, frame_->ElementAt(2));
4230 __ mov(ebx, Operand(edx, eax, times_2, 4230 __ mov(ebx, FixedArrayElementOperand(edx, eax));
4231 FixedArray::kHeaderSize - kHeapObjectTag));
4232 4231
4233 // Get the expected map from the stack or a zero map in the 4232 // Get the expected map from the stack or a zero map in the
4234 // permanent slow case eax: current iteration count ebx: i'th entry 4233 // permanent slow case eax: current iteration count ebx: i'th entry
4235 // of the enum cache 4234 // of the enum cache
4236 __ mov(edx, frame_->ElementAt(3)); 4235 __ mov(edx, frame_->ElementAt(3));
4237 // Check if the expected map still matches that of the enumerable. 4236 // Check if the expected map still matches that of the enumerable.
4238 // If not, we have to filter the key. 4237 // If not, we have to filter the key.
4239 // eax: current iteration count 4238 // eax: current iteration count
4240 // ebx: i'th entry of the enum cache 4239 // ebx: i'th entry of the enum cache
4241 // edx: expected map value 4240 // edx: expected map value
(...skipping 2385 matching lines...) Expand 10 before | Expand all | Expand 10 after
6627 virtual void Generate(); 6626 virtual void Generate();
6628 6627
6629 private: 6628 private:
6630 Register dst_; // on invocation Smi index of finger, on exit 6629 Register dst_; // on invocation Smi index of finger, on exit
6631 // holds value being looked up. 6630 // holds value being looked up.
6632 Register cache_; // instance of JSFunctionResultCache. 6631 Register cache_; // instance of JSFunctionResultCache.
6633 Register key_; // key being looked up. 6632 Register key_; // key being looked up.
6634 }; 6633 };
6635 6634
6636 6635
6637 // Return a position of the element at |index_as_smi| + |additional_offset|
6638 // in FixedArray pointer to which is held in |array|. |index_as_smi| is Smi.
6639 static Operand ArrayElement(Register array,
6640 Register index_as_smi,
6641 int additional_offset = 0) {
6642 int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize;
6643 return FieldOperand(array, index_as_smi, times_half_pointer_size, offset);
6644 }
6645
6646
6647 void DeferredSearchCache::Generate() { 6636 void DeferredSearchCache::Generate() {
6648 Label first_loop, search_further, second_loop, cache_miss; 6637 Label first_loop, search_further, second_loop, cache_miss;
6649 6638
6650 // Smi-tagging is equivalent to multiplying by 2. 6639 // Smi-tagging is equivalent to multiplying by 2.
6651 STATIC_ASSERT(kSmiTag == 0); 6640 STATIC_ASSERT(kSmiTag == 0);
6652 STATIC_ASSERT(kSmiTagSize == 1); 6641 STATIC_ASSERT(kSmiTagSize == 1);
6653 6642
6654 Smi* kEntrySizeSmi = Smi::FromInt(JSFunctionResultCache::kEntrySize); 6643 Smi* kEntrySizeSmi = Smi::FromInt(JSFunctionResultCache::kEntrySize);
6655 Smi* kEntriesIndexSmi = Smi::FromInt(JSFunctionResultCache::kEntriesIndex); 6644 Smi* kEntriesIndexSmi = Smi::FromInt(JSFunctionResultCache::kEntriesIndex);
6656 6645
6657 // Check the cache from finger to start of the cache. 6646 // Check the cache from finger to start of the cache.
6658 __ bind(&first_loop); 6647 __ bind(&first_loop);
6659 __ sub(Operand(dst_), Immediate(kEntrySizeSmi)); 6648 __ sub(Operand(dst_), Immediate(kEntrySizeSmi));
6660 __ cmp(Operand(dst_), Immediate(kEntriesIndexSmi)); 6649 __ cmp(Operand(dst_), Immediate(kEntriesIndexSmi));
6661 __ j(less, &search_further); 6650 __ j(less, &search_further);
6662 6651
6663 __ cmp(key_, ArrayElement(cache_, dst_)); 6652 __ cmp(key_, CodeGenerator::FixedArrayElementOperand(cache_, dst_));
6664 __ j(not_equal, &first_loop); 6653 __ j(not_equal, &first_loop);
6665 6654
6666 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_); 6655 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
6667 __ mov(dst_, ArrayElement(cache_, dst_, 1)); 6656 __ mov(dst_, CodeGenerator::FixedArrayElementOperand(cache_, dst_, 1));
6668 __ jmp(exit_label()); 6657 __ jmp(exit_label());
6669 6658
6670 __ bind(&search_further); 6659 __ bind(&search_further);
6671 6660
6672 // Check the cache from end of cache up to finger. 6661 // Check the cache from end of cache up to finger.
6673 __ mov(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset)); 6662 __ mov(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset));
6674 6663
6675 __ bind(&second_loop); 6664 __ bind(&second_loop);
6676 __ sub(Operand(dst_), Immediate(kEntrySizeSmi)); 6665 __ sub(Operand(dst_), Immediate(kEntrySizeSmi));
6677 // Consider prefetching into some reg. 6666 // Consider prefetching into some reg.
6678 __ cmp(dst_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset)); 6667 __ cmp(dst_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset));
6679 __ j(less_equal, &cache_miss); 6668 __ j(less_equal, &cache_miss);
6680 6669
6681 __ cmp(key_, ArrayElement(cache_, dst_)); 6670 __ cmp(key_, CodeGenerator::FixedArrayElementOperand(cache_, dst_));
6682 __ j(not_equal, &second_loop); 6671 __ j(not_equal, &second_loop);
6683 6672
6684 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_); 6673 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_);
6685 __ mov(dst_, ArrayElement(cache_, dst_, 1)); 6674 __ mov(dst_, CodeGenerator::FixedArrayElementOperand(cache_, dst_, 1));
6686 __ jmp(exit_label()); 6675 __ jmp(exit_label());
6687 6676
6688 __ bind(&cache_miss); 6677 __ bind(&cache_miss);
6689 __ push(cache_); // store a reference to cache 6678 __ push(cache_); // store a reference to cache
6690 __ push(key_); // store a key 6679 __ push(key_); // store a key
6691 Handle<Object> receiver(Top::global_context()->global()); 6680 Handle<Object> receiver(Top::global_context()->global());
6692 __ push(Immediate(receiver)); 6681 __ push(Immediate(receiver));
6693 __ push(key_); 6682 __ push(key_);
6694 // On ia32 function must be in edi. 6683 // On ia32 function must be in edi.
6695 __ mov(edi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset)); 6684 __ mov(edi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset));
(...skipping 27 matching lines...) Expand all
6723 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset)); 6712 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset));
6724 __ lea(ebx, Operand(edx, JSFunctionResultCache::kEntrySize << 1)); 6713 __ lea(ebx, Operand(edx, JSFunctionResultCache::kEntrySize << 1));
6725 __ mov(FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset), ebx); 6714 __ mov(FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset), ebx);
6726 6715
6727 // Update the cache itself. 6716 // Update the cache itself.
6728 // edx holds the index. 6717 // edx holds the index.
6729 __ bind(&update_cache); 6718 __ bind(&update_cache);
6730 __ pop(ebx); // restore the key 6719 __ pop(ebx); // restore the key
6731 __ mov(FieldOperand(ecx, JSFunctionResultCache::kFingerOffset), edx); 6720 __ mov(FieldOperand(ecx, JSFunctionResultCache::kFingerOffset), edx);
6732 // Store key. 6721 // Store key.
6733 __ mov(ArrayElement(ecx, edx), ebx); 6722 __ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
6734 __ RecordWrite(ecx, 0, ebx, edx); 6723 __ RecordWrite(ecx, 0, ebx, edx);
6735 6724
6736 // Store value. 6725 // Store value.
6737 __ pop(ecx); // restore the cache. 6726 __ pop(ecx); // restore the cache.
6738 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset)); 6727 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset));
6739 __ add(Operand(edx), Immediate(Smi::FromInt(1))); 6728 __ add(Operand(edx), Immediate(Smi::FromInt(1)));
6740 __ mov(ebx, eax); 6729 __ mov(ebx, eax);
6741 __ mov(ArrayElement(ecx, edx), ebx); 6730 __ mov(CodeGenerator::FixedArrayElementOperand(ecx, edx), ebx);
6742 __ RecordWrite(ecx, 0, ebx, edx); 6731 __ RecordWrite(ecx, 0, ebx, edx);
6743 6732
6744 if (!dst_.is(eax)) { 6733 if (!dst_.is(eax)) {
6745 __ mov(dst_, eax); 6734 __ mov(dst_, eax);
6746 } 6735 }
6747 } 6736 }
6748 6737
6749 6738
6750 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { 6739 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
6751 ASSERT_EQ(2, args->length()); 6740 ASSERT_EQ(2, args->length());
(...skipping 26 matching lines...) Expand all
6778 Result tmp = allocator()->Allocate(); 6767 Result tmp = allocator()->Allocate();
6779 ASSERT(tmp.is_valid()); 6768 ASSERT(tmp.is_valid());
6780 6769
6781 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(), 6770 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
6782 cache.reg(), 6771 cache.reg(),
6783 key.reg()); 6772 key.reg());
6784 6773
6785 // tmp.reg() now holds finger offset as a smi. 6774 // tmp.reg() now holds finger offset as a smi.
6786 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 6775 ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
6787 __ mov(tmp.reg(), FieldOperand(cache.reg(), 6776 __ mov(tmp.reg(), FieldOperand(cache.reg(),
6788 JSFunctionResultCache::kFingerOffset)); 6777 JSFunctionResultCache::kFingerOffset));
6789 __ cmp(key.reg(), ArrayElement(cache.reg(), tmp.reg())); 6778 __ cmp(key.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg()));
6790 deferred->Branch(not_equal); 6779 deferred->Branch(not_equal);
6791 6780
6792 __ mov(tmp.reg(), ArrayElement(cache.reg(), tmp.reg(), 1)); 6781 __ mov(tmp.reg(), FixedArrayElementOperand(cache.reg(), tmp.reg(), 1));
6793 6782
6794 deferred->BindExit(); 6783 deferred->BindExit();
6795 frame_->Push(&tmp); 6784 frame_->Push(&tmp);
6796 } 6785 }
6797 6786
6798 6787
6799 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { 6788 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) {
6800 ASSERT_EQ(args->length(), 1); 6789 ASSERT_EQ(args->length(), 1);
6801 6790
6802 // Load the argument on the stack and call the stub. 6791 // Load the argument on the stack and call the stub.
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
6881 STATIC_ASSERT(kSmiTag == 0); 6870 STATIC_ASSERT(kSmiTag == 0);
6882 STATIC_ASSERT(kSmiTagSize == 1); 6871 STATIC_ASSERT(kSmiTagSize == 1);
6883 6872
6884 // Check that both indices are smis. 6873 // Check that both indices are smis.
6885 __ mov(tmp2.reg(), index1.reg()); 6874 __ mov(tmp2.reg(), index1.reg());
6886 __ or_(tmp2.reg(), Operand(index2.reg())); 6875 __ or_(tmp2.reg(), Operand(index2.reg()));
6887 __ test(tmp2.reg(), Immediate(kSmiTagMask)); 6876 __ test(tmp2.reg(), Immediate(kSmiTagMask));
6888 deferred->Branch(not_zero); 6877 deferred->Branch(not_zero);
6889 6878
6890 // Bring addresses into index1 and index2. 6879 // Bring addresses into index1 and index2.
6891 __ lea(index1.reg(), FieldOperand(tmp1.reg(), 6880 __ lea(index1.reg(), FixedArrayElementOperand(tmp1.reg(), index1.reg()));
6892 index1.reg(), 6881 __ lea(index2.reg(), FixedArrayElementOperand(tmp1.reg(), index2.reg()));
6893 times_half_pointer_size, // index1 is Smi
6894 FixedArray::kHeaderSize));
6895 __ lea(index2.reg(), FieldOperand(tmp1.reg(),
6896 index2.reg(),
6897 times_half_pointer_size, // index2 is Smi
6898 FixedArray::kHeaderSize));
6899 6882
6900 // Swap elements. 6883 // Swap elements.
6901 __ mov(object.reg(), Operand(index1.reg(), 0)); 6884 __ mov(object.reg(), Operand(index1.reg(), 0));
6902 __ mov(tmp2.reg(), Operand(index2.reg(), 0)); 6885 __ mov(tmp2.reg(), Operand(index2.reg(), 0));
6903 __ mov(Operand(index2.reg(), 0), object.reg()); 6886 __ mov(Operand(index2.reg(), 0), object.reg());
6904 __ mov(Operand(index1.reg(), 0), tmp2.reg()); 6887 __ mov(Operand(index1.reg(), 0), tmp2.reg());
6905 6888
6906 Label done; 6889 Label done;
6907 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done); 6890 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
6908 // Possible optimization: do a check that both values are Smis 6891 // Possible optimization: do a check that both values are Smis
(...skipping 1852 matching lines...) Expand 10 before | Expand all | Expand 10 after
8761 // Bind the deferred code patch site to be able to locate the fixed 8744 // Bind the deferred code patch site to be able to locate the fixed
8762 // array map comparison. When debugging, we patch this comparison to 8745 // array map comparison. When debugging, we patch this comparison to
8763 // always fail so that we will hit the IC call in the deferred code 8746 // always fail so that we will hit the IC call in the deferred code
8764 // which will allow the debugger to break for fast case stores. 8747 // which will allow the debugger to break for fast case stores.
8765 __ bind(deferred->patch_site()); 8748 __ bind(deferred->patch_site());
8766 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset), 8749 __ cmp(FieldOperand(tmp.reg(), HeapObject::kMapOffset),
8767 Immediate(Factory::fixed_array_map())); 8750 Immediate(Factory::fixed_array_map()));
8768 deferred->Branch(not_equal); 8751 deferred->Branch(not_equal);
8769 8752
8770 // Store the value. 8753 // Store the value.
8771 __ mov(Operand(tmp.reg(), 8754 __ mov(FixedArrayElementOperand(tmp.reg(), key.reg()), result.reg());
8772 key.reg(),
8773 times_2,
8774 FixedArray::kHeaderSize - kHeapObjectTag),
8775 result.reg());
8776 __ IncrementCounter(&Counters::keyed_store_inline, 1); 8755 __ IncrementCounter(&Counters::keyed_store_inline, 1);
8777 8756
8778 deferred->BindExit(); 8757 deferred->BindExit();
8779 } else { 8758 } else {
8780 result = frame()->CallKeyedStoreIC(); 8759 result = frame()->CallKeyedStoreIC();
8781 // Make sure that we do not have a test instruction after the 8760 // Make sure that we do not have a test instruction after the
8782 // call. A test instruction after the call is used to 8761 // call. A test instruction after the call is used to
8783 // indicate that we have generated an inline version of the 8762 // indicate that we have generated an inline version of the
8784 // keyed store. 8763 // keyed store.
8785 __ nop(); 8764 __ nop();
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
9067 // All sizes here are multiples of kPointerSize. 9046 // All sizes here are multiples of kPointerSize.
9068 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0; 9047 int elements_size = (length_ > 0) ? FixedArray::SizeFor(length_) : 0;
9069 int size = JSArray::kSize + elements_size; 9048 int size = JSArray::kSize + elements_size;
9070 9049
9071 // Load boilerplate object into ecx and check if we need to create a 9050 // Load boilerplate object into ecx and check if we need to create a
9072 // boilerplate. 9051 // boilerplate.
9073 Label slow_case; 9052 Label slow_case;
9074 __ mov(ecx, Operand(esp, 3 * kPointerSize)); 9053 __ mov(ecx, Operand(esp, 3 * kPointerSize));
9075 __ mov(eax, Operand(esp, 2 * kPointerSize)); 9054 __ mov(eax, Operand(esp, 2 * kPointerSize));
9076 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 9055 ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
9077 __ mov(ecx, FieldOperand(ecx, eax, times_2, FixedArray::kHeaderSize)); 9056 __ mov(ecx, CodeGenerator::FixedArrayElementOperand(ecx, eax));
9078 __ cmp(ecx, Factory::undefined_value()); 9057 __ cmp(ecx, Factory::undefined_value());
9079 __ j(equal, &slow_case); 9058 __ j(equal, &slow_case);
9080 9059
9081 // Allocate both the JS array and the elements array in one big 9060 // Allocate both the JS array and the elements array in one big
9082 // allocation. This avoids multiple limit checks. 9061 // allocation. This avoids multiple limit checks.
9083 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT); 9062 __ AllocateInNewSpace(size, eax, ebx, edx, &slow_case, TAG_OBJECT);
9084 9063
9085 // Copy the JS array part. 9064 // Copy the JS array part.
9086 for (int i = 0; i < JSArray::kSize; i += kPointerSize) { 9065 for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
9087 if ((i != JSArray::kElementsOffset) || (length_ == 0)) { 9066 if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
(...skipping 4201 matching lines...) Expand 10 before | Expand all | Expand 10 after
13289 13268
13290 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 13269 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
13291 // tagged as a small integer. 13270 // tagged as a small integer.
13292 __ bind(&runtime); 13271 __ bind(&runtime);
13293 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13272 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
13294 } 13273 }
13295 13274
13296 #undef __ 13275 #undef __
13297 13276
13298 } } // namespace v8::internal 13277 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698