| 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 |