Changeset 49734 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Oct 16, 2009, 10:52:20 PM (16 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSCell.h
r49726 r49734 113 113 }; 114 114 115 // FIXME: We should deprecate this and just use JSValue::asCell() instead.116 JSCell* asCell(JSValue);117 118 inline JSCell* asCell(JSValue value)119 {120 return value.asCell();121 }122 123 115 inline JSCell::JSCell(Structure* structure) 124 116 : m_structure(structure) -
trunk/JavaScriptCore/runtime/JSObject.cpp
r49726 r49734 444 444 void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) 445 445 { 446 bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || m_structure->isDictionary());447 448 if (shouldCache) {449 if (PropertyNameArrayData* data = m_structure->enumerationCache()) {450 if (data->cachedPrototypeChain() == m_structure->prototypeChain(exec)) {451 propertyNames.setData(data);452 return;453 }454 455 m_structure->clearEnumerationCache();456 }457 }458 459 446 getOwnPropertyNames(exec, propertyNames); 460 447 461 if (prototype().isObject()) { 462 propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. 463 JSObject* prototype = asObject(this->prototype()); 464 while(1) { 465 if (prototype->structure()->typeInfo().overridesGetPropertyNames()) { 466 prototype->getPropertyNames(exec, propertyNames); 467 break; 468 } 469 prototype->getOwnPropertyNames(exec, propertyNames); 470 JSValue nextProto = prototype->prototype(); 471 if (!nextProto.isObject()) 472 break; 473 prototype = asObject(nextProto); 474 } 475 } 476 477 if (shouldCache) { 478 StructureChain* protoChain = m_structure->prototypeChain(exec); 479 if (!protoChain->isCacheable()) 480 return; 481 RefPtr<PropertyNameArrayData> data = propertyNames.data(); 482 data->setCachedPrototypeChain(protoChain); 483 data->setCachedStructure(m_structure); 484 m_structure->setEnumerationCache(data.release()); 448 if (prototype().isNull()) 449 return; 450 451 JSObject* prototype = asObject(this->prototype()); 452 while(1) { 453 if (prototype->structure()->typeInfo().overridesGetPropertyNames()) { 454 prototype->getPropertyNames(exec, propertyNames); 455 break; 456 } 457 prototype->getOwnPropertyNames(exec, propertyNames); 458 JSValue nextProto = prototype->prototype(); 459 if (nextProto.isNull()) 460 break; 461 prototype = asObject(nextProto); 485 462 } 486 463 } -
trunk/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
r49726 r49734 30 30 #include "JSPropertyNameIterator.h" 31 31 32 #include "JSGlobalObject.h" 33 32 34 namespace JSC { 33 35 34 36 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator); 35 37 36 JSPropertyNameIterator ::~JSPropertyNameIterator()38 JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) 37 39 { 40 ASSERT(!o->structure()->enumerationCache() || 41 o->structure()->enumerationCache()->cachedStructure() != o->structure() || 42 o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec)); 43 44 PropertyNameArray propertyNames(exec); 45 o->getPropertyNames(exec, propertyNames); 46 JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data()); 47 48 if (o->structure()->isDictionary()) 49 return jsPropertyNameIterator; 50 51 if (o->structure()->typeInfo().overridesGetPropertyNames()) 52 return jsPropertyNameIterator; 53 54 size_t count = normalizePrototypeChain(exec, o); 55 StructureChain* structureChain = o->structure()->prototypeChain(exec); 56 RefPtr<Structure>* structure = structureChain->head(); 57 for (size_t i = 0; i < count; ++i) { 58 if (structure[i]->typeInfo().overridesGetPropertyNames()) 59 return jsPropertyNameIterator; 60 } 61 62 jsPropertyNameIterator->setCachedPrototypeChain(structureChain); 63 jsPropertyNameIterator->setCachedStructure(o->structure()); 64 o->structure()->setEnumerationCache(jsPropertyNameIterator); 65 return jsPropertyNameIterator; 66 } 67 68 JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) 69 { 70 JSValue& identifier = m_jsStrings[i]; 71 if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec)) 72 return identifier; 73 74 if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value()))) 75 return JSValue(); 76 return identifier; 38 77 } 39 78 40 79 void JSPropertyNameIterator::markChildren(MarkStack& markStack) 41 80 { 42 JSCell::markChildren(markStack); 43 if (m_object) 44 markStack.append(m_object); 45 } 46 47 void JSPropertyNameIterator::invalidate() 48 { 49 ASSERT(m_position == m_end); 50 m_object = 0; 51 m_data.clear(); 81 markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues); 52 82 } 53 83 -
trunk/JavaScriptCore/runtime/JSPropertyNameIterator.h
r49726 r49734 32 32 #include "JSObject.h" 33 33 #include "JSString.h" 34 #include "Operations.h" 34 35 #include "PropertyNameArray.h" 35 36 … … 40 41 41 42 class JSPropertyNameIterator : public JSCell { 43 friend class JIT; 44 42 45 public: 43 static JSPropertyNameIterator* create(ExecState*, JSValue); 44 45 virtual ~JSPropertyNameIterator(); 46 47 virtual void markChildren(MarkStack&); 48 49 JSValue next(ExecState*); 50 void invalidate(); 46 static JSPropertyNameIterator* create(ExecState*, JSObject*); 51 47 52 48 static PassRefPtr<Structure> createStructure(JSValue prototype) … … 54 50 return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren)); 55 51 } 52 53 virtual void markChildren(MarkStack&); 54 55 JSValue get(ExecState*, JSObject*, size_t i); 56 size_t size() { return m_jsStringsSize; } 57 58 void setCachedStructure(Structure* structure) { m_cachedStructure = structure; } 59 Structure* cachedStructure() { return m_cachedStructure; } 60 61 void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } 62 StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } 63 56 64 private: 57 JSPropertyNameIterator(ExecState*); 58 JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData); 65 JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData); 59 66 60 JSObject* m_object;61 RefPtr< PropertyNameArrayData> m_data;62 PropertyNameArrayData::const_iterator m_position;63 PropertyNameArrayData::const_iterator m_end;67 Structure* m_cachedStructure; 68 RefPtr<StructureChain> m_cachedPrototypeChain; 69 size_t m_jsStringsSize; 70 OwnArrayPtr<JSValue> m_jsStrings; 64 71 }; 65 72 66 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec )73 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData) 67 74 : JSCell(exec->globalData().propertyNameIteratorStructure.get()) 68 , m_ object(0)69 , m_ position(0)70 , m_ end(0)75 , m_cachedStructure(0) 76 , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) 77 , m_jsStrings(new JSValue[m_jsStringsSize]) 71 78 { 79 PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector(); 80 for (size_t i = 0; i < m_jsStringsSize; ++i) 81 m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring()); 72 82 } 73 83 74 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData) 75 : JSCell(exec->globalData().propertyNameIteratorStructure.get()) 76 , m_object(object) 77 , m_data(propertyNameArrayData) 78 , m_position(m_data->begin()) 79 , m_end(m_data->end()) 84 inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) 80 85 { 81 } 82 83 inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v) 84 { 85 if (v.isUndefinedOrNull()) 86 return new (exec) JSPropertyNameIterator(exec); 87 88 JSObject* o = v.toObject(exec); 89 PropertyNameArray propertyNames(exec); 90 o->getPropertyNames(exec, propertyNames); 91 return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData()); 92 } 93 94 inline JSValue JSPropertyNameIterator::next(ExecState* exec) 95 { 96 if (m_position == m_end) 97 return JSValue(); 98 99 if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec)) 100 return jsOwnedString(exec, (*m_position++).ustring()); 101 102 do { 103 if (m_object->hasProperty(exec, *m_position)) 104 return jsOwnedString(exec, (*m_position++).ustring()); 105 m_position++; 106 } while (m_position != m_end); 107 108 return JSValue(); 86 ASSERT(!isDictionary()); 87 m_enumerationCache = enumerationCache; 109 88 } 110 89 -
trunk/JavaScriptCore/runtime/JSValue.h
r49726 r49734 374 374 } 375 375 376 // FIXME: We should deprecate this and just use JSValue::asCell() instead. 377 JSCell* asCell(JSValue); 378 379 inline JSCell* asCell(JSValue value) 380 { 381 return value.asCell(); 382 } 383 376 384 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const 377 385 { -
trunk/JavaScriptCore/runtime/MarkStack.h
r49726 r49734 48 48 49 49 ALWAYS_INLINE void append(JSValue); 50 ALWAYS_INLINEvoid append(JSCell*);50 void append(JSCell*); 51 51 52 52 ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues) -
trunk/JavaScriptCore/runtime/ObjectConstructor.cpp
r49726 r49734 126 126 } 127 127 128 // FIXME: Use the enumeration cache. 128 129 JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args) 129 130 { -
trunk/JavaScriptCore/runtime/Operations.h
r49726 r49734 225 225 } 226 226 227 inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot)228 { 229 JSCell* cell = asCell(base Value);227 inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase) 228 { 229 JSCell* cell = asCell(base); 230 230 size_t count = 0; 231 231 232 while (slot .slotBase()!= cell) {232 while (slotBase != cell) { 233 233 JSValue v = cell->structure()->prototypeForLookup(callFrame); 234 234 235 // If we didn't find slotBase in base Value's prototype chain, then baseValue235 // If we didn't find slotBase in base's prototype chain, then base 236 236 // must be a proxy for another object. 237 237 … … 251 251 ASSERT(count); 252 252 return count; 253 } 254 255 inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base) 256 { 257 size_t count = 0; 258 while (1) { 259 JSValue v = base->structure()->prototypeForLookup(callFrame); 260 if (v.isNull()) 261 return count; 262 263 base = asCell(v); 264 265 // Since we're accessing a prototype in a loop, it's a good bet that it 266 // should not be treated as a dictionary. 267 if (base->structure()->isDictionary()) 268 asObject(base)->setStructure(Structure::fromDictionaryTransition(base->structure())); 269 270 ++count; 271 } 253 272 } 254 273 -
trunk/JavaScriptCore/runtime/PropertyNameArray.cpp
r49726 r49734 48 48 } 49 49 50 m_data->propertyNameVector().append(Identifier(m_globalData, identifier));50 addKnownUnique(identifier); 51 51 } 52 52 -
trunk/JavaScriptCore/runtime/PropertyNameArray.h
r49726 r49734 25 25 #include "Identifier.h" 26 26 #include <wtf/HashSet.h> 27 #include <wtf/OwnArrayPtr.h> 27 28 #include <wtf/Vector.h> 28 29 … … 32 33 class StructureChain; 33 34 35 // FIXME: Rename to PropertyNameArray. 34 36 class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> { 35 37 public: 36 38 typedef Vector<Identifier, 20> PropertyNameVector; 37 typedef PropertyNameVector::const_iterator const_iterator;38 39 39 40 static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); } 40 41 41 const_iterator begin() const { return m_propertyNameVector.begin(); }42 const_iterator end() const { return m_propertyNameVector.end(); }43 44 42 PropertyNameVector& propertyNameVector() { return m_propertyNameVector; } 45 46 void setCachedStructure(Structure* structure) { m_cachedStructure = structure; }47 Structure* cachedStructure() const { return m_cachedStructure; }48 49 void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; }50 StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); }51 43 52 44 private: 53 45 PropertyNameArrayData() 54 : m_cachedStructure(0)55 46 { 56 47 } 57 48 58 49 PropertyNameVector m_propertyNameVector; 59 Structure* m_cachedStructure;60 RefPtr<StructureChain> m_cachedPrototypeChain;61 50 }; 62 51 52 // FIXME: Rename to PropertyNameArrayBuilder. 63 53 class PropertyNameArray { 64 54 public: 65 typedef PropertyNameArrayData::const_iterator const_iterator;66 67 55 PropertyNameArray(JSGlobalData* globalData) 68 56 : m_data(PropertyNameArrayData::create()) … … 85 73 void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } 86 74 87 size_t size() const { return m_data->propertyNameVector().size(); }88 89 75 Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } 90 76 const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; } 91 77 92 const_iterator begin() const { return m_data->begin(); }93 const_iterator end() const { return m_data->end(); }94 95 78 void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; } 96 79 PropertyNameArrayData* data() { return m_data.get(); } 97 98 80 PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); } 99 81 100 void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; } 101 bool shouldCache() const { return m_shouldCache; } 82 // FIXME: Remove these functions. 83 typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator; 84 size_t size() const { return m_data->propertyNameVector().size(); } 85 const_iterator begin() const { return m_data->propertyNameVector().begin(); } 86 const_iterator end() const { return m_data->propertyNameVector().end(); } 102 87 103 88 private: -
trunk/JavaScriptCore/runtime/Protect.h
r49726 r49734 23 23 #define Protect_h 24 24 25 #include "JSCell.h"26 25 #include "Collector.h" 26 #include "JSValue.h" 27 27 28 28 namespace JSC { -
trunk/JavaScriptCore/runtime/Structure.cpp
r49726 r49734 29 29 #include "Identifier.h" 30 30 #include "JSObject.h" 31 #include "JSPropertyNameIterator.h" 32 #include "Lookup.h" 31 33 #include "PropertyNameArray.h" 32 34 #include "StructureChain.h" 33 #include "Lookup.h"34 35 #include <wtf/RefCountedLeakCounter.h> 35 36 #include <wtf/RefPtr.h> … … 160 161 161 162 } 162 163 if (m_ cachedPropertyNameArrayData)164 m_ cachedPropertyNameArrayData->setCachedStructure(0);163 164 if (m_enumerationCache) 165 m_enumerationCache->setCachedStructure(0); 165 166 166 167 if (m_propertyTable) { … … 281 282 insertIntoPropertyMapHashTable(entry); 282 283 } 283 }284 285 void Structure::clearEnumerationCache()286 {287 if (m_cachedPropertyNameArrayData)288 m_cachedPropertyNameArrayData->setCachedStructure(0);289 m_cachedPropertyNameArrayData.clear();290 284 } 291 285 … … 553 547 size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) 554 548 { 549 ASSERT(!m_enumerationCache); 555 550 materializePropertyMapIfNecessary(); 556 551 … … 559 554 if (propertyStorageSize() > propertyStorageCapacity()) 560 555 growPropertyStorageCapacity(); 561 clearEnumerationCache();562 556 return offset; 563 557 } … … 566 560 { 567 561 ASSERT(isUncacheableDictionary()); 562 ASSERT(!m_enumerationCache); 568 563 569 564 materializePropertyMapIfNecessary(); … … 571 566 m_isPinnedPropertyTable = true; 572 567 size_t offset = remove(propertyName); 573 clearEnumerationCache();574 568 return offset; 575 569 } -
trunk/JavaScriptCore/runtime/Structure.h
r49726 r49734 32 32 #include "PropertyMapHashTable.h" 33 33 #include "PropertyNameArray.h" 34 #include "Protect.h" 34 35 #include "StructureChain.h" 35 36 #include "StructureTransitionTable.h" … … 124 125 void despecifyDictionaryFunction(const Identifier& propertyName); 125 126 126 void setEnumerationCache(PassRefPtr<PropertyNameArrayData> data) { m_cachedPropertyNameArrayData = data; } 127 PropertyNameArrayData* enumerationCache() { return m_cachedPropertyNameArrayData.get(); } 128 void clearEnumerationCache(); 127 void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. 128 JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); } 129 129 void getEnumerablePropertyNames(PropertyNameArray&); 130 130 … … 187 187 StructureTransitionTable table; 188 188 189 RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData;189 ProtectedPtr<JSPropertyNameIterator> m_enumerationCache; 190 190 191 191 PropertyMapHashTable* m_propertyTable; -
trunk/JavaScriptCore/runtime/StructureChain.cpp
r49726 r49734 47 47 } 48 48 49 bool StructureChain::isCacheable() const50 {51 uint32_t i = 0;52 53 while (m_vector[i]) {54 // Both classes of dictionary structure may change arbitrarily so we can't cache them55 if (m_vector[i]->isDictionary())56 return false;57 if (m_vector[i++]->typeInfo().overridesGetPropertyNames())58 return false;59 }60 return true;61 }62 63 49 } // namespace JSC -
trunk/JavaScriptCore/runtime/StructureChain.h
r49726 r49734 37 37 38 38 class StructureChain : public RefCounted<StructureChain> { 39 friend class JIT; 40 39 41 public: 40 42 static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } 41 43 RefPtr<Structure>* head() { return m_vector.get(); } 42 bool isCacheable() const;43 44 44 45 private:
Note:
See TracChangeset
for help on using the changeset viewer.