53 void HbCssConverterUtils::unregisterOffsetHolder(int *offset) |
53 void HbCssConverterUtils::unregisterOffsetHolder(int *offset) |
54 { |
54 { |
55 registered.remove(offset); |
55 registered.remove(offset); |
56 } |
56 } |
57 |
57 |
58 |
58 QMultiHash<int, int *> HbCssConverterUtils::registeredOffsetHolders() |
59 QList<int *> HbCssConverterUtils::registeredOffsetHolders() |
59 { |
60 { |
60 QMultiHash<int, int *> holders; |
61 return registered.keys(); |
61 holders.reserve(registered.size()); |
|
62 QMap<int *, int>::const_iterator end = registered.constEnd(); |
|
63 for (QMap<int *, int>::const_iterator i = registered.constBegin(); i != end; ++i) { |
|
64 int *holder = i.key(); |
|
65 holders.insertMulti(*holder, holder); |
|
66 } |
|
67 return holders; |
62 } |
68 } |
63 |
69 |
64 void HbCssConverterUtils::unregisterAll() |
70 void HbCssConverterUtils::unregisterAll() |
65 { |
71 { |
66 registered.clear(); |
72 registered.clear(); |
82 if (size > 0) { |
88 if (size > 0) { |
83 // Make sure there are no registered offset holders in the freed cell any more |
89 // Make sure there are no registered offset holders in the freed cell any more |
84 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
90 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
85 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
91 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
86 const char *chunkBase = static_cast<const char *>(shared->base()); |
92 const char *chunkBase = static_cast<const char *>(shared->base()); |
87 |
93 const char *freedEnd = chunkBase + offset + size; |
88 QList<int *> offsetHolders = HbCssConverterUtils::registeredOffsetHolders(); |
94 const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset); |
89 for (int i = 0; i<offsetHolders.count(); ++i) { |
95 |
90 int *holder = offsetHolders.at(i); |
96 QMap<int *, int>::iterator freedHolders = |
91 if ((char*)holder >= chunkBase + offset && (char*)holder < chunkBase + offset + size) { |
97 registered.lowerBound(const_cast<int *>(freedStart)); |
92 HbCssConverterUtils::unregisterOffsetHolder(holder); |
98 while(freedHolders != registered.end() |
93 } |
99 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
|
100 freedHolders = registered.erase(freedHolders); |
94 } |
101 } |
95 } |
102 } |
96 } |
103 } |
97 |
104 |
98 void HbCssConverterUtils::cellMoved(int offset, int newOffset) |
105 void HbCssConverterUtils::cellMoved(int offset, int newOffset) |
100 int size = cells.value(offset, 0); |
107 int size = cells.value(offset, 0); |
101 |
108 |
102 if (size > 0) { |
109 if (size > 0) { |
103 // Check if there were registered offset holders in the old cell |
110 // Check if there were registered offset holders in the old cell |
104 // and register corresponding ones in the reallocated cell. |
111 // and register corresponding ones in the reallocated cell. |
105 QList<int *> holders = HbCssConverterUtils::registeredOffsetHolders(); |
|
106 |
|
107 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
112 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
108 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
113 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
109 const char *chunkBase = static_cast<const char *>(shared->base()); |
114 const char *chunkBase = static_cast<const char *>(shared->base()); |
110 |
115 const char *freedEnd = chunkBase + offset + size; |
111 for (int i=0; i<holders.count(); i++) { |
116 const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset); |
112 int *holder = holders.at(i); |
117 |
113 char *holderC = (char*)holder; |
118 QMap<int *, int>::iterator freedHolders = |
114 if (holderC >= chunkBase + offset && holderC < chunkBase + offset + size) { |
119 registered.lowerBound(const_cast<int *>(freedStart)); |
115 HbCssConverterUtils::unregisterOffsetHolder(holder); |
120 QList<int *> newHolders; |
116 HbCssConverterUtils::registerOffsetHolder((int*)(holderC + newOffset - offset)); |
121 while(freedHolders != registered.end() |
117 } |
122 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
|
123 char *holderC = reinterpret_cast<char*>(freedHolders.key()); |
|
124 newHolders.append(reinterpret_cast<int*>(holderC + newOffset - offset)); |
|
125 freedHolders = registered.erase(freedHolders); |
|
126 } |
|
127 for (int i = 0; i < newHolders.size(); ++i) { |
|
128 registerOffsetHolder(newHolders.at(i)); |
118 } |
129 } |
119 } |
130 } |
120 } |
131 } |
121 |
132 |
122 /** |
133 /** |
127 int HbCssConverterUtils::defragmentChunk() |
138 int HbCssConverterUtils::defragmentChunk() |
128 { |
139 { |
129 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
140 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
130 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
141 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
131 |
142 |
132 // Register shared cache pointer in chunk header as shared cache may also be moved in defragmentation |
143 // Register shared cache pointer in chunk header |
133 HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base()); |
144 //as shared cache may also be moved in defragmentation |
134 HbCssConverterUtils::registerOffsetHolder(reinterpret_cast<int *>(&chunkHeader->sharedCacheOffset)); |
145 HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base()); |
135 |
146 registerOffsetHolder(reinterpret_cast<int *>(&chunkHeader->sharedCacheOffset)); |
136 QList<int *> offsetHolders = HbCssConverterUtils::registeredOffsetHolders(); |
147 |
|
148 QMultiHash<int, int *> offsetHolders = registeredOffsetHolders(); |
137 |
149 |
138 // Create new buffer where the current chunk contents are defragmented |
150 // Create new buffer where the current chunk contents are defragmented |
139 void *buffer = ::malloc(shared->size()); |
151 char *buffer = static_cast<char*>(::malloc(shared->size())); |
140 int newCurrentOffset = 0; |
152 int newCurrentOffset = 0; |
141 |
153 |
142 // Create new cell order and update offset holders |
154 // Create new cell order and update offset holders |
143 QMap<int,int>::const_iterator i = cells.constBegin(); |
155 QMap<int,int>::const_iterator end = cells.constEnd(); |
144 |
156 |
145 while (i != cells.constEnd()) { |
157 for (QMap<int,int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
146 // Get the old cell |
158 // Get the old cell |
147 int offset = i.key(); |
159 int offset = i.key(); |
148 int size = i.value(); |
160 int size = i.value(); |
149 |
161 |
150 // Update registered offset holders |
162 // Update registered offset holders |
151 |
163 QList<int *> values = offsetHolders.values(offset); |
152 // TODO: optimize this, now there's linear search for each cell! |
164 offsetHolders.remove(offset); |
153 for (int j=0; j<offsetHolders.count(); ++j) { |
165 int newOffset = newCurrentOffset + sizeof(HbSharedChunkHeader); |
154 int *holder = offsetHolders.at(j); |
166 for (int j = 0; j < values.size(); ++j) { |
155 if (*holder == offset) { |
167 int *holder = values[j]; |
156 // Change stored offset value |
168 *holder = newOffset; |
157 *holder = newCurrentOffset + sizeof(HbSharedChunkHeader); |
169 offsetHolders.insertMulti(*holder, holder); |
158 } |
170 } |
159 } |
|
160 |
|
161 newCurrentOffset += size; |
171 newCurrentOffset += size; |
162 i++; |
172 } |
163 } |
173 |
164 |
|
165 i = cells.constBegin(); |
|
166 newCurrentOffset = 0; |
174 newCurrentOffset = 0; |
167 |
|
168 // Move allocated cells to a linear buffer |
175 // Move allocated cells to a linear buffer |
169 while (i != cells.constEnd()) { |
176 for (QMap<int, int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
170 // Get the old cell |
177 // Get the old cell |
171 int offset = i.key(); |
178 int offset = i.key(); |
172 int size = i.value(); |
179 int size = i.value(); |
173 // Copy to new chunk |
180 // Copy to new chunk |
174 memcpy((char*)buffer + newCurrentOffset, (char*)shared->base() + offset, size); |
181 memcpy(buffer + newCurrentOffset, static_cast<char*>(shared->base()) + offset, size); |
175 |
|
176 newCurrentOffset += size; |
182 newCurrentOffset += size; |
177 i++; |
|
178 } |
183 } |
179 |
184 |
180 // Free all cells from the shared chunk and move the defragmented buffer in the beginning of the chunk. |
185 // Free all cells from the shared chunk and move the defragmented buffer in the beginning of the chunk. |
181 // Note that chunk memory management is screwed up after this point, so no more allocations should be |
186 // Note that chunk memory management is screwed up after this point, so no more allocations should be |
182 // done in it after this. |
187 // done in it after this. |
183 |
188 |
184 HbCssConverterUtils::unregisterAll(); |
189 unregisterAll(); |
185 QList<int> keys = cells.keys(); |
190 QList<int> keys = cells.keys(); |
186 |
191 |
187 for (int j=0; j<keys.count(); ++j) { |
192 for (int j = 0; j < keys.count(); ++j) { |
188 shared->free(keys.at(j)); |
193 shared->free(keys.at(j)); |
189 } |
194 } |
190 |
195 |
191 // CSS binary data is placed after the chunk header. |
196 // CSS binary data is placed after the chunk header. |
192 int cssBinaryOffset = sizeof(HbSharedChunkHeader); |
197 int cssBinaryOffset = sizeof(HbSharedChunkHeader); |