diff options
Diffstat (limited to 'JavaScriptCore/runtime')
-rw-r--r-- | JavaScriptCore/runtime/ArrayPrototype.cpp | 8 | ||||
-rw-r--r-- | JavaScriptCore/runtime/Executable.cpp | 18 | ||||
-rw-r--r-- | JavaScriptCore/runtime/Executable.h | 12 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSGlobalData.cpp | 5 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSGlobalData.h | 7 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSImmediate.h | 8 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSString.cpp | 1 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSValue.cpp | 6 | ||||
-rw-r--r-- | JavaScriptCore/runtime/JSZombie.cpp | 2 | ||||
-rw-r--r-- | JavaScriptCore/runtime/RegExpCache.cpp | 78 | ||||
-rw-r--r-- | JavaScriptCore/runtime/RegExpCache.h | 57 | ||||
-rw-r--r-- | JavaScriptCore/runtime/RegExpConstructor.cpp | 3 | ||||
-rw-r--r-- | JavaScriptCore/runtime/RegExpKey.h | 112 | ||||
-rw-r--r-- | JavaScriptCore/runtime/RegExpPrototype.cpp | 3 | ||||
-rw-r--r-- | JavaScriptCore/runtime/StringPrototype.cpp | 5 | ||||
-rw-r--r-- | JavaScriptCore/runtime/SymbolTable.h | 7 |
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 |