Fixed http://bugs.webkit.org/show_bug.cgi?id=15902
15% of string-validate-input.js is spent compiling the same regular expression
Store a compiled representation of the regular expression in the AST.
Only a .2% SunSpider speedup overall, but a 10.6% speedup on
string-validate-input.js.
* kjs/nodes.cpp:
(KJS::RegExpNode::evaluate):
* kjs/nodes.h:
(KJS::RegExpNode::):
* kjs/nodes2string.cpp:
(KJS::RegExpNode::streamTo):
* kjs/regexp.cpp:
(KJS::RegExp::flags):
* kjs/regexp.h:
(KJS::RegExp::pattern):
* kjs/regexp_object.cpp:
(KJS::RegExpObjectImp::construct):
(KJS::RegExpObjectImp::createRegExpImp):
* kjs/regexp_object.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27702
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-11-11 Geoffrey Garen <ggaren@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ Fixed http://bugs.webkit.org/show_bug.cgi?id=15902
+ 15% of string-validate-input.js is spent compiling the same regular expression
+
+ Store a compiled representation of the regular expression in the AST.
+
+ Only a .2% SunSpider speedup overall, but a 10.6% speedup on
+ string-validate-input.js.
+
+ * kjs/nodes.cpp:
+ (KJS::RegExpNode::evaluate):
+ * kjs/nodes.h:
+ (KJS::RegExpNode::):
+ * kjs/nodes2string.cpp:
+ (KJS::RegExpNode::streamTo):
+ * kjs/regexp.cpp:
+ (KJS::RegExp::flags):
+ * kjs/regexp.h:
+ (KJS::RegExp::pattern):
+ * kjs/regexp_object.cpp:
+ (KJS::RegExpObjectImp::construct):
+ (KJS::RegExpObjectImp::createRegExpImp):
+ * kjs/regexp_object.h:
+
2007-11-11 Oliver Hunt <oliver@apple.com>
Reviewed by Eric.
JSValue* RegExpNode::evaluate(ExecState* exec)
{
- List list;
- list.append(jsOwnedString(m_pattern));
- list.append(jsOwnedString(m_flags));
-
- JSObject* reg = exec->lexicalInterpreter()->builtinRegExp();
- return reg->construct(exec, list);
+ return exec->lexicalInterpreter()->builtinRegExp()->createRegExpImp(exec, m_regExp);
}
// ------------------------------ ThisNode -------------------------------------
#include "Parser.h"
#include "internal.h"
+#include "RegExp.h"
#include "SymbolTable.h"
#include <wtf/ListRefPtr.h>
#include <wtf/OwnPtr.h>
class RegExpNode : public ExpressionNode {
public:
RegExpNode(const UString& pattern, const UString& flags) KJS_FAST_CALL
- : m_pattern(pattern), m_flags(flags) { }
- virtual JSValue* evaluate(ExecState*) KJS_FAST_CALL;
+ : m_regExp(new RegExp(pattern, flags))
+ {
+ }
+ JSValue* evaluate(ExecState*) KJS_FAST_CALL;
virtual void streamTo(SourceStream&) const KJS_FAST_CALL;
virtual Precedence precedence() const { return PrecPrimary; }
private:
- UString m_pattern;
- UString m_flags;
+ RefPtr<RegExp> m_regExp;
};
class ThisNode : public ExpressionNode {
void RegExpNode::streamTo(SourceStream& s) const
{
- s << '/' << m_pattern << '/' << m_flags;
+ s << '/' << m_regExp->pattern() << '/' << m_regExp->flags();
}
void ThisNode::streamTo(SourceStream& s) const
// -*- c-basic-offset: 2 -*-
/*
* This file is part of the KDE libraries
- * Copyright (C) 1999-2001,2004 Harri Porten (porten@kde.org)
+ * Copyright (C) 1999-2001, 2004 Harri Porten (porten@kde.org)
+ * Copyright (c) 2007, Apple Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
RegExp::RegExp(const UString& pattern)
: m_refCount(0)
, m_pattern(pattern)
- , m_flags(0)
+ , m_flagBits(0)
, m_constructionError(0)
, m_numSubpatterns(0)
{
- m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(m_pattern.data()), m_pattern.size(),
+ m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(pattern.data()), pattern.size(),
JSRegExpDoNotIgnoreCase, JSRegExpSingleLine, &m_numSubpatterns, &m_constructionError);
}
RegExp::RegExp(const UString& pattern, const UString& flags)
: m_refCount(0)
, m_pattern(pattern)
- , m_flags(0)
+ , m_flags(flags)
+ , m_flagBits(0)
, m_constructionError(0)
, m_numSubpatterns(0)
{
// NOTE: The global flag is handled on a case-by-case basis by functions like
// String::match and RegExpImp::match.
if (flags.find('g') != -1)
- m_flags |= Global;
+ m_flagBits |= Global;
// FIXME: Eliminate duplication by adding a way ask a JSRegExp what its flags are?
JSRegExpIgnoreCaseOption ignoreCaseOption = JSRegExpDoNotIgnoreCase;
if (flags.find('i') != -1) {
- m_flags |= IgnoreCase;
+ m_flagBits |= IgnoreCase;
ignoreCaseOption = JSRegExpIgnoreCase;
}
JSRegExpMultilineOption multilineOption = JSRegExpSingleLine;
if (flags.find('m') != -1) {
- m_flags |= Multiline;
+ m_flagBits |= Multiline;
multilineOption = JSRegExpMultiline;
}
- m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(m_pattern.data()), m_pattern.size(),
+ m_regExp = jsRegExpCompile(reinterpret_cast<const ::UChar*>(pattern.data()), pattern.size(),
ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError);
}
void deref() { if (--m_refCount == 0) delete this; }
int refCount() { return m_refCount; }
- bool global() const { return m_flags & Global; }
- bool ignoreCase() const { return m_flags & IgnoreCase; }
- bool multiline() const { return m_flags & Multiline; }
+ bool global() const { return m_flagBits & Global; }
+ bool ignoreCase() const { return m_flagBits & IgnoreCase; }
+ bool multiline() const { return m_flagBits & Multiline; }
+
const UString& pattern() const { return m_pattern; }
+ const UString& flags() const { return m_flags; }
bool isValid() const { return !m_constructionError; }
const char* errorMessage() const { return m_constructionError; }
int m_refCount;
// Data supplied by caller.
- UString m_pattern;
- int m_flags;
+ UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this.
+ UString m_flags; // FIXME: Just decompile m_regExp instead of storing this.
+ int m_flagBits;
// Data supplied by PCRE.
JSRegExp* m_regExp;
UString pattern = arg0->isUndefined() ? UString("") : arg0->toString(exec);
UString flags = arg1->isUndefined() ? UString("") : arg1->toString(exec);
- RefPtr<RegExp> regExp = new RegExp(pattern, flags);
+
+ return createRegExpImp(exec, new RegExp(pattern, flags));
+}
- return regExp->isValid()
- ? new RegExpImp(static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype()), regExp.release())
- : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
+JSObject* RegExpObjectImp::createRegExpImp(ExecState* exec, PassRefPtr<RegExp> regExp)
+{
+ return regExp->isValid()
+ ? new RegExpImp(static_cast<RegExpPrototype*>(exec->lexicalInterpreter()->builtinRegExpPrototype()), regExp)
+ : throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage()));
}
// ECMA 15.10.3
virtual bool implementsConstruct() const;
virtual JSObject* construct(ExecState*, const List&);
+ JSObject* createRegExpImp(ExecState*, PassRefPtr<RegExp>);
virtual JSValue* callAsFunction(ExecState*, JSObject*, const List&);
virtual void put(ExecState*, const Identifier&, JSValue*, int attributes = None);
void putValueProperty(ExecState*, int token, JSValue*, int attributes);