Commit a862ba22 authored by ggaren@apple.com's avatar ggaren@apple.com
Browse files

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:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@27702 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent acca0adc
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.
......
......@@ -453,12 +453,7 @@ bool StringNode::evaluateToBoolean(ExecState*)
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 -------------------------------------
......
......@@ -28,6 +28,7 @@
#include "Parser.h"
#include "internal.h"
#include "RegExp.h"
#include "SymbolTable.h"
#include <wtf/ListRefPtr.h>
#include <wtf/OwnPtr.h>
......@@ -270,13 +271,14 @@ namespace KJS {
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 {
......
......@@ -290,7 +290,7 @@ void StringNode::streamTo(SourceStream& s) const
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
......@@ -33,40 +34,41 @@ namespace KJS {
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);
}
......
......@@ -46,10 +46,12 @@ namespace KJS {
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; }
......@@ -63,8 +65,9 @@ namespace KJS {
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;
......
......@@ -448,11 +448,15 @@ JSObject *RegExpObjectImp::construct(ExecState *exec, const List &args)
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
......
......@@ -85,6 +85,7 @@ namespace KJS {
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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment