OLD | NEW |
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 6562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6573 class DeferredSearchCache: public DeferredCode { | 6573 class DeferredSearchCache: public DeferredCode { |
6574 public: | 6574 public: |
6575 DeferredSearchCache(Register dst, Register cache, Register key) | 6575 DeferredSearchCache(Register dst, Register cache, Register key) |
6576 : dst_(dst), cache_(cache), key_(key) { | 6576 : dst_(dst), cache_(cache), key_(key) { |
6577 set_comment("[ DeferredSearchCache"); | 6577 set_comment("[ DeferredSearchCache"); |
6578 } | 6578 } |
6579 | 6579 |
6580 virtual void Generate(); | 6580 virtual void Generate(); |
6581 | 6581 |
6582 private: | 6582 private: |
6583 Register dst_, cache_, key_; | 6583 Register dst_; // on invocation Smi index of finger, on exit |
| 6584 // holds value being looked up. |
| 6585 Register cache_; // instance of JSFunctionResultCache. |
| 6586 Register key_; // key being looked up. |
6584 }; | 6587 }; |
6585 | 6588 |
6586 | 6589 |
| 6590 // Return a position of the element at |index_as_smi| + |additional_offset| |
| 6591 // in FixedArray pointer to which is held in |array|. |index_as_smi| is Smi. |
| 6592 static Operand ArrayElement(Register array, |
| 6593 Register index_as_smi, |
| 6594 int additional_offset = 0) { |
| 6595 int offset = FixedArray::kHeaderSize + additional_offset * kPointerSize; |
| 6596 return FieldOperand(array, index_as_smi, times_half_pointer_size, offset); |
| 6597 } |
| 6598 |
| 6599 |
6587 void DeferredSearchCache::Generate() { | 6600 void DeferredSearchCache::Generate() { |
6588 __ push(cache_); | 6601 Label first_loop, search_further, second_loop, cache_miss; |
| 6602 |
| 6603 // Smi-tagging is equivalent to multiplying by 2. |
| 6604 STATIC_ASSERT(kSmiTag == 0); |
| 6605 STATIC_ASSERT(kSmiTagSize == 1); |
| 6606 |
| 6607 Smi* kEntrySizeSmi = Smi::FromInt(JSFunctionResultCache::kEntrySize); |
| 6608 Smi* kEntriesIndexSmi = Smi::FromInt(JSFunctionResultCache::kEntriesIndex); |
| 6609 |
| 6610 // Check the cache from finger to start of the cache. |
| 6611 __ bind(&first_loop); |
| 6612 __ sub(Operand(dst_), Immediate(kEntrySizeSmi)); |
| 6613 __ cmp(Operand(dst_), Immediate(kEntriesIndexSmi)); |
| 6614 __ j(less, &search_further); |
| 6615 |
| 6616 __ cmp(key_, ArrayElement(cache_, dst_)); |
| 6617 __ j(not_equal, &first_loop); |
| 6618 |
| 6619 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_); |
| 6620 __ mov(dst_, ArrayElement(cache_, dst_, 1)); |
| 6621 __ jmp(exit_label()); |
| 6622 |
| 6623 __ bind(&search_further); |
| 6624 |
| 6625 // Check the cache from end of cache up to finger. |
| 6626 __ mov(dst_, FieldOperand(cache_, JSFunctionResultCache::kCacheSizeOffset)); |
| 6627 |
| 6628 __ bind(&second_loop); |
| 6629 __ sub(Operand(dst_), Immediate(kEntrySizeSmi)); |
| 6630 // Consider prefetching into some reg. |
| 6631 __ cmp(dst_, FieldOperand(cache_, JSFunctionResultCache::kFingerOffset)); |
| 6632 __ j(less_equal, &cache_miss); |
| 6633 |
| 6634 __ cmp(key_, ArrayElement(cache_, dst_)); |
| 6635 __ j(not_equal, &second_loop); |
| 6636 |
| 6637 __ mov(FieldOperand(cache_, JSFunctionResultCache::kFingerOffset), dst_); |
| 6638 __ mov(dst_, ArrayElement(cache_, dst_, 1)); |
| 6639 __ jmp(exit_label()); |
| 6640 |
| 6641 __ bind(&cache_miss); |
| 6642 __ push(cache_); // store a reference to cache |
| 6643 __ push(key_); // store a key |
| 6644 Handle<Object> receiver(Top::global_context()->global()); |
| 6645 __ push(Immediate(receiver)); |
6589 __ push(key_); | 6646 __ push(key_); |
6590 __ CallRuntime(Runtime::kGetFromCache, 2); | 6647 // On ia32 function must be in edi. |
| 6648 __ mov(edi, FieldOperand(cache_, JSFunctionResultCache::kFactoryOffset)); |
| 6649 ParameterCount expected(1); |
| 6650 __ InvokeFunction(edi, expected, CALL_FUNCTION); |
| 6651 |
| 6652 // Find a place to put new cached value into. |
| 6653 Label add_new_entry, update_cache; |
| 6654 __ mov(ecx, Operand(esp, kPointerSize)); // restore the cache |
| 6655 // Possible optimization: cache size is constant for the given cache |
| 6656 // so technically we could use a constant here. However, if we have |
| 6657 // cache miss this optimization would hardly matter much. |
| 6658 |
| 6659 // Check if we could add new entry to cache. |
| 6660 __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset)); |
| 6661 __ SmiTag(ebx); |
| 6662 __ cmp(ebx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset)); |
| 6663 __ j(greater, &add_new_entry); |
| 6664 |
| 6665 // Check if we could evict entry after finger. |
| 6666 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset)); |
| 6667 __ add(Operand(edx), Immediate(kEntrySizeSmi)); |
| 6668 __ cmp(ebx, Operand(edx)); |
| 6669 __ j(greater, &update_cache); |
| 6670 |
| 6671 // Need to wrap over the cache. |
| 6672 __ mov(edx, Immediate(kEntriesIndexSmi)); |
| 6673 __ jmp(&update_cache); |
| 6674 |
| 6675 __ bind(&add_new_entry); |
| 6676 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset)); |
| 6677 __ lea(ebx, Operand(edx, JSFunctionResultCache::kEntrySize << 1)); |
| 6678 __ mov(FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset), ebx); |
| 6679 |
| 6680 // Update the cache itself. |
| 6681 // edx holds the index. |
| 6682 __ bind(&update_cache); |
| 6683 __ pop(ebx); // restore the key |
| 6684 __ mov(FieldOperand(ecx, JSFunctionResultCache::kFingerOffset), edx); |
| 6685 // Store key. |
| 6686 __ mov(ArrayElement(ecx, edx), ebx); |
| 6687 __ RecordWrite(ecx, 0, ebx, edx); |
| 6688 |
| 6689 // Store value. |
| 6690 __ pop(ecx); // restore the cache. |
| 6691 __ mov(edx, FieldOperand(ecx, JSFunctionResultCache::kFingerOffset)); |
| 6692 __ add(Operand(edx), Immediate(Smi::FromInt(1))); |
| 6693 __ mov(ebx, eax); |
| 6694 __ mov(ArrayElement(ecx, edx), ebx); |
| 6695 __ RecordWrite(ecx, 0, ebx, edx); |
| 6696 |
6591 if (!dst_.is(eax)) { | 6697 if (!dst_.is(eax)) { |
6592 __ mov(dst_, eax); | 6698 __ mov(dst_, eax); |
6593 } | 6699 } |
6594 } | 6700 } |
6595 | 6701 |
6596 | 6702 |
6597 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { | 6703 void CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) { |
6598 ASSERT_EQ(2, args->length()); | 6704 ASSERT_EQ(2, args->length()); |
6599 | 6705 |
6600 ASSERT_NE(NULL, args->at(0)->AsLiteral()); | 6706 ASSERT_NE(NULL, args->at(0)->AsLiteral()); |
(...skipping 21 matching lines...) Expand all Loading... |
6622 __ mov(cache.reg(), | 6728 __ mov(cache.reg(), |
6623 FieldOperand(cache.reg(), FixedArray::OffsetOfElementAt(cache_id))); | 6729 FieldOperand(cache.reg(), FixedArray::OffsetOfElementAt(cache_id))); |
6624 | 6730 |
6625 Result tmp = allocator()->Allocate(); | 6731 Result tmp = allocator()->Allocate(); |
6626 ASSERT(tmp.is_valid()); | 6732 ASSERT(tmp.is_valid()); |
6627 | 6733 |
6628 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(), | 6734 DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(), |
6629 cache.reg(), | 6735 cache.reg(), |
6630 key.reg()); | 6736 key.reg()); |
6631 | 6737 |
6632 const int kFingerOffset = | |
6633 FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex); | |
6634 // tmp.reg() now holds finger offset as a smi. | 6738 // tmp.reg() now holds finger offset as a smi. |
6635 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 6739 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
6636 __ mov(tmp.reg(), FieldOperand(cache.reg(), kFingerOffset)); | 6740 __ mov(tmp.reg(), FieldOperand(cache.reg(), |
6637 __ cmp(key.reg(), FieldOperand(cache.reg(), | 6741 JSFunctionResultCache::kFingerOffset)); |
6638 tmp.reg(), // as smi | 6742 __ cmp(key.reg(), ArrayElement(cache.reg(), tmp.reg())); |
6639 times_half_pointer_size, | |
6640 FixedArray::kHeaderSize)); | |
6641 deferred->Branch(not_equal); | 6743 deferred->Branch(not_equal); |
6642 | 6744 |
6643 __ mov(tmp.reg(), FieldOperand(cache.reg(), | 6745 __ mov(tmp.reg(), ArrayElement(cache.reg(), tmp.reg(), 1)); |
6644 tmp.reg(), // as smi | |
6645 times_half_pointer_size, | |
6646 kPointerSize + FixedArray::kHeaderSize)); | |
6647 | 6746 |
6648 deferred->BindExit(); | 6747 deferred->BindExit(); |
6649 frame_->Push(&tmp); | 6748 frame_->Push(&tmp); |
6650 } | 6749 } |
6651 | 6750 |
6652 | 6751 |
6653 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { | 6752 void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
6654 ASSERT_EQ(args->length(), 1); | 6753 ASSERT_EQ(args->length(), 1); |
6655 | 6754 |
6656 // Load the argument on the stack and call the stub. | 6755 // Load the argument on the stack and call the stub. |
(...skipping 6486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13143 | 13242 |
13144 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 13243 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
13145 // tagged as a small integer. | 13244 // tagged as a small integer. |
13146 __ bind(&runtime); | 13245 __ bind(&runtime); |
13147 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 13246 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
13148 } | 13247 } |
13149 | 13248 |
13150 #undef __ | 13249 #undef __ |
13151 | 13250 |
13152 } } // namespace v8::internal | 13251 } } // namespace v8::internal |
OLD | NEW |