Changeset 2749 in webkit for trunk/JavaScriptCore
- Timestamp:
- Nov 18, 2002, 10:53:35 PM (23 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r2748 r2749 1 2002-11-18 Darin Adler <[email protected]> 2 3 - property and string improvements giving a 7% or so improvement in JavaScript iBench 4 5 * kjs/property_map.h: Rewrite to use a hash table. 6 * kjs/property_map.cpp: Ditto. 7 8 * kjs/string_object.h: 9 * kjs/string_object.cpp: 10 (StringInstanceImp::StringInstanceImp): Construct a string with the right value 11 instead of putting the string in later. 12 (StringInstanceImp::get): Get the length from the string, not a separate property. 13 (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in 14 the property map. 15 (StringInstanceImp::hasProperty): Return true for length. 16 (StringInstanceImp::deleteProperty): Return false for length. 17 (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try 18 to set a length property. 19 20 * kjs/ustring.h: Make the rep deref know how to deallocate the rep. 21 * kjs/ustring.cpp: 22 (UString::release): Move the real work to the rep's deref, since the hash table 23 now uses the rep directly. 24 25 * kjs/object.h: Remove unused field. 26 1 27 2002-11-18 Maciej Stachowiak <[email protected]> 2 28 -
trunk/JavaScriptCore/ChangeLog-2002-12-03
r2748 r2749 1 2002-11-18 Darin Adler <[email protected]> 2 3 - property and string improvements giving a 7% or so improvement in JavaScript iBench 4 5 * kjs/property_map.h: Rewrite to use a hash table. 6 * kjs/property_map.cpp: Ditto. 7 8 * kjs/string_object.h: 9 * kjs/string_object.cpp: 10 (StringInstanceImp::StringInstanceImp): Construct a string with the right value 11 instead of putting the string in later. 12 (StringInstanceImp::get): Get the length from the string, not a separate property. 13 (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in 14 the property map. 15 (StringInstanceImp::hasProperty): Return true for length. 16 (StringInstanceImp::deleteProperty): Return false for length. 17 (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try 18 to set a length property. 19 20 * kjs/ustring.h: Make the rep deref know how to deallocate the rep. 21 * kjs/ustring.cpp: 22 (UString::release): Move the real work to the rep's deref, since the hash table 23 now uses the rep directly. 24 25 * kjs/object.h: Remove unused field. 26 1 27 2002-11-18 Maciej Stachowiak <[email protected]> 2 28 -
trunk/JavaScriptCore/ChangeLog-2003-10-25
r2748 r2749 1 2002-11-18 Darin Adler <[email protected]> 2 3 - property and string improvements giving a 7% or so improvement in JavaScript iBench 4 5 * kjs/property_map.h: Rewrite to use a hash table. 6 * kjs/property_map.cpp: Ditto. 7 8 * kjs/string_object.h: 9 * kjs/string_object.cpp: 10 (StringInstanceImp::StringInstanceImp): Construct a string with the right value 11 instead of putting the string in later. 12 (StringInstanceImp::get): Get the length from the string, not a separate property. 13 (StringInstanceImp::put): Ignore attempts to set length, since we don't put it in 14 the property map. 15 (StringInstanceImp::hasProperty): Return true for length. 16 (StringInstanceImp::deleteProperty): Return false for length. 17 (StringObjectImp::construct): Call new StringInstanceImp constructor. Don't try 18 to set a length property. 19 20 * kjs/ustring.h: Make the rep deref know how to deallocate the rep. 21 * kjs/ustring.cpp: 22 (UString::release): Move the real work to the rep's deref, since the hash table 23 now uses the rep directly. 24 25 * kjs/object.h: Remove unused field. 26 1 27 2002-11-18 Maciej Stachowiak <[email protected]> 2 28 -
trunk/JavaScriptCore/kjs/object.h
r2741 r2749 44 44 namespace KJS { 45 45 46 class ObjectImpPrivate;47 46 class PropertyMap; 48 47 class HashTable; … … 584 583 private: 585 584 const HashEntry* findPropertyHashEntry( const UString& propertyName ) const; 586 ObjectImpPrivate *_od;587 585 PropertyMap *_prop; 588 586 ValueImp *_proto; -
trunk/JavaScriptCore/kjs/property_map.cpp
r2740 r2749 2 2 /* 3 3 * This file is part of the KDE libraries 4 * Copyright (C) 200 1 Peter Kelly (pmk@post.com)4 * Copyright (C) 2002 Darin Adler (darin@apple.com) 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 21 21 */ 22 22 23 24 23 #include "property_map.h" 25 24 … … 27 26 #include "reference_list.h" 28 27 29 #include <string.h>30 #include <assert.h>31 #include <stdio.h>32 33 28 namespace KJS { 34 29 35 // ------------------------------ PropertyMapNode ------------------------------ 36 37 class PropertyMapNode { 38 public: 39 PropertyMapNode(const UString &n, ValueImp *v, int att, PropertyMapNode *p) 40 : name(n), value(v), attr(att), left(0), right(0), parent(p), height(1) {} 41 42 UString name; 43 ValueImp *value; 44 int attr; 45 46 void setLeft(PropertyMapNode *newLeft); 47 void setRight(PropertyMapNode *newRight); 48 PropertyMapNode *findMax(); 49 PropertyMapNode *findMin(); 50 51 PropertyMapNode *next(); 52 53 PropertyMapNode *left; 54 PropertyMapNode *right; 55 PropertyMapNode *parent; 56 int height; 57 58 private: 59 void setParent(PropertyMapNode *newParent); 60 }; 61 62 void PropertyMapNode::setLeft(PropertyMapNode *newLeft) 63 { 64 if (left) 65 left->setParent(0); 66 left = newLeft; 67 if (left) 68 left->setParent(this); 69 } 70 71 void PropertyMapNode::setRight(PropertyMapNode *newRight) 72 { 73 if (right) 74 right->setParent(0); 75 right = newRight; 76 if (right) 77 right->setParent(this); 78 } 79 80 void PropertyMapNode::setParent(PropertyMapNode *newParent) 81 { 82 if (parent) { 83 //assert(this == parent->left || this == parent->right); 84 if (this == parent->left) 85 parent->left = 0; 86 else 87 parent->right = 0; 88 } 89 parent = newParent; 90 } 91 92 PropertyMapNode *PropertyMapNode::findMax() 93 { 94 PropertyMapNode *max = this; 95 while (max->right) 96 max = max->right; 97 return max; 98 } 99 100 PropertyMapNode *PropertyMapNode::findMin() 101 { 102 PropertyMapNode *min = this; 103 while (min->left) 104 min = min->left; 105 return min; 106 } 107 108 PropertyMapNode *PropertyMapNode::next() 109 { 110 // find the next node, going from lowest name to highest name 111 112 // We have a right node. Starting from our right node, keep going left as far as we can 113 if (right) { 114 PropertyMapNode *n = right; 115 while (n->left) 116 n = n->left; 117 return n; 118 } 119 120 // We have no right node. Keep going up to the left, until we find a node that has a parent 121 // to the right. If we find one, go to it. Otherwise, we have reached the end. 122 PropertyMapNode *n = this; 123 while (n->parent && n->parent->right == n) { 124 // parent is to our left 125 n = n->parent; 126 } 127 if (n->parent && n->parent->left == n) { 128 // parent is to our right 129 return n->parent; 130 } 131 132 return 0; 133 } 134 135 // ------------------------------ PropertyMap ---------------------------------- 136 137 int KJS::uscompare(const UString &s1, const UString &s2) 138 { 139 int len1 = s1.size(); 140 int len2 = s2.size(); 141 if (len1 < len2) 142 return -1; 143 else if (len1 > len2) 144 return 1; 145 else 146 return memcmp(s1.data(), s2.data(), len1*sizeof(UChar)); 147 } 148 149 PropertyMap::PropertyMap() 150 { 151 root = 0; 30 // Algorithm concepts from Algorithms in C++, Sedgewick. 31 32 PropertyMap::PropertyMap() : _tableSize(0), _table(0), _keyCount(0) 33 { 152 34 } 153 35 154 36 PropertyMap::~PropertyMap() 155 37 { 156 clear(); 157 } 158 159 void PropertyMap::put(const UString &name, ValueImp *value, int attr) 160 { 161 // if not root; make the root the new node 162 if (!root) { 163 root = new PropertyMapNode(name, value, attr, 0); 164 return; 165 } 166 167 // try to find the parent node 168 PropertyMapNode *parent = root; 169 int isLeft = false; 170 while (true) { 171 int cmp = uscompare(name, parent->name); 172 if (cmp < 0) { 173 // traverse to left node (if any) 174 isLeft = true; 175 if (!parent->left) 176 break; 177 else 178 parent = parent->left; 179 } 180 else if (cmp > 0) { 181 // traverse to right node (if any) 182 isLeft = false; 183 if (!parent->right) 184 break; 185 else 186 parent = parent->right; 187 } 188 else { 189 // a node with this name already exists; just replace the value 190 parent->value = value; 191 return; 192 } 193 } 194 195 // we found the parent 196 //assert(parent); 197 198 if (isLeft) { 199 //assert(!parent->left); 200 parent->left = new PropertyMapNode(name, value, attr, parent); 201 } 202 else { 203 //assert(!parent->right); 204 parent->right = new PropertyMapNode(name, value, attr, parent); 205 } 206 updateHeight(parent); 207 208 209 PropertyMapNode *node = parent; 210 while (node) { 211 PropertyMapNode *p = node->parent; 212 balance(node); // may change node 213 node = p; 214 } 38 //printf("key count is %d\n", _keyCount); 39 UString::Rep *key = _singleEntry.key; 40 if (key) 41 key->deref(); 42 for (int i = 0; i < _tableSize; i++) { 43 key = _table[i].key; 44 if (key) 45 key->deref(); 46 } 47 free(_table); 48 } 49 50 void PropertyMap::clear() 51 { 52 UString::Rep *key = _singleEntry.key; 53 if (key) { 54 key->deref(); 55 _singleEntry.key = 0; 56 } 57 for (int i = 0; i < _tableSize; i++) { 58 UString::Rep *key = _table[i].key; 59 if (key) { 60 key->deref(); 61 _table[i].key = 0; 62 } 63 } 64 _keyCount = 0; 65 } 66 67 int PropertyMap::hash(const UString::Rep *s) const 68 { 69 int h = 0; 70 int length = s->len; 71 int prefixLength = length < 8 ? length : 8; 72 for (int i = 0; i < prefixLength; i++) 73 h = (127 * h + s->dat[i].unicode()) & _tableSizeHashMask; 74 int suffixPosition = length < 16 ? 8 : length - 8; 75 for (int i = suffixPosition; i < length; i++) 76 h = (127 * h + s->dat[i].unicode()) & _tableSizeHashMask; 77 return h; 78 } 79 80 bool PropertyMap::keysMatch(const UString::Rep *a, const UString::Rep *b) 81 { 82 if (a == b) 83 return true; 84 85 int len = a->len; 86 if (len != b->len) 87 return false; 88 89 for (int i = 0; i != len; ++i) 90 if (a->dat[i].unicode() != b->dat[i].unicode()) 91 return false; 92 93 return true; 94 } 95 96 ValueImp *PropertyMap::get(const UString &name, int &attributes) const 97 { 98 if (!_table) { 99 UString::Rep *key = _singleEntry.key; 100 if (key && keysMatch(name.rep, key)) { 101 attributes = _singleEntry.attributes; 102 return _singleEntry.value; 103 } 104 return 0; 105 } 106 107 int i = hash(name.rep); 108 while (UString::Rep *key = _table[i].key) { 109 if (keysMatch(name.rep, key)) { 110 attributes = _table[i].attributes; 111 return _table[i].value; 112 } 113 i = (i + 1) % _tableSize; 114 } 115 return 0; 116 } 117 118 ValueImp *PropertyMap::get(const UString &name) const 119 { 120 if (!_table) { 121 UString::Rep *key = _singleEntry.key; 122 if (key && keysMatch(name.rep, key)) 123 return _singleEntry.value; 124 return 0; 125 } 126 127 int i = hash(name.rep); 128 while (UString::Rep *key = _table[i].key) { 129 if (keysMatch(name.rep, key)) 130 return _table[i].value; 131 i = (i + 1) % _tableSize; 132 } 133 return 0; 134 } 135 136 void PropertyMap::put(const UString &name, ValueImp *value, int attributes) 137 { 138 if (!_table) { 139 UString::Rep *key = _singleEntry.key; 140 if (key) { 141 if (keysMatch(name.rep, key)) { 142 _singleEntry.value = value; 143 return; 144 } 145 } else { 146 name.rep->ref(); 147 _singleEntry.key = name.rep; 148 _singleEntry.value = value; 149 _singleEntry.attributes = attributes; 150 _keyCount = 1; 151 return; 152 } 153 } 154 155 if (_keyCount >= _tableSize / 2) 156 expand(); 157 158 int i = hash(name.rep); 159 while (UString::Rep *key = _table[i].key) { 160 if (keysMatch(name.rep, key)) { 161 // Put a new value in an existing hash table entry. 162 _table[i].value = value; 163 // Attributes are intentionally not updated. 164 return; 165 } 166 i = (i + 1) % _tableSize; 167 } 168 169 // Create a new hash table entry. 170 name.rep->ref(); 171 _table[i].key = name.rep; 172 _table[i].value = value; 173 _table[i].attributes = attributes; 174 ++_keyCount; 175 } 176 177 inline void PropertyMap::insert(UString::Rep *key, ValueImp *value, int attributes) 178 { 179 int i = hash(key); 180 while (_table[i].key) 181 i = (i + 1) % _tableSize; 182 183 _table[i].key = key; 184 _table[i].value = value; 185 _table[i].attributes = attributes; 186 } 187 188 void PropertyMap::expand() 189 { 190 int oldTableSize = _tableSize; 191 Entry *oldTable = _table; 192 193 _tableSize = oldTableSize ? oldTableSize * 2 : 16; 194 _tableSizeHashMask = _tableSize - 1; 195 _table = (Entry *)calloc(_tableSize, sizeof(Entry)); 196 197 UString::Rep *key = _singleEntry.key; 198 if (key) { 199 insert(key, _singleEntry.value, _singleEntry.attributes); 200 _singleEntry.key = 0; 201 } 202 203 for (int i = 0; i != oldTableSize; ++i) { 204 key = oldTable[i].key; 205 if (key) 206 insert(key, oldTable[i].value, oldTable[i].attributes); 207 } 208 209 free(oldTable); 215 210 } 216 211 217 212 void PropertyMap::remove(const UString &name) 218 213 { 219 PropertyMapNode *node = getNode(name); 220 if (!node) // name not in tree 221 return; 222 223 PropertyMapNode *removed = remove(node); 224 if (removed) 225 delete node; 226 } 227 228 ValueImp *PropertyMap::get(const UString &name) const 229 { 230 const PropertyMapNode *n = getNode(name); 231 return n ? n->value : 0; 232 } 233 234 ValueImp *PropertyMap::get(const UString &name, int &attributes) const 235 { 236 const PropertyMapNode *n = getNode(name); 237 attributes = n ? n->attr : 0; 238 return n ? n->value : 0; 239 } 240 241 void PropertyMap::clear() 242 { 243 clear(0); 244 } 245 246 void PropertyMap::mark() 247 { 248 PropertyMapNode *node = first(); 249 while (node) { 250 if (!node->value->marked()) 251 node->value->mark(); 252 node = node->next(); 253 } 214 UString::Rep *key; 215 216 if (!_table) { 217 key = _singleEntry.key; 218 if (key && keysMatch(name.rep, key)) { 219 key->deref(); 220 _singleEntry.key = 0; 221 _keyCount = 0; 222 } 223 return; 224 } 225 226 // Find the thing to remove. 227 int i = hash(name.rep); 228 while ((key = _table[i].key)) { 229 if (keysMatch(name.rep, key)) 230 break; 231 i = (i + 1) % _tableSize; 232 } 233 if (!key) 234 return; 235 236 // Remove the one key. 237 key->deref(); 238 _table[i].key = 0; 239 --_keyCount; 240 241 // Reinsert all the items to the right in the same cluster. 242 while (1) { 243 i = (i + 1) % _tableSize; 244 key = _table[i].key; 245 if (!key) 246 break; 247 _table[i].key = 0; 248 insert(key, _table[i].value, _table[i].attributes); 249 } 250 } 251 252 void PropertyMap::mark() const 253 { 254 if (_singleEntry.key) { 255 ValueImp *v = _singleEntry.value; 256 if (!v->marked()) 257 v->mark(); 258 } 259 for (int i = 0; i != _tableSize; ++i) { 260 if (_table[i].key) { 261 ValueImp *v = _table[i].value; 262 if (!v->marked()) 263 v->mark(); 264 } 265 } 254 266 } 255 267 256 268 void PropertyMap::addEnumerablesToReferenceList(ReferenceList &list, const Object &base) const 257 269 { 258 PropertyMapNode *node = first(); 259 while (node) { 260 if (!(node->attr & DontEnum)) 261 list.append(Reference(base, node->name)); 262 node = node->next(); 263 } 264 } 265 266 void PropertyMap::clear(PropertyMapNode *node) 267 { 268 if (node == 0) 269 node = root; 270 if (node == 0) // nothing to do 271 return; 272 273 if (node->left) 274 clear(node->left); 275 if (node->right) 276 clear(node->right); 277 if (node == root) 278 root = 0; 279 delete node; 280 } 281 282 void PropertyMap::dump(const PropertyMapNode *node, int indent) const 283 { 284 if (!node && indent > 0) 285 return; 286 if (!node) 287 node = root; 288 if (!node) 289 return; 290 291 assert(!node->right || node->right->parent == node); 292 dump(node->right, indent+1); 293 for (int i = 0; i < indent; i++) { 294 printf(" "); 295 } 296 printf("[%d] %s\n", node->height, node->name.ascii()); 297 assert(!node->left || node->left->parent == node); 298 dump(node->left, indent+1); 299 } 300 301 void PropertyMap::checkTree(const PropertyMapNode *node) const 302 { 303 if (!root) 304 return; 305 if (node == 0) 306 node = root; 307 if (node == root) { 308 assert(!node->parent); 309 } 310 assert(!node->right || node->right->parent == node); 311 assert(!node->left || node->left->parent == node); 312 assert(node->left != node); 313 assert(node->right != node); 314 if (node->left && node->right) 315 assert(node->left != node->right); 316 317 PropertyMapNode *n = node->parent; 318 while (n) { 319 assert(n != node); 320 n = n->parent; 321 } 322 323 if (node->right) 324 checkTree(node->right); 325 if (node->left) 326 checkTree(node->left); 327 } 328 329 PropertyMapNode *PropertyMap::getNode(const UString &name) const 330 { 331 PropertyMapNode *node = root; 332 333 while (true) { 334 if (!node) 335 return 0; 336 337 int cmp = uscompare(name, node->name); 338 if (cmp < 0) 339 node = node->left; 340 else if (cmp > 0) 341 node = node->right; 342 else 343 return node; 344 } 345 } 346 347 PropertyMapNode *PropertyMap::first() const 348 { 349 if (!root) 350 return 0; 351 352 PropertyMapNode *node = root; 353 while (node->left) 354 node = node->left; 355 return node; 356 } 357 358 PropertyMapNode * PropertyMap::remove(PropertyMapNode *node) 359 { 360 PropertyMapNode *parent = node->parent; 361 //assert(!parent || (node == parent->left || node == parent->right)); 362 bool isLeft = (parent && node == parent->left); 363 364 PropertyMapNode *replace = 0; 365 if (node->left && node->right) { 366 PropertyMapNode *maxLeft = node->left->findMax(); 367 if (maxLeft == node->left) { 368 maxLeft->setRight(node->right); 369 replace = maxLeft; 370 } 371 else { 372 remove(maxLeft); 373 374 maxLeft->setLeft(node->left); 375 maxLeft->setRight(node->right); 376 replace = maxLeft; 377 } 378 // removing maxLeft could have re-balanced the tree, so recalculate 379 // parent again 380 parent = node->parent; 381 //assert(!parent || (node == parent->left || node == parent->right)); 382 isLeft = (parent && node == parent->left); 383 } 384 else if (node->left) { 385 replace = node->left; 386 } 387 else if (node->right) { 388 replace = node->right; 389 } 390 else { 391 replace = 0; 392 } 393 394 if (parent) { 395 if (isLeft) 396 parent->setLeft(replace); 397 else 398 parent->setRight(replace); 399 } 400 else { 401 root = replace; 402 if (replace) 403 replace->parent = 0; 404 } 405 406 if (replace) 407 updateHeight(replace); // will also update parent's height 408 else if (parent) 409 updateHeight(parent); 410 else if (root) 411 updateHeight(root); 412 413 414 // balance the tree 415 PropertyMapNode *bal = parent; 416 while (bal) { 417 PropertyMapNode *p = bal->parent; 418 balance(bal); // may change bal 419 bal = p; 420 } 421 422 return node; 423 } 424 425 void PropertyMap::balance(PropertyMapNode* node) 426 { 427 int lheight = node->left ? node->left->height : 0; 428 int rheight = node->right ? node->right->height : 0; 429 430 int bal = rheight-lheight; 431 432 if (bal < -1) { 433 //assert(node->left); 434 int llheight = node->left->left ? node->left->left->height : 0; 435 int lrheight = node->left->right ? node->left->right->height : 0; 436 int lbal = lrheight - llheight; 437 438 if (lbal < 0) { 439 rotateLL(node); // LL rotation 440 } 441 else { 442 // lbal >= 0 443 rotateLR(node); 444 } 445 } 446 else if (bal > 1) { 447 int rlheight = node->right->left ? node->right->left->height : 0; 448 int rrheight = node->right->right ? node->right->right->height : 0; 449 int rbal = rrheight - rlheight; 450 if (rbal < 0) { 451 rotateRL(node); 452 } 453 else { 454 // rbal >= 0 455 rotateRR(node); // RR rotateion 456 } 457 } 458 } 459 460 void PropertyMap::updateHeight(PropertyMapNode* &node) 461 { 462 int lheight = node->left ? node->left->height : 0; 463 int rheight = node->right ? node->right->height : 0; 464 if (lheight > rheight) 465 node->height = lheight+1; 466 else 467 node->height = rheight+1; 468 //assert(node->parent != node); 469 if (node->parent) 470 updateHeight(node->parent); 471 } 472 473 void PropertyMap::rotateRR(PropertyMapNode* &node) 474 { 475 /* 476 Perform a RR ("single left") rotation, e.g. 477 478 a b 479 / \ / \ 480 X b --> a Z 481 / \ / \ 482 Y Z X Y 483 */ 484 485 // Here, node is initially a, will be replaced with b 486 487 PropertyMapNode *a = node; 488 PropertyMapNode *b = node->right; 489 490 PropertyMapNode *parent = a->parent; 491 //assert(!parent || (a == parent->left || a == parent->right)); 492 bool isLeft = (parent && a == parent->left); 493 494 // do the rotation 495 a->setRight(b->left); 496 b->setLeft(a); 497 498 // now node is b 499 node = b; 500 if (parent) { 501 if (isLeft) 502 parent->setLeft(b); 503 else 504 parent->setRight(b); 505 } 506 else { 507 // a was the root node 508 root = b; 509 } 510 511 updateHeight(a); 512 updateHeight(b); 513 } 514 515 516 void PropertyMap::rotateLL(PropertyMapNode* &node) 517 { 518 /* 519 Perform a LL ("single right") rotation, e.g. 520 521 522 a b 523 / \ / \ 524 b Z --> X a 525 / \ / \ 526 X Y Y Z 527 */ 528 529 // Here, node is initially a, will be replaced with b 530 531 PropertyMapNode *a = node; 532 PropertyMapNode *b = node->left; 533 534 PropertyMapNode *parent = a->parent; 535 //assert(!parent || (a == parent->left || a == parent->right)); 536 bool isLeft = (parent && a == parent->left); 537 538 // do the rotation 539 a->setLeft(b->right); 540 b->setRight(a); 541 542 // now node is b 543 node = b; 544 if (parent) { 545 if (isLeft) 546 parent->setLeft(b); 547 else 548 parent->setRight(b); 549 } 550 else { 551 // a was the root node 552 root = b; 553 } 554 555 updateHeight(a); 556 updateHeight(b); 557 } 558 559 void PropertyMap::rotateRL(PropertyMapNode* &node) 560 { 561 /* 562 Perform a RL ("double left") rotation, e.g. 563 564 a a b 565 / \ LL on c / \ RR on b / \ 566 W c --> W b --> a c 567 / \ / \ / \ / \ 568 b Z X c W X Y Z 569 / \ / \ 570 X Y Y Z 571 572 */ 573 574 PropertyMapNode *a = node; 575 PropertyMapNode *c = node->right; 576 PropertyMapNode *b = node->right->left; 577 578 rotateLL(c); 579 rotateRR(b); 580 581 updateHeight(a); 582 updateHeight(c); 583 updateHeight(b); 584 } 585 586 void PropertyMap::rotateLR(PropertyMapNode* &node) 587 { 588 /* 589 Perform a LR ("double right") rotation, e.g. 590 591 a a b 592 / \ RR on c / \ LL on a / \ 593 c Z --> b Z --> c a 594 / \ / \ / \ / \ 595 W b c Y W X Y Z 596 / \ / \ 597 X Y W X 598 */ 599 600 PropertyMapNode *a = node; 601 PropertyMapNode *c = node->left; 602 PropertyMapNode *b = node->left->right; 603 604 rotateRR(c); 605 rotateLL(a); 606 607 updateHeight(c); 608 updateHeight(a); 609 updateHeight(b); 270 UString::Rep *key = _singleEntry.key; 271 if (key && !(_singleEntry.attributes & DontEnum)) 272 list.append(Reference(base, key)); 273 for (int i = 0; i != _tableSize; ++i) { 274 UString::Rep *key = _table[i].key; 275 if (key && !(_table[i].attributes & DontEnum)) 276 list.append(Reference(base, key)); 277 } 610 278 } 611 279 -
trunk/JavaScriptCore/kjs/property_map.h
r2740 r2749 2 2 /* 3 3 * This file is part of the KDE libraries 4 * Copyright (C) 200 1 Peter Kelly (pmk@post.com)4 * Copyright (C) 2002 Darin Adler (darin@apple.com) 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 21 21 */ 22 22 23 24 23 #ifndef _KJS_PROPERTY_MAP_H_ 25 24 #define _KJS_PROPERTY_MAP_H_ 26 25 27 26 #include "ustring.h" 28 #include "value.h"29 27 30 28 namespace KJS { 31 29 32 class PropertyMapNode; 33 class ReferenceList; 30 class Object; 31 class ReferenceList; 32 class ValueImp; 33 34 struct PropertyMapHashTableEntry 35 { 36 PropertyMapHashTableEntry() : key(0) { } 37 UString::Rep *key; 38 ValueImp *value; 39 int attributes; 40 }; 41 42 class PropertyMap { 43 public: 44 PropertyMap(); 45 ~PropertyMap(); 34 46 35 /** 36 * @internal 37 * 38 * Provides a name/value map for storing properties based on UString keys. The 39 * map is implemented using an AVL tree, which provides O(log2 n) performance 40 * for insertion and deletion, and retrieval. 41 * 42 * For a description of AVL tree operations, see 43 * http://www.cis.ksu.edu/~howell/300f99/minavl/rotations.html 44 * http://www.cgc.cs.jhu.edu/~jkloss/htmls/structures/avltree.html 45 */ 46 class PropertyMap { 47 public: 48 PropertyMap(); 49 ~PropertyMap(); 47 void clear(); 48 49 void put(const UString &name, ValueImp *value, int attributes); 50 void remove(const UString &name); 51 ValueImp *get(const UString &name) const; 52 ValueImp *get(const UString &name, int &attributes) const; 50 53 51 void put(const UString &name, ValueImp *value, int attr); 52 void remove(const UString &name); 53 ValueImp *get(const UString &name) const; 54 ValueImp *get(const UString &name, int &attributes) const; 55 56 void clear(); 57 void mark(); 58 59 void addEnumerablesToReferenceList(ReferenceList &, const Object &) const; 54 void mark() const; 55 void addEnumerablesToReferenceList(ReferenceList &, const Object &) const; 60 56 61 private: 62 63 void clear(PropertyMapNode *node); 64 void dump(const PropertyMapNode *node = 0, int indent = 0) const; 65 void checkTree(const PropertyMapNode *node = 0) const; 66 67 PropertyMapNode *getNode(const UString &name) const; 68 PropertyMapNode *first() const; 69 70 PropertyMapNode *remove(PropertyMapNode *node); 71 void balance(PropertyMapNode* node); 72 void updateHeight(PropertyMapNode* &node); 73 74 void rotateRR(PropertyMapNode* &node); 75 void rotateLL(PropertyMapNode* &node); 76 void rotateRL(PropertyMapNode* &node); 77 void rotateLR(PropertyMapNode* &node); 78 79 PropertyMapNode *root; 80 }; 81 82 int uscompare(const UString &s1, const UString &s2); 57 private: 58 int hash(const UString::Rep *) const; 59 static bool keysMatch(const UString::Rep *, const UString::Rep *); 60 void expand(); 61 62 void insert(UString::Rep *, ValueImp *value, int attributes); 63 64 typedef PropertyMapHashTableEntry Entry; 65 66 int _tableSizeHashMask; 67 int _tableSize; 68 Entry *_table; 69 int _keyCount; 70 71 Entry _singleEntry; 72 }; 83 73 84 74 }; // namespace -
trunk/JavaScriptCore/kjs/string_object.cpp
r1824 r2749 42 42 { 43 43 setInternalValue(String("")); 44 } 45 46 StringInstanceImp::StringInstanceImp(const Object &proto, const UString &string) 47 : ObjectImp(proto) 48 { 49 setInternalValue(String(string)); 50 } 51 52 Value StringInstanceImp::get(ExecState *exec, const UString &propertyName) const 53 { 54 if (propertyName == lengthPropertyName) 55 return Number(internalValue().toString(exec).size()); 56 return ObjectImp::get(exec, propertyName); 57 } 58 59 void StringInstanceImp::put(ExecState *exec, const UString &propertyName, const Value &value, int attr) 60 { 61 if (propertyName == lengthPropertyName) 62 return; 63 ObjectImp::put(exec, propertyName, value, attr); 64 } 65 66 bool StringInstanceImp::hasProperty(ExecState *exec, const UString &propertyName) const 67 { 68 if (propertyName == lengthPropertyName) 69 return true; 70 return ObjectImp::hasProperty(exec, propertyName); 71 } 72 73 bool StringInstanceImp::deleteProperty(ExecState *exec, const UString &propertyName) 74 { 75 if (propertyName == lengthPropertyName) 76 return false; 77 return ObjectImp::deleteProperty(exec, propertyName); 44 78 } 45 79 … … 517 551 { 518 552 Object proto = exec->interpreter()->builtinStringPrototype(); 519 Object obj(new StringInstanceImp(proto )); 520 521 UString s; 522 if (args.size() > 0) 523 s = args.begin()->dispatchToString(exec); 524 else 525 s = UString(""); 526 527 obj.setInternalValue(String(s)); 528 obj.put(exec, lengthPropertyName, Number(s.size()), ReadOnly|DontEnum|DontDelete); 529 530 return obj; 553 if (args.size() == 0) 554 return Object(new StringInstanceImp(proto)); 555 return Object(new StringInstanceImp(proto, args.begin()->dispatchToString(exec))); 531 556 } 532 557 -
trunk/JavaScriptCore/kjs/string_object.h
r1024 r2749 31 31 public: 32 32 StringInstanceImp(const Object &proto); 33 StringInstanceImp(const Object &proto, const UString &string); 34 35 virtual Value get(ExecState *exec, const UString &propertyName) const; 36 virtual void put(ExecState *exec, const UString &propertyName, const Value &value, int attr = None); 37 virtual bool hasProperty(ExecState *exec, const UString &propertyName) const; 38 virtual bool deleteProperty(ExecState *exec, const UString &propertyName); 33 39 34 40 virtual const ClassInfo *classInfo() const { return &info; } -
trunk/JavaScriptCore/kjs/ustring.cpp
r2740 r2749 592 592 void UString::release() 593 593 { 594 if (!rep->deref()) { 595 delete [] rep->dat; 596 delete rep; 597 } 594 rep->deref(); 598 595 } 599 596 … … 665 662 return (l1 < l2) ? 1 : -1; 666 663 } 667 668 // Algorithm concept from Algorithms in C++, Sedgewick, Program 14.1.669 int KJS::hash(const UString &s, int hashTableSize)670 {671 int h = 0;672 int length = s.size();673 int prefix = length < 8 ? length : 8;674 for (int i = 0; i != prefix; i++)675 h = (127 * h + s[i].unicode()) % hashTableSize;676 int suffix = length < 16 ? 8 : length - 8;677 for (int i = suffix; i != length; i++)678 h = (127 * h + s[i].unicode()) % hashTableSize;679 return h;680 } -
trunk/JavaScriptCore/kjs/ustring.h
r2740 r2749 144 144 * @return Unicode value. 145 145 */ 146 unsigned short unicode() const { return ref().u nicode(); }146 unsigned short unicode() const { return ref().uc; } 147 147 /** 148 148 * @return Lower byte. 149 149 */ 150 unsigned char low() const { return ref().uc & 0xFF; }150 unsigned char low() const { return ref().uc; } 151 151 /** 152 152 * @return Higher byte. … … 200 200 friend bool operator==(const UString&, const UString&); 201 201 friend class UCharReference; 202 friend class PropertyMap; 203 friend class PropertyMapHashTableEntry; 202 204 /** 203 205 * @internal … … 211 213 212 214 inline void ref() { rc++; } 213 inline int deref() { return --rc; } 215 inline void deref() { 216 if (--rc == 0) { 217 delete [] dat; 218 delete this; 219 } 220 } 214 221 215 222 UChar *dat; … … 403 410 #endif 404 411 private: 412 UString(Rep *r) { attach(r); } 405 413 void attach(Rep *r); 406 414 void detach(); … … 433 441 434 442 int compare(const UString &, const UString &); 435 int hash(const UString &, int hashTableSize);436 443 437 444 }; // namespace
Note:
See TracChangeset
for help on using the changeset viewer.