X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/runtime/JSCell.cpp diff --git a/runtime/JSCell.cpp b/runtime/JSCell.cpp index 0606cd4..2c403c8 100644 --- a/runtime/JSCell.cpp +++ b/runtime/JSCell.cpp @@ -23,67 +23,39 @@ #include "config.h" #include "JSCell.h" +#include "ArrayBufferView.h" #include "JSFunction.h" #include "JSString.h" #include "JSObject.h" +#include "NumberObject.h" +#include "JSCInlines.h" #include namespace JSC { -#if defined NAN && defined INFINITY - -extern const double NaN = NAN; -extern const double Inf = INFINITY; - -#else // !(defined NAN && defined INFINITY) - -// The trick is to define the NaN and Inf globals with a different type than the declaration. -// This trick works because the mangled name of the globals does not include the type, although -// I'm not sure that's guaranteed. There could be alignment issues with this, since arrays of -// characters don't necessarily need the same alignment doubles do, but for now it seems to work. -// It would be good to figure out a 100% clean way that still avoids code that runs at init time. - -// Note, we have to use union to ensure alignment. Otherwise, NaN_Bytes can start anywhere, -// while NaN_double has to be 4-byte aligned for 32-bits. -// With -fstrict-aliasing enabled, unions are the only safe way to do type masquerading. - -static const union { - struct { - unsigned char NaN_Bytes[8]; - unsigned char Inf_Bytes[8]; - } bytes; - - struct { - double NaN_Double; - double Inf_Double; - } doubles; - -} NaNInf = { { -#if CPU(BIG_ENDIAN) - { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }, - { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } -#elif CPU(MIDDLE_ENDIAN) - { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 }, - { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } -#else - { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f }, - { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } -#endif -} } ; - -extern const double NaN = NaNInf.doubles.NaN_Double; -extern const double Inf = NaNInf.doubles.Inf_Double; - -#endif // !(defined NAN && defined INFINITY) - -const ClassInfo JSCell::s_dummyCellInfo = { "DummyCell", 0, 0, 0 }; - -bool JSCell::getUInt32(uint32_t&) const +COMPILE_ASSERT(sizeof(JSCell) == sizeof(uint64_t), jscell_is_eight_bytes); +STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSCell); + +void JSCell::destroy(JSCell* cell) +{ + cell->JSCell::~JSCell(); +} + +void JSCell::dump(PrintStream& out) const +{ + methodTable()->dumpToStream(this, out); +} + +void JSCell::dumpToStream(const JSCell* cell, PrintStream& out) +{ + out.printf("<%p, %s>", cell, cell->className()); +} + +void JSCell::copyBackingStore(JSCell*, CopyVisitor&, CopyToken) { - return false; } -bool JSCell::getString(ExecState* exec, UString&stringValue) const +bool JSCell::getString(ExecState* exec, String& stringValue) const { if (!isString()) return false; @@ -91,9 +63,9 @@ bool JSCell::getString(ExecState* exec, UString&stringValue) const return true; } -UString JSCell::getString(ExecState* exec) const +String JSCell::getString(ExecState* exec) const { - return isString() ? static_cast(this)->value(exec) : UString(); + return isString() ? static_cast(this)->value(exec) : String(); } JSObject* JSCell::getObject() @@ -106,124 +78,186 @@ const JSObject* JSCell::getObject() const return isObject() ? static_cast(this) : 0; } -CallType JSCell::getCallData(CallData&) +CallType JSCell::getCallData(JSCell*, CallData& callData) { + callData.js.functionExecutable = 0; + callData.js.scope = 0; + callData.native.function = 0; return CallTypeNone; } -ConstructType JSCell::getConstructData(ConstructData&) +ConstructType JSCell::getConstructData(JSCell*, ConstructData& constructData) { + constructData.js.functionExecutable = 0; + constructData.js.scope = 0; + constructData.native.function = 0; return ConstructTypeNone; } -bool JSCell::getOwnPropertySlot(ExecState* exec, const Identifier& identifier, PropertySlot& slot) +void JSCell::put(JSCell* cell, ExecState* exec, PropertyName identifier, JSValue value, PutPropertySlot& slot) { - // This is not a general purpose implementation of getOwnPropertySlot. - // It should only be called by JSValue::get. - // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec, exec->lexicalGlobalObject()); - slot.setBase(object); - if (!object->getPropertySlot(exec, identifier, slot)) - slot.setUndefined(); - return true; + if (cell->isString() || cell->isSymbol()) { + JSValue(cell).putToPrimitive(exec, identifier, value, slot); + return; + } + JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); + thisObject->methodTable(exec->vm())->put(thisObject, exec, identifier, value, slot); } -bool JSCell::getOwnPropertySlot(ExecState* exec, unsigned identifier, PropertySlot& slot) +void JSCell::putByIndex(JSCell* cell, ExecState* exec, unsigned identifier, JSValue value, bool shouldThrow) { - // This is not a general purpose implementation of getOwnPropertySlot. - // It should only be called by JSValue::get. - // It calls getPropertySlot, not getOwnPropertySlot. - JSObject* object = toObject(exec, exec->lexicalGlobalObject()); - slot.setBase(object); - if (!object->getPropertySlot(exec, identifier, slot)) - slot.setUndefined(); - return true; + if (cell->isString() || cell->isSymbol()) { + PutPropertySlot slot(cell, shouldThrow); + JSValue(cell).putToPrimitive(exec, Identifier::from(exec, identifier), value, slot); + return; + } + JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); + thisObject->methodTable(exec->vm())->putByIndex(thisObject, exec, identifier, value, shouldThrow); } -void JSCell::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot) +bool JSCell::deleteProperty(JSCell* cell, ExecState* exec, PropertyName identifier) { - toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value, slot); + JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); + return thisObject->methodTable(exec->vm())->deleteProperty(thisObject, exec, identifier); } -void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) +bool JSCell::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned identifier) { - toObject(exec, exec->lexicalGlobalObject())->put(exec, identifier, value); + JSObject* thisObject = cell->toObject(exec, exec->lexicalGlobalObject()); + return thisObject->methodTable(exec->vm())->deletePropertyByIndex(thisObject, exec, identifier); } -bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier) +JSValue JSCell::toThis(JSCell* cell, ExecState* exec, ECMAMode ecmaMode) { - return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); + if (ecmaMode == StrictMode) + return cell; + return cell->toObject(exec, exec->lexicalGlobalObject()); } -bool JSCell::deleteProperty(ExecState* exec, unsigned identifier) +JSValue JSCell::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const { - return toObject(exec, exec->lexicalGlobalObject())->deleteProperty(exec, identifier); + if (isString()) + return static_cast(this)->toPrimitive(exec, preferredType); + if (isSymbol()) + return static_cast(this)->toPrimitive(exec, preferredType); + return static_cast(this)->toPrimitive(exec, preferredType); } -JSObject* JSCell::toThisObject(ExecState* exec) const +bool JSCell::getPrimitiveNumber(ExecState* exec, double& number, JSValue& value) const { - return toObject(exec, exec->lexicalGlobalObject()); + if (isString()) + return static_cast(this)->getPrimitiveNumber(exec, number, value); + if (isSymbol()) + return static_cast(this)->getPrimitiveNumber(exec, number, value); + return static_cast(this)->getPrimitiveNumber(exec, number, value); +} + +double JSCell::toNumber(ExecState* exec) const +{ + if (isString()) + return static_cast(this)->toNumber(exec); + if (isSymbol()) + return static_cast(this)->toNumber(exec); + return static_cast(this)->toNumber(exec); } -JSValue JSCell::getJSNumber() +JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const { - return JSValue(); + if (isString()) + return static_cast(this)->toObject(exec, globalObject); + if (isSymbol()) + return static_cast(this)->toObject(exec, globalObject); + ASSERT(isObject()); + return jsCast(const_cast(this)); } -bool JSCell::isGetterSetter() const +void slowValidateCell(JSCell* cell) { + ASSERT_GC_OBJECT_LOOKS_VALID(cell); +} + +JSValue JSCell::defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType) +{ + RELEASE_ASSERT_NOT_REACHED(); + return jsUndefined(); +} + +bool JSCell::getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&) +{ + RELEASE_ASSERT_NOT_REACHED(); + return false; +} + +bool JSCell::getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned, PropertySlot&) +{ + RELEASE_ASSERT_NOT_REACHED(); return false; } -JSValue JSCell::toPrimitive(ExecState*, PreferredPrimitiveType) const +void JSCell::getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode) +{ + RELEASE_ASSERT_NOT_REACHED(); +} + +void JSCell::getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode) +{ + RELEASE_ASSERT_NOT_REACHED(); +} + +String JSCell::className(const JSObject*) { - ASSERT_NOT_REACHED(); - return JSValue(); + RELEASE_ASSERT_NOT_REACHED(); + return String(); } -bool JSCell::getPrimitiveNumber(ExecState*, double&, JSValue&) +const char* JSCell::className() const { - ASSERT_NOT_REACHED(); + return classInfo()->className; +} + +void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode) +{ + RELEASE_ASSERT_NOT_REACHED(); +} + +bool JSCell::customHasInstance(JSObject*, ExecState*, JSValue) +{ + RELEASE_ASSERT_NOT_REACHED(); return false; } -bool JSCell::toBoolean(ExecState*) const +bool JSCell::defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return false; } -double JSCell::toNumber(ExecState*) const +ArrayBuffer* JSCell::slowDownAndWasteMemory(JSArrayBufferView*) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return 0; } -UString JSCell::toString(ExecState*) const +PassRefPtr JSCell::getTypedArrayImpl(JSArrayBufferView*) { - ASSERT_NOT_REACHED(); - return UString(); + RELEASE_ASSERT_NOT_REACHED(); + return 0; } -JSObject* JSCell::toObject(ExecState*, JSGlobalObject*) const +uint32_t JSCell::getEnumerableLength(ExecState*, JSObject*) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return 0; } -bool isZombie(const JSCell* cell) +void JSCell::getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode) { -#if ENABLE(JSC_ZOMBIES) - return cell && cell->isZombie(); -#else - UNUSED_PARAM(cell); - return false; -#endif + RELEASE_ASSERT_NOT_REACHED(); } -void slowValidateCell(JSCell* cell) +void JSCell::getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode) { - ASSERT_GC_OBJECT_LOOKS_VALID(cell); + RELEASE_ASSERT_NOT_REACHED(); } } // namespace JSC