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 6676 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6687 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | 6687 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); |
6688 | 6688 |
6689 if (!dst_.is(eax)) __ mov(dst_, eax); | 6689 if (!dst_.is(eax)) __ mov(dst_, eax); |
6690 } | 6690 } |
6691 | 6691 |
6692 | 6692 |
6693 class DeferredReferenceSetKeyedValue: public DeferredCode { | 6693 class DeferredReferenceSetKeyedValue: public DeferredCode { |
6694 public: | 6694 public: |
6695 DeferredReferenceSetKeyedValue(Register value, | 6695 DeferredReferenceSetKeyedValue(Register value, |
6696 Register key, | 6696 Register key, |
6697 Register receiver) | 6697 Register receiver, |
6698 : value_(value), key_(key), receiver_(receiver) { | 6698 Register scratch) |
| 6699 : value_(value), |
| 6700 key_(key), |
| 6701 receiver_(receiver), |
| 6702 scratch_(scratch) { |
6699 set_comment("[ DeferredReferenceSetKeyedValue"); | 6703 set_comment("[ DeferredReferenceSetKeyedValue"); |
6700 } | 6704 } |
6701 | 6705 |
6702 virtual void Generate(); | 6706 virtual void Generate(); |
6703 | 6707 |
6704 Label* patch_site() { return &patch_site_; } | 6708 Label* patch_site() { return &patch_site_; } |
6705 | 6709 |
6706 private: | 6710 private: |
6707 Register value_; | 6711 Register value_; |
6708 Register key_; | 6712 Register key_; |
6709 Register receiver_; | 6713 Register receiver_; |
| 6714 Register scratch_; |
6710 Label patch_site_; | 6715 Label patch_site_; |
6711 }; | 6716 }; |
6712 | 6717 |
6713 | 6718 |
6714 void DeferredReferenceSetKeyedValue::Generate() { | 6719 void DeferredReferenceSetKeyedValue::Generate() { |
6715 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); | 6720 __ IncrementCounter(&Counters::keyed_store_inline_miss, 1); |
6716 // Push receiver and key arguments on the stack. | 6721 // Move value_ to eax, key_ to ecx, and receiver_ to edx. |
6717 __ push(receiver_); | 6722 Register old_value = value_; |
6718 __ push(key_); | 6723 |
6719 // Move value argument to eax as expected by the IC stub. | 6724 // First, move value to eax. |
6720 if (!value_.is(eax)) __ mov(eax, value_); | 6725 if (!value_.is(eax)) { |
| 6726 if (key_.is(eax)) { |
| 6727 // Move key_ out of eax, preferably to ecx. |
| 6728 if (!value_.is(ecx) && !receiver_.is(ecx)) { |
| 6729 __ mov(ecx, key_); |
| 6730 key_ = ecx; |
| 6731 } else { |
| 6732 __ mov(scratch_, key_); |
| 6733 key_ = scratch_; |
| 6734 } |
| 6735 } |
| 6736 if (receiver_.is(eax)) { |
| 6737 // Move receiver_ out of eax, preferably to edx. |
| 6738 if (!value_.is(edx) && !key_.is(edx)) { |
| 6739 __ mov(edx, receiver_); |
| 6740 receiver_ = edx; |
| 6741 } else { |
| 6742 // Both moves to scratch are from eax, also, no valid path hits both. |
| 6743 __ mov(scratch_, receiver_); |
| 6744 receiver_ = scratch_; |
| 6745 } |
| 6746 } |
| 6747 __ mov(eax, value_); |
| 6748 value_ = eax; |
| 6749 } |
| 6750 |
| 6751 // Now value_ is in eax. Move the other two to the right positions. |
| 6752 // We do not update the variables key_ and receiver_ to ecx and edx. |
| 6753 if (key_.is(ecx)) { |
| 6754 if (!receiver_.is(edx)) { |
| 6755 __ mov(edx, receiver_); |
| 6756 } |
| 6757 } else if (key_.is(edx)) { |
| 6758 if (receiver_.is(ecx)) { |
| 6759 __ xchg(edx, ecx); |
| 6760 } else { |
| 6761 __ mov(ecx, key_); |
| 6762 if (!receiver_.is(edx)) { |
| 6763 __ mov(edx, receiver_); |
| 6764 } |
| 6765 } |
| 6766 } else { // Key is not in edx or ecx. |
| 6767 if (!receiver_.is(edx)) { |
| 6768 __ mov(edx, receiver_); |
| 6769 } |
| 6770 __ mov(ecx, key_); |
| 6771 } |
| 6772 |
6721 // Call the IC stub. | 6773 // Call the IC stub. |
6722 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); | 6774 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); |
6723 __ call(ic, RelocInfo::CODE_TARGET); | 6775 __ call(ic, RelocInfo::CODE_TARGET); |
6724 // The delta from the start of the map-compare instruction to the | 6776 // The delta from the start of the map-compare instruction to the |
6725 // test instruction. We use masm_-> directly here instead of the | 6777 // test instruction. We use masm_-> directly here instead of the |
6726 // __ macro because the macro sometimes uses macro expansion to turn | 6778 // __ macro because the macro sometimes uses macro expansion to turn |
6727 // into something that can't return a value. This is encountered | 6779 // into something that can't return a value. This is encountered |
6728 // when doing generated code coverage tests. | 6780 // when doing generated code coverage tests. |
6729 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); | 6781 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); |
6730 // Here we use masm_-> instead of the __ macro because this is the | 6782 // Here we use masm_-> instead of the __ macro because this is the |
6731 // instruction that gets patched and coverage code gets in the way. | 6783 // instruction that gets patched and coverage code gets in the way. |
6732 masm_->test(eax, Immediate(-delta_to_patch_site)); | 6784 masm_->test(eax, Immediate(-delta_to_patch_site)); |
6733 // Restore value (returned from store IC), key and receiver | 6785 // Restore value (returned from store IC) register. |
6734 // registers. | 6786 if (!old_value.is(eax)) __ mov(old_value, eax); |
6735 if (!value_.is(eax)) __ mov(value_, eax); | |
6736 __ pop(key_); | |
6737 __ pop(receiver_); | |
6738 } | 6787 } |
6739 | 6788 |
6740 | 6789 |
6741 Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { | 6790 Result CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { |
6742 #ifdef DEBUG | 6791 #ifdef DEBUG |
6743 int original_height = frame()->height(); | 6792 int original_height = frame()->height(); |
6744 #endif | 6793 #endif |
6745 Result result; | 6794 Result result; |
6746 // Do not inline the inobject property case for loads from the global | 6795 // Do not inline the inobject property case for loads from the global |
6747 // object. Also do not inline for unoptimized code. This saves time in | 6796 // object. Also do not inline for unoptimized code. This saves time in |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6926 bool value_is_constant = result.is_constant(); | 6975 bool value_is_constant = result.is_constant(); |
6927 | 6976 |
6928 // Make sure that value, key and receiver are in registers. | 6977 // Make sure that value, key and receiver are in registers. |
6929 result.ToRegister(); | 6978 result.ToRegister(); |
6930 key.ToRegister(); | 6979 key.ToRegister(); |
6931 receiver.ToRegister(); | 6980 receiver.ToRegister(); |
6932 | 6981 |
6933 DeferredReferenceSetKeyedValue* deferred = | 6982 DeferredReferenceSetKeyedValue* deferred = |
6934 new DeferredReferenceSetKeyedValue(result.reg(), | 6983 new DeferredReferenceSetKeyedValue(result.reg(), |
6935 key.reg(), | 6984 key.reg(), |
6936 receiver.reg()); | 6985 receiver.reg(), |
| 6986 tmp.reg()); |
6937 | 6987 |
6938 // Check that the value is a smi if it is not a constant. We can skip | 6988 // Check that the value is a smi if it is not a constant. We can skip |
6939 // the write barrier for smis and constants. | 6989 // the write barrier for smis and constants. |
6940 if (!value_is_constant) { | 6990 if (!value_is_constant) { |
6941 __ test(result.reg(), Immediate(kSmiTagMask)); | 6991 __ test(result.reg(), Immediate(kSmiTagMask)); |
6942 deferred->Branch(not_zero); | 6992 deferred->Branch(not_zero); |
6943 } | 6993 } |
6944 | 6994 |
6945 // Check that the key is a non-negative smi. | 6995 // Check that the key is a non-negative smi. |
6946 __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000)); | 6996 __ test(key.reg(), Immediate(kSmiTagMask | 0x80000000)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6986 __ IncrementCounter(&Counters::keyed_store_inline, 1); | 7036 __ IncrementCounter(&Counters::keyed_store_inline, 1); |
6987 | 7037 |
6988 deferred->BindExit(); | 7038 deferred->BindExit(); |
6989 } else { | 7039 } else { |
6990 result = frame()->CallKeyedStoreIC(); | 7040 result = frame()->CallKeyedStoreIC(); |
6991 // Make sure that we do not have a test instruction after the | 7041 // Make sure that we do not have a test instruction after the |
6992 // call. A test instruction after the call is used to | 7042 // call. A test instruction after the call is used to |
6993 // indicate that we have generated an inline version of the | 7043 // indicate that we have generated an inline version of the |
6994 // keyed store. | 7044 // keyed store. |
6995 __ nop(); | 7045 __ nop(); |
6996 frame()->Drop(2); | |
6997 } | 7046 } |
6998 ASSERT(frame()->height() == original_height - 3); | 7047 ASSERT(frame()->height() == original_height - 3); |
6999 return result; | 7048 return result; |
7000 } | 7049 } |
7001 | 7050 |
7002 | 7051 |
7003 #undef __ | 7052 #undef __ |
7004 #define __ ACCESS_MASM(masm) | 7053 #define __ ACCESS_MASM(masm) |
7005 | 7054 |
7006 | 7055 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7128 Result answer = cgen_->EmitNamedStore(GetName(), false); | 7177 Result answer = cgen_->EmitNamedStore(GetName(), false); |
7129 cgen_->frame()->Push(&answer); | 7178 cgen_->frame()->Push(&answer); |
7130 set_unloaded(); | 7179 set_unloaded(); |
7131 break; | 7180 break; |
7132 } | 7181 } |
7133 | 7182 |
7134 case KEYED: { | 7183 case KEYED: { |
7135 Comment cmnt(masm, "[ Store to keyed Property"); | 7184 Comment cmnt(masm, "[ Store to keyed Property"); |
7136 Property* property = expression()->AsProperty(); | 7185 Property* property = expression()->AsProperty(); |
7137 ASSERT(property != NULL); | 7186 ASSERT(property != NULL); |
| 7187 |
7138 Result answer = cgen_->EmitKeyedStore(property->key()->type()); | 7188 Result answer = cgen_->EmitKeyedStore(property->key()->type()); |
7139 cgen_->frame()->Push(&answer); | 7189 cgen_->frame()->Push(&answer); |
7140 set_unloaded(); | 7190 set_unloaded(); |
7141 break; | 7191 break; |
7142 } | 7192 } |
7143 | 7193 |
7144 case UNLOADED: | 7194 case UNLOADED: |
7145 case ILLEGAL: | 7195 case ILLEGAL: |
7146 UNREACHABLE(); | 7196 UNREACHABLE(); |
7147 } | 7197 } |
(...skipping 3860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11008 | 11058 |
11009 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 11059 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
11010 // tagged as a small integer. | 11060 // tagged as a small integer. |
11011 __ bind(&runtime); | 11061 __ bind(&runtime); |
11012 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 11062 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
11013 } | 11063 } |
11014 | 11064 |
11015 #undef __ | 11065 #undef __ |
11016 | 11066 |
11017 } } // namespace v8::internal | 11067 } } // namespace v8::internal |
OLD | NEW |