Changeset 49726 in webkit for trunk/JavaScriptCore/runtime
- Timestamp:
- Oct 16, 2009, 7:31:42 PM (16 years ago)
- Location:
- trunk/JavaScriptCore/runtime
- Files:
-
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/runtime/JSCell.h
r49717 r49726 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 115 123 inline JSCell::JSCell(Structure* structure) 116 124 : m_structure(structure) -
trunk/JavaScriptCore/runtime/JSObject.cpp
r49717 r49726 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 446 459 getOwnPropertyNames(exec, propertyNames); 447 460 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); 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()); 462 485 } 463 486 } -
trunk/JavaScriptCore/runtime/JSPropertyNameIterator.cpp
r49717 r49726 30 30 #include "JSPropertyNameIterator.h" 31 31 32 #include "JSGlobalObject.h"33 34 32 namespace JSC { 35 33 36 34 ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator); 37 35 38 JSPropertyNameIterator * JSPropertyNameIterator::create(ExecState* exec, JSObject* o)36 JSPropertyNameIterator::~JSPropertyNameIterator() 39 37 { 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;77 38 } 78 39 79 40 void JSPropertyNameIterator::markChildren(MarkStack& markStack) 80 41 { 81 markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues); 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(); 82 52 } 83 53 -
trunk/JavaScriptCore/runtime/JSPropertyNameIterator.h
r49717 r49726 32 32 #include "JSObject.h" 33 33 #include "JSString.h" 34 #include "Operations.h"35 34 #include "PropertyNameArray.h" 36 35 … … 41 40 42 41 class JSPropertyNameIterator : public JSCell { 43 friend class JIT; 42 public: 43 static JSPropertyNameIterator* create(ExecState*, JSValue); 44 44 45 public: 46 static JSPropertyNameIterator* create(ExecState*, JSObject*); 45 virtual ~JSPropertyNameIterator(); 46 47 virtual void markChildren(MarkStack&); 48 49 JSValue next(ExecState*); 50 void invalidate(); 47 51 48 52 static PassRefPtr<Structure> createStructure(JSValue prototype) … … 50 54 return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren)); 51 55 } 56 private: 57 JSPropertyNameIterator(ExecState*); 58 JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData); 52 59 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 64 private: 65 JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData); 66 67 Structure* m_cachedStructure; 68 RefPtr<StructureChain> m_cachedPrototypeChain; 69 size_t m_jsStringsSize; 70 OwnArrayPtr<JSValue> m_jsStrings; 60 JSObject* m_object; 61 RefPtr<PropertyNameArrayData> m_data; 62 PropertyNameArrayData::const_iterator m_position; 63 PropertyNameArrayData::const_iterator m_end; 71 64 }; 72 65 73 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec , PropertyNameArrayData* propertyNameArrayData)66 inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec) 74 67 : JSCell(exec->globalData().propertyNameIteratorStructure.get()) 75 , m_ cachedStructure(0)76 , m_ jsStringsSize(propertyNameArrayData->propertyNameVector().size())77 , m_ jsStrings(new JSValue[m_jsStringsSize])68 , m_object(0) 69 , m_position(0) 70 , m_end(0) 78 71 { 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());82 72 } 83 73 84 inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) 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()) 85 80 { 86 ASSERT(!isDictionary()); 87 m_enumerationCache = enumerationCache; 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(); 88 109 } 89 110 -
trunk/JavaScriptCore/runtime/JSValue.h
r49717 r49726 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 384 376 ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const 385 377 { -
trunk/JavaScriptCore/runtime/MarkStack.h
r49717 r49726 48 48 49 49 ALWAYS_INLINE void append(JSValue); 50 void append(JSCell*);50 ALWAYS_INLINE void append(JSCell*); 51 51 52 52 ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues) -
trunk/JavaScriptCore/runtime/ObjectConstructor.cpp
r49717 r49726 126 126 } 127 127 128 // FIXME: Use the enumeration cache.129 128 JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args) 130 129 { -
trunk/JavaScriptCore/runtime/Operations.h
r49717 r49726 225 225 } 226 226 227 inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase)228 { 229 JSCell* cell = asCell(base );227 inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot) 228 { 229 JSCell* cell = asCell(baseValue); 230 230 size_t count = 0; 231 231 232 while (slot Base!= cell) {232 while (slot.slotBase() != cell) { 233 233 JSValue v = cell->structure()->prototypeForLookup(callFrame); 234 234 235 // If we didn't find slotBase in base 's prototype chain, then base235 // If we didn't find slotBase in baseValue's prototype chain, then baseValue 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 it266 // should not be treated as a dictionary.267 if (base->structure()->isDictionary())268 asObject(base)->setStructure(Structure::fromDictionaryTransition(base->structure()));269 270 ++count;271 }272 253 } 273 254 -
trunk/JavaScriptCore/runtime/PropertyNameArray.cpp
r49717 r49726 48 48 } 49 49 50 addKnownUnique(identifier);50 m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); 51 51 } 52 52 -
trunk/JavaScriptCore/runtime/PropertyNameArray.h
r49717 r49726 25 25 #include "Identifier.h" 26 26 #include <wtf/HashSet.h> 27 #include <wtf/OwnArrayPtr.h>28 27 #include <wtf/Vector.h> 29 28 … … 33 32 class StructureChain; 34 33 35 // FIXME: Rename to PropertyNameArray.36 34 class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> { 37 35 public: 38 36 typedef Vector<Identifier, 20> PropertyNameVector; 37 typedef PropertyNameVector::const_iterator const_iterator; 39 38 40 39 static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); } 41 40 41 const_iterator begin() const { return m_propertyNameVector.begin(); } 42 const_iterator end() const { return m_propertyNameVector.end(); } 43 42 44 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(); } 43 51 44 52 private: 45 53 PropertyNameArrayData() 54 : m_cachedStructure(0) 46 55 { 47 56 } 48 57 49 58 PropertyNameVector m_propertyNameVector; 59 Structure* m_cachedStructure; 60 RefPtr<StructureChain> m_cachedPrototypeChain; 50 61 }; 51 62 52 // FIXME: Rename to PropertyNameArrayBuilder.53 63 class PropertyNameArray { 54 64 public: 65 typedef PropertyNameArrayData::const_iterator const_iterator; 66 55 67 PropertyNameArray(JSGlobalData* globalData) 56 68 : m_data(PropertyNameArrayData::create()) … … 73 85 void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } 74 86 87 size_t size() const { return m_data->propertyNameVector().size(); } 88 75 89 Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } 76 90 const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; } 77 91 92 const_iterator begin() const { return m_data->begin(); } 93 const_iterator end() const { return m_data->end(); } 94 78 95 void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; } 79 96 PropertyNameArrayData* data() { return m_data.get(); } 97 80 98 PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); } 81 99 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(); } 100 void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; } 101 bool shouldCache() const { return m_shouldCache; } 87 102 88 103 private: -
trunk/JavaScriptCore/runtime/Protect.h
r49717 r49726 23 23 #define Protect_h 24 24 25 #include "JSCell.h" 25 26 #include "Collector.h" 26 #include "JSValue.h"27 27 28 28 namespace JSC { -
trunk/JavaScriptCore/runtime/Structure.cpp
r49717 r49726 29 29 #include "Identifier.h" 30 30 #include "JSObject.h" 31 #include "JSPropertyNameIterator.h"32 #include "Lookup.h"33 31 #include "PropertyNameArray.h" 34 32 #include "StructureChain.h" 33 #include "Lookup.h" 35 34 #include <wtf/RefCountedLeakCounter.h> 36 35 #include <wtf/RefPtr.h> … … 161 160 162 161 } 163 164 if (m_ enumerationCache)165 m_ enumerationCache->setCachedStructure(0);162 163 if (m_cachedPropertyNameArrayData) 164 m_cachedPropertyNameArrayData->setCachedStructure(0); 166 165 167 166 if (m_propertyTable) { … … 282 281 insertIntoPropertyMapHashTable(entry); 283 282 } 283 } 284 285 void Structure::clearEnumerationCache() 286 { 287 if (m_cachedPropertyNameArrayData) 288 m_cachedPropertyNameArrayData->setCachedStructure(0); 289 m_cachedPropertyNameArrayData.clear(); 284 290 } 285 291 … … 547 553 size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) 548 554 { 549 ASSERT(!m_enumerationCache);550 555 materializePropertyMapIfNecessary(); 551 556 … … 554 559 if (propertyStorageSize() > propertyStorageCapacity()) 555 560 growPropertyStorageCapacity(); 561 clearEnumerationCache(); 556 562 return offset; 557 563 } … … 560 566 { 561 567 ASSERT(isUncacheableDictionary()); 562 ASSERT(!m_enumerationCache);563 568 564 569 materializePropertyMapIfNecessary(); … … 566 571 m_isPinnedPropertyTable = true; 567 572 size_t offset = remove(propertyName); 573 clearEnumerationCache(); 568 574 return offset; 569 575 } -
trunk/JavaScriptCore/runtime/Structure.h
r49717 r49726 32 32 #include "PropertyMapHashTable.h" 33 33 #include "PropertyNameArray.h" 34 #include "Protect.h"35 34 #include "StructureChain.h" 36 35 #include "StructureTransitionTable.h" … … 125 124 void despecifyDictionaryFunction(const Identifier& propertyName); 126 125 127 void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. 128 JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); } 126 void setEnumerationCache(PassRefPtr<PropertyNameArrayData> data) { m_cachedPropertyNameArrayData = data; } 127 PropertyNameArrayData* enumerationCache() { return m_cachedPropertyNameArrayData.get(); } 128 void clearEnumerationCache(); 129 129 void getEnumerablePropertyNames(PropertyNameArray&); 130 130 … … 187 187 StructureTransitionTable table; 188 188 189 ProtectedPtr<JSPropertyNameIterator> m_enumerationCache;189 RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData; 190 190 191 191 PropertyMapHashTable* m_propertyTable; -
trunk/JavaScriptCore/runtime/StructureChain.cpp
r49717 r49726 47 47 } 48 48 49 bool StructureChain::isCacheable() const 50 { 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 them 55 if (m_vector[i]->isDictionary()) 56 return false; 57 if (m_vector[i++]->typeInfo().overridesGetPropertyNames()) 58 return false; 59 } 60 return true; 61 } 62 49 63 } // namespace JSC -
trunk/JavaScriptCore/runtime/StructureChain.h
r49717 r49726 37 37 38 38 class StructureChain : public RefCounted<StructureChain> { 39 friend class JIT;40 41 39 public: 42 40 static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } 43 41 RefPtr<Structure>* head() { return m_vector.get(); } 42 bool isCacheable() const; 44 43 45 44 private:
Note:
See TracChangeset
for help on using the changeset viewer.