Ignore:
Timestamp:
May 25, 2008, 12:15:42 AM (17 years ago)
Author:
[email protected]
Message:

Reviewed by Darin.

Changed regular expression matching result array to be lazily filled, because many callers
only care about it being non-null.

2% improvement on Acid3 test 26.

  • kjs/array_instance.cpp: Added a void* member to ArrayStorage for ArrayInstance subclasses to use.
  • kjs/array_instance.h: (KJS::ArrayInstance::lazyCreationData): (KJS::ArrayInstance::setLazyCreationData): Added methods to access it from subclasses.
  • kjs/regexp_object.cpp: (KJS::RegExpMatchesArray::RegExpMatchesArray): (KJS::RegExpMatchesArray::getOwnPropertySlot): (KJS::RegExpMatchesArray::put): (KJS::RegExpMatchesArray::deleteProperty): (KJS::RegExpMatchesArray::getPropertyNames): (KJS::RegExpMatchesArray::fillArrayInstanceIfNeeded): (KJS::RegExpMatchesArray::~RegExpMatchesArray): (KJS::RegExpObjectImp::arrayOfMatches): RegExpMatchesArray is a subclass of ArrayInstance that isn't filled until accessed for the first time.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/regexp_object.cpp

    r33979 r34118  
    315315}
    316316
     317class RegExpMatchesArray : public ArrayInstance {
     318public:
     319    RegExpMatchesArray(ExecState*, RegExpObjectImpPrivate*);
     320
     321    virtual ~RegExpMatchesArray();
     322
     323    virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (!lazyCreationData()) fillArrayInstance(exec); return ArrayInstance::getOwnPropertySlot(exec, propertyName, slot); }
     324    virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (!lazyCreationData()) fillArrayInstance(exec); return ArrayInstance::getOwnPropertySlot(exec, propertyName, slot); }
     325    virtual void put(ExecState* exec, const Identifier& propertyName, JSValue* v) { if (!lazyCreationData()) fillArrayInstance(exec); ArrayInstance::put(exec, propertyName, v); }
     326    virtual void put(ExecState* exec, unsigned propertyName, JSValue* v) { if (!lazyCreationData()) fillArrayInstance(exec); ArrayInstance::put(exec, propertyName, v); }
     327    virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { if (!lazyCreationData()) fillArrayInstance(exec); return ArrayInstance::deleteProperty(exec, propertyName); }
     328    virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { if (!lazyCreationData()) fillArrayInstance(exec); return ArrayInstance::deleteProperty(exec, propertyName); }
     329    virtual void getPropertyNames(ExecState* exec, PropertyNameArray& arr) { if (!lazyCreationData()) fillArrayInstance(exec); ArrayInstance::getPropertyNames(exec, arr); }
     330
     331private:
     332    void fillArrayInstance(ExecState*);
     333};
     334
     335RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpObjectImpPrivate* data)
     336    : ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), data->lastNumSubPatterns + 1)
     337{
     338    RegExpObjectImpPrivate* d = new RegExpObjectImpPrivate;
     339    d->lastInput = data->lastInput;
     340    d->lastNumSubPatterns = data->lastNumSubPatterns;
     341    unsigned offsetVectorSize = (data->lastNumSubPatterns + 1) * 2; // only copying the result part of the vector
     342    d->lastOvector.set(new int[offsetVectorSize]);
     343    memcpy(d->lastOvector.get(), data->lastOvector.get(), offsetVectorSize * sizeof(int));
     344    // d->multiline is not needed, and remains uninitialized
     345
     346    setLazyCreationData(d);
     347}
     348
     349RegExpMatchesArray::~RegExpMatchesArray()
     350{
     351    delete static_cast<RegExpObjectImpPrivate*>(lazyCreationData());
     352}
     353
     354void RegExpMatchesArray::fillArrayInstance(ExecState* exec)
     355{
     356    RegExpObjectImpPrivate* d = static_cast<RegExpObjectImpPrivate*>(lazyCreationData());
     357    ASSERT(d);
     358
     359    unsigned lastNumSubpatterns = d->lastNumSubPatterns;
     360
     361    for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
     362        int start = d->lastOvector[2 * i];
     363        if (start >= 0)
     364            ArrayInstance::put(exec, i, jsString(d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start)));
     365    }
     366    ArrayInstance::put(exec, exec->propertyNames().index, jsNumber(d->lastOvector[0]));
     367    ArrayInstance::put(exec, exec->propertyNames().input, jsString(d->lastInput));
     368
     369    delete d;
     370    setLazyCreationData(0);
     371}
     372
    317373JSObject* RegExpObjectImp::arrayOfMatches(ExecState* exec) const
    318374{
    319   unsigned lastNumSubpatterns = d->lastNumSubPatterns;
    320   ArrayInstance* arr = new ArrayInstance(exec->lexicalGlobalObject()->arrayPrototype(), lastNumSubpatterns + 1);
    321   for (unsigned i = 0; i <= lastNumSubpatterns; ++i) {
    322     int start = d->lastOvector[2 * i];
    323     if (start >= 0)
    324       arr->put(exec, i, jsString(d->lastInput.substr(start, d->lastOvector[2 * i + 1] - start)));
    325   }
    326   arr->put(exec, exec->propertyNames().index, jsNumber(d->lastOvector[0]));
    327   arr->put(exec, exec->propertyNames().input, jsString(d->lastInput));
    328   return arr;
     375    return new RegExpMatchesArray(exec, d.get());
    329376}
    330377
Note: See TracChangeset for help on using the changeset viewer.