X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..refs/heads/master:/API/JSClassRef.cpp diff --git a/API/JSClassRef.cpp b/API/JSClassRef.cpp index 08dc721..e0dbe60 100644 --- a/API/JSClassRef.cpp +++ b/API/JSClassRef.cpp @@ -10,10 +10,10 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR @@ -27,12 +27,13 @@ #include "JSClassRef.h" #include "APICast.h" +#include "Identifier.h" +#include "InitializeThreading.h" #include "JSCallbackObject.h" +#include "JSGlobalObject.h" #include "JSObjectRef.h" -#include -#include -#include -#include +#include "ObjectPrototype.h" +#include "JSCInlines.h" #include #include @@ -42,20 +43,6 @@ using namespace WTF::Unicode; const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static inline UString tryCreateStringFromUTF8(const char* string) -{ - if (!string) - return UString(); - - size_t length = strlen(string); - Vector buffer(length); - UChar* p = buffer.data(); - if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) - return UString(); - - return UString(buffer.data(), p - buffer.data()); -} - OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* protoClass) : parentClass(definition->parentClass) , prototypeClass(0) @@ -70,40 +57,26 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* , callAsConstructor(definition->callAsConstructor) , hasInstance(definition->hasInstance) , convertToType(definition->convertToType) - , m_className(tryCreateStringFromUTF8(definition->className)) - , m_staticValues(0) - , m_staticFunctions(0) + , m_className(String::fromUTF8(definition->className)) { initializeThreading(); if (const JSStaticValue* staticValue = definition->staticValues) { - m_staticValues = new OpaqueJSClassStaticValuesTable(); + m_staticValues = std::make_unique(); while (staticValue->name) { - UString valueName = tryCreateStringFromUTF8(staticValue->name); - if (!valueName.isNull()) { - // Use a local variable here to sidestep an RVCT compiler bug. - StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); - StringImpl* impl = valueName.impl(); - StaticValueEntry* existingEntry = m_staticValues->get(impl); - m_staticValues->set(impl, entry); - delete existingEntry; - } + String valueName = String::fromUTF8(staticValue->name); + if (!valueName.isNull()) + m_staticValues->set(valueName.impl(), std::make_unique(staticValue->getProperty, staticValue->setProperty, staticValue->attributes, valueName)); ++staticValue; } } if (const JSStaticFunction* staticFunction = definition->staticFunctions) { - m_staticFunctions = new OpaqueJSClassStaticFunctionsTable(); + m_staticFunctions = std::make_unique(); while (staticFunction->name) { - UString functionName = tryCreateStringFromUTF8(staticFunction->name); - if (!functionName.isNull()) { - // Use a local variable here to sidestep an RVCT compiler bug. - StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); - StringImpl* impl = functionName.impl(); - StaticFunctionEntry* existingEntry = m_staticFunctions->get(impl); - m_staticFunctions->set(impl, entry); - delete existingEntry; - } + String functionName = String::fromUTF8(staticFunction->name); + if (!functionName.isNull()) + m_staticFunctions->set(functionName.impl(), std::make_unique(staticFunction->callAsFunction, staticFunction->attributes)); ++staticFunction; } } @@ -115,36 +88,32 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* OpaqueJSClass::~OpaqueJSClass() { // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below. - ASSERT(!m_className.length() || !m_className.impl()->isIdentifier()); + ASSERT(!m_className.length() || !m_className.impl()->isAtomic()); +#ifndef NDEBUG if (m_staticValues) { OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end(); - for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->isIdentifier()); - delete it->second; - } - delete m_staticValues; + for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) + ASSERT(!it->key->isAtomic()); } if (m_staticFunctions) { OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end(); - for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->isIdentifier()); - delete it->second; - } - delete m_staticFunctions; + for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) + ASSERT(!it->key->isAtomic()); } +#endif if (prototypeClass) JSClassRelease(prototypeClass); } -PassRefPtr OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition) +Ref OpaqueJSClass::createNoAutomaticPrototype(const JSClassDefinition* definition) { - return adoptRef(new OpaqueJSClass(definition, 0)); + return adoptRef(*new OpaqueJSClass(definition, 0)); } -PassRefPtr OpaqueJSClass::create(const JSClassDefinition* clientDefinition) +Ref OpaqueJSClass::create(const JSClassDefinition* clientDefinition) { JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy. @@ -155,75 +124,54 @@ PassRefPtr OpaqueJSClass::create(const JSClassDefinition* clientD // We are supposed to use JSClassRetain/Release but since we know that we currently have // the only reference to this class object we cheat and use a RefPtr instead. RefPtr protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0)); - return adoptRef(new OpaqueJSClass(&definition, protoClass.get())); + return adoptRef(*new OpaqueJSClass(&definition, protoClass.get())); } -OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSClass* jsClass) +OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::VM&, OpaqueJSClass* jsClass) : m_class(jsClass) { if (jsClass->m_staticValues) { - staticValues = new OpaqueJSClassStaticValuesTable; + staticValues = std::make_unique(); OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end(); for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->isIdentifier()); - // Use a local variable here to sidestep an RVCT compiler bug. - StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes); - staticValues->add(StringImpl::create(it->first->characters(), it->first->length()), entry); + ASSERT(!it->key->isAtomic()); + String valueName = it->key->isolatedCopy(); + staticValues->add(valueName.impl(), std::make_unique(it->value->getProperty, it->value->setProperty, it->value->attributes, valueName)); } - } else - staticValues = 0; + } if (jsClass->m_staticFunctions) { - staticFunctions = new OpaqueJSClassStaticFunctionsTable; + staticFunctions = std::make_unique(); OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end(); for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->isIdentifier()); - // Use a local variable here to sidestep an RVCT compiler bug. - StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes); - staticFunctions->add(StringImpl::create(it->first->characters(), it->first->length()), entry); + ASSERT(!it->key->isAtomic()); + staticFunctions->add(it->key->isolatedCopy(), std::make_unique(it->value->callAsFunction, it->value->attributes)); } - - } else - staticFunctions = 0; -} - -OpaqueJSClassContextData::~OpaqueJSClassContextData() -{ - if (staticValues) { - deleteAllValues(*staticValues); - delete staticValues; - } - - if (staticFunctions) { - deleteAllValues(*staticFunctions); - delete staticFunctions; } } OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec) { - OpaqueJSClassContextData*& contextData = exec->globalData().opaqueJSClassData.add(this, 0).first->second; + std::unique_ptr& contextData = exec->lexicalGlobalObject()->opaqueJSClassData().add(this, nullptr).iterator->value; if (!contextData) - contextData = new OpaqueJSClassContextData(exec->globalData(), this); + contextData = std::make_unique(exec->vm(), this); return *contextData; } -UString OpaqueJSClass::className() +String OpaqueJSClass::className() { - // Make a deep copy, so that the caller has no chance to put the original into IdentifierTable. - return UString(m_className.characters(), m_className.length()); + // Make a deep copy, so that the caller has no chance to put the original into AtomicStringTable. + return m_className.isolatedCopy(); } OpaqueJSClassStaticValuesTable* OpaqueJSClass::staticValues(JSC::ExecState* exec) { - OpaqueJSClassContextData& jsClassData = contextData(exec); - return jsClassData.staticValues; + return contextData(exec).staticValues.get(); } OpaqueJSClassStaticFunctionsTable* OpaqueJSClass::staticFunctions(JSC::ExecState* exec) { - OpaqueJSClassContextData& jsClassData = contextData(exec); - return jsClassData.staticFunctions; + return contextData(exec).staticFunctions.get(); } /*! @@ -243,19 +191,22 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) * | | | * DerivedClass | DerivedClassPrototype */ - + if (!prototypeClass) return 0; OpaqueJSClassContextData& jsClassData = contextData(exec); - if (!jsClassData.cachedPrototype) { - // Recursive, but should be good enough for our purposes - jsClassData.cachedPrototype.set(exec->globalData(), new (exec) JSCallbackObject(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction - if (parentClass) { - if (JSObject* prototype = parentClass->prototype(exec)) - jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype); - } + if (JSObject* prototype = jsClassData.cachedPrototype.get()) + return prototype; + + // Recursive, but should be good enough for our purposes + JSObject* prototype = JSCallbackObject::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData); // set jsClassData as the object's private data, so it can clear our reference on destruction + if (parentClass) { + if (JSObject* parentPrototype = parentClass->prototype(exec)) + prototype->setPrototype(exec->vm(), parentPrototype); } - return jsClassData.cachedPrototype.get(); + + jsClassData.cachedPrototype = Weak(prototype); + return prototype; }