Ignore:
Timestamp:
Nov 4, 2016, 4:02:19 PM (9 years ago)
Author:
[email protected]
Message:

EvalCodeCache should not give up in strict mode and other cases
https://bugs.webkit.org/show_bug.cgi?id=164357

Reviewed by Michael Saboff.

JSTests:

  • microbenchmarks/eval-cached.js: Added. 45x faster now.
  • stress/eval-cached.js: Added. Try running the same eval text in a bunch

of different scopes and verify that we access the right scope.

Source/JavaScriptCore:

EvalCodeCache gives up in non-trivial cases because generated eval code
can't soundly migrate from, for example, a let scope to a non-let scope.
The number of cases has grown over time.

Instead, let's cache eval code based on the location of the call to
eval(). That way, we never relocate the code, and it's sound to make
normal assumptions about our surrounding scope.

  • bytecode/EvalCodeCache.h:

(JSC::EvalCodeCache::CacheKey::CacheKey): Use CallSiteIndex to uniquely
identify the location of our call to eval().

(JSC::EvalCodeCache::CacheKey::hash):
(JSC::EvalCodeCache::CacheKey::operator==):
(JSC::EvalCodeCache::CacheKey::Hash::equal): Use CallSiteIndex instead
of lots of other flags.

(JSC::EvalCodeCache::tryGet): No need to include details that are implied
by our CallSiteIndex.

(JSC::EvalCodeCache::getSlow): No need to skip caching in complex
situations. We promise we'll never relocate the cached code.

(JSC::EvalCodeCache::isCacheableScope): Deleted.
(JSC::EvalCodeCache::isCacheable): Deleted.

  • interpreter/Interpreter.cpp:

(JSC::eval): Pass through a CallSiteIndex to uniquely identify this call
to eval().

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r208377 r208404  
    110110   
    111111    CallFrame* callerFrame = callFrame->callerFrame();
     112    CallSiteIndex callerCallSiteIndex = callerFrame->callSiteIndex();
    112113    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
    113114    JSScope* callerScopeChain = callerFrame->uncheckedR(callerCodeBlock->scopeRegister().offset()).Register::scope();
     
    131132        evalContextType = EvalContextType::None;
    132133
    133     EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(callerCodeBlock->isStrictMode(), programSource, derivedContextType, evalContextType, isArrowFunctionContext, callerScopeChain);
     134    EvalExecutable* eval = callerCodeBlock->evalCodeCache().tryGet(programSource, callerCallSiteIndex);
    134135    if (!eval) {
    135136        if (!callerCodeBlock->isStrictMode()) {
     
    148149        ASSERT(!scope.exception());
    149150
    150         eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, callerCodeBlock->isStrictMode(), derivedContextType, evalContextType, isArrowFunctionContext, programSource, callerScopeChain);
     151        eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock, programSource, callerCallSiteIndex, callerCodeBlock->isStrictMode(), derivedContextType, evalContextType, isArrowFunctionContext, callerScopeChain);
    151152
    152153        if (!eval)
Note: See TracChangeset for help on using the changeset viewer.