summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r--JavaScriptCore/runtime/ArrayPrototype.cpp8
-rw-r--r--JavaScriptCore/runtime/Executable.cpp18
-rw-r--r--JavaScriptCore/runtime/Executable.h12
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.cpp5
-rw-r--r--JavaScriptCore/runtime/JSGlobalData.h7
-rw-r--r--JavaScriptCore/runtime/JSImmediate.h8
-rw-r--r--JavaScriptCore/runtime/JSString.cpp1
-rw-r--r--JavaScriptCore/runtime/JSValue.cpp6
-rw-r--r--JavaScriptCore/runtime/JSZombie.cpp2
-rw-r--r--JavaScriptCore/runtime/RegExpCache.cpp78
-rw-r--r--JavaScriptCore/runtime/RegExpCache.h57
-rw-r--r--JavaScriptCore/runtime/RegExpConstructor.cpp3
-rw-r--r--JavaScriptCore/runtime/RegExpKey.h112
-rw-r--r--JavaScriptCore/runtime/RegExpPrototype.cpp3
-rw-r--r--JavaScriptCore/runtime/StringPrototype.cpp5
-rw-r--r--JavaScriptCore/runtime/SymbolTable.h7
16 files changed, 308 insertions, 24 deletions
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp
index 699fbe6..9407be7 100644
--- a/JavaScriptCore/runtime/ArrayPrototype.cpp
+++ b/JavaScriptCore/runtime/ArrayPrototype.cpp
@@ -77,12 +77,14 @@ static inline bool isNumericCompareFunction(ExecState* exec, CallType callType,
// If the JIT is enabled then we need to preserve the invariant that every
// function with a CodeBlock also has JIT code.
callData.js.functionExecutable->jitCodeForCall(exec, callData.js.scopeChain);
- CodeBlock& codeBlock = callData.js.functionExecutable->generatedBytecodeForCall();
+ CodeBlock* codeBlock = &callData.js.functionExecutable->generatedBytecodeForCall();
#else
- CodeBlock& codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
+ CodeBlock* codeBlock = callData.js.functionExecutable->bytecodeForCall(exec, callData.js.scopeChain);
#endif
+ if (!codeBlock)
+ return false;
- return codeBlock.isNumericCompareFunction();
+ return codeBlock->isNumericCompareFunction();
}
// ------------------------------ ArrayPrototype ----------------------------
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index a18e80c..f33f3b4 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -119,10 +119,12 @@ JSObject* ProgramExecutable::compile(ExecState* exec, ScopeChainNode* scopeChain
return 0;
}
-void FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)
+bool FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNode)
{
JSGlobalData* globalData = scopeChainNode->globalData;
RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!body)
+ return false;
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
@@ -141,12 +143,15 @@ void FunctionExecutable::compileForCall(ExecState*, ScopeChainNode* scopeChainNo
m_symbolTable = m_codeBlockForCall->sharedSymbolTable();
body->destroyData();
+ return true;
}
-void FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode)
+bool FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeChainNode)
{
JSGlobalData* globalData = scopeChainNode->globalData;
RefPtr<FunctionBodyNode> body = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!body)
+ return false;
if (m_forceUsesArguments)
body->setUsesArguments();
body->finishParsing(m_parameters, m_name);
@@ -165,6 +170,7 @@ void FunctionExecutable::compileForConstruct(ExecState*, ScopeChainNode* scopeCh
m_symbolTable = m_codeBlockForConstruct->sharedSymbolTable();
body->destroyData();
+ return true;
}
#if ENABLE(JIT)
@@ -193,7 +199,7 @@ void ProgramExecutable::generateJITCode(ExecState* exec, ScopeChainNode* scopeCh
void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- CodeBlock* codeBlock = &bytecodeForCall(exec, scopeChainNode);
+ CodeBlock* codeBlock = bytecodeForCall(exec, scopeChainNode);
m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForCallWithArityCheck);
#if !ENABLE(OPCODE_SAMPLING)
@@ -204,7 +210,7 @@ void FunctionExecutable::generateJITCodeForCall(ExecState* exec, ScopeChainNode*
void FunctionExecutable::generateJITCodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
- CodeBlock* codeBlock = &bytecodeForConstruct(exec, scopeChainNode);
+ CodeBlock* codeBlock = bytecodeForConstruct(exec, scopeChainNode);
m_jitCodeForConstruct = JIT::compile(scopeChainNode->globalData, codeBlock, &m_jitCodeForConstructWithArityCheck);
#if !ENABLE(OPCODE_SAMPLING)
@@ -226,6 +232,8 @@ void FunctionExecutable::markAggregate(MarkStack& markStack)
ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<FunctionBodyNode> newFunctionBody = globalData->parser->parse<FunctionBodyNode>(globalData, 0, 0, m_source);
+ if (!newFunctionBody)
+ return 0;
if (m_forceUsesArguments)
newFunctionBody->setUsesArguments();
newFunctionBody->finishParsing(m_parameters, m_name);
@@ -255,6 +263,8 @@ ExceptionInfo* FunctionExecutable::reparseExceptionInfo(JSGlobalData* globalData
ExceptionInfo* EvalExecutable::reparseExceptionInfo(JSGlobalData* globalData, ScopeChainNode* scopeChainNode, CodeBlock* codeBlock)
{
RefPtr<EvalNode> newEvalBody = globalData->parser->parse<EvalNode>(globalData, 0, 0, m_source);
+ if (!newEvalBody)
+ return 0;
ScopeChain scopeChain(scopeChainNode);
JSGlobalObject* globalObject = scopeChain.globalObject();
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
index 39ddf49..3320fe1 100644
--- a/JavaScriptCore/runtime/Executable.h
+++ b/JavaScriptCore/runtime/Executable.h
@@ -305,12 +305,12 @@ namespace JSC {
return *m_codeBlockForConstruct;
}
- FunctionCodeBlock& bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
+ FunctionCodeBlock* bytecodeForCall(ExecState* exec, ScopeChainNode* scopeChainNode)
{
ASSERT(scopeChainNode);
if (!m_codeBlockForCall)
compileForCall(exec, scopeChainNode);
- return *m_codeBlockForCall;
+ return m_codeBlockForCall;
}
bool isGeneratedForCall() const
@@ -324,12 +324,12 @@ namespace JSC {
return *m_codeBlockForCall;
}
- FunctionCodeBlock& bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
+ FunctionCodeBlock* bytecodeForConstruct(ExecState* exec, ScopeChainNode* scopeChainNode)
{
ASSERT(scopeChainNode);
if (!m_codeBlockForConstruct)
compileForConstruct(exec, scopeChainNode);
- return *m_codeBlockForConstruct;
+ return m_codeBlockForConstruct;
}
bool isGeneratedForConstruct() const
@@ -383,8 +383,8 @@ namespace JSC {
m_lastLine = lastLine;
}
- void compileForCall(ExecState*, ScopeChainNode*);
- void compileForConstruct(ExecState*, ScopeChainNode*);
+ bool compileForCall(ExecState*, ScopeChainNode*);
+ bool compileForConstruct(ExecState*, ScopeChainNode*);
unsigned m_numVariables : 31;
bool m_forceUsesArguments : 1;
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 3f24ea4..30a5ef9 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -49,6 +49,7 @@
#include "Lookup.h"
#include "Nodes.h"
#include "Parser.h"
+#include "RegExpCache.h"
#include <wtf/WTFThreadData.h>
#if ENABLE(JSC_MULTIPLE_THREADS)
@@ -147,6 +148,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, cachedUTCOffset(NaN)
, weakRandom(static_cast<int>(currentTime()))
, maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
+ , m_regExpCache(new RegExpCache(this))
#ifndef NDEBUG
, exclusiveThread(0)
#endif
@@ -196,6 +198,7 @@ JSGlobalData::~JSGlobalData()
deleteIdentifierTable(identifierTable);
delete clientData;
+ delete m_regExpCache;
}
PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
@@ -246,7 +249,7 @@ const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
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->bytecodeForCall(exec, exec->scopeChain()).instructions();
+ lazyNumericCompareFunction = function->bytecodeForCall(exec, exec->scopeChain())->instructions();
initializingLazyNumericCompareFunction = false;
}
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index f48aec8..f99c8d6 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -44,6 +44,7 @@
#include <wtf/Forward.h>
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
+#include <wtf/ThreadSpecific.h>
struct OpaqueJSClass;
struct OpaqueJSClassContextData;
@@ -58,6 +59,7 @@ namespace JSC {
class JSObject;
class Lexer;
class Parser;
+ class RegExpCache;
class Stringifier;
class Structure;
class UString;
@@ -211,17 +213,22 @@ namespace JSC {
WeakRandom weakRandom;
int maxReentryDepth;
+
+ RegExpCache* m_regExpCache;
+
#ifndef NDEBUG
ThreadIdentifier exclusiveThread;
#endif
CachedTranscendentalFunction<sin> cachedSin;
+ WTF::ThreadSpecific<char*> stackGuards;
void resetDateCache();
void startSampling();
void stopSampling();
void dumpSampleData(ExecState* exec);
+ RegExpCache* regExpCache() { return m_regExpCache; }
private:
JSGlobalData(GlobalDataType, ThreadStackType);
static JSGlobalData*& sharedInstanceInternal();
diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h
index 9127b6a..f33d9fe 100644
--- a/JavaScriptCore/runtime/JSImmediate.h
+++ b/JavaScriptCore/runtime/JSImmediate.h
@@ -44,6 +44,8 @@ namespace JSC {
class JSObject;
class UString;
+ extern const size_t CELL_MASK;
+
#if USE(JSVALUE64)
inline intptr_t reinterpretDoubleToIntptr(double value)
{
@@ -595,7 +597,13 @@ namespace JSC {
inline bool JSValue::isCell() const
{
+#ifndef NDEBUG
+ bool r = !JSImmediate::isImmediate(asValue());
+ ASSERT(!r || !(JSImmediate::rawValue(asValue()) & CELL_MASK));
+ return r;
+#else
return !JSImmediate::isImmediate(asValue());
+#endif
}
inline bool JSValue::isInt32() const
diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp
index 473eb77..1d5e639 100644
--- a/JavaScriptCore/runtime/JSString.cpp
+++ b/JavaScriptCore/runtime/JSString.cpp
@@ -150,6 +150,7 @@ JSValue JSString::replaceCharacter(ExecState* exec, UChar character, const UStri
if (replacement.size())
builder.append(replacement);
builder.append(UString(string).substr(matchPosition + 1));
+ matchString = 0;
}
JSGlobalData* globalData = &exec->globalData();
diff --git a/JavaScriptCore/runtime/JSValue.cpp b/JavaScriptCore/runtime/JSValue.cpp
index 728cbcf..e752d3f 100644
--- a/JavaScriptCore/runtime/JSValue.cpp
+++ b/JavaScriptCore/runtime/JSValue.cpp
@@ -126,10 +126,10 @@ char* JSValue::description()
snprintf(description, size, "False");
else if (isNull())
snprintf(description, size, "Null");
- else {
- ASSERT(isUndefined());
+ else if (isUndefined())
snprintf(description, size, "Undefined");
- }
+ else
+ snprintf(description, size, "INVALID");
return description;
}
diff --git a/JavaScriptCore/runtime/JSZombie.cpp b/JavaScriptCore/runtime/JSZombie.cpp
index 072d29b..22aabb9 100644
--- a/JavaScriptCore/runtime/JSZombie.cpp
+++ b/JavaScriptCore/runtime/JSZombie.cpp
@@ -37,7 +37,7 @@ Structure* JSZombie::leakedZombieStructure() {
static Structure* structure = 0;
if (!structure) {
Structure::startIgnoringLeaks();
- structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType)).releaseRef();
+ structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType), 0).releaseRef();
Structure::stopIgnoringLeaks();
}
return structure;
diff --git a/JavaScriptCore/runtime/RegExpCache.cpp b/JavaScriptCore/runtime/RegExpCache.cpp
new file mode 100644
index 0000000..192df4d
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpCache.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR
+ * 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 "RegExpCache.h"
+
+namespace JSC {
+
+PassRefPtr<RegExp> RegExpCache::lookupOrCreate(const UString& patternString, const UString& flags)
+{
+ if (patternString.size() < maxCacheablePatternLength) {
+ pair<HashMap<RegExpKey, RefPtr<RegExp> >::iterator, bool> result = m_cacheMap.add(RegExpKey(flags, patternString), 0);
+ if (!result.second)
+ return result.first->second;
+ }
+ return create(patternString, flags);
+}
+
+PassRefPtr<RegExp> RegExpCache::create(const UString& patternString, const UString& flags)
+{
+ RefPtr<RegExp> regExp;
+
+ if (!flags.isNull())
+ regExp = RegExp::create(m_globalData, patternString, flags);
+ else
+ regExp = RegExp::create(m_globalData, patternString);
+
+ if (patternString.size() >= maxCacheablePatternLength)
+ return regExp;
+
+ ++m_nextKeyToEvict;
+ if (m_nextKeyToEvict == maxCacheableEntries) {
+ m_nextKeyToEvict = 0;
+ m_isFull = true;
+ }
+ if (m_isFull)
+ m_cacheMap.remove(RegExpKey(patternKeyArray[m_nextKeyToEvict].flagsValue, patternKeyArray[m_nextKeyToEvict].pattern));
+
+ RegExpKey key = RegExpKey(flags, patternString);
+ m_cacheMap.set(key, regExp);
+ patternKeyArray[m_nextKeyToEvict].flagsValue = key.flagsValue;
+ patternKeyArray[m_nextKeyToEvict].pattern = patternString.rep();
+ return regExp;
+}
+
+RegExpCache::RegExpCache(JSGlobalData* globalData)
+ : m_globalData(globalData)
+ , m_nextKeyToEvict(-1)
+ , m_isFull(false)
+{
+}
+
+}
diff --git a/JavaScriptCore/runtime/RegExpCache.h b/JavaScriptCore/runtime/RegExpCache.h
new file mode 100644
index 0000000..03b73ac
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpCache.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR
+ * 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 "RegExp.h"
+#include "RegExpKey.h"
+#include "UString.h"
+
+#ifndef RegExpCache_h
+#define RegExpCache_h
+
+namespace JSC {
+
+class RegExpCache {
+public:
+ PassRefPtr<RegExp> lookupOrCreate(const UString& patternString, const UString& flags);
+ PassRefPtr<RegExp> create(const UString& patternString, const UString& flags);
+ RegExpCache(JSGlobalData* globalData);
+
+private:
+ static const unsigned maxCacheablePatternLength = 256;
+ static const int maxCacheableEntries = 256;
+
+ typedef HashMap<RegExpKey, RefPtr<RegExp> > RegExpCacheMap;
+ RegExpKey patternKeyArray[maxCacheableEntries];
+ RegExpCacheMap m_cacheMap;
+ JSGlobalData* m_globalData;
+ int m_nextKeyToEvict;
+ bool m_isFull;
+};
+
+} // namespace JSC
+
+#endif // RegExpCache_h
diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp
index 24476d6..166a021 100644
--- a/JavaScriptCore/runtime/RegExpConstructor.cpp
+++ b/JavaScriptCore/runtime/RegExpConstructor.cpp
@@ -34,6 +34,7 @@
#include "RegExpObject.h"
#include "RegExpPrototype.h"
#include "RegExp.h"
+#include "RegExpCache.h"
namespace JSC {
@@ -302,7 +303,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args)
UString pattern = arg0.isUndefined() ? UString("") : arg0.toString(exec);
UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
- RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ RefPtr<RegExp> regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
if (!regExp->isValid())
return throwError(exec, createSyntaxError(exec, makeString("Invalid regular expression: ", regExp->errorMessage())));
return new (exec) RegExpObject(exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->regExpStructure(), regExp.release());
diff --git a/JavaScriptCore/runtime/RegExpKey.h b/JavaScriptCore/runtime/RegExpKey.h
new file mode 100644
index 0000000..e5ab438
--- /dev/null
+++ b/JavaScriptCore/runtime/RegExpKey.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Renata Hodovan (hodovan@inf.u-szeged.hu)
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR
+ * 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 "UString.h"
+
+#ifndef RegExpKey_h
+#define RegExpKey_h
+
+namespace JSC {
+
+struct RegExpKey {
+ int flagsValue;
+ RefPtr<UString::Rep> pattern;
+
+ RegExpKey()
+ : flagsValue(0)
+ {
+ }
+
+ RegExpKey(int flags)
+ : flagsValue(flags)
+ {
+ }
+
+ RegExpKey(int flags, const UString& pattern)
+ : flagsValue(flags)
+ , pattern(pattern.rep())
+ {
+ }
+
+ RegExpKey(int flags, const PassRefPtr<UString::Rep> pattern)
+ : flagsValue(flags)
+ , pattern(pattern)
+ {
+ }
+
+ RegExpKey(const UString& flags, const UString& pattern)
+ : pattern(pattern.rep())
+ {
+ flagsValue = getFlagsValue(flags);
+ }
+
+ int getFlagsValue(const UString flags)
+ {
+ flagsValue = 0;
+ if (flags.find('g') != UString::NotFound)
+ flagsValue += 4;
+ if (flags.find('i') != UString::NotFound)
+ flagsValue += 2;
+ if (flags.find('m') != UString::NotFound)
+ flagsValue += 1;
+ return flagsValue;
+ }
+};
+} // namespace JSC
+
+namespace WTF {
+template<typename T> struct DefaultHash;
+template<typename T> struct RegExpHash;
+
+inline bool operator==(const JSC::RegExpKey& a, const JSC::RegExpKey& b)
+{
+ if (a.flagsValue != b.flagsValue)
+ return false;
+ if (!a.pattern)
+ return !b.pattern;
+ if (!b.pattern)
+ return false;
+ return equal(a.pattern.get(), b.pattern.get());
+}
+
+template<> struct RegExpHash<JSC::RegExpKey> {
+ static unsigned hash(const JSC::RegExpKey& key) { return key.pattern->hash(); }
+ static bool equal(const JSC::RegExpKey& a, const JSC::RegExpKey& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = false;
+};
+
+template<> struct DefaultHash<JSC::RegExpKey> {
+ typedef RegExpHash<JSC::RegExpKey> Hash;
+};
+
+template<> struct HashTraits<JSC::RegExpKey> : GenericHashTraits<JSC::RegExpKey> {
+ static void constructDeletedValue(JSC::RegExpKey& slot) { slot.flagsValue = -1; }
+ static bool isDeletedValue(const JSC::RegExpKey& value) { return value.flagsValue == -1; }
+};
+} // namespace WTF
+
+#endif // RegExpKey_h
diff --git a/JavaScriptCore/runtime/RegExpPrototype.cpp b/JavaScriptCore/runtime/RegExpPrototype.cpp
index 9d78f59..834412b 100644
--- a/JavaScriptCore/runtime/RegExpPrototype.cpp
+++ b/JavaScriptCore/runtime/RegExpPrototype.cpp
@@ -33,6 +33,7 @@
#include "PrototypeFunction.h"
#include "RegExpObject.h"
#include "RegExp.h"
+#include "RegExpCache.h"
namespace JSC {
@@ -91,7 +92,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
} else {
UString pattern = !exec->argumentCount() ? UString("") : arg0.toString(exec);
UString flags = arg1.isUndefined() ? UString("") : arg1.toString(exec);
- regExp = RegExp::create(&exec->globalData(), pattern, flags);
+ regExp = exec->globalData().regExpCache()->lookupOrCreate(pattern, flags);
}
if (!regExp->isValid())
diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp
index 5b90456..8b56d53 100644
--- a/JavaScriptCore/runtime/StringPrototype.cpp
+++ b/JavaScriptCore/runtime/StringPrototype.cpp
@@ -33,6 +33,7 @@
#include "ObjectPrototype.h"
#include "Operations.h"
#include "PropertyNameArray.h"
+#include "RegExpCache.h"
#include "RegExpConstructor.h"
#include "RegExpObject.h"
#include <wtf/ASCIICType.h>
@@ -585,7 +586,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
@@ -636,7 +637,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec)
* If regexp is not an object whose [[Class]] property is "RegExp", it is
* replaced with the result of the expression new RegExp(regexp).
*/
- reg = RegExp::create(&exec->globalData(), a0.toString(exec));
+ reg = exec->globalData().regExpCache()->lookupOrCreate(a0.toString(exec), UString::null());
}
RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
int pos;
diff --git a/JavaScriptCore/runtime/SymbolTable.h b/JavaScriptCore/runtime/SymbolTable.h
index f5e2669..2717075 100644
--- a/JavaScriptCore/runtime/SymbolTable.h
+++ b/JavaScriptCore/runtime/SymbolTable.h
@@ -121,8 +121,11 @@ namespace JSC {
typedef HashMap<RefPtr<UString::Rep>, SymbolTableEntry, IdentifierRepHash, HashTraits<RefPtr<UString::Rep> >, SymbolTableIndexHashTraits> SymbolTable;
- class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable>
- {
+ class SharedSymbolTable : public SymbolTable, public RefCounted<SharedSymbolTable> {
+ public:
+ static PassRefPtr<SharedSymbolTable> create() { return adoptRef(new SharedSymbolTable); }
+ private:
+ SharedSymbolTable() { }
};
} // namespace JSC