| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 6930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6941 masm->sw(ra, MemOperand(sp, kCArgsSlotsSize)); | 6941 masm->sw(ra, MemOperand(sp, kCArgsSlotsSize)); |
| 6942 masm->li(ra, Operand(reinterpret_cast<intptr_t>(GetCode().location()), | 6942 masm->li(ra, Operand(reinterpret_cast<intptr_t>(GetCode().location()), |
| 6943 RelocInfo::CODE_TARGET), true); | 6943 RelocInfo::CODE_TARGET), true); |
| 6944 // Call the function. | 6944 // Call the function. |
| 6945 masm->Jump(t9); | 6945 masm->Jump(t9); |
| 6946 // Make sure the stored 'ra' points to this position. | 6946 // Make sure the stored 'ra' points to this position. |
| 6947 ASSERT_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra)); | 6947 ASSERT_EQ(kNumInstructionsToJump, masm->InstructionsGeneratedSince(&find_ra)); |
| 6948 } | 6948 } |
| 6949 | 6949 |
| 6950 | 6950 |
| 6951 MaybeObject* StringDictionaryLookupStub::GenerateNegativeLookup( | 6951 void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
| 6952 Label* miss, |
| 6953 Label* done, |
| 6954 Register receiver, |
| 6955 Register properties, |
| 6956 Handle<String> name, |
| 6957 Register scratch0) { |
| 6958 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| 6959 // not equal to the name and kProbes-th slot is not used (its name is the |
| 6960 // undefined value), it guarantees the hash table doesn't contain the |
| 6961 // property. It's true even if some slots represent deleted properties |
| 6962 // (their names are the null value). |
| 6963 for (int i = 0; i < kInlinedProbes; i++) { |
| 6964 // scratch0 points to properties hash. |
| 6965 // Compute the masked index: (hash + i + i * i) & mask. |
| 6966 Register index = scratch0; |
| 6967 // Capacity is smi 2^n. |
| 6968 __ lw(index, FieldMemOperand(properties, kCapacityOffset)); |
| 6969 __ Subu(index, index, Operand(1)); |
| 6970 __ And(index, index, Operand( |
| 6971 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); |
| 6972 |
| 6973 // Scale the index by multiplying by the entry size. |
| 6974 ASSERT(StringDictionary::kEntrySize == 3); |
| 6975 __ sll(at, index, 1); |
| 6976 __ Addu(index, index, at); |
| 6977 |
| 6978 Register entity_name = scratch0; |
| 6979 // Having undefined at this place means the name is not contained. |
| 6980 ASSERT_EQ(kSmiTagSize, 1); |
| 6981 Register tmp = properties; |
| 6982 __ sll(tmp, index, 1); |
| 6983 __ Addu(tmp, properties, tmp); |
| 6984 __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); |
| 6985 |
| 6986 ASSERT(!tmp.is(entity_name)); |
| 6987 __ LoadRoot(tmp, Heap::kUndefinedValueRootIndex); |
| 6988 __ Branch(done, eq, entity_name, Operand(tmp)); |
| 6989 |
| 6990 if (i != kInlinedProbes - 1) { |
| 6991 // Stop if found the property. |
| 6992 __ Branch(miss, eq, entity_name, Operand(Handle<String>(name))); |
| 6993 |
| 6994 // Check if the entry name is not a symbol. |
| 6995 __ lw(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset)); |
| 6996 __ lbu(entity_name, |
| 6997 FieldMemOperand(entity_name, Map::kInstanceTypeOffset)); |
| 6998 __ And(tmp, entity_name, Operand(kIsSymbolMask)); |
| 6999 __ Branch(miss, eq, tmp, Operand(zero_reg)); |
| 7000 |
| 7001 // Restore the properties. |
| 7002 __ lw(properties, |
| 7003 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7004 } |
| 7005 } |
| 7006 |
| 7007 const int spill_mask = |
| 7008 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | |
| 7009 a2.bit() | a1.bit() | a0.bit() | v0.bit()); |
| 7010 |
| 7011 __ MultiPush(spill_mask); |
| 7012 __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7013 __ li(a1, Operand(Handle<String>(name))); |
| 7014 StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); |
| 7015 __ CallStub(&stub); |
| 7016 __ mov(at, v0); |
| 7017 __ MultiPop(spill_mask); |
| 7018 |
| 7019 __ Branch(done, eq, at, Operand(zero_reg)); |
| 7020 __ Branch(miss, ne, at, Operand(zero_reg)); |
| 7021 } |
| 7022 |
| 7023 |
| 7024 // TODO(kmillikin): Eliminate this function when the stub cache is fully |
| 7025 // handlified. |
| 7026 MaybeObject* StringDictionaryLookupStub::TryGenerateNegativeLookup( |
| 6952 MacroAssembler* masm, | 7027 MacroAssembler* masm, |
| 6953 Label* miss, | 7028 Label* miss, |
| 6954 Label* done, | 7029 Label* done, |
| 6955 Register receiver, | 7030 Register receiver, |
| 6956 Register properties, | 7031 Register properties, |
| 6957 String* name, | 7032 String* name, |
| 6958 Register scratch0) { | 7033 Register scratch0) { |
| 6959 // If names of slots in range from 1 to kProbes - 1 for the hash value are | 7034 // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| 6960 // not equal to the name and kProbes-th slot is not used (its name is the | 7035 // not equal to the name and kProbes-th slot is not used (its name is the |
| 6961 // undefined value), it guarantees the hash table doesn't contain the | 7036 // undefined value), it guarantees the hash table doesn't contain the |
| 6962 // property. It's true even if some slots represent deleted properties | 7037 // property. It's true even if some slots represent deleted properties |
| 6963 // (their names are the null value). | 7038 // (their names are the null value). |
| 6964 for (int i = 0; i < kInlinedProbes; i++) { | 7039 for (int i = 0; i < kInlinedProbes; i++) { |
| 6965 // scratch0 points to properties hash. | 7040 // scratch0 points to properties hash. |
| 6966 // Compute the masked index: (hash + i + i * i) & mask. | 7041 // Compute the masked index: (hash + i + i * i) & mask. |
| 6967 Register index = scratch0; | 7042 Register index = scratch0; |
| 6968 // Capacity is smi 2^n. | 7043 // Capacity is smi 2^n. |
| 6969 __ lw(index, FieldMemOperand(properties, kCapacityOffset)); | 7044 __ lw(index, FieldMemOperand(properties, kCapacityOffset)); |
| 6970 __ Subu(index, index, Operand(1)); | 7045 __ Subu(index, index, Operand(1)); |
| 6971 __ And(index, index, Operand( | 7046 __ And(index, index, Operand( |
| 6972 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); | 7047 Smi::FromInt(name->Hash() + StringDictionary::GetProbeOffset(i)))); |
| 6973 | 7048 |
| 6974 // Scale the index by multiplying by the entry size. | 7049 // Scale the index by multiplying by the entry size. |
| 6975 ASSERT(StringDictionary::kEntrySize == 3); | 7050 ASSERT(StringDictionary::kEntrySize == 3); |
| 6976 // index *= 3. | 7051 // index *= 3. |
| 6977 __ mov(at, index); | 7052 __ sll(at, index, 1); |
| 6978 __ sll(index, index, 1); | |
| 6979 __ Addu(index, index, at); | 7053 __ Addu(index, index, at); |
| 6980 | 7054 |
| 6981 Register entity_name = scratch0; | 7055 Register entity_name = scratch0; |
| 6982 // Having undefined at this place means the name is not contained. | 7056 // Having undefined at this place means the name is not contained. |
| 6983 ASSERT_EQ(kSmiTagSize, 1); | 7057 ASSERT_EQ(kSmiTagSize, 1); |
| 6984 Register tmp = properties; | 7058 Register tmp = properties; |
| 6985 | 7059 |
| 6986 __ sll(scratch0, index, 1); | 7060 __ sll(scratch0, index, 1); |
| 6987 __ Addu(tmp, properties, scratch0); | 7061 __ Addu(tmp, properties, scratch0); |
| 6988 __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); | 7062 __ lw(entity_name, FieldMemOperand(tmp, kElementsStartOffset)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 7003 __ Branch(miss, eq, scratch0, Operand(zero_reg)); | 7077 __ Branch(miss, eq, scratch0, Operand(zero_reg)); |
| 7004 | 7078 |
| 7005 // Restore the properties. | 7079 // Restore the properties. |
| 7006 __ lw(properties, | 7080 __ lw(properties, |
| 7007 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 7081 FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7008 } | 7082 } |
| 7009 } | 7083 } |
| 7010 | 7084 |
| 7011 const int spill_mask = | 7085 const int spill_mask = |
| 7012 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | | 7086 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | a3.bit() | |
| 7013 a2.bit() | a1.bit() | a0.bit()); | 7087 a2.bit() | a1.bit() | a0.bit() | v0.bit()); |
| 7014 | 7088 |
| 7015 __ MultiPush(spill_mask); | 7089 __ MultiPush(spill_mask); |
| 7016 __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | 7090 __ lw(a0, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 7017 __ li(a1, Operand(Handle<String>(name))); | 7091 __ li(a1, Operand(Handle<String>(name))); |
| 7018 StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); | 7092 StringDictionaryLookupStub stub(NEGATIVE_LOOKUP); |
| 7019 MaybeObject* result = masm->TryCallStub(&stub); | 7093 MaybeObject* result = masm->TryCallStub(&stub); |
| 7020 if (result->IsFailure()) return result; | 7094 if (result->IsFailure()) return result; |
| 7095 __ mov(at, v0); |
| 7021 __ MultiPop(spill_mask); | 7096 __ MultiPop(spill_mask); |
| 7022 | 7097 |
| 7023 __ Branch(done, eq, v0, Operand(zero_reg)); | 7098 __ Branch(done, eq, at, Operand(zero_reg)); |
| 7024 __ Branch(miss, ne, v0, Operand(zero_reg)); | 7099 __ Branch(miss, ne, at, Operand(zero_reg)); |
| 7025 return result; | 7100 return result; |
| 7026 } | 7101 } |
| 7027 | 7102 |
| 7028 | 7103 |
| 7029 // Probe the string dictionary in the |elements| register. Jump to the | 7104 // Probe the string dictionary in the |elements| register. Jump to the |
| 7030 // |done| label if a property with the given name is found. Jump to | 7105 // |done| label if a property with the given name is found. Jump to |
| 7031 // the |miss| label otherwise. | 7106 // the |miss| label otherwise. |
| 7032 // If lookup was successful |scratch2| will be equal to elements + 4 * index. | 7107 // If lookup was successful |scratch2| will be equal to elements + 4 * index. |
| 7033 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, | 7108 void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, |
| 7034 Label* miss, | 7109 Label* miss, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 7060 __ Addu(scratch2, scratch2, Operand( | 7135 __ Addu(scratch2, scratch2, Operand( |
| 7061 StringDictionary::GetProbeOffset(i) << String::kHashShift)); | 7136 StringDictionary::GetProbeOffset(i) << String::kHashShift)); |
| 7062 } | 7137 } |
| 7063 __ srl(scratch2, scratch2, String::kHashShift); | 7138 __ srl(scratch2, scratch2, String::kHashShift); |
| 7064 __ And(scratch2, scratch1, scratch2); | 7139 __ And(scratch2, scratch1, scratch2); |
| 7065 | 7140 |
| 7066 // Scale the index by multiplying by the element size. | 7141 // Scale the index by multiplying by the element size. |
| 7067 ASSERT(StringDictionary::kEntrySize == 3); | 7142 ASSERT(StringDictionary::kEntrySize == 3); |
| 7068 // scratch2 = scratch2 * 3. | 7143 // scratch2 = scratch2 * 3. |
| 7069 | 7144 |
| 7070 __ mov(at, scratch2); | 7145 __ sll(at, scratch2, 1); |
| 7071 __ sll(scratch2, scratch2, 1); | |
| 7072 __ Addu(scratch2, scratch2, at); | 7146 __ Addu(scratch2, scratch2, at); |
| 7073 | 7147 |
| 7074 // Check if the key is identical to the name. | 7148 // Check if the key is identical to the name. |
| 7075 __ sll(at, scratch2, 2); | 7149 __ sll(at, scratch2, 2); |
| 7076 __ Addu(scratch2, elements, at); | 7150 __ Addu(scratch2, elements, at); |
| 7077 __ lw(at, FieldMemOperand(scratch2, kElementsStartOffset)); | 7151 __ lw(at, FieldMemOperand(scratch2, kElementsStartOffset)); |
| 7078 __ Branch(done, eq, name, Operand(at)); | 7152 __ Branch(done, eq, name, Operand(at)); |
| 7079 } | 7153 } |
| 7080 | 7154 |
| 7081 const int spill_mask = | 7155 const int spill_mask = |
| 7082 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | | 7156 (ra.bit() | t2.bit() | t1.bit() | t0.bit() | |
| 7083 a3.bit() | a2.bit() | a1.bit() | a0.bit()) & | 7157 a3.bit() | a2.bit() | a1.bit() | a0.bit() | v0.bit()) & |
| 7084 ~(scratch1.bit() | scratch2.bit()); | 7158 ~(scratch1.bit() | scratch2.bit()); |
| 7085 | 7159 |
| 7086 __ MultiPush(spill_mask); | 7160 __ MultiPush(spill_mask); |
| 7087 __ Move(a0, elements); | 7161 if (name.is(a0)) { |
| 7088 __ Move(a1, name); | 7162 ASSERT(!elements.is(a1)); |
| 7163 __ Move(a1, name); |
| 7164 __ Move(a0, elements); |
| 7165 } else { |
| 7166 __ Move(a0, elements); |
| 7167 __ Move(a1, name); |
| 7168 } |
| 7089 StringDictionaryLookupStub stub(POSITIVE_LOOKUP); | 7169 StringDictionaryLookupStub stub(POSITIVE_LOOKUP); |
| 7090 __ CallStub(&stub); | 7170 __ CallStub(&stub); |
| 7091 __ mov(scratch2, a2); | 7171 __ mov(scratch2, a2); |
| 7172 __ mov(at, v0); |
| 7092 __ MultiPop(spill_mask); | 7173 __ MultiPop(spill_mask); |
| 7093 | 7174 |
| 7094 __ Branch(done, ne, v0, Operand(zero_reg)); | 7175 __ Branch(done, ne, at, Operand(zero_reg)); |
| 7095 __ Branch(miss, eq, v0, Operand(zero_reg)); | 7176 __ Branch(miss, eq, at, Operand(zero_reg)); |
| 7096 } | 7177 } |
| 7097 | 7178 |
| 7098 | 7179 |
| 7099 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { | 7180 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { |
| 7100 // This stub overrides SometimesSetsUpAFrame() to return false. That means | 7181 // This stub overrides SometimesSetsUpAFrame() to return false. That means |
| 7101 // we cannot call anything that could cause a GC from this stub. | 7182 // we cannot call anything that could cause a GC from this stub. |
| 7102 // Registers: | 7183 // Registers: |
| 7103 // result: StringDictionary to probe | 7184 // result: StringDictionary to probe |
| 7104 // a1: key | 7185 // a1: key |
| 7105 // : StringDictionary to probe. | 7186 // : StringDictionary to probe. |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7460 | 7541 |
| 7461 // Fall through when we need to inform the incremental marker. | 7542 // Fall through when we need to inform the incremental marker. |
| 7462 } | 7543 } |
| 7463 | 7544 |
| 7464 | 7545 |
| 7465 #undef __ | 7546 #undef __ |
| 7466 | 7547 |
| 7467 } } // namespace v8::internal | 7548 } } // namespace v8::internal |
| 7468 | 7549 |
| 7469 #endif // V8_TARGET_ARCH_MIPS | 7550 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |