X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/fb8617cde5834786bd4e4afd579883e4acf5666e..4e4e5a6f2694187498445a6ac6f1634ce8141119:/runtime/JSObject.h diff --git a/runtime/JSObject.h b/runtime/JSObject.h index 2b31a65..6824c23 100644 --- a/runtime/JSObject.h +++ b/runtime/JSObject.h @@ -26,6 +26,7 @@ #include "ArgList.h" #include "ClassInfo.h" #include "CommonIdentifiers.h" +#include "Completion.h" #include "CallFrame.h" #include "JSCell.h" #include "JSNumberCell.h" @@ -35,6 +36,7 @@ #include "ScopeChain.h" #include "Structure.h" #include "JSGlobalData.h" +#include "JSString.h" #include namespace JSC { @@ -170,6 +172,7 @@ namespace JSC { void putDirect(const Identifier& propertyName, JSValue value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); void putDirect(const Identifier& propertyName, JSValue value, unsigned attr = 0); + void putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot&); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr = 0); void putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attr, bool checkReadOnly, PutPropertySlot& slot); @@ -194,9 +197,10 @@ namespace JSC { virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } virtual bool isActivationObject() const { return false; } - virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } + virtual ComplType exceptionType() const { return Throw; } + void allocatePropertyStorage(size_t oldSize, size_t newSize); void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } @@ -436,12 +440,20 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue JSCell* currentSpecificFunction; size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { + // If there is currently a specific function, and there now either isn't, + // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) m_structure->despecifyDictionaryFunction(propertyName); if (checkReadOnly && currentAttributes & ReadOnly) return; putDirectOffset(offset, value); - if (!specificFunction && !currentSpecificFunction) + // At this point, the objects structure only has a specific value set if previously there + // had been one set, and if the new value being specified is the same (otherwise we would + // have despecified, above). So, if currentSpecificFunction is not set, or if the new + // value is different (or there is no new value), then the slot now has no value - and + // as such it is cachable. + // If there was previously a value, and the new value is the same, then we cannot cache. + if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) slot.setExistingProperty(this, offset); return; } @@ -468,7 +480,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); putDirectOffset(offset, value); - // See comment on setNewProperty call below. + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); return; @@ -481,14 +494,28 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (checkReadOnly && currentAttributes & ReadOnly) return; - if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) { + // There are three possibilities here: + // (1) There is an existing specific value set, and we're overwriting with *the same value*. + // * Do nothing - no need to despecify, but that means we can't cache (a cached + // put could write a different value). Leave the slot in an uncachable state. + // (2) There is a specific value currently set, but we're writing a different value. + // * First, we have to despecify. Having done so, this is now a regular slot + // with no specific value, so go ahead & cache like normal. + // (3) Normal case, there is no specific value set. + // * Go ahead & cache like normal. + if (currentSpecificFunction) { + // case (1) Do the put, then return leaving the slot uncachable. + if (specificFunction == currentSpecificFunction) { + putDirectOffset(offset, value); + return; + } + // case (2) Despecify, fall through to (3). setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); - putDirectOffset(offset, value); - // Function transitions are not currently cachable, so leave the slot in an uncachable state. - return; } - putDirectOffset(offset, value); + + // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); + putDirectOffset(offset, value); return; } @@ -510,7 +537,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); putDirectOffset(offset, value); - // Function transitions are not currently cachable, so leave the slot in an uncachable state. + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); } @@ -543,6 +571,11 @@ inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, u putDirectInternal(propertyName, value, attributes, false, slot, 0); } +inline void JSObject::putDirect(const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + putDirectInternal(propertyName, value, 0, false, slot, 0); +} + inline void JSObject::putDirectFunction(const Identifier& propertyName, JSCell* value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { putDirectInternal(propertyName, value, attributes, checkReadOnly, slot, value); @@ -645,6 +678,12 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu asCell()->put(exec, propertyName, value, slot); } +inline void JSValue::putDirect(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +{ + ASSERT(isCell() && isObject()); + asObject(asCell())->putDirect(propertyName, value, slot); +} + inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) { if (UNLIKELY(!isCell())) { @@ -685,6 +724,18 @@ ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) markStack.appendValues(reinterpret_cast(storage), storageSize); } +// --- JSValue inlines ---------------------------- + +ALWAYS_INLINE UString JSValue::toThisString(ExecState* exec) const +{ + return isString() ? static_cast(asCell())->value(exec) : toThisObject(exec)->toString(exec); +} + +inline JSString* JSValue::toThisJSString(ExecState* exec) const +{ + return isString() ? static_cast(asCell()) : jsString(exec, toThisObject(exec)->toString(exec)); +} + } // namespace JSC #endif // JSObject_h