| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2009, 2012 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2009, 2012 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
| 5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
| 6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
| 7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
| 8 * | 8 * |
| 9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "wtf/RetainPtr.h" | 28 #include "wtf/RetainPtr.h" |
| 29 #include "wtf/Threading.h" | 29 #include "wtf/Threading.h" |
| 30 #include <CoreFoundation/CoreFoundation.h> | 30 #include <CoreFoundation/CoreFoundation.h> |
| 31 | 31 |
| 32 namespace WTF { | 32 namespace WTF { |
| 33 | 33 |
| 34 namespace StringWrapperCFAllocator { | 34 namespace StringWrapperCFAllocator { |
| 35 | 35 |
| 36 static StringImpl* currentString; | 36 static StringImpl* currentString; |
| 37 | 37 |
| 38 static const void* retain(const void* info) | 38 static const void* retain(const void* info) { |
| 39 { | 39 return info; |
| 40 return info; | |
| 41 } | 40 } |
| 42 | 41 |
| 43 NO_RETURN_DUE_TO_ASSERT | 42 NO_RETURN_DUE_TO_ASSERT |
| 44 static void release(const void*) | 43 static void release(const void*) { |
| 45 { | 44 ASSERT_NOT_REACHED(); |
| 46 ASSERT_NOT_REACHED(); | |
| 47 } | 45 } |
| 48 | 46 |
| 49 static CFStringRef copyDescription(const void*) | 47 static CFStringRef copyDescription(const void*) { |
| 50 { | 48 return CFSTR("WTF::String-based allocator"); |
| 51 return CFSTR("WTF::String-based allocator"); | |
| 52 } | 49 } |
| 53 | 50 |
| 54 static void* allocate(CFIndex size, CFOptionFlags, void*) | 51 static void* allocate(CFIndex size, CFOptionFlags, void*) { |
| 55 { | 52 StringImpl* underlyingString = 0; |
| 56 StringImpl* underlyingString = 0; | 53 if (isMainThread()) { |
| 57 if (isMainThread()) { | 54 underlyingString = currentString; |
| 58 underlyingString = currentString; | 55 if (underlyingString) { |
| 59 if (underlyingString) { | 56 currentString = 0; |
| 60 currentString = 0; | 57 underlyingString |
| 61 underlyingString->ref(); // Balanced by call to deref in deallocate
below. | 58 ->ref(); // Balanced by call to deref in deallocate below. |
| 62 } | |
| 63 } | 59 } |
| 64 StringImpl** header = static_cast<StringImpl**>(WTF::Partitions::fastMalloc(
sizeof(StringImpl*) + size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*))); | 60 } |
| 65 *header = underlyingString; | 61 StringImpl** header = static_cast<StringImpl**>(WTF::Partitions::fastMalloc( |
| 66 return header + 1; | 62 sizeof(StringImpl*) + size, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*))); |
| 63 *header = underlyingString; |
| 64 return header + 1; |
| 67 } | 65 } |
| 68 | 66 |
| 69 static void* reallocate(void* pointer, CFIndex newSize, CFOptionFlags, void*) | 67 static void* reallocate(void* pointer, CFIndex newSize, CFOptionFlags, void*) { |
| 70 { | 68 size_t newAllocationSize = sizeof(StringImpl*) + newSize; |
| 71 size_t newAllocationSize = sizeof(StringImpl*) + newSize; | 69 StringImpl** header = static_cast<StringImpl**>(pointer) - 1; |
| 72 StringImpl** header = static_cast<StringImpl**>(pointer) - 1; | 70 ASSERT(!*header); |
| 73 ASSERT(!*header); | 71 header = static_cast<StringImpl**>(WTF::Partitions::fastRealloc( |
| 74 header = static_cast<StringImpl**>(WTF::Partitions::fastRealloc(header, newA
llocationSize, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*))); | 72 header, newAllocationSize, WTF_HEAP_PROFILER_TYPE_NAME(StringImpl*))); |
| 75 return header + 1; | 73 return header + 1; |
| 76 } | 74 } |
| 77 | 75 |
| 78 static void deallocateOnMainThread(void* headerPointer) | 76 static void deallocateOnMainThread(void* headerPointer) { |
| 79 { | 77 StringImpl** header = static_cast<StringImpl**>(headerPointer); |
| 80 StringImpl** header = static_cast<StringImpl**>(headerPointer); | 78 StringImpl* underlyingString = *header; |
| 81 StringImpl* underlyingString = *header; | 79 ASSERT(underlyingString); |
| 82 ASSERT(underlyingString); | 80 underlyingString->deref(); // Balanced by call to ref in allocate above. |
| 83 underlyingString->deref(); // Balanced by call to ref in allocate above. | 81 WTF::Partitions::fastFree(header); |
| 84 WTF::Partitions::fastFree(header); | |
| 85 } | 82 } |
| 86 | 83 |
| 87 static void deallocate(void* pointer, void*) | 84 static void deallocate(void* pointer, void*) { |
| 88 { | 85 StringImpl** header = static_cast<StringImpl**>(pointer) - 1; |
| 89 StringImpl** header = static_cast<StringImpl**>(pointer) - 1; | 86 StringImpl* underlyingString = *header; |
| 90 StringImpl* underlyingString = *header; | 87 if (!underlyingString) { |
| 91 if (!underlyingString) { | 88 WTF::Partitions::fastFree(header); |
| 92 WTF::Partitions::fastFree(header); | 89 } else { |
| 90 if (!isMainThread()) { |
| 91 internal::callOnMainThread(&deallocateOnMainThread, header); |
| 93 } else { | 92 } else { |
| 94 if (!isMainThread()) { | 93 underlyingString->deref(); // Balanced by call to ref in allocate above. |
| 95 internal::callOnMainThread(&deallocateOnMainThread, header); | 94 WTF::Partitions::fastFree(header); |
| 96 } else { | |
| 97 underlyingString->deref(); // Balanced by call to ref in allocate ab
ove. | |
| 98 WTF::Partitions::fastFree(header); | |
| 99 } | |
| 100 } | 95 } |
| 96 } |
| 101 } | 97 } |
| 102 | 98 |
| 103 static CFIndex preferredSize(CFIndex size, CFOptionFlags, void*) | 99 static CFIndex preferredSize(CFIndex size, CFOptionFlags, void*) { |
| 104 { | 100 // FIXME: If FastMalloc provided a "good size" callback, we'd want to use it h
ere. |
| 105 // FIXME: If FastMalloc provided a "good size" callback, we'd want to use it
here. | 101 // Note that this optimization would help performance for strings created with
the |
| 106 // Note that this optimization would help performance for strings created wi
th the | 102 // allocator that are mutable, and those typically are only created by callers
who |
| 107 // allocator that are mutable, and those typically are only created by calle
rs who | 103 // make a new string using the old string's allocator, such as some of the cal
l |
| 108 // make a new string using the old string's allocator, such as some of the c
all | 104 // sites in CFURL. |
| 109 // sites in CFURL. | 105 return size; |
| 110 return size; | |
| 111 } | 106 } |
| 112 | 107 |
| 113 static CFAllocatorRef create() | 108 static CFAllocatorRef create() { |
| 114 { | 109 CFAllocatorContext context = { |
| 115 CFAllocatorContext context = { 0, 0, retain, release, copyDescription, alloc
ate, reallocate, deallocate, preferredSize }; | 110 0, 0, retain, release, copyDescription, |
| 116 return CFAllocatorCreate(0, &context); | 111 allocate, reallocate, deallocate, preferredSize}; |
| 112 return CFAllocatorCreate(0, &context); |
| 117 } | 113 } |
| 118 | 114 |
| 119 static CFAllocatorRef allocator() | 115 static CFAllocatorRef allocator() { |
| 120 { | 116 static CFAllocatorRef allocator = create(); |
| 121 static CFAllocatorRef allocator = create(); | 117 return allocator; |
| 122 return allocator; | 118 } |
| 123 } | 119 } |
| 124 | 120 |
| 125 } | 121 RetainPtr<CFStringRef> StringImpl::createCFString() { |
| 122 // Since garbage collection isn't compatible with custom allocators, we |
| 123 // can't use the NoCopy variants of CFStringCreate*() when GC is enabled. |
| 124 if (!m_length || !isMainThread()) { |
| 125 if (is8Bit()) |
| 126 return adoptCF(CFStringCreateWithBytes( |
| 127 0, reinterpret_cast<const UInt8*>(characters8()), m_length, |
| 128 kCFStringEncodingISOLatin1, false)); |
| 129 return adoptCF(CFStringCreateWithCharacters( |
| 130 0, reinterpret_cast<const UniChar*>(characters16()), m_length)); |
| 131 } |
| 132 CFAllocatorRef allocator = StringWrapperCFAllocator::allocator(); |
| 126 | 133 |
| 127 RetainPtr<CFStringRef> StringImpl::createCFString() | 134 // Put pointer to the StringImpl in a global so the allocator can store it wit
h the CFString. |
| 128 { | 135 ASSERT(!StringWrapperCFAllocator::currentString); |
| 129 // Since garbage collection isn't compatible with custom allocators, we | 136 StringWrapperCFAllocator::currentString = this; |
| 130 // can't use the NoCopy variants of CFStringCreate*() when GC is enabled. | |
| 131 if (!m_length || !isMainThread()) { | |
| 132 if (is8Bit()) | |
| 133 return adoptCF(CFStringCreateWithBytes(0, reinterpret_cast<const UIn
t8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false)); | |
| 134 return adoptCF(CFStringCreateWithCharacters(0, reinterpret_cast<const Un
iChar*>(characters16()), m_length)); | |
| 135 } | |
| 136 CFAllocatorRef allocator = StringWrapperCFAllocator::allocator(); | |
| 137 | 137 |
| 138 // Put pointer to the StringImpl in a global so the allocator can store it w
ith the CFString. | 138 CFStringRef string; |
| 139 ASSERT(!StringWrapperCFAllocator::currentString); | 139 if (is8Bit()) |
| 140 StringWrapperCFAllocator::currentString = this; | 140 string = CFStringCreateWithBytesNoCopy( |
| 141 allocator, reinterpret_cast<const UInt8*>(characters8()), m_length, |
| 142 kCFStringEncodingISOLatin1, false, kCFAllocatorNull); |
| 143 else |
| 144 string = CFStringCreateWithCharactersNoCopy( |
| 145 allocator, reinterpret_cast<const UniChar*>(characters16()), m_length, |
| 146 kCFAllocatorNull); |
| 147 // CoreFoundation might not have to allocate anything, we clear currentString
in case we did not execute allocate(). |
| 148 StringWrapperCFAllocator::currentString = 0; |
| 141 | 149 |
| 142 CFStringRef string; | 150 return adoptCF(string); |
| 143 if (is8Bit()) | |
| 144 string = CFStringCreateWithBytesNoCopy(allocator, reinterpret_cast<const
UInt8*>(characters8()), m_length, kCFStringEncodingISOLatin1, false, kCFAllocat
orNull); | |
| 145 else | |
| 146 string = CFStringCreateWithCharactersNoCopy(allocator, reinterpret_cast<
const UniChar*>(characters16()), m_length, kCFAllocatorNull); | |
| 147 // CoreFoundation might not have to allocate anything, we clear currentStrin
g in case we did not execute allocate(). | |
| 148 StringWrapperCFAllocator::currentString = 0; | |
| 149 | |
| 150 return adoptCF(string); | |
| 151 } | 151 } |
| 152 | 152 |
| 153 // On StringImpl creation we could check if the allocator is the StringWrapperCF
Allocator. | 153 // On StringImpl creation we could check if the allocator is the StringWrapperCF
Allocator. |
| 154 // If it is, then we could find the original StringImpl and just return that. Bu
t to | 154 // If it is, then we could find the original StringImpl and just return that. Bu
t to |
| 155 // do that we'd have to compute the offset from CFStringRef to the allocated blo
ck; | 155 // do that we'd have to compute the offset from CFStringRef to the allocated blo
ck; |
| 156 // the CFStringRef is *not* at the start of an allocated block. Testing shows 10
00x | 156 // the CFStringRef is *not* at the start of an allocated block. Testing shows 10
00x |
| 157 // more calls to createCFString than calls to the create functions with the appr
opriate | 157 // more calls to createCFString than calls to the create functions with the appr
opriate |
| 158 // allocator, so it's probably not urgent optimize that case. | 158 // allocator, so it's probably not urgent optimize that case. |
| 159 | |
| 160 } | 159 } |
| 161 | 160 |
| 162 #endif // OS(MACOSX) | 161 #endif // OS(MACOSX) |
| OLD | NEW |