JSGlobalData.cpp 19.8 KB
Newer Older
ap@webkit.org's avatar
ap@webkit.org committed
1
/*
2
 * Copyright (C) 2008, 2011 Apple Inc. All rights reserved.
ap@webkit.org's avatar
ap@webkit.org committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * 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"

weinig@apple.com's avatar
weinig@apple.com committed
32
#include "ArgList.h"
33
#include "CodeCache.h"
ap@webkit.org's avatar
ap@webkit.org committed
34
#include "CommonIdentifiers.h"
35
#include "DFGLongLivedState.h"
36
#include "DebuggerActivation.h"
ggaren@apple.com's avatar
ggaren@apple.com committed
37
#include "FunctionConstructor.h"
38
#include "GCActivityCallback.h"
39
#include "GetterSetter.h"
40
#include "Heap.h"
41
#include "HostCallReturnValue.h"
42
#include "IncrementalSweeper.h"
43
#include "Interpreter.h"
mjs@apple.com's avatar
mjs@apple.com committed
44
#include "JSActivation.h"
45
#include "JSAPIValueWrapper.h"
46
#include "JSArray.h"
47
#include "JSFunction.h"
ap@webkit.org's avatar
ap@webkit.org committed
48
#include "JSLock.h"
49
#include "JSNameScope.h"
darin@apple.com's avatar
darin@apple.com committed
50
#include "JSNotAnObject.h"
51
#include "JSPropertyNameIterator.h"
52
#include "JSWithScope.h"
53
#include "Lexer.h"
54
#include "Lookup.h"
55
#include "Nodes.h"
56
#include "ParserArena.h"
57 58
#include "RegExpCache.h"
#include "RegExpObject.h"
59
#include "SourceProviderCache.h"
60
#include "StrictEvalActivation.h"
61
#include "StrongInlines.h"
62
#include "UnlinkedCodeBlock.h"
63
#include <wtf/RetainPtr.h>
ap@webkit.org's avatar
ap@webkit.org committed
64
#include <wtf/Threading.h>
65
#include <wtf/WTFThreadData.h>
66

67 68 69 70
#if ENABLE(DFG_JIT)
#include "ConservativeRoots.h"
#endif

71 72 73 74
#if ENABLE(REGEXP_TRACING)
#include "RegExp.h"
#endif

75
#if USE(CF)
76
#include <CoreFoundation/CoreFoundation.h>
77 78
#endif

ap@webkit.org's avatar
ap@webkit.org committed
79 80
using namespace WTF;

81
namespace JSC {
ap@webkit.org's avatar
ap@webkit.org committed
82

83 84 85 86 87 88 89 90 91 92 93
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;
94
JS_EXPORTDATA extern const HashTable objectConstructorTable;
95
extern const HashTable privateNamePrototypeTable;
96 97 98 99
extern const HashTable regExpTable;
extern const HashTable regExpConstructorTable;
extern const HashTable regExpPrototypeTable;
extern const HashTable stringConstructorTable;
ap@webkit.org's avatar
ap@webkit.org committed
100

101 102 103 104 105
// Note: Platform.h will enforce that ENABLE(ASSEMBLER) is true if either
// ENABLE(JIT) or ENABLE(YARR_JIT) or both are enabled. The code below
// just checks for ENABLE(JIT) or ENABLE(YARR_JIT) with this premise in mind.

#if ENABLE(ASSEMBLER)
106 107
static bool enableAssembler(ExecutableAllocator& executableAllocator)
{
108
    if (!executableAllocator.isValid() || (!Options::useJIT() && !Options::useRegExpJIT()))
109 110 111
        return false;

#if USE(CF)
112 113 114 115 116 117 118 119 120
#if COMPILER(GCC) && !COMPILER(CLANG)
    // FIXME: remove this once the EWS have been upgraded to LLVM.
    // Work around a bug of GCC with strict-aliasing.
    RetainPtr<CFStringRef> canUseJITKeyRetain(AdoptCF, CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman));
    CFStringRef canUseJITKey = canUseJITKeyRetain.get();
#else
    CFStringRef canUseJITKey = CFSTR("JavaScriptCoreUseJIT");
#endif // COMPILER(GCC) && !COMPILER(CLANG)
    RetainPtr<CFBooleanRef> canUseJIT(AdoptCF, (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication));
121
    if (canUseJIT)
122
        return kCFBooleanTrue == canUseJIT.get();
123 124 125 126 127 128 129 130 131
#endif

#if USE(CF) || OS(UNIX)
    char* canUseJITString = getenv("JavaScriptCoreUseJIT");
    return !canUseJITString || atoi(canUseJITString);
#else
    return true;
#endif
}
132
#endif // ENABLE(!ASSEMBLER)
133

134
JSGlobalData::JSGlobalData(GlobalDataType globalDataType, HeapType heapType)
135 136 137 138 139
    :
#if ENABLE(ASSEMBLER)
      executableAllocator(*this),
#endif
      heap(this, heapType)
140
    , globalDataType(globalDataType)
ggaren@apple.com's avatar
ggaren@apple.com committed
141
    , clientData(0)
142
    , topCallFrame(CallFrame::noCaller())
143 144 145
    , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable))
    , arrayPrototypeTable(fastNew<HashTable>(JSC::arrayPrototypeTable))
    , booleanPrototypeTable(fastNew<HashTable>(JSC::booleanPrototypeTable))
146
    , dateTable(fastNew<HashTable>(JSC::dateTable))
147 148 149
    , dateConstructorTable(fastNew<HashTable>(JSC::dateConstructorTable))
    , errorPrototypeTable(fastNew<HashTable>(JSC::errorPrototypeTable))
    , globalObjectTable(fastNew<HashTable>(JSC::globalObjectTable))
150
    , jsonTable(fastNew<HashTable>(JSC::jsonTable))
151
    , mathTable(fastNew<HashTable>(JSC::mathTable))
152 153
    , numberConstructorTable(fastNew<HashTable>(JSC::numberConstructorTable))
    , numberPrototypeTable(fastNew<HashTable>(JSC::numberPrototypeTable))
154
    , objectConstructorTable(fastNew<HashTable>(JSC::objectConstructorTable))
155
    , privateNamePrototypeTable(fastNew<HashTable>(JSC::privateNamePrototypeTable))
156 157
    , regExpTable(fastNew<HashTable>(JSC::regExpTable))
    , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
158 159
    , regExpPrototypeTable(fastNew<HashTable>(JSC::regExpPrototypeTable))
    , stringConstructorTable(fastNew<HashTable>(JSC::stringConstructorTable))
160
    , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
ap@webkit.org's avatar
ap@webkit.org committed
161
    , propertyNames(new CommonIdentifiers(this))
162
    , emptyList(new MarkedArgumentBuffer)
163 164
    , parserArena(adoptPtr(new ParserArena))
    , keywords(adoptPtr(new Keywords(this)))
165
    , interpreter(0)
166 167
    , jsArrayClassInfo(&JSArray::s_info)
    , jsFinalObjectClassInfo(&JSFinalObject::s_info)
168
#if ENABLE(DFG_JIT)
169
    , sizeOfLastScratchBuffer(0)
170
#endif
171
    , dynamicGlobalObject(0)
172
    , cachedUTCOffset(QNaN)
173
    , m_enabledProfiler(0)
174
    , m_regExpCache(new RegExpCache(this))
175 176 177
#if ENABLE(REGEXP_TRACING)
    , m_rtTraceList(new RTTraceList())
#endif
ap@apple.com's avatar
ap@apple.com committed
178
#ifndef NDEBUG
179
    , exclusiveThread(0)
ap@apple.com's avatar
ap@apple.com committed
180
#endif
181 182 183
#if CPU(X86) && ENABLE(JIT)
    , m_timeoutCount(512)
#endif
184
    , m_newStringsSinceLastHashCons(0)
185
#if ENABLE(ASSEMBLER)
186
    , m_canUseAssembler(enableAssembler(executableAllocator))
187 188
#endif
#if ENABLE(JIT)
189
    , m_canUseJIT(m_canUseAssembler && Options::useJIT())
190 191
#endif
#if ENABLE(YARR_JIT)
192
    , m_canUseRegExpJIT(m_canUseAssembler && Options::useRegExpJIT())
193
#endif
194
#if ENABLE(GC_VALIDATION)
195
    , m_initializingObjectClass(0)
196
#endif
197
    , m_inDefineOwnProperty(false)
198
    , m_codeCache(CodeCache::create())
ap@webkit.org's avatar
ap@webkit.org committed
199
{
200
    interpreter = new Interpreter(*this);
201

202
    // Need to be careful to keep everything consistent here
203
    JSLockHolder lock(this);
204 205
    IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
    structureStructure.set(*this, Structure::createStructure(*this));
206
    structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
207
    debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
208 209
    interruptedExecutionErrorStructure.set(*this, InterruptedExecutionError::createStructure(*this, 0, jsNull()));
    terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
210 211 212 213 214
    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()));
ggaren@apple.com's avatar
ggaren@apple.com committed
215
    JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull()));
216 217 218 219 220 221
    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()));
222
    sharedSymbolTableStructure.set(*this, SharedSymbolTable::createStructure(*this, 0, jsNull()));
223
    structureChainStructure.set(*this, StructureChain::createStructure(*this, 0, jsNull()));
224
    sparseArrayValueMapStructure.set(*this, SparseArrayValueMap::createStructure(*this, 0, jsNull()));
225 226 227 228 229
    withScopeStructure.set(*this, JSWithScope::createStructure(*this, 0, jsNull()));
    unlinkedFunctionExecutableStructure.set(*this, UnlinkedFunctionExecutable::createStructure(*this, 0, jsNull()));
    unlinkedProgramCodeBlockStructure.set(*this, UnlinkedProgramCodeBlock::createStructure(*this, 0, jsNull()));
    unlinkedEvalCodeBlockStructure.set(*this, UnlinkedEvalCodeBlock::createStructure(*this, 0, jsNull()));
    unlinkedFunctionCodeBlockStructure.set(*this, UnlinkedFunctionCodeBlock::createStructure(*this, 0, jsNull()));
230
    propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
231
    smallStrings.initializeCommonStrings(*this);
232 233 234

    wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable);

235
#if ENABLE(JIT)
236 237
    jitStubs = adoptPtr(new JITThunks());
    performPlatformSpecificJITAssertions(this);
238
#endif
239
    
240
    interpreter->initialize(this->canUseJIT());
241
    
242
#if ENABLE(JIT)
243
    initializeHostCallReturnValue(); // This is needed to convince the linker not to drop host call return support.
244
#endif
245

246
    heap.notifyIsSafeToCollect();
247

248
    LLInt::Data::performAssertions(*this);
249 250 251
    
    if (Options::enableProfiler())
        m_perBytecodeProfiler = adoptPtr(new Profiler::Database(*this));
252 253 254 255 256

#if ENABLE(DFG_JIT)
    if (canUseJIT())
        m_dfgState = adoptPtr(new DFG::LongLivedState());
#endif
ap@webkit.org's avatar
ap@webkit.org committed
257 258 259 260
}

JSGlobalData::~JSGlobalData()
{
261 262 263
    // Clear this first to ensure that nobody tries to remove themselves from it.
    m_perBytecodeProfiler.clear();
    
264
    ASSERT(!m_apiLock.currentThreadIsHoldingLock());
265
    heap.didStartVMShutdown();
266

ggaren@apple.com's avatar
ggaren@apple.com committed
267
    delete interpreter;
ap@webkit.org's avatar
ap@webkit.org committed
268
#ifndef NDEBUG
269
    interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef);
ap@webkit.org's avatar
ap@webkit.org committed
270
#endif
ap@webkit.org's avatar
ap@webkit.org committed
271

272 273 274
    arrayPrototypeTable->deleteTable();
    arrayConstructorTable->deleteTable();
    booleanPrototypeTable->deleteTable();
ap@webkit.org's avatar
ap@webkit.org committed
275
    dateTable->deleteTable();
276 277 278
    dateConstructorTable->deleteTable();
    errorPrototypeTable->deleteTable();
    globalObjectTable->deleteTable();
279
    jsonTable->deleteTable();
ap@webkit.org's avatar
ap@webkit.org committed
280
    mathTable->deleteTable();
281 282
    numberConstructorTable->deleteTable();
    numberPrototypeTable->deleteTable();
283
    objectConstructorTable->deleteTable();
284
    privateNamePrototypeTable->deleteTable();
ap@webkit.org's avatar
ap@webkit.org committed
285 286
    regExpTable->deleteTable();
    regExpConstructorTable->deleteTable();
287 288
    regExpPrototypeTable->deleteTable();
    stringConstructorTable->deleteTable();
289

290 291 292
    fastDelete(const_cast<HashTable*>(arrayConstructorTable));
    fastDelete(const_cast<HashTable*>(arrayPrototypeTable));
    fastDelete(const_cast<HashTable*>(booleanPrototypeTable));
293
    fastDelete(const_cast<HashTable*>(dateTable));
294 295 296
    fastDelete(const_cast<HashTable*>(dateConstructorTable));
    fastDelete(const_cast<HashTable*>(errorPrototypeTable));
    fastDelete(const_cast<HashTable*>(globalObjectTable));
297
    fastDelete(const_cast<HashTable*>(jsonTable));
298
    fastDelete(const_cast<HashTable*>(mathTable));
299 300
    fastDelete(const_cast<HashTable*>(numberConstructorTable));
    fastDelete(const_cast<HashTable*>(numberPrototypeTable));
301
    fastDelete(const_cast<HashTable*>(objectConstructorTable));
302
    fastDelete(const_cast<HashTable*>(privateNamePrototypeTable));
303 304
    fastDelete(const_cast<HashTable*>(regExpTable));
    fastDelete(const_cast<HashTable*>(regExpConstructorTable));
305 306
    fastDelete(const_cast<HashTable*>(regExpPrototypeTable));
    fastDelete(const_cast<HashTable*>(stringConstructorTable));
ap@webkit.org's avatar
ap@webkit.org committed
307

ap@webkit.org's avatar
ap@webkit.org committed
308 309
    delete emptyList;

ap@webkit.org's avatar
ap@webkit.org committed
310
    delete propertyNames;
311 312
    if (globalDataType != Default)
        deleteIdentifierTable(identifierTable);
ap@webkit.org's avatar
ap@webkit.org committed
313

ap@webkit.org's avatar
ap@webkit.org committed
314
    delete clientData;
315
    delete m_regExpCache;
316 317 318
#if ENABLE(REGEXP_TRACING)
    delete m_rtTraceList;
#endif
319

320
#if ENABLE(DFG_JIT)
321 322
    for (unsigned i = 0; i < scratchBuffers.size(); ++i)
        fastFree(scratchBuffers[i]);
323
#endif
ap@webkit.org's avatar
ap@webkit.org committed
324 325
}

326
PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(HeapType heapType)
327
{
328
    return adoptRef(new JSGlobalData(APIContextGroup, heapType));
329 330
}

331
PassRefPtr<JSGlobalData> JSGlobalData::create(HeapType heapType)
332
{
333
    return adoptRef(new JSGlobalData(Default, heapType));
334 335
}

336
PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(HeapType heapType)
weinig@apple.com's avatar
weinig@apple.com committed
337
{
338
    return create(heapType);
weinig@apple.com's avatar
weinig@apple.com committed
339 340
}

ap@webkit.org's avatar
ap@webkit.org committed
341 342 343 344 345 346 347
bool JSGlobalData::sharedInstanceExists()
{
    return sharedInstanceInternal();
}

JSGlobalData& JSGlobalData::sharedInstance()
{
348
    GlobalJSLock globalLock;
ap@webkit.org's avatar
ap@webkit.org committed
349
    JSGlobalData*& instance = sharedInstanceInternal();
ap@webkit.org's avatar
ap@webkit.org committed
350
    if (!instance) {
351
        instance = adoptRef(new JSGlobalData(APIShared, SmallHeap)).leakRef();
ap@webkit.org's avatar
ap@webkit.org committed
352 353
        instance->makeUsableFromMultipleThreads();
    }
ap@webkit.org's avatar
ap@webkit.org committed
354 355 356 357 358 359 360 361 362
    return *instance;
}

JSGlobalData*& JSGlobalData::sharedInstanceInternal()
{
    static JSGlobalData* sharedInstance;
    return sharedInstance;
}

363
#if ENABLE(JIT)
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
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;
    }
}

394
NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
395
{
396
    return jitStubs->hostFunctionStub(this, function, constructor);
397
}
398
NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, Intrinsic intrinsic)
399
{
400
    ASSERT(canUseJIT());
401
    return jitStubs->hostFunctionStub(this, function, intrinsic != NoIntrinsic ? thunkGeneratorForIntrinsic(intrinsic) : 0, intrinsic);
402
}
403 404

#else // !ENABLE(JIT)
405
NativeExecutable* JSGlobalData::getHostFunction(NativeFunction function, NativeFunction constructor)
406
{
407
    return NativeExecutable::create(*this, function, constructor);
408
}
409
#endif // !ENABLE(JIT)
410

ggaren@apple.com's avatar
ggaren@apple.com committed
411 412
JSGlobalData::ClientData::~ClientData()
{
ap@webkit.org's avatar
ap@webkit.org committed
413
}
ggaren@apple.com's avatar
ggaren@apple.com committed
414

415 416
void JSGlobalData::resetDateCache()
{
417
    cachedUTCOffset = QNaN;
ggaren@apple.com's avatar
ggaren@apple.com committed
418
    dstOffsetCache.reset();
419
    cachedDateString = String();
420
    cachedDateStringValue = QNaN;
421
    dateInstanceCache.reset();
422 423
}

oliver@apple.com's avatar
oliver@apple.com committed
424 425 426 427 428 429 430 431 432 433
void JSGlobalData::startSampling()
{
    interpreter->startSampling();
}

void JSGlobalData::stopSampling()
{
    interpreter->stopSampling();
}

434 435 436 437
void JSGlobalData::discardAllCode()
{
    m_codeCache->clear();
    heap.deleteAllCompiledCode();
438
    heap.reportAbandonedObjectGraph();
439 440
}

oliver@apple.com's avatar
oliver@apple.com committed
441 442 443
void JSGlobalData::dumpSampleData(ExecState* exec)
{
    interpreter->dumpSampleData(exec);
444 445 446
#if ENABLE(ASSEMBLER)
    ExecutableAllocator::dumpProfile();
#endif
oliver@apple.com's avatar
oliver@apple.com committed
447 448
}

449 450 451 452 453 454 455 456 457 458 459 460 461
SourceProviderCache* JSGlobalData::addSourceProviderCache(SourceProvider* sourceProvider)
{
    SourceProviderCacheMap::AddResult addResult = sourceProviderCacheMap.add(sourceProvider, 0);
    if (addResult.isNewEntry)
        addResult.iterator->value = adoptRef(new SourceProviderCache);
    return addResult.iterator->value.get();
}

void JSGlobalData::clearSourceProviderCaches()
{
    sourceProviderCacheMap.clear();
}

462 463 464 465 466 467
struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
    HashSet<FunctionExecutable*> currentlyExecutingFunctions;
    void operator()(JSCell* cell)
    {
        if (!cell->inherits(&FunctionExecutable::s_info))
            return;
468
        FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
469 470
        if (currentlyExecutingFunctions.contains(executable))
            return;
471
        executable->clearCodeIfNotCompiling();
472 473 474
    }
};

475 476
void JSGlobalData::releaseExecutableMemory()
{
477 478 479 480 481 482 483 484 485 486 487
    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)) {
488
                JSFunction* function = jsCast<JSFunction*>(*ptr);
489 490 491 492 493 494 495 496 497 498 499
                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));
                
        }
500
        heap.objectSpace().forEachLiveCell<StackPreservingRecompiler>(recompiler);
501
    }
502
    m_regExpCache->invalidateCode();
503
    heap.collectAllGarbage();
504 505 506 507 508 509 510
}
    
void releaseExecutableMemory(JSGlobalData& globalData)
{
    globalData.releaseExecutableMemory();
}

511 512 513 514 515 516 517 518 519 520 521 522 523
#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<void*>(static_cast<char*>(bufferStart) + scratchBuffer->activeLength()));
        }
    }
}
#endif

524
#if ENABLE(REGEXP_TRACING)
525
void JSGlobalData::addRegExpToTrace(RegExp* regExp)
526 527 528 529 530 531 532 533 534 535
{
    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()) {
536 537 538 539
        dataLogF("\nRegExp Tracing\n");
        dataLogF("                                                            match()    matches\n");
        dataLogF("Regular Expression                          JIT Address      calls      found\n");
        dataLogF("----------------------------------------+----------------+----------+----------\n");
540 541 542 543 544 545
    
        unsigned reCount = 0;
    
        for (; iter != m_rtTraceList->end(); ++iter, ++reCount)
            (*iter)->printTraceData();

546
        dataLogF("%d Regular Expressions\n", reCount);
547 548 549 550 551 552 553 554 555 556
    }
    
    m_rtTraceList->clear();
}
#else
void JSGlobalData::dumpRegExpTrace()
{
}
#endif

ggaren@apple.com's avatar
ggaren@apple.com committed
557
} // namespace JSC