#ifndef EvalCodeCache_h
#define EvalCodeCache_h
#include "Executable.h"
#include "JSGlobalObject.h"
#include "SourceCode.h"
#include <wtf/HashMap.h>
#include <wtf/RefPtr.h>
#include <wtf/text/StringHash.h>
namespace JSC {
class CodeCache;
class SlotVisitor;
class EvalCodeCache {
public:
EvalExecutable* tryGet(bool inStrictContext, const String& evalSource, JSScope* scope)
{
if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && scope->begin()->isVariableObject())
return m_cacheMap.get(evalSource.impl()).get();
return 0;
}
EvalExecutable* getSlow(ExecState* exec, CodeCache* codeCache, ScriptExecutable* owner, bool inStrictContext, const String& evalSource, JSScope* scope, JSValue& exceptionValue)
{
EvalExecutable* evalExecutable = EvalExecutable::create(exec, codeCache, makeSource(evalSource), inStrictContext);
exceptionValue = evalExecutable->compile(exec, scope);
if (exceptionValue)
return 0;
if (!inStrictContext && evalSource.length() < maxCacheableSourceLength && scope->begin()->isVariableObject() && m_cacheMap.size() < maxCacheEntries)
m_cacheMap.set(evalSource.impl(), WriteBarrier<EvalExecutable>(exec->vm(), owner, evalExecutable));
return evalExecutable;
}
EvalExecutable* get(ExecState* exec, CodeCache* codeCache, ScriptExecutable* owner, bool inStrictContext, const String& evalSource, JSScope* scope, JSValue& exceptionValue)
{
EvalExecutable* evalExecutable = tryGet(inStrictContext, evalSource, scope);
if (!evalExecutable)
evalExecutable = getSlow(exec, codeCache, owner, inStrictContext, evalSource, scope, exceptionValue);
return evalExecutable;
}
bool isEmpty() const { return m_cacheMap.isEmpty(); }
void visitAggregate(SlotVisitor&);
void clear()
{
m_cacheMap.clear();
}
private:
static const unsigned maxCacheableSourceLength = 256;
static const int maxCacheEntries = 64;
typedef HashMap<RefPtr<StringImpl>, WriteBarrier<EvalExecutable> > EvalCacheMap;
EvalCacheMap m_cacheMap;
};
}
#endif // EvalCodeCache_h