]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/JSGlobalData.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / runtime / JSGlobalData.cpp
index 41b841e454a515f98559a93c2ded524a11ce2ec9..31ba6b4915ac744bcf987bac8b4d017df9e7f0be 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * 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
 #include "JSGlobalData.h"
 
 #include "ArgList.h"
-#include "Collector.h"
-#include "CollectorHeapIterator.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 "JSByteArray.h"
 #include "JSClassRef.h"
 #include "JSFunction.h"
 #include "JSLock.h"
 #include "Lexer.h"
 #include "Lookup.h"
 #include "Nodes.h"
-#include "Parser.h"
+#include "ParserArena.h"
 #include "RegExpCache.h"
+#include "RegExpObject.h"
+#include "StrictEvalActivation.h"
+#include "StrongInlines.h"
+#include <wtf/Threading.h>
 #include <wtf/WTFThreadData.h>
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-#include <wtf/Threading.h>
+#if ENABLE(DFG_JIT)
+#include "ConservativeRoots.h"
 #endif
 
-#if PLATFORM(MAC)
-#include "ProfilerServer.h"
+#if ENABLE(REGEXP_TRACING)
+#include "RegExp.h"
+#endif
+
+#if USE(CF)
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
@@ -66,151 +74,199 @@ using namespace WTF;
 
 namespace JSC {
 
-extern JSC_CONST_HASHTABLE HashTable arrayTable;
-extern JSC_CONST_HASHTABLE HashTable jsonTable;
-extern JSC_CONST_HASHTABLE HashTable dateTable;
-extern JSC_CONST_HASHTABLE HashTable mathTable;
-extern JSC_CONST_HASHTABLE HashTable numberTable;
-extern JSC_CONST_HASHTABLE HashTable regExpTable;
-extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
-extern JSC_CONST_HASHTABLE HashTable stringTable;
-
-void* JSGlobalData::jsArrayVPtr;
-void* JSGlobalData::jsByteArrayVPtr;
-void* JSGlobalData::jsStringVPtr;
-void* JSGlobalData::jsFunctionVPtr;
-
-void JSGlobalData::storeVPtrs()
+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)
 {
-    CollectorCell cell;
-    void* storage = &cell;
-
-    COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
-    JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
-    JSGlobalData::jsArrayVPtr = jsArray->vptr();
-    jsArray->~JSCell();
-
-    COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
-    JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
-    JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
-    jsByteArray->~JSCell();
-
-    COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
-    JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
-    JSGlobalData::jsStringVPtr = jsString->vptr();
-    jsString->~JSCell();
-
-    COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
-    JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
-    JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
-    jsFunction->~JSCell();
+    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)
-    : globalDataType(globalDataType)
+JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize)
+    : heap(this, heapSize)
+    , globalDataType(globalDataType)
     , clientData(0)
-    , arrayTable(fastNew<HashTable>(JSC::arrayTable))
+    , topCallFrame(CallFrame::noCaller())
+    , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
+    , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
+    , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
     , dateTable(fastNew<HashTable>(JSC::dateTable))
+    , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
+    , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
+    , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
     , jsonTable(fastNew<HashTable>(JSC::jsonTable))
     , mathTable(fastNew<HashTable>(JSC::mathTable))
-    , numberTable(fastNew<HashTable>(JSC::numberTable))
+    , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
+    , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
+    , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
+    , objectPrototypeTable(fastNew<HashTable>(JSC::objectPrototypeTable))
     , regExpTable(fastNew<HashTable>(JSC::regExpTable))
     , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
+    , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
     , stringTable(fastNew<HashTable>(JSC::stringTable))
-    , activationStructure(JSActivation::createStructure(jsNull()))
-    , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
-    , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
-    , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
-    , stringStructure(JSString::createStructure(jsNull()))
-    , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
-    , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
-    , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
-    , getterSetterStructure(GetterSetter::createStructure(jsNull()))
-    , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
-    , dummyMarkableCellStructure(JSCell::createDummyStructure())
-#if USE(JSVALUE32)
-    , numberStructure(JSNumberCell::createStructure(jsNull()))
-#endif
+    , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
     , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
     , propertyNames(new CommonIdentifiers(this))
     , emptyList(new MarkedArgumentBuffer)
-    , lexer(new Lexer(this))
-    , parser(new Parser)
-    , interpreter(new Interpreter)
-    , heap(this)
-    , initializingLazyNumericCompareFunction(false)
-    , head(0)
+#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)
-    , functionCodeBlockBeingReparsed(0)
-    , firstStringifierToMark(0)
-    , markStack(jsArrayVPtr)
-    , cachedUTCOffset(NaN)
+    , cachedUTCOffset(std::numeric_limits<double>::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 PLATFORM(MAC)
-    startProfilerServerIfNeeded();
+#if CPU(X86) && ENABLE(JIT)
+    , m_timeoutCount(512)
 #endif
-#if ENABLE(JIT) && ENABLE(INTERPRETER)
-#if PLATFORM(CF)
-    CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
-    CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
-    if (canUseJIT) {
-        m_canUseJIT = kCFBooleanTrue == canUseJIT;
-        CFRelease(canUseJIT);
-    } else
-        m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
-    CFRelease(canUseJITKey);
-#elif OS(UNIX)
-    m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
-#else
-    m_canUseJIT = true;
+#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)
-#if ENABLE(INTERPRETER)
-    if (m_canUseJIT)
-        m_canUseJIT = executableAllocator.isValid();
-#endif
-    jitStubs.set(new JITThunks(this));
+    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()
 {
-    // By the time this is destroyed, heap.destroy() must already have been called.
+    ASSERT(!m_apiLock.currentThreadIsHoldingLock());
+    if (heap.activityCallback())
+        heap.activityCallback()->didStartVMShutdown();
+    heap.lastChanceToFinalize();
 
     delete interpreter;
 #ifndef NDEBUG
-    // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
-    interpreter = 0;
+    interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef);
 #endif
 
-    arrayTable->deleteTable();
+    arrayPrototypeTable->deleteTable();
+    arrayConstructorTable->deleteTable();
+    booleanPrototypeTable->deleteTable();
     dateTable->deleteTable();
+    dateConstructorTable->deleteTable();
+    errorPrototypeTable->deleteTable();
+    globalObjectTable->deleteTable();
     jsonTable->deleteTable();
     mathTable->deleteTable();
-    numberTable->deleteTable();
+    numberConstructorTable->deleteTable();
+    numberPrototypeTable->deleteTable();
+    objectConstructorTable->deleteTable();
+    objectPrototypeTable->deleteTable();
     regExpTable->deleteTable();
     regExpConstructorTable->deleteTable();
+    regExpPrototypeTable->deleteTable();
     stringTable->deleteTable();
+    stringConstructorTable->deleteTable();
 
-    fastDelete(const_cast<HashTable*>(arrayTable));
+    fastDelete(const_cast<HashTable*>(arrayConstructorTable));
+    fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
+    fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
     fastDelete(const_cast<HashTable*>(dateTable));
+    fastDelete(const_cast<HashTable*>(dateConstructorTable));
+    fastDelete(const_cast<HashTable*>(errorPrototypeTable));
+    fastDelete(const_cast<HashTable*>(globalObjectTable));
     fastDelete(const_cast<HashTable*>(jsonTable));
     fastDelete(const_cast<HashTable*>(mathTable));
-    fastDelete(const_cast<HashTable*>(numberTable));
+    fastDelete(const_cast<HashTable*>(numberConstructorTable));
+    fastDelete(const_cast<HashTable*>(numberPrototypeTable));
+    fastDelete(const_cast<HashTable*>(objectConstructorTable));
+    fastDelete(const_cast<HashTable*>(objectPrototypeTable));
     fastDelete(const_cast<HashTable*>(regExpTable));
     fastDelete(const_cast<HashTable*>(regExpConstructorTable));
+    fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
     fastDelete(const_cast<HashTable*>(stringTable));
+    fastDelete(const_cast<HashTable*>(stringConstructorTable));
 
-    delete parser;
-    delete lexer;
-
-    deleteAllValues(opaqueJSClassData);
+    opaqueJSClassData.clear();
 
     delete emptyList;
 
@@ -220,24 +276,29 @@ JSGlobalData::~JSGlobalData()
 
     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> JSGlobalData::createContextGroup(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type, HeapSize heapSize)
 {
-    return adoptRef(new JSGlobalData(APIContextGroup, type));
+    return adoptRef(new JSGlobalData(APIContextGroup, type, heapSize));
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type, HeapSize heapSize)
 {
-    return adoptRef(new JSGlobalData(Default, type));
+    return adoptRef(new JSGlobalData(Default, type, heapSize));
 }
 
-PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
+PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type, HeapSize heapSize)
 {
-    Structure::startIgnoringLeaks();
-    RefPtr<JSGlobalData> data = create(type);
-    Structure::stopIgnoringLeaks();
-    return data.release();
+    return create(type, heapSize);
 }
 
 bool JSGlobalData::sharedInstanceExists()
@@ -247,35 +308,71 @@ bool JSGlobalData::sharedInstanceExists()
 
 JSGlobalData& JSGlobalData::sharedInstance()
 {
+    GlobalJSLock globalLock;
     JSGlobalData*& instance = sharedInstanceInternal();
     if (!instance) {
-        instance = new JSGlobalData(APIShared, ThreadStackTypeSmall);
-#if ENABLE(JSC_MULTIPLE_THREADS)
+        instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall, SmallHeap)).leakRef();
         instance->makeUsableFromMultipleThreads();
-#endif
     }
     return *instance;
 }
 
 JSGlobalData*& JSGlobalData::sharedInstanceInternal()
 {
-    ASSERT(JSLock::currentThreadIsHoldingLock());
     static JSGlobalData* sharedInstance;
     return sharedInstance;
 }
 
-// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
-const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
+#if ENABLE(JIT)
+static ThunkGenerator thunkGeneratorForIntrinsic(Intrinsic intrinsic)
 {
-    if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
-        initializingLazyNumericCompareFunction = true;
-        RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
-        lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions();
-        initializingLazyNumericCompareFunction = false;
+    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;
     }
+}
 
-    return lazyNumericCompareFunction;
+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()
 {
@@ -283,9 +380,10 @@ JSGlobalData::ClientData::~ClientData()
 
 void JSGlobalData::resetDateCache()
 {
-    cachedUTCOffset = NaN;
+    cachedUTCOffset = std::numeric_limits<double>::quiet_NaN();
     dstOffsetCache.reset();
     cachedDateString = UString();
+    cachedDateStringValue = std::numeric_limits<double>::quiet_NaN();
     dateInstanceCache.reset();
 }
 
@@ -302,23 +400,106 @@ void JSGlobalData::stopSampling()
 void JSGlobalData::dumpSampleData(ExecState* exec)
 {
     interpreter->dumpSampleData(exec);
+#if ENABLE(ASSEMBLER)
+    ExecutableAllocator::dumpProfile();
+#endif
+}
+
+struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
+    HashSet<FunctionExecutable*> currentlyExecutingFunctions;
+    void operator()(JSCell* cell)
+    {
+        if (!cell->inherits(&FunctionExecutable::s_info))
+            return;
+        FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
+        if (currentlyExecutingFunctions.contains(executable))
+            return;
+        executable->discardCode();
+    }
+};
+
+void JSGlobalData::releaseExecutableMemory()
+{
+    if (dynamicGlobalObject) {
+        StackPreservingRecompiler recompiler;
+        HashSet<JSCell*> roots;
+        heap.getConservativeRegisterRoots(roots);
+        HashSet<JSCell*>::iterator end = roots.end();
+        for (HashSet<JSCell*>::iterator ptr = roots.begin(); ptr != end; ++ptr) {
+            ScriptExecutable* executable = 0;
+            JSCell* cell = *ptr;
+            if (cell->inherits(&ScriptExecutable::s_info))
+                executable = static_cast<ScriptExecutable*>(*ptr);
+            else if (cell->inherits(&JSFunction::s_info)) {
+                JSFunction* function = jsCast<JSFunction*>(*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<FunctionExecutable*>(executable));
+                
+        }
+        heap.objectSpace().forEachCell<StackPreservingRecompiler>(recompiler);
+    }
+    m_regExpCache->invalidateCode();
+    heap.collectAllGarbage();
 }
 
-void JSGlobalData::recompileAllJSFunctions()
+#if ENABLE(ASSEMBLER)
+void releaseExecutableMemory(JSGlobalData& globalData)
+{
+    globalData.releaseExecutableMemory();
+}
+#endif
+
+#if ENABLE(DFG_JIT)
+void JSGlobalData::gatherConservativeRoots(ConservativeRoots& conservativeRoots)
 {
-    // If JavaScript is running, it's not safe to recompile, since we'll end
-    // up throwing away code that is live on the stack.
-    ASSERT(!dynamicGlobalObject);
-
-    LiveObjectIterator it = heap.primaryHeapBegin();
-    LiveObjectIterator heapEnd = heap.primaryHeapEnd();
-    for ( ; it != heapEnd; ++it) {
-        if ((*it)->inherits(&JSFunction::info)) {
-            JSFunction* function = asFunction(*it);
-            if (!function->executable()->isHostFunction())
-                function->jsExecutable()->recompile();
+    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<void*>(static_cast<char*>(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