X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/a253471d7f8e4d91bf6ebabab00155c3b387d3d0..93a3786624b2768d89bfa27e46598dc64e2fb70a:/runtime/JSGlobalData.cpp?ds=inline diff --git a/runtime/JSGlobalData.cpp b/runtime/JSGlobalData.cpp deleted file mode 100644 index 31ba6b4..0000000 --- a/runtime/JSGlobalData.cpp +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2008, 2011 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "JSGlobalData.h" - -#include "ArgList.h" -#include "Heap.h" -#include "CommonIdentifiers.h" -#include "DebuggerActivation.h" -#include "FunctionConstructor.h" -#include "GCActivityCallback.h" -#include "GetterSetter.h" -#include "HostCallReturnValue.h" -#include "Interpreter.h" -#include "JSActivation.h" -#include "JSAPIValueWrapper.h" -#include "JSArray.h" -#include "JSClassRef.h" -#include "JSFunction.h" -#include "JSLock.h" -#include "JSNotAnObject.h" -#include "JSPropertyNameIterator.h" -#include "JSStaticScopeObject.h" -#include "Lexer.h" -#include "Lookup.h" -#include "Nodes.h" -#include "ParserArena.h" -#include "RegExpCache.h" -#include "RegExpObject.h" -#include "StrictEvalActivation.h" -#include "StrongInlines.h" -#include -#include - -#if ENABLE(DFG_JIT) -#include "ConservativeRoots.h" -#endif - -#if ENABLE(REGEXP_TRACING) -#include "RegExp.h" -#endif - -#if USE(CF) -#include -#endif - -using namespace WTF; - -namespace JSC { - -extern const HashTable arrayConstructorTable; -extern const HashTable arrayPrototypeTable; -extern const HashTable booleanPrototypeTable; -extern const HashTable jsonTable; -extern const HashTable dateTable; -extern const HashTable dateConstructorTable; -extern const HashTable errorPrototypeTable; -extern const HashTable globalObjectTable; -extern const HashTable mathTable; -extern const HashTable numberConstructorTable; -extern const HashTable numberPrototypeTable; -JS_EXPORTDATA extern const HashTable objectConstructorTable; -extern const HashTable objectPrototypeTable; -extern const HashTable regExpTable; -extern const HashTable regExpConstructorTable; -extern const HashTable regExpPrototypeTable; -extern const HashTable stringTable; -extern const HashTable stringConstructorTable; - -#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) -static bool enableAssembler(ExecutableAllocator& executableAllocator) -{ - if (!executableAllocator.isValid() || !Options::useJIT) - return false; -#if USE(CF) - CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); - CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); - if (canUseJIT) { - return kCFBooleanTrue == canUseJIT; - CFRelease(canUseJIT); - } - CFRelease(canUseJITKey); -#endif - -#if USE(CF) || OS(UNIX) - char* canUseJITString = getenv("JavaScriptCoreUseJIT"); - return !canUseJITString || atoi(canUseJITString); -#else - return true; -#endif -} -#endif - -JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize) - : heap(this, heapSize) - , globalDataType(globalDataType) - , clientData(0) - , topCallFrame(CallFrame::noCaller()) - , arrayConstructorTable(fastNew(JSC::arrayConstructorTable)) - , arrayPrototypeTable(fastNew(JSC::arrayPrototypeTable)) - , booleanPrototypeTable(fastNew(JSC::booleanPrototypeTable)) - , dateTable(fastNew(JSC::dateTable)) - , dateConstructorTable(fastNew(JSC::dateConstructorTable)) - , errorPrototypeTable(fastNew(JSC::errorPrototypeTable)) - , globalObjectTable(fastNew(JSC::globalObjectTable)) - , jsonTable(fastNew(JSC::jsonTable)) - , mathTable(fastNew(JSC::mathTable)) - , numberConstructorTable(fastNew(JSC::numberConstructorTable)) - , numberPrototypeTable(fastNew(JSC::numberPrototypeTable)) - , objectConstructorTable(fastNew(JSC::objectConstructorTable)) - , objectPrototypeTable(fastNew(JSC::objectPrototypeTable)) - , regExpTable(fastNew(JSC::regExpTable)) - , regExpConstructorTable(fastNew(JSC::regExpConstructorTable)) - , regExpPrototypeTable(fastNew(JSC::regExpPrototypeTable)) - , stringTable(fastNew(JSC::stringTable)) - , stringConstructorTable(fastNew(JSC::stringConstructorTable)) - , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) - , propertyNames(new CommonIdentifiers(this)) - , emptyList(new MarkedArgumentBuffer) -#if ENABLE(ASSEMBLER) - , executableAllocator(*this) -#endif - , parserArena(adoptPtr(new ParserArena)) - , keywords(adoptPtr(new Keywords(this))) - , interpreter(0) - , jsArrayClassInfo(&JSArray::s_info) - , jsFinalObjectClassInfo(&JSFinalObject::s_info) -#if ENABLE(DFG_JIT) - , sizeOfLastScratchBuffer(0) -#endif - , dynamicGlobalObject(0) - , cachedUTCOffset(std::numeric_limits::quiet_NaN()) - , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) - , m_regExpCache(new RegExpCache(this)) -#if ENABLE(REGEXP_TRACING) - , m_rtTraceList(new RTTraceList()) -#endif -#ifndef NDEBUG - , exclusiveThread(0) -#endif -#if CPU(X86) && ENABLE(JIT) - , m_timeoutCount(512) -#endif -#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) - , m_canUseAssembler(enableAssembler(executableAllocator)) -#endif -#if ENABLE(GC_VALIDATION) - , m_initializingObjectClass(0) -#endif - , m_inDefineOwnProperty(false) -{ - interpreter = new Interpreter; - - // Need to be careful to keep everything consistent here - JSLockHolder lock(this); - IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); - structureStructure.set(*this, Structure::createStructure(*this)); - debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); - activationStructure.set(*this, JSActivation::createStructure(*this, 0, jsNull())); - interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull())); - terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull())); - staticScopeStructure.set(*this, JSStaticScopeObject::createStructure(*this, 0, jsNull())); - strictEvalActivationStructure.set(*this, StrictEvalActivation::createStructure(*this, 0, jsNull())); - stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull())); - notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull())); - propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull())); - getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull())); - apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull())); - scopeChainNodeStructure.set(*this, ScopeChainNode::createStructure(*this, 0, jsNull())); - executableStructure.set(*this, ExecutableBase::createStructure(*this, 0, jsNull())); - nativeExecutableStructure.set(*this, NativeExecutable::createStructure(*this, 0, jsNull())); - evalExecutableStructure.set(*this, EvalExecutable::createStructure(*this, 0, jsNull())); - programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); - functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); - regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); - structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull())); - - wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); - -#if ENABLE(JIT) - jitStubs = adoptPtr(new JITThunks(this)); -#endif - - interpreter->initialize(&llintData, this->canUseJIT()); - - initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support. - - heap.notifyIsSafeToCollect(); - - llintData.performAssertions(*this); -} - -JSGlobalData::~JSGlobalData() -{ - ASSERT(!m_apiLock.currentThreadIsHoldingLock()); - if (heap.activityCallback()) - heap.activityCallback()->didStartVMShutdown(); - heap.lastChanceToFinalize(); - - delete interpreter; -#ifndef NDEBUG - interpreter = reinterpret_cast(0xbbadbeef); -#endif - - arrayPrototypeTable->deleteTable(); - arrayConstructorTable->deleteTable(); - booleanPrototypeTable->deleteTable(); - dateTable->deleteTable(); - dateConstructorTable->deleteTable(); - errorPrototypeTable->deleteTable(); - globalObjectTable->deleteTable(); - jsonTable->deleteTable(); - mathTable->deleteTable(); - numberConstructorTable->deleteTable(); - numberPrototypeTable->deleteTable(); - objectConstructorTable->deleteTable(); - objectPrototypeTable->deleteTable(); - regExpTable->deleteTable(); - regExpConstructorTable->deleteTable(); - regExpPrototypeTable->deleteTable(); - stringTable->deleteTable(); - stringConstructorTable->deleteTable(); - - fastDelete(const_cast(arrayConstructorTable)); - fastDelete(const_cast(arrayPrototypeTable)); - fastDelete(const_cast(booleanPrototypeTable)); - fastDelete(const_cast(dateTable)); - fastDelete(const_cast(dateConstructorTable)); - fastDelete(const_cast(errorPrototypeTable)); - fastDelete(const_cast(globalObjectTable)); - fastDelete(const_cast(jsonTable)); - fastDelete(const_cast(mathTable)); - fastDelete(const_cast(numberConstructorTable)); - fastDelete(const_cast(numberPrototypeTable)); - fastDelete(const_cast(objectConstructorTable)); - fastDelete(const_cast(objectPrototypeTable)); - fastDelete(const_cast(regExpTable)); - fastDelete(const_cast(regExpConstructorTable)); - fastDelete(const_cast(regExpPrototypeTable)); - fastDelete(const_cast(stringTable)); - fastDelete(const_cast(stringConstructorTable)); - - opaqueJSClassData.clear(); - - delete emptyList; - - delete propertyNames; - if (globalDataType != Default) - deleteIdentifierTable(identifierTable); - - delete clientData; - delete m_regExpCache; -#if ENABLE(REGEXP_TRACING) - delete m_rtTraceList; -#endif - -#if ENABLE(DFG_JIT) - for (unsigned i = 0; i < scratchBuffers.size(); ++i) - fastFree(scratchBuffers[i]); -#endif -} - -PassRefPtr JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize) -{ - return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize)); -} - -PassRefPtr JSGlobalData::create(ThreadStackType type, HeapSize heapSize) -{ - return adoptRef(new JSGlobalData(Default, type, heapSize)); -} - -PassRefPtr JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize) -{ - return create(type, heapSize); -} - -bool JSGlobalData::sharedInstanceExists() -{ - return sharedInstanceInternal(); -} - -JSGlobalData& JSGlobalData::sharedInstance() -{ - GlobalJSLock globalLock; - JSGlobalData*& instance = sharedInstanceInternal(); - if (!instance) { - instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall, SmallHeap)).leakRef(); - instance->makeUsableFromMultipleThreads(); - } - return *instance; -} - -JSGlobalData*& JSGlobalData::sharedInstanceInternal() -{ - static JSGlobalData* sharedInstance; - return sharedInstance; -} - -#if ENABLE(JIT) -static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic) -{ - switch (intrinsic) { - case CharCodeAtIntrinsic: - return charCodeAtThunkGenerator; - case CharAtIntrinsic: - return charAtThunkGenerator; - case FromCharCodeIntrinsic: - return fromCharCodeThunkGenerator; - case SqrtIntrinsic: - return sqrtThunkGenerator; - case PowIntrinsic: - return powThunkGenerator; - case AbsIntrinsic: - return absThunkGenerator; - case FloorIntrinsic: - return floorThunkGenerator; - case CeilIntrinsic: - return ceilThunkGenerator; - case RoundIntrinsic: - return roundThunkGenerator; - case ExpIntrinsic: - return expThunkGenerator; - case LogIntrinsic: - return logThunkGenerator; - default: - return 0; - } -} - -NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor) -{ -#if ENABLE(CLASSIC_INTERPRETER) - if (!canUseJIT()) - return NativeExecutable::create(*this, function, constructor); -#endif - return jitStubs->hostFunctionStub(this, function, constructor); -} -NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic) -{ - ASSERT(canUseJIT()); - return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic); -} -#else -NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor) -{ - return NativeExecutable::create(*this, function, constructor); -} -#endif - -JSGlobalData::ClientData::~ClientData() -{ -} - -void JSGlobalData::resetDateCache() -{ - cachedUTCOffset = std::numeric_limits::quiet_NaN(); - dstOffsetCache.reset(); - cachedDateString = UString(); - cachedDateStringValue = std::numeric_limits::quiet_NaN(); - dateInstanceCache.reset(); -} - -void JSGlobalData::startSampling() -{ - interpreter->startSampling(); -} - -void JSGlobalData::stopSampling() -{ - interpreter->stopSampling(); -} - -void JSGlobalData::dumpSampleData(ExecState* exec) -{ - interpreter->dumpSampleData(exec); -#if ENABLE(ASSEMBLER) - ExecutableAllocator::dumpProfile(); -#endif -} - -struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor { - HashSet currentlyExecutingFunctions; - void operator()(JSCell* cell) - { - if (!cell->inherits(&FunctionExecutable::s_info)) - return; - FunctionExecutable* executable = jsCast(cell); - if (currentlyExecutingFunctions.contains(executable)) - return; - executable->discardCode(); - } -}; - -void JSGlobalData::releaseExecutableMemory() -{ - if (dynamicGlobalObject) { - StackPreservingRecompiler recompiler; - HashSet roots; - heap.getConservativeRegisterRoots(roots); - HashSet::iterator end = roots.end(); - for (HashSet::iterator ptr = roots.begin(); ptr != end; ++ptr) { - ScriptExecutable* executable = 0; - JSCell* cell = *ptr; - if (cell->inherits(&ScriptExecutable::s_info)) - executable = static_cast(*ptr); - else if (cell->inherits(&JSFunction::s_info)) { - JSFunction* function = jsCast(*ptr); - if (function->isHostFunction()) - continue; - executable = function->jsExecutable(); - } else - continue; - ASSERT(executable->inherits(&ScriptExecutable::s_info)); - executable->unlinkCalls(); - if (executable->inherits(&FunctionExecutable::s_info)) - recompiler.currentlyExecutingFunctions.add(static_cast(executable)); - - } - heap.objectSpace().forEachCell(recompiler); - } - m_regExpCache->invalidateCode(); - heap.collectAllGarbage(); -} - -#if ENABLE(ASSEMBLER) -void releaseExecutableMemory(JSGlobalData& globalData) -{ - globalData.releaseExecutableMemory(); -} -#endif - -#if ENABLE(DFG_JIT) -void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots) -{ - for (size_t i = 0; i < scratchBuffers.size(); i++) { - ScratchBuffer* scratchBuffer = scratchBuffers[i]; - if (scratchBuffer->activeLength()) { - void* bufferStart = scratchBuffer->dataBuffer(); - conservativeRoots.add(bufferStart, static_cast(static_cast(bufferStart) + scratchBuffer->activeLength())); - } - } -} -#endif - -#if ENABLE(REGEXP_TRACING) -void JSGlobalData::addRegExpToTrace(RegExp* regExp) -{ - m_rtTraceList->add(regExp); -} - -void JSGlobalData::dumpRegExpTrace() -{ - // The first RegExp object is ignored. It is create by the RegExpPrototype ctor and not used. - RTTraceList::iterator iter = ++m_rtTraceList->begin(); - - if (iter != m_rtTraceList->end()) { - dataLog("\nRegExp Tracing\n"); - dataLog(" match() matches\n"); - dataLog("Regular Expression JIT Address calls found\n"); - dataLog("----------------------------------------+----------------+----------+----------\n"); - - unsigned reCount = 0; - - for (; iter != m_rtTraceList->end(); ++iter, ++reCount) - (*iter)->printTraceData(); - - dataLog("%d Regular Expressions\n", reCount); - } - - m_rtTraceList->clear(); -} -#else -void JSGlobalData::dumpRegExpTrace() -{ -} -#endif - -} // namespace JSC