diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/runtime/RegExpMatchesArray.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/runtime/RegExpMatchesArray.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/RegExpMatchesArray.h | 207 |
1 files changed, 101 insertions, 106 deletions
diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h index 67fdcb6e1..64ceccb8f 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -17,124 +17,119 @@ * */ -#ifndef RegExpMatchesArray_h -#define RegExpMatchesArray_h +#pragma once +#include "ButterflyInlines.h" +#include "GCDeferralContextInlines.h" #include "JSArray.h" +#include "JSCInlines.h" #include "JSGlobalObject.h" +#include "RegExpInlines.h" #include "RegExpObject.h" namespace JSC { - class RegExpMatchesArray : public JSArray { - private: - RegExpMatchesArray(VM&, Butterfly*, JSGlobalObject*, JSString*, RegExp*, MatchResult); - - enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll }; - - public: - typedef JSArray Base; - - static RegExpMatchesArray* create(ExecState*, JSString*, RegExp*, MatchResult); - - JSString* leftContext(ExecState*); - JSString* rightContext(ExecState*); - - DECLARE_INFO; - - static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) - { - return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayWithSlowPutArrayStorage); - } - - static void visitChildren(JSCell*, SlotVisitor&); - - protected: - void finishCreation(VM&); - - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags; - - private: - ALWAYS_INLINE void reifyAllPropertiesIfNecessary(ExecState* exec) - { - if (m_state != ReifiedAll) - reifyAllProperties(exec); - } - - ALWAYS_INLINE void reifyMatchPropertyIfNecessary(ExecState* exec) - { - if (m_state == ReifiedNone) - reifyMatchProperty(exec); - } - - static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - thisObject->reifyAllPropertiesIfNecessary(exec); - return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot); - } +static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100; +static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101; + +ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(VM& vm, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength) +{ + unsigned vectorLength = initialLength; + if (vectorLength > MAX_STORAGE_VECTOR_LENGTH) + return 0; + + void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue))); + if (!temp) + return nullptr; + Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity()); + butterfly->setVectorLength(vectorLength); + butterfly->setPublicLength(initialLength); + + for (unsigned i = initialLength; i < vectorLength; ++i) + butterfly->contiguous()[i].clear(); + + return JSArray::createWithButterfly(vm, deferralContext, structure, butterfly); +} - static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned propertyName, PropertySlot& slot) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - if (propertyName) - thisObject->reifyAllPropertiesIfNecessary(exec); +ALWAYS_INLINE JSArray* createRegExpMatchesArray( + VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue, + RegExp* regExp, unsigned startOffset, MatchResult& result) +{ + Vector<int, 32> subpatternResults; + int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults); + if (position == -1) { + result = MatchResult::failed(); + return nullptr; + } + + result.start = position; + result.end = subpatternResults[1]; + + JSArray* array; + + // FIXME: This should handle array allocation errors gracefully. + // https://bugs.webkit.org/show_bug.cgi?id=155144 + + auto setProperties = [&] () { + array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start)); + array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input); + }; + + unsigned numSubpatterns = regExp->numSubpatterns(); + + GCDeferralContext deferralContext(vm.heap); + + if (UNLIKELY(globalObject->isHavingABadTime())) { + array = JSArray::tryCreateForInitializationPrivate(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1); + // FIXME: we should probably throw an out of memory error here, but + // when making this change we should check that all clients of this + // function will correctly handle an exception being thrown from here. + // https://bugs.webkit.org/show_bug.cgi?id=169786 + RELEASE_ASSERT(array); + + setProperties(); + + array->initializeIndexWithoutBarrier(0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start)); + + for (unsigned i = 1; i <= numSubpatterns; ++i) { + int start = subpatternResults[2 * i]; + JSValue value; + if (start >= 0) + value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start); else - thisObject->reifyMatchPropertyIfNecessary(exec); - return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot); - } - - static void put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue v, PutPropertySlot& slot) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - thisObject->reifyAllPropertiesIfNecessary(exec); - JSArray::put(thisObject, exec, propertyName, v, slot); + value = jsUndefined(); + array->initializeIndexWithoutBarrier(i, value); } + } else { + array = tryCreateUninitializedRegExpMatchesArray(vm, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1); + RELEASE_ASSERT(array); - static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - thisObject->reifyAllPropertiesIfNecessary(exec); - JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow); - } - - static bool deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - thisObject->reifyAllPropertiesIfNecessary(exec); - return JSArray::deleteProperty(thisObject, exec, propertyName); - } - - static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - thisObject->reifyAllPropertiesIfNecessary(exec); - return JSArray::deletePropertyByIndex(thisObject, exec, propertyName); - } - - static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - thisObject->reifyAllPropertiesIfNecessary(exec); - JSArray::getOwnPropertyNames(thisObject, exec, arr, mode); - } + setProperties(); + + // Now the object is safe to scan by GC. - static bool defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow) - { - RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - thisObject->reifyAllPropertiesIfNecessary(exec); - return JSArray::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); + array->initializeIndexWithoutBarrier(0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous); + + for (unsigned i = 1; i <= numSubpatterns; ++i) { + int start = subpatternResults[2 * i]; + JSValue value; + if (start >= 0) + value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start); + else + value = jsUndefined(); + array->initializeIndexWithoutBarrier(i, value, ArrayWithContiguous); } + } + return array; +} - void reifyAllProperties(ExecState*); - void reifyMatchProperty(ExecState*); - - WriteBarrier<JSString> m_input; - WriteBarrier<RegExp> m_regExp; - MatchResult m_result; - ReifiedState m_state; -}; - +inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset) +{ + MatchResult ignoredResult; + return createRegExpMatchesArray(globalObject->vm(), globalObject, string, string->value(exec), regExp, startOffset, ignoredResult); } +JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*); +Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*); +Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*); -#endif // RegExpMatchesArray_h +} // namespace JSC |