Changeset 53400 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jan 18, 2010, 4:14:49 AM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r53397 r53400 1 2010-01-18 Csaba Osztrogonác <[email protected]> 2 3 Rubber-stamped by Gustavo Noronha Silva. 4 5 Rolling out r53391 and r53392 because of random crashes on buildbots. 6 https://bugs.webkit.org/show_bug.cgi?id=33731 7 8 * bytecode/CodeBlock.h: 9 (JSC::CallLinkInfo::seenOnce): 10 (JSC::CallLinkInfo::setSeen): 11 (JSC::MethodCallLinkInfo::MethodCallLinkInfo): 12 (JSC::MethodCallLinkInfo::seenOnce): 13 (JSC::MethodCallLinkInfo::setSeen): 14 * jit/JIT.cpp: 15 (JSC::JIT::unlinkCall): 16 * jit/JITPropertyAccess.cpp: 17 (JSC::JIT::patchMethodCallProto): 18 * runtime/UString.cpp: 19 (JSC::UString::spliceSubstringsWithSeparators): 20 (JSC::UString::replaceRange): 21 * runtime/UString.h: 22 * runtime/UStringImpl.cpp: 23 (JSC::UStringImpl::baseSharedBuffer): 24 (JSC::UStringImpl::sharedBuffer): 25 (JSC::UStringImpl::~UStringImpl): 26 * runtime/UStringImpl.h: 27 (JSC::UntypedPtrAndBitfield::UntypedPtrAndBitfield): 28 (JSC::UntypedPtrAndBitfield::asPtr): 29 (JSC::UntypedPtrAndBitfield::operator&=): 30 (JSC::UntypedPtrAndBitfield::operator|=): 31 (JSC::UntypedPtrAndBitfield::operator&): 32 (JSC::UStringImpl::create): 33 (JSC::UStringImpl::cost): 34 (JSC::UStringImpl::isIdentifier): 35 (JSC::UStringImpl::setIsIdentifier): 36 (JSC::UStringImpl::ref): 37 (JSC::UStringImpl::deref): 38 (JSC::UStringImpl::checkConsistency): 39 (JSC::UStringImpl::UStringImpl): 40 (JSC::UStringImpl::bufferOwnerString): 41 (JSC::UStringImpl::bufferOwnership): 42 (JSC::UStringImpl::isStatic): 43 * wtf/StringHashFunctions.h: 44 (WTF::stringHash): 45 1 46 2010-01-18 Simon Hausmann <[email protected]> 2 47 -
trunk/JavaScriptCore/bytecode/CodeBlock.h
r53391 r53400 111 111 CodeLocationDataLabelPtr hotPathBegin; 112 112 CodeLocationNearCall hotPathOther; 113 CodeBlock*ownerCodeBlock;113 PtrAndFlags<CodeBlock, HasSeenShouldRepatch> ownerCodeBlock; 114 114 CodeBlock* callee; 115 unsigned position : 31; 116 unsigned hasSeenShouldRepatch : 1; 115 unsigned position; 117 116 118 117 void setUnlinked() { callee = 0; } … … 121 120 bool seenOnce() 122 121 { 123 return hasSeenShouldRepatch;122 return ownerCodeBlock.isFlagSet(hasSeenShouldRepatch); 124 123 } 125 124 126 125 void setSeen() 127 126 { 128 hasSeenShouldRepatch = true; 129 } 130 }; 131 132 #define MethodCallLinkInfo_seenFlag ((Structure*)1) 127 ownerCodeBlock.setFlag(hasSeenShouldRepatch); 128 } 129 }; 133 130 134 131 struct MethodCallLinkInfo { 135 132 MethodCallLinkInfo() 136 133 : cachedStructure(0) 137 , cachedPrototypeStructure(0)138 134 { 139 135 } … … 141 137 bool seenOnce() 142 138 { 143 ASSERT(!cachedStructure); 144 return cachedPrototypeStructure; 139 return cachedPrototypeStructure.isFlagSet(hasSeenShouldRepatch); 145 140 } 146 141 147 142 void setSeen() 148 143 { 149 ASSERT(!cachedStructure && !cachedPrototypeStructure); 150 // We use the values of cachedStructure & cachedPrototypeStructure to indicate the 151 // current state. 152 // - In the initial state, both are null. 153 // - Once this transition has been taken once, cachedStructure is 154 // null and cachedPrototypeStructure is set to a nun-null value. 155 // - Once the call is linked both structures are set to non-null values. 156 cachedPrototypeStructure = MethodCallLinkInfo_seenFlag; 144 cachedPrototypeStructure.setFlag(hasSeenShouldRepatch); 157 145 } 158 146 … … 160 148 CodeLocationDataLabelPtr structureLabel; 161 149 Structure* cachedStructure; 162 Structure*cachedPrototypeStructure;150 PtrAndFlags<Structure, HasSeenShouldRepatch> cachedPrototypeStructure; 163 151 }; 164 152 -
trunk/JavaScriptCore/jit/JIT.cpp
r53391 r53400 583 583 // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive 584 584 // match). Reset the check so it no longer matches. 585 RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock );585 RepatchBuffer repatchBuffer(callLinkInfo->ownerCodeBlock.get()); 586 586 #if USE(JSVALUE32_64) 587 587 repatchBuffer.repatch(callLinkInfo->hotPathBegin, 0); -
trunk/JavaScriptCore/jit/JITPropertyAccess.cpp
r53391 r53400 645 645 646 646 Structure* prototypeStructure = proto->structure(); 647 ASSERT(!methodCallLinkInfo.cachedPrototypeStructure); 647 648 methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure; 648 649 prototypeStructure->ref(); … … 1594 1595 1595 1596 Structure* prototypeStructure = proto->structure(); 1597 ASSERT(!methodCallLinkInfo.cachedPrototypeStructure); 1596 1598 methodCallLinkInfo.cachedPrototypeStructure = prototypeStructure; 1597 1599 prototypeStructure->ref(); -
trunk/JavaScriptCore/runtime/UString.cpp
r53392 r53400 349 349 UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const 350 350 { 351 m_rep->checkConsistency(); 352 351 353 if (rangeCount == 1 && separatorCount == 0) { 352 354 int thisSize = size(); … … 390 392 UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const 391 393 { 394 m_rep->checkConsistency(); 395 392 396 int replacementLength = replacement.size(); 393 397 int totalLength = size() - rangeLength + replacementLength; -
trunk/JavaScriptCore/runtime/UString.h
r53391 r53400 32 32 #include <wtf/OwnFastMallocPtr.h> 33 33 #include <wtf/PassRefPtr.h> 34 #include <wtf/PtrAndFlags.h> 34 35 #include <wtf/RefPtr.h> 35 36 #include <wtf/Vector.h> -
trunk/JavaScriptCore/runtime/UStringImpl.cpp
r53392 r53400 36 36 namespace JSC { 37 37 38 SharedUChar* UStringImpl::baseSharedBuffer() 39 { 40 ASSERT((bufferOwnership() == BufferShared) 41 || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>())); 42 43 if (bufferOwnership() != BufferShared) 44 m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared); 45 46 return m_dataBuffer.asPtr<SharedUChar*>(); 47 } 48 38 49 SharedUChar* UStringImpl::sharedBuffer() 39 50 { 40 if (m_length < s_minLengthToShare || isStatic()) 51 if (m_length < s_minLengthToShare) 52 return 0; 53 ASSERT(!isStatic()); 54 55 UStringImpl* owner = bufferOwnerString(); 56 if (owner->bufferOwnership() == BufferInternal) 41 57 return 0; 42 58 43 switch (bufferOwnership()) { 44 case BufferInternal: 45 return 0; 46 case BufferOwned: 47 m_bufferShared = SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(); 48 m_refCountAndFlags &= ~s_refCountMaskBufferOwnership; 49 m_refCountAndFlags |= BufferShared; 50 return m_bufferShared; 51 case BufferSubstring: 52 return m_bufferSubstring->sharedBuffer(); 53 case BufferShared: 54 return m_bufferShared; 55 } 56 57 ASSERT_NOT_REACHED(); 58 return 0; 59 return owner->baseSharedBuffer(); 59 60 } 60 61 … … 62 63 { 63 64 ASSERT(!isStatic()); 65 checkConsistency(); 64 66 65 67 if (isIdentifier()) 66 68 Identifier::remove(this); 67 69 68 switch (bufferOwnership()) { 69 case BufferInternal: 70 return; 71 case BufferOwned: 72 fastFree(m_data); 73 return; 74 case BufferSubstring: 75 m_bufferSubstring->deref(); 76 return; 77 case BufferShared: 78 m_bufferSubstring->deref(); 70 if (bufferOwnership() != BufferInternal) { 71 if (bufferOwnership() == BufferOwned) 72 fastFree(m_data); 73 else if (bufferOwnership() == BufferSubstring) 74 m_dataBuffer.asPtr<UStringImpl*>()->deref(); 75 else { 76 ASSERT(bufferOwnership() == BufferShared); 77 m_dataBuffer.asPtr<SharedUChar*>()->deref(); 78 } 79 79 } 80 80 } 81 81 82 } // namespace JSC82 } -
trunk/JavaScriptCore/runtime/UStringImpl.h
r53392 r53400 41 41 typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; 42 42 43 class UntypedPtrAndBitfield { 44 public: 45 UntypedPtrAndBitfield() {} 46 47 UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue) 48 : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue) 49 #ifndef NDEBUG 50 , m_leaksPtr(ptrValue) 51 #endif 52 { 53 ASSERT(ptrValue == asPtr<void*>()); 54 ASSERT((*this & ~s_alignmentMask) == bitValue); 55 } 56 57 template<typename T> 58 T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); } 59 60 UntypedPtrAndBitfield& operator&=(uintptr_t bits) 61 { 62 m_value &= bits | s_alignmentMask; 63 return *this; 64 } 65 66 UntypedPtrAndBitfield& operator|=(uintptr_t bits) 67 { 68 m_value |= bits & ~s_alignmentMask; 69 return *this; 70 } 71 72 uintptr_t operator&(uintptr_t mask) const 73 { 74 return m_value & mask & ~s_alignmentMask; 75 } 76 77 private: 78 static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7); 79 uintptr_t m_value; 80 #ifndef NDEBUG 81 void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced. 82 #endif 83 }; 84 43 85 class UStringImpl : Noncopyable { 44 86 public: … … 64 106 { 65 107 ASSERT(rep); 66 if (rep->bufferOwnership() == BufferSubstring) 67 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->m_bufferSubstring)); 68 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep)); 108 rep->checkConsistency(); 109 return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString())); 69 110 } 70 111 … … 111 152 // For substrings, return the cost of the base string. 112 153 if (bufferOwnership() == BufferSubstring) 113 return m_bufferSubstring->cost(); 114 if (m_refCountAndFlags & s_refCountFlagHasReportedCost) 154 return m_dataBuffer.asPtr<UStringImpl*>()->cost(); 155 156 if (m_dataBuffer & s_reportedCostBit) 115 157 return 0; 116 ASSERT(!isStatic()); 117 m_refCountAndFlags |= s_refCountFlagHasReportedCost; 158 m_dataBuffer |= s_reportedCostBit; 118 159 return m_length; 119 160 } … … 121 162 unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers 122 163 void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers 123 bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } 124 void setIsIdentifier(bool isIdentifier) 125 { 126 ASSERT(!isStatic()); 127 if (isIdentifier) 128 m_refCountAndFlags |= s_refCountFlagIsIdentifier; 129 else 130 m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; 131 } 132 133 UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } 134 ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } 164 bool isIdentifier() const { return m_isIdentifier; } 165 void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; } 166 167 UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; } 168 ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; } 135 169 136 170 static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) … … 149 183 static UStringImpl& null() { return *s_null; } 150 184 static UStringImpl& empty() { return *s_empty; } 185 186 ALWAYS_INLINE void checkConsistency() const 187 { 188 // There is no recursion of substrings. 189 ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring); 190 // Static strings cannot be put in identifier tables, because they are globally shared. 191 ASSERT(!isStatic() || !isIdentifier()); 192 } 151 193 152 194 private: … … 164 206 UStringImpl(UChar* data, int length, BufferOwnership ownership) 165 207 : m_data(data) 166 , m_buffer(0)167 208 , m_length(length) 168 , m_refCount AndFlags(s_refCountIncrement | ownership)209 , m_refCount(s_refCountIncrement) 169 210 , m_hash(0) 211 , m_isIdentifier(false) 212 , m_dataBuffer(0, ownership) 170 213 { 171 214 ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); 215 checkConsistency(); 172 216 } 173 217 … … 178 222 UStringImpl(UChar* data, int length, StaticStringConstructType) 179 223 : m_data(data) 180 , m_buffer(0)181 224 , m_length(length) 182 , m_refCount AndFlags(s_refCountFlagStatic | s_refCountFlagHasReportedCost | BufferOwned)225 , m_refCount(s_staticRefCountInitialValue) 183 226 , m_hash(0) 184 { 227 , m_isIdentifier(false) 228 , m_dataBuffer(0, BufferOwned) 229 { 230 checkConsistency(); 185 231 } 186 232 … … 188 234 UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base) 189 235 : m_data(data) 190 , m_bufferSubstring(base.releaseRef())191 236 , m_length(length) 192 , m_refCount AndFlags(s_refCountIncrement | BufferSubstring)237 , m_refCount(s_refCountIncrement) 193 238 , m_hash(0) 239 , m_isIdentifier(false) 240 , m_dataBuffer(base.releaseRef(), BufferSubstring) 194 241 { 195 242 // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes 196 243 // that all pointers will be at least 8-byte aligned, we cannot guarantee that of 197 244 // UStringImpls that are not heap allocated. 198 ASSERT(m_ bufferSubstring->size());199 ASSERT(!m_ bufferSubstring->isStatic());200 ASSERT(m_bufferSubstring->bufferOwnership() != BufferSubstring);245 ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size()); 246 ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic()); 247 checkConsistency(); 201 248 } 202 249 … … 204 251 UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer) 205 252 : m_data(data) 206 , m_bufferShared(sharedBuffer.releaseRef())207 253 , m_length(length) 208 , m_refCount AndFlags(s_refCountIncrement | BufferShared)254 , m_refCount(s_refCountIncrement) 209 255 , m_hash(0) 210 { 256 , m_isIdentifier(false) 257 , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) 258 { 259 checkConsistency(); 211 260 } 212 261 … … 217 266 218 267 // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. 219 static const unsigneds_minLengthToShare = 10;268 static const int s_minLengthToShare = 10; 220 269 static const unsigned s_copyCharsInlineCutOff = 20; 221 222 bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } 223 BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } 224 270 static const uintptr_t s_bufferOwnershipMask = 3; 271 static const uintptr_t s_reportedCostBit = 4; 225 272 // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. 226 273 // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero. 227 static const unsigned s_refCountMask = 0xFFFFFFF0; 228 static const unsigned s_refCountIncrement = 0x20; 229 static const unsigned s_refCountFlagStatic = 0x10; 230 static const unsigned s_refCountFlagHasReportedCost = 0x8; 231 static const unsigned s_refCountFlagIsIdentifier = 0x4; 232 static const unsigned s_refCountMaskBufferOwnership = 0x3; 233 274 static const int s_refCountIncrement = 2; 275 static const int s_staticRefCountInitialValue = 1; 276 277 UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } 278 const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } 279 SharedUChar* baseSharedBuffer(); 280 unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; } 281 bool isStatic() const { return m_refCount & 1; } 282 283 // unshared data 234 284 UChar* m_data; 235 union { 236 void* m_buffer; 237 UStringImpl* m_bufferSubstring; 238 SharedUChar* m_bufferShared; 239 }; 240 unsigned m_length; 241 unsigned m_refCountAndFlags; 242 mutable unsigned m_hash; 285 int m_length; 286 unsigned m_refCount; 287 mutable unsigned m_hash : 31; 288 mutable unsigned m_isIdentifier : 1; 289 UntypedPtrAndBitfield m_dataBuffer; 243 290 244 291 JS_EXPORTDATA static UStringImpl* s_null; -
trunk/JavaScriptCore/wtf/StringHashFunctions.h
r53392 r53400 61 61 hash ^= hash << 10; 62 62 63 hash &= 0x7fffffff; 64 63 65 // this avoids ever returning a hash code of 0, since that is used to 64 66 // signal "hash not computed yet", using a value that is likely to be 65 67 // effectively the same as 0 when the low bits are masked 66 68 if (hash == 0) 67 hash = 0x 80000000;69 hash = 0x40000000; 68 70 69 71 return hash; … … 99 101 hash ^= hash << 10; 100 102 103 hash &= 0x7fffffff; 104 101 105 // this avoids ever returning a hash code of 0, since that is used to 102 106 // signal "hash not computed yet", using a value that is likely to be 103 107 // effectively the same as 0 when the low bits are masked 104 108 if (hash == 0) 105 hash = 0x 80000000;109 hash = 0x40000000; 106 110 107 111 return hash; … … 138 142 hash ^= hash << 10; 139 143 144 hash &= 0x7fffffff; 145 140 146 // This avoids ever returning a hash code of 0, since that is used to 141 147 // signal "hash not computed yet", using a value that is likely to be 142 148 // effectively the same as 0 when the low bits are masked. 143 149 if (hash == 0) 144 hash = 0x 80000000;150 hash = 0x40000000; 145 151 146 152 return hash;
Note:
See TracChangeset
for help on using the changeset viewer.