Changeset 47405 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Aug 17, 2009, 6:05:37 PM (16 years ago)
Author:
[email protected]
Message:

Fix 300,000+ leaks seen during the regression tests.

Reviewed by Darin Adler.

EvalCodeCache::get was heap-allocating an EvalExecutable instance without adopting the initial reference.
While fixing this we noticed that EvalExecutable was a RefCounted type that was sometimes stack allocated.
To make this cleaner and to prevent clients from attempting to ref a stack-allocated instance, we move the
refcounting down to a new CacheableEvalExecutable class that derives from EvalExecutable. EvalCodeCache::get
now uses CacheableEvalExecutable::create and avoids the leak.

  • bytecode/EvalCodeCache.h:

(JSC::EvalCodeCache::get):

  • interpreter/Interpreter.cpp:

(JSC::Interpreter::callEval):

  • runtime/Executable.h:

(JSC::CacheableEvalExecutable::create):
(JSC::CacheableEvalExecutable::CacheableEvalExecutable):

Location:
trunk/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r47404 r47405  
     12009-08-17  Mark Rowe  <[email protected]>
     2
     3        Reviewed by Darin Adler.
     4
     5        Fix 300,000+ leaks seen during the regression tests.
     6
     7        EvalCodeCache::get was heap-allocating an EvalExecutable instance without adopting the initial reference.
     8        While fixing this we noticed that EvalExecutable was a RefCounted type that was sometimes stack allocated.
     9        To make this cleaner and to prevent clients from attempting to ref a stack-allocated instance, we move the
     10        refcounting down to a new CacheableEvalExecutable class that derives from EvalExecutable. EvalCodeCache::get
     11        now uses CacheableEvalExecutable::create and avoids the leak.
     12
     13        * bytecode/EvalCodeCache.h:
     14        (JSC::EvalCodeCache::get):
     15        * interpreter/Interpreter.cpp:
     16        (JSC::Interpreter::callEval):
     17        * runtime/Executable.h:
     18        (JSC::CacheableEvalExecutable::create):
     19        (JSC::CacheableEvalExecutable::CacheableEvalExecutable):
     20
    1212009-08-17  Oliver Hunt  <[email protected]>
    222
  • trunk/JavaScriptCore/bytecode/EvalCodeCache.h

    r47304 r47405  
    4343    class EvalCodeCache {
    4444    public:
    45         PassRefPtr<EvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
     45        PassRefPtr<CacheableEvalExecutable> get(ExecState* exec, const UString& evalSource, ScopeChainNode* scopeChain, JSValue& exceptionValue)
    4646        {
    47             RefPtr<EvalExecutable> evalExecutable;
     47            RefPtr<CacheableEvalExecutable> evalExecutable;
    4848
    4949            if (evalSource.size() < maxCacheableSourceLength && (*scopeChain->begin())->isVariableObject())
     
    5151
    5252            if (!evalExecutable) {
    53                 evalExecutable = new EvalExecutable(makeSource(evalSource));
     53                evalExecutable = CacheableEvalExecutable::create(makeSource(evalSource));
    5454                exceptionValue = evalExecutable->parse(exec);
    5555                if (exceptionValue)
     
    7575        static const int maxCacheEntries = 64;
    7676
    77         typedef HashMap<RefPtr<UString::Rep>, RefPtr<EvalExecutable> > EvalCacheMap;
     77        typedef HashMap<RefPtr<UString::Rep>, RefPtr<CacheableEvalExecutable> > EvalCacheMap;
    7878        EvalCacheMap m_cacheMap;
    7979    };
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r47304 r47405  
    351351    if (JSValue parsedObject = preparser.tryLiteralParse())
    352352        return parsedObject;
    353    
    354    
     353
    355354    ScopeChainNode* scopeChain = callFrame->scopeChain();
    356355    CodeBlock* codeBlock = callFrame->codeBlock();
    357     RefPtr<EvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
     356    RefPtr<CacheableEvalExecutable> eval = codeBlock->evalCodeCache().get(callFrame, programSource, scopeChain, exceptionValue);
    358357
    359358    JSValue result = jsUndefined();
  • trunk/JavaScriptCore/runtime/Executable.h

    r47330 r47405  
    5757    };
    5858
    59     class EvalExecutable : public TemplateExecutable<EvalNode, EvalCodeBlock>, public RefCounted<EvalExecutable> {
     59    class EvalExecutable : public TemplateExecutable<EvalNode, EvalCodeBlock> {
    6060    public:
    6161        EvalExecutable(const SourceCode& source)
     
    6565
    6666        JSObject* parse(ExecState* exec, bool allowDebug = true);
     67    };
     68
     69    class CacheableEvalExecutable : public EvalExecutable, public RefCounted<CacheableEvalExecutable> {
     70    public:
     71        static PassRefPtr<CacheableEvalExecutable> create(const SourceCode& source) { return adoptRef(new CacheableEvalExecutable(source)); }
     72
     73    private:
     74        CacheableEvalExecutable(const SourceCode& source)
     75            : EvalExecutable(source)
     76        {
     77        }
    6778    };
    6879
Note: See TracChangeset for help on using the changeset viewer.