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 |