35 // Global list that stores pointers to the member variables where shared container instances |
35 // Global list that stores pointers to the member variables where shared container instances |
36 // store offsets returned my memory allocator. |
36 // store offsets returned my memory allocator. |
37 // CSS converter utilizes it to automatically adjust the offsets if allocated cells are moved. |
37 // CSS converter utilizes it to automatically adjust the offsets if allocated cells are moved. |
38 |
38 |
39 // Map is used only to get faster lookups, item's value is obsolete |
39 // Map is used only to get faster lookups, item's value is obsolete |
40 static QMap<int *, int> registered; |
40 static QMap<qptrdiff *, int> registered; |
41 |
41 |
42 |
42 |
43 // Shared chunk allocation information for css data |
43 // Shared chunk allocation information for css data |
44 static int totalAllocated = 0; |
44 static int totalAllocated = 0; |
45 // Using map instead of hash to guarantee that the items are in order |
45 // Using map instead of hash to guarantee that the items are in order |
46 // so the cell with offset 0 which is the HbCss::StyleSheet structure |
46 // so the cell with offset 0 which is the HbCss::StyleSheet structure |
47 // is always first in the cell list, so its offset does not get changed |
47 // is always first in the cell list, so its offset does not get changed |
48 // when the chunk is defragmented. |
48 // when the chunk is defragmented. |
49 static QMap<int, int> cells; |
49 static QMap<qptrdiff, int> cells; |
50 |
50 |
51 |
51 |
52 void HbCssConverterUtils::registerOffsetHolder(int *offset) |
52 void HbCssConverterUtils::registerOffsetHolder(qptrdiff *offset) |
53 { |
53 { |
54 registered.insert(offset, 1); |
54 registered.insert(offset, 1); |
55 } |
55 } |
56 |
56 |
57 void HbCssConverterUtils::unregisterOffsetHolder(int *offset) |
57 void HbCssConverterUtils::unregisterOffsetHolder(qptrdiff *offset) |
58 { |
58 { |
59 registered.remove(offset); |
59 registered.remove(offset); |
60 } |
60 } |
61 |
61 |
62 QMultiHash<int, int *> HbCssConverterUtils::registeredOffsetHolders() |
62 QMultiHash<int, qptrdiff *> HbCssConverterUtils::registeredOffsetHolders() |
63 { |
63 { |
64 QMultiHash<int, int *> holders; |
64 QMultiHash<int, qptrdiff *> holders; |
65 holders.reserve(registered.size()); |
65 holders.reserve(registered.size()); |
66 QMap<int *, int>::const_iterator end = registered.constEnd(); |
66 QMap<qptrdiff *, int>::const_iterator end = registered.constEnd(); |
67 for (QMap<int *, int>::const_iterator i = registered.constBegin(); i != end; ++i) { |
67 for (QMap<qptrdiff *, int>::const_iterator i = registered.constBegin(); i != end; ++i) { |
68 int *holder = i.key(); |
68 qptrdiff *holder = i.key(); |
69 holders.insertMulti(*holder, holder); |
69 holders.insertMulti(*holder, holder); |
70 } |
70 } |
71 return holders; |
71 return holders; |
72 } |
72 } |
73 |
73 |
75 { |
75 { |
76 registered.clear(); |
76 registered.clear(); |
77 } |
77 } |
78 |
78 |
79 |
79 |
80 void HbCssConverterUtils::cellAllocated(int offset, int size) |
80 void HbCssConverterUtils::cellAllocated(qptrdiff offset, int size) |
81 { |
81 { |
82 cells.insert(offset, ALIGN(size)); |
82 cells.insert(offset, ALIGN(size)); |
83 totalAllocated += ALIGN(size); |
83 totalAllocated += ALIGN(size); |
84 } |
84 } |
85 |
85 |
86 void HbCssConverterUtils::cellFreed(int offset) |
86 void HbCssConverterUtils::cellFreed(qptrdiff offset) |
87 { |
87 { |
88 int size = cells.value(offset, 0); |
88 int size = cells.value(offset, 0); |
89 totalAllocated -= size; |
89 totalAllocated -= size; |
90 cells.remove(offset); |
90 cells.remove(offset); |
91 |
91 |
93 // Make sure there are no registered offset holders in the freed cell any more |
93 // Make sure there are no registered offset holders in the freed cell any more |
94 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
94 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
95 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
95 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
96 const char *chunkBase = static_cast<const char *>(shared->base()); |
96 const char *chunkBase = static_cast<const char *>(shared->base()); |
97 const char *freedEnd = chunkBase + offset + size; |
97 const char *freedEnd = chunkBase + offset + size; |
98 const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset); |
98 const qptrdiff *freedStart = reinterpret_cast<const qptrdiff *>(chunkBase + offset); |
99 |
99 |
100 QMap<int *, int>::iterator freedHolders = |
100 QMap<qptrdiff *, int>::iterator freedHolders = |
101 registered.lowerBound(const_cast<int *>(freedStart)); |
101 registered.lowerBound(const_cast<qptrdiff *>(freedStart)); |
102 while(freedHolders != registered.end() |
102 while(freedHolders != registered.end() |
103 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
103 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
104 freedHolders = registered.erase(freedHolders); |
104 freedHolders = registered.erase(freedHolders); |
105 } |
105 } |
106 } |
106 } |
107 } |
107 } |
108 |
108 |
109 void HbCssConverterUtils::cellMoved(int offset, int newOffset) |
109 void HbCssConverterUtils::cellMoved(qptrdiff offset, qptrdiff newOffset) |
110 { |
110 { |
111 int size = cells.value(offset, 0); |
111 int size = cells.value(offset, 0); |
112 |
112 |
113 if (size > 0) { |
113 if (size > 0) { |
114 // Check if there were registered offset holders in the old cell |
114 // Check if there were registered offset holders in the old cell |
115 // and register corresponding ones in the reallocated cell. |
115 // and register corresponding ones in the reallocated cell. |
116 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
116 GET_MEMORY_MANAGER(HbMemoryManager::SharedMemory); |
117 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
117 HbSharedMemoryManager *shared = static_cast<HbSharedMemoryManager*>(manager); |
118 const char *chunkBase = static_cast<const char *>(shared->base()); |
118 const char *chunkBase = static_cast<const char *>(shared->base()); |
119 const char *freedEnd = chunkBase + offset + size; |
119 const char *freedEnd = chunkBase + offset + size; |
120 const int *freedStart = reinterpret_cast<const int *>(chunkBase + offset); |
120 const qptrdiff *freedStart = reinterpret_cast<const qptrdiff *>(chunkBase + offset); |
121 |
121 |
122 QMap<int *, int>::iterator freedHolders = |
122 QMap<qptrdiff *, int>::iterator freedHolders = |
123 registered.lowerBound(const_cast<int *>(freedStart)); |
123 registered.lowerBound(const_cast<qptrdiff *>(freedStart)); |
124 QList<int *> newHolders; |
124 QList<qptrdiff *> newHolders; |
125 while(freedHolders != registered.end() |
125 while(freedHolders != registered.end() |
126 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
126 && reinterpret_cast<char*>(freedHolders.key()) < freedEnd) { |
127 char *holderC = reinterpret_cast<char*>(freedHolders.key()); |
127 char *holderC = reinterpret_cast<char*>(freedHolders.key()); |
128 newHolders.append(reinterpret_cast<int*>(holderC + newOffset - offset)); |
128 newHolders.append(reinterpret_cast<qptrdiff*>(holderC + newOffset - offset)); |
129 freedHolders = registered.erase(freedHolders); |
129 freedHolders = registered.erase(freedHolders); |
130 } |
130 } |
131 for (int i = 0; i < newHolders.size(); ++i) { |
131 for (int i = 0; i < newHolders.size(); ++i) { |
132 registerOffsetHolder(newHolders.at(i)); |
132 registerOffsetHolder(newHolders.at(i)); |
133 } |
133 } |
146 strMap.clear(); |
146 strMap.clear(); |
147 |
147 |
148 // Register shared cache pointer in chunk header |
148 // Register shared cache pointer in chunk header |
149 //as shared cache may also be moved in defragmentation |
149 //as shared cache may also be moved in defragmentation |
150 HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base()); |
150 HbSharedChunkHeader *chunkHeader = static_cast<HbSharedChunkHeader*>(shared->base()); |
151 registerOffsetHolder(reinterpret_cast<int *>(&chunkHeader->sharedCacheOffset)); |
151 registerOffsetHolder(reinterpret_cast<qptrdiff *>(&chunkHeader->sharedCacheOffset)); |
152 |
152 |
153 QMultiHash<int, int *> offsetHolders = registeredOffsetHolders(); |
153 QMultiHash<int, qptrdiff *> offsetHolders = registeredOffsetHolders(); |
154 |
154 |
155 // Create new buffer where the current chunk contents are defragmented |
155 // Create new buffer where the current chunk contents are defragmented |
156 char *buffer = static_cast<char*>(::malloc(shared->size())); |
156 char *buffer = static_cast<char*>(::malloc(shared->size())); |
157 int newCurrentOffset = 0; |
157 qptrdiff newCurrentOffset = 0; |
158 |
158 |
159 // Create new cell order and update offset holders |
159 // Create new cell order and update offset holders |
160 QMap<int,int>::const_iterator end = cells.constEnd(); |
160 QMap<qptrdiff,int>::const_iterator end = cells.constEnd(); |
161 |
161 |
162 for (QMap<int,int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
162 for (QMap<qptrdiff,int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
163 // Get the old cell |
163 // Get the old cell |
164 int offset = i.key(); |
164 qptrdiff offset = i.key(); |
165 int size = i.value(); |
165 int size = i.value(); |
166 |
166 |
167 // Update registered offset holders |
167 // Update registered offset holders |
168 QList<int *> values = offsetHolders.values(offset); |
168 QList<qptrdiff *> values = offsetHolders.values(offset); |
169 offsetHolders.remove(offset); |
169 offsetHolders.remove(offset); |
170 int newOffset = newCurrentOffset + sizeof(HbSharedChunkHeader); |
170 qptrdiff newOffset = newCurrentOffset + sizeof(HbSharedChunkHeader); |
171 for (int j = 0; j < values.size(); ++j) { |
171 for (int j = 0; j < values.size(); ++j) { |
172 int *holder = values[j]; |
172 qptrdiff *holder = values[j]; |
173 *holder = newOffset; |
173 *holder = newOffset; |
174 offsetHolders.insertMulti(*holder, holder); |
174 offsetHolders.insertMulti(*holder, holder); |
175 } |
175 } |
176 newCurrentOffset += size; |
176 newCurrentOffset += size; |
177 } |
177 } |
178 |
178 |
179 newCurrentOffset = 0; |
179 newCurrentOffset = 0; |
180 // Move allocated cells to a linear buffer |
180 // Move allocated cells to a linear buffer |
181 for (QMap<int, int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
181 for (QMap<qptrdiff, int>::const_iterator i = cells.constBegin(); i != end; ++i) { |
182 // Get the old cell |
182 // Get the old cell |
183 int offset = i.key(); |
183 qptrdiff offset = i.key(); |
184 int size = i.value(); |
184 int size = i.value(); |
185 // Copy to new chunk |
185 // Copy to new chunk |
186 memcpy(buffer + newCurrentOffset, static_cast<char*>(shared->base()) + offset, size); |
186 memcpy(buffer + newCurrentOffset, static_cast<char*>(shared->base()) + offset, size); |
187 newCurrentOffset += size; |
187 newCurrentOffset += size; |
188 } |
188 } |
190 // Free all cells from the shared chunk and move the defragmented buffer in the beginning of the chunk. |
190 // Free all cells from the shared chunk and move the defragmented buffer in the beginning of the chunk. |
191 // Note that chunk memory management is screwed up after this point, so no more allocations should be |
191 // Note that chunk memory management is screwed up after this point, so no more allocations should be |
192 // done in it after this. |
192 // done in it after this. |
193 |
193 |
194 unregisterAll(); |
194 unregisterAll(); |
195 QList<int> keys = cells.keys(); |
195 QList<qptrdiff> keys = cells.keys(); |
196 |
196 |
197 for (int j = 0; j < keys.count(); ++j) { |
197 for (int j = 0; j < keys.count(); ++j) { |
198 shared->free(keys.at(j)); |
198 shared->free(keys.at(j)); |
199 } |
199 } |
200 |
200 |
201 // CSS binary data is placed after the chunk header. |
201 // CSS binary data is placed after the chunk header. |
202 int cssBinaryOffset = sizeof(HbSharedChunkHeader); |
202 qptrdiff cssBinaryOffset = sizeof(HbSharedChunkHeader); |
203 char *address = HbMemoryUtils::getAddress<char>(HbMemoryManager::SharedMemory, cssBinaryOffset); |
203 char *address = HbMemoryUtils::getAddress<char>(HbMemoryManager::SharedMemory, cssBinaryOffset); |
204 memcpy(address, buffer, newCurrentOffset); |
204 memcpy(address, buffer, newCurrentOffset); |
205 |
205 |
206 cells.clear(); |
206 cells.clear(); |
207 totalAllocated = 0; |
207 totalAllocated = 0; |