Changeset 26847 in webkit for trunk/JavaScriptCore/kjs/array_object.cpp
- Timestamp:
- Oct 21, 2007, 8:12:08 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/array_object.cpp
r26688 r26847 36 36 37 37 38 using namespace KJS; 38 namespace KJS { 39 40 typedef HashMap<unsigned, JSValue*> OverflowMap; 41 42 static inline OverflowMap* overflowMap(JSValue** storage) 43 { 44 return storage ? reinterpret_cast<OverflowMap*>(storage[-2]) : 0; 45 } 39 46 40 47 // ------------------------------ ArrayInstance ----------------------------- … … 49 56 return 0; 50 57 51 // store capacity in extra space before the beginning of the storage array to save space52 JSValue** storage = static_cast<JSValue**>(fastCalloc(capacity + 1, sizeof(JSValue *))) + 1;58 // store capacity and overflow map in extra space before the beginning of the storage array to save space 59 JSValue** storage = static_cast<JSValue**>(fastCalloc(capacity + 2, sizeof(JSValue *))) + 2; 53 60 storage[-1] = reinterpret_cast<JSValue*>(capacity); 54 61 return storage; … … 58 65 { 59 66 if (!storage) { 60 storage = 67 storage = allocateStorage(newCapacity); 61 68 return; 62 69 } 63 70 64 // store capacity in extra space before the beginning of the storage array to save space65 storage = static_cast<JSValue**>(fastRealloc(storage - 1, (newCapacity + 1) * sizeof (JSValue*))) + 1;71 // store capacity and overflow map in extra space before the beginning of the storage array to save space 72 storage = static_cast<JSValue**>(fastRealloc(storage - 2, (newCapacity + 2) * sizeof (JSValue*))) + 2; 66 73 storage[-1] = reinterpret_cast<JSValue*>(newCapacity); 67 74 } … … 69 76 static inline void freeStorage(JSValue** storage) 70 77 { 71 if (storage) 72 fastFree(storage - 1); 78 fastFree(storage - 2); 73 79 } 74 80 … … 90 96 ListIterator it = list.begin(); 91 97 unsigned l = length; 92 for (unsigned i = 0; i < l; ++i) {98 for (unsigned i = 0; i < l; ++i) 93 99 storage[i] = it++; 94 } 95 // When the array is created non-empty its cells are filled so it's really no worse than 100 // When the array is created non-empty, its cells are filled so it's really no worse than 96 101 // a property map. Therefore don't report extra memory cost. 97 102 } … … 99 104 ArrayInstance::~ArrayInstance() 100 105 { 101 freeStorage(storage); 106 if (storage) { 107 delete reinterpret_cast<OverflowMap*>(storage[-2]); 108 freeStorage(storage); 109 } 102 110 } 103 111 104 112 JSValue* ArrayInstance::getItem(unsigned i) const 105 113 { 106 if (i >= length) 114 if (i < storageLength) { 115 JSValue* value = storage[i]; 116 return value ? value : jsUndefined(); 117 } 118 119 const OverflowMap* overflow = overflowMap(storage); 120 if (!overflow) 107 121 return jsUndefined(); 108 109 JSValue* val = (i < storageLength) ? 110 storage[i] : 111 getDirect(Identifier::from(i)); 112 113 return val ? val : jsUndefined(); 122 123 JSValue* value = overflow->get(i); 124 return value ? value : jsUndefined(); 114 125 } 115 126 … … 128 139 bool ok; 129 140 unsigned index = propertyName.toArrayIndex(&ok); 130 if (ok) { 131 if (index >= length) 132 return false; 133 if (index < storageLength) { 134 JSValue *v = storage[index]; 135 if (!v) 136 return false; 137 slot.setValueSlot(this, &storage[index]); 138 return true; 139 } 140 } 141 142 return JSObject::getOwnPropertySlot(exec, propertyName, slot); 141 if (!ok) 142 return JSObject::getOwnPropertySlot(exec, propertyName, slot); 143 144 if (index < storageLength) { 145 JSValue *v = storage[index]; 146 if (!v) 147 return false; 148 slot.setValueSlot(this, &storage[index]); 149 return true; 150 } 151 if (index > MAX_ARRAY_INDEX) 152 return JSObject::getOwnPropertySlot(exec, propertyName, slot); 153 OverflowMap* overflow = overflowMap(storage); 154 if (!overflow) 155 return false; 156 OverflowMap::iterator it = overflow->find(index); 157 if (it == overflow->end()) 158 return false; 159 slot.setValueSlot(this, &it->second); 160 return true; 143 161 } 144 162 145 163 bool ArrayInstance::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot) 146 164 { 147 if (index > MAX_ARRAY_INDEX)148 return getOwnPropertySlot(exec, Identifier::from(index), slot);149 150 if (index >= length)151 return false;152 165 if (index < storageLength) { 153 166 JSValue *v = storage[index]; … … 157 170 return true; 158 171 } 159 160 return JSObject::getOwnPropertySlot(exec, index, slot); 172 if (index > MAX_ARRAY_INDEX) 173 return getOwnPropertySlot(exec, Identifier::from(index), slot); 174 OverflowMap* overflow = overflowMap(storage); 175 if (!overflow) 176 return false; 177 OverflowMap::iterator it = overflow->find(index); 178 if (it == overflow->end()) 179 return false; 180 slot.setValueSlot(this, &it->second); 181 return true; 161 182 } 162 183 … … 173 194 return; 174 195 } 175 196 176 197 bool ok; 177 198 unsigned index = propertyName.toArrayIndex(&ok); … … 180 201 return; 181 202 } 182 203 183 204 JSObject::put(exec, propertyName, value, attr); 184 205 } … … 186 207 void ArrayInstance::put(ExecState *exec, unsigned index, JSValue *value, int attr) 187 208 { 188 //0xFFFF FFFF is a bit weird --- it should be treated as a non-array index, even when 189 //it's a string 209 // 0xFFFFFFFF is a bit weird --- it should be treated as a non-array index, even when it's a string 190 210 if (index > MAX_ARRAY_INDEX) { 191 211 put(exec, Identifier::from(index), value, attr); … … 193 213 } 194 214 195 if (index < sparseArrayCutoff && index >= storageLength) {215 if (index < sparseArrayCutoff && index >= storageLength) 196 216 resizeStorage(index + 1); 197 } 198 199 if (index >= length) { 217 218 if (index >= length) 200 219 length = index + 1; 201 }202 220 203 221 if (index < storageLength) { … … 205 223 return; 206 224 } 207 208 ASSERT(index >= sparseArrayCutoff); 209 JSObject::put(exec, Identifier::from(index), value, attr); 225 226 OverflowMap* overflow = overflowMap(storage); 227 if (!overflow) { 228 overflow = new OverflowMap; 229 if (!storage) 230 allocateStorage(1); 231 storage[-2] = reinterpret_cast<JSValue*>(overflow); 232 } 233 overflow->add(index, value); 210 234 } 211 235 … … 214 238 if (propertyName == exec->propertyNames().length) 215 239 return false; 216 240 217 241 bool ok; 218 242 uint32_t index = propertyName.toArrayIndex(&ok); … … 224 248 return true; 225 249 } 226 } 227 250 if (OverflowMap* overflow = overflowMap(storage)) { 251 OverflowMap::iterator it = overflow->find(index); 252 if (it == overflow->end()) 253 return false; 254 overflow->remove(it); 255 return true; 256 } 257 return false; 258 } 259 228 260 return JSObject::deleteProperty(exec, propertyName); 229 261 } … … 240 272 return true; 241 273 } 242 243 return JSObject::deleteProperty(exec, Identifier::from(index)); 274 OverflowMap* overflow = overflowMap(storage); 275 if (!overflow) 276 return false; 277 OverflowMap::iterator it = overflow->find(index); 278 if (it == overflow->end()) 279 return false; 280 overflow->remove(it); 281 return true; 244 282 } 245 283 … … 253 291 if (value && value != undefined) 254 292 propertyNames.add(Identifier::from(i)); 293 } 294 295 OverflowMap* overflow = overflowMap(storage); 296 if (overflow) { 297 OverflowMap::iterator end = overflow->end(); 298 for (OverflowMap::iterator it = overflow->begin(); it != end; ++it) { 299 JSValue* value = it->second; 300 if (value && value != undefined) 301 propertyNames.add(Identifier::from(it->first)); 302 } 255 303 } 256 304 … … 283 331 void ArrayInstance::setLength(unsigned newLength, ExecState *exec) 284 332 { 285 if (newLength <= storageLength) {333 if (newLength <= storageLength) 286 334 resizeStorage(newLength); 287 }288 335 289 336 if (newLength < length) { 290 PropertyNameArray sparseProperties; 291 292 _prop.getSparseArrayPropertyNames(sparseProperties); 293 294 PropertyNameArrayIterator end = sparseProperties.end(); 295 296 for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) { 297 Identifier name = *it; 298 bool ok; 299 unsigned index = name.toArrayIndex(&ok); 300 if (ok && index > newLength) 301 deleteProperty(exec, name); 337 if (OverflowMap* overflow = overflowMap(storage)) { 338 OverflowMap copy = *overflow; 339 OverflowMap::iterator end = copy.end(); 340 for (OverflowMap::iterator it = copy.begin(); it != end; ++it) { 341 if (it->first >= newLength) 342 overflow->remove(it->first); 343 } 302 344 } 303 345 } … … 311 353 unsigned l = storageLength; 312 354 for (unsigned i = 0; i < l; ++i) { 313 JSValue *imp = storage[i];355 JSValue* imp = storage[i]; 314 356 if (imp && !imp->marked()) 315 357 imp->mark(); 358 } 359 if (OverflowMap* overflow = overflowMap(storage)) { 360 OverflowMap::iterator end = overflow->end(); 361 for (OverflowMap::iterator it = overflow->begin(); it != end; ++it) { 362 JSValue* value = it->second; 363 if (value && !value->marked()) 364 value->mark(); 365 } 316 366 } 317 367 } … … 324 374 JSValue *va = *(JSValue **)a; 325 375 JSValue *vb = *(JSValue **)b; 326 if (va->isUndefined()) { 327 return vb->isUndefined() ? 0 : 1; 328 } 329 if (vb->isUndefined()) { 330 return -1; 331 } 376 ASSERT(!va->isUndefined()); 377 ASSERT(!vb->isUndefined()); 332 378 return compare(va->toString(exec), vb->toString(exec)); 333 379 } … … 385 431 JSValue *va = *(JSValue **)a; 386 432 JSValue *vb = *(JSValue **)b; 387 if (va->isUndefined()) { 388 return vb->isUndefined() ? 0 : 1; 389 } 390 if (vb->isUndefined()) { 391 return -1; 392 } 433 ASSERT(!va->isUndefined()); 434 ASSERT(!vb->isUndefined()); 393 435 394 436 args->arguments.clear(); … … 442 484 } 443 485 444 PropertyNameArray sparseProperties; 445 _prop.getSparseArrayPropertyNames(sparseProperties); 446 unsigned newLength = o + sparseProperties.size(); 447 448 if (newLength > storageLength) 449 resizeStorage(newLength); 450 451 PropertyNameArrayIterator end = sparseProperties.end(); 452 for (PropertyNameArrayIterator it = sparseProperties.begin(); it != end; ++it) { 453 Identifier name = *it; 454 storage[o] = getDirect(name); 455 _prop.remove(name); 456 o++; 486 unsigned newLength = o; 487 488 if (OverflowMap* overflow = overflowMap(storage)) { 489 OverflowMap::iterator end = overflow->end(); 490 for (OverflowMap::iterator it = overflow->begin(); it != end; ++it) 491 newLength += it->second != undefined; 492 493 if (newLength > storageLength) 494 resizeStorage(newLength); 495 496 for (OverflowMap::iterator it = overflow->begin(); it != end; ++it) { 497 JSValue* v = it->second; 498 if (v != undefined) { 499 storage[o] = v; 500 o++; 501 } 502 } 503 delete overflow; 504 storage[-2] = 0; 457 505 } 458 506 … … 1047 1095 return construct(exec,args); 1048 1096 } 1097 1098 }
Note:
See TracChangeset
for help on using the changeset viewer.