X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..12899fa232562c774004a3a9d7d3149944dec712:/runtime/Lookup.h diff --git a/runtime/Lookup.h b/runtime/Lookup.h index 43184e5..c90ceae 100644 --- a/runtime/Lookup.h +++ b/runtime/Lookup.h @@ -22,20 +22,13 @@ #define Lookup_h #include "CallFrame.h" +#include "Intrinsic.h" #include "Identifier.h" #include "JSGlobalObject.h" -#include "JSObject.h" #include "PropertySlot.h" #include #include -// Bug #26843: Work around Metrowerks compiler bug -#if COMPILER(WINSCW) -#define JSC_CONST_HASHTABLE -#else -#define JSC_CONST_HASHTABLE const -#endif - namespace JSC { // Hash table generated by the create_hash_table script. struct HashTableValue { @@ -43,9 +36,7 @@ namespace JSC { unsigned char attributes; // JSObject attributes intptr_t value1; intptr_t value2; -#if ENABLE(JIT) - ThunkGenerator generator; -#endif + Intrinsic intrinsic; }; // FIXME: There is no reason this get function can't be simpler. @@ -56,19 +47,13 @@ namespace JSC { class HashEntry { WTF_MAKE_FAST_ALLOCATED; public: - void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2 -#if ENABLE(JIT) - , ThunkGenerator generator = 0 -#endif - ) + void initialize(StringImpl* key, unsigned char attributes, intptr_t v1, intptr_t v2, Intrinsic intrinsic) { m_key = key; m_attributes = attributes; m_u.store.value1 = v1; m_u.store.value2 = v2; -#if ENABLE(JIT) - m_u.function.generator = generator; -#endif + m_intrinsic = intrinsic; m_next = 0; } @@ -77,9 +62,12 @@ namespace JSC { unsigned char attributes() const { return m_attributes; } -#if ENABLE(JIT) && ENABLE(JIT_OPTIMIZE_NATIVE_CALL) - ThunkGenerator generator() const { ASSERT(m_attributes & Function); return m_u.function.generator; } -#endif + Intrinsic intrinsic() const + { + ASSERT(m_attributes & Function); + return m_intrinsic; + } + NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; } unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast(m_u.function.length); } @@ -94,6 +82,7 @@ namespace JSC { private: StringImpl* m_key; unsigned char m_attributes; // JSObject attributes + Intrinsic m_intrinsic; union { struct { @@ -103,9 +92,6 @@ namespace JSC { struct { NativeFunction functionValue; intptr_t length; // number of arguments for function -#if ENABLE(JIT) - ThunkGenerator generator; -#endif } function; struct { GetFunction get; @@ -128,45 +114,113 @@ namespace JSC { const HashTableValue* values; // Fixed values generated by script. mutable const HashEntry* table; // Table allocated at runtime. - ALWAYS_INLINE void initializeIfNeeded(JSGlobalData* globalData) const + ALWAYS_INLINE HashTable copy() const + { + // Don't copy dynamic table since it's thread specific. + HashTable result = { compactSize, compactHashSizeMask, values, 0 }; + return result; + } + + ALWAYS_INLINE void initializeIfNeeded(VM* vm) const { if (!table) - createTable(globalData); + createTable(vm); } ALWAYS_INLINE void initializeIfNeeded(ExecState* exec) const { if (!table) - createTable(&exec->globalData()); + createTable(&exec->vm()); } - void deleteTable() const; + JS_EXPORT_PRIVATE void deleteTable() const; // Find an entry in the table, and return the entry. - ALWAYS_INLINE const HashEntry* entry(JSGlobalData* globalData, const Identifier& identifier) const + ALWAYS_INLINE const HashEntry* entry(VM* vm, PropertyName identifier) const { - initializeIfNeeded(globalData); + initializeIfNeeded(vm); return entry(identifier); } - ALWAYS_INLINE const HashEntry* entry(ExecState* exec, const Identifier& identifier) const + ALWAYS_INLINE const HashEntry* entry(ExecState* exec, PropertyName identifier) const { initializeIfNeeded(exec); return entry(identifier); } + class ConstIterator { + public: + ConstIterator(const HashTable* table, int position) + : m_table(table) + , m_position(position) + { + skipInvalidKeys(); + } + + const HashEntry* operator->() + { + return &m_table->table[m_position]; + } + + const HashEntry* operator*() + { + return &m_table->table[m_position]; + } + + bool operator!=(const ConstIterator& other) + { + ASSERT(m_table == other.m_table); + return m_position != other.m_position; + } + + ConstIterator& operator++() + { + ASSERT(m_position < m_table->compactSize); + ++m_position; + skipInvalidKeys(); + return *this; + } + + private: + void skipInvalidKeys() + { + ASSERT(m_position <= m_table->compactSize); + while (m_position < m_table->compactSize && !m_table->table[m_position].key()) + ++m_position; + ASSERT(m_position <= m_table->compactSize); + } + + const HashTable* m_table; + int m_position; + }; + + ConstIterator begin(VM& vm) const + { + initializeIfNeeded(&vm); + return ConstIterator(this, 0); + } + ConstIterator end(VM& vm) const + { + initializeIfNeeded(&vm); + return ConstIterator(this, compactSize); + } + private: - ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const + ALWAYS_INLINE const HashEntry* entry(PropertyName propertyName) const { + StringImpl* impl = propertyName.publicName(); + if (!impl) + return 0; + ASSERT(table); - const HashEntry* entry = &table[identifier.impl()->existingHash() & compactHashSizeMask]; + const HashEntry* entry = &table[impl->existingHash() & compactHashSizeMask]; if (!entry->key()) return 0; do { - if (entry->key() == identifier.impl()) + if (entry->key() == impl) return entry; entry = entry->next(); } while (entry); @@ -175,10 +229,10 @@ namespace JSC { } // Convert the hash table keys to identifiers. - void createTable(JSGlobalData*) const; + JS_EXPORT_PRIVATE void createTable(VM*) const; }; - void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&); + JS_EXPORT_PRIVATE bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, PropertyName, PropertySlot&); /** * This method does it all (looking in the hashtable, checking for function @@ -187,35 +241,37 @@ namespace JSC { * unknown property). */ template - inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) + inline bool getStaticPropertySlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, PropertyName propertyName, PropertySlot& slot) { const HashEntry* entry = table->entry(exec, propertyName); if (!entry) // not found, forward to parent - return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); + return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot); if (entry->attributes() & Function) - setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); - else - slot.setCacheableCustom(thisObj, entry->propertyGetter()); + return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + slot.setCacheableCustom(thisObj, entry->propertyGetter()); return true; } template - inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, PropertyName propertyName, PropertyDescriptor& descriptor) { const HashEntry* entry = table->entry(exec, propertyName); if (!entry) // not found, forward to parent - return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor); + return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor); PropertySlot slot; - if (entry->attributes() & Function) - setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); - else - slot.setCustom(thisObj, entry->propertyGetter()); + if (entry->attributes() & Function) { + bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + if (present) + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return present; + } + slot.setCustom(thisObj, entry->propertyGetter()); descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); return true; } @@ -226,17 +282,16 @@ namespace JSC { * a dummy getValueProperty. */ template - inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot) + inline bool getStaticFunctionSlot(ExecState* exec, const HashTable* table, JSObject* thisObj, PropertyName propertyName, PropertySlot& slot) { - if (static_cast(thisObj)->ParentImp::getOwnPropertySlot(exec, propertyName, slot)) + if (ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot)) return true; const HashEntry* entry = table->entry(exec, propertyName); if (!entry) return false; - setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); - return true; + return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); } /** @@ -245,9 +300,9 @@ namespace JSC { * a dummy getValueProperty. */ template - inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, PropertyName propertyName, PropertyDescriptor& descriptor) { - if (static_cast(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor)) + if (ParentImp::getOwnPropertyDescriptor(static_cast(thisObj), exec, propertyName, descriptor)) return true; const HashEntry* entry = table->entry(exec, propertyName); @@ -255,9 +310,10 @@ namespace JSC { return false; PropertySlot slot; - setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); - descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); - return true; + bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); + if (present) + descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes()); + return present; } /** @@ -265,12 +321,12 @@ namespace JSC { * Using this instead of getStaticPropertySlot removes the need for a FuncImp class. */ template - inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertySlot& slot) + inline bool getStaticValueSlot(ExecState* exec, const HashTable* table, ThisImp* thisObj, PropertyName propertyName, PropertySlot& slot) { const HashEntry* entry = table->entry(exec, propertyName); if (!entry) // not found, forward to parent - return thisObj->ParentImp::getOwnPropertySlot(exec, propertyName, slot); + return ParentImp::getOwnPropertySlot(thisObj, exec, propertyName, slot); ASSERT(!(entry->attributes() & Function)); @@ -283,12 +339,12 @@ namespace JSC { * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class. */ template - inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor) + inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, PropertyName propertyName, PropertyDescriptor& descriptor) { const HashEntry* entry = table->entry(exec, propertyName); if (!entry) // not found, forward to parent - return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor); + return ParentImp::getOwnPropertyDescriptor(thisObj, exec, propertyName, descriptor); ASSERT(!(entry->attributes() & Function)); PropertySlot slot; @@ -297,27 +353,32 @@ namespace JSC { return true; } + template + inline void putEntry(ExecState* exec, const HashEntry* entry, PropertyName propertyName, JSValue value, ThisImp* thisObj, bool shouldThrow = false) + { + // If this is a function put it as an override property. + if (entry->attributes() & Function) + thisObj->putDirect(exec->vm(), propertyName, value); + else if (!(entry->attributes() & ReadOnly)) + entry->propertyPutter()(exec, thisObj, value); + else if (shouldThrow) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); + } + /** * This one is for "put". * It looks up a hash entry for the property to be set. If an entry * is found it sets the value and returns true, else it returns false. */ template - inline bool lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj) + inline bool lookupPut(ExecState* exec, PropertyName propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, bool shouldThrow = false) { const HashEntry* entry = table->entry(exec, propertyName); - + if (!entry) return false; - if (entry->attributes() & Function) { // function: put as override property - if (LIKELY(value.isCell())) - thisObj->putDirectFunction(exec->globalData(), propertyName, value.asCell()); - else - thisObj->putDirect(exec->globalData(), propertyName, value); - } else if (!(entry->attributes() & ReadOnly)) - entry->propertyPutter()(exec, thisObj, value); - + putEntry(exec, entry, propertyName, value, thisObj, shouldThrow); return true; } @@ -328,10 +389,10 @@ namespace JSC { * then it calls put() on the ParentImp class. */ template - inline void lookupPut(ExecState* exec, const Identifier& propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) + inline void lookupPut(ExecState* exec, PropertyName propertyName, JSValue value, const HashTable* table, ThisImp* thisObj, PutPropertySlot& slot) { - if (!lookupPut(exec, propertyName, value, table, thisObj)) - thisObj->ParentImp::put(exec, propertyName, value, slot); // not found: forward to parent + if (!lookupPut(exec, propertyName, value, table, thisObj, slot.isStrictMode())) + ParentImp::put(thisObj, exec, propertyName, value, slot); // not found: forward to parent } } // namespace JSC