2 * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "ButterflyInlines.h"
23 #include "GCDeferralContextInlines.h"
25 #include "JSCInlines.h"
26 #include "JSGlobalObject.h"
27 #include "RegExpInlines.h"
28 #include "RegExpObject.h"
32 static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
33 static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
35 ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
38 unsigned vectorLength = initialLength;
39 if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
42 JSGlobalObject* globalObject = structure->globalObject();
43 bool createUninitialized = globalObject->isOriginalArrayStructure(structure);
44 void* temp = vm.auxiliarySpace.tryAllocate(deferralContext, Butterfly::totalSize(0, structure->outOfLineCapacity(), true, vectorLength * sizeof(EncodedJSValue)));
47 Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
48 butterfly->setVectorLength(vectorLength);
49 butterfly->setPublicLength(initialLength);
51 unsigned i = (createUninitialized ? initialLength : 0);
52 for (; i < vectorLength; ++i)
53 butterfly->contiguous()[i].clear();
55 JSArray* result = JSArray::createWithButterfly(vm, deferralContext, structure, butterfly);
56 scope.notifyAllocated(result, createUninitialized);
60 ALWAYS_INLINE JSArray* createRegExpMatchesArray(
61 VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue,
62 RegExp* regExp, unsigned startOffset, MatchResult& result)
64 Vector<int, 32> subpatternResults;
65 int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults);
67 result = MatchResult::failed();
71 result.start = position;
72 result.end = subpatternResults[1];
76 // FIXME: This should handle array allocation errors gracefully.
77 // https://bugs.webkit.org/show_bug.cgi?id=155144
79 auto setProperties = [&] () {
80 array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start));
81 array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
84 unsigned numSubpatterns = regExp->numSubpatterns();
86 GCDeferralContext deferralContext(vm.heap);
88 if (UNLIKELY(globalObject->isHavingABadTime())) {
89 ObjectInitializationScope scope(vm);
90 array = JSArray::tryCreateUninitializedRestricted(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
91 // FIXME: we should probably throw an out of memory error here, but
92 // when making this change we should check that all clients of this
93 // function will correctly handle an exception being thrown from here.
94 // https://bugs.webkit.org/show_bug.cgi?id=169786
95 RELEASE_ASSERT(array);
99 array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));
101 for (unsigned i = 1; i <= numSubpatterns; ++i) {
102 int start = subpatternResults[2 * i];
105 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
107 value = jsUndefined();
108 array->initializeIndexWithoutBarrier(scope, i, value);
111 ObjectInitializationScope scope(vm);
112 array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
113 RELEASE_ASSERT(array);
117 // Now the object is safe to scan by GC.
119 array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);
121 for (unsigned i = 1; i <= numSubpatterns; ++i) {
122 int start = subpatternResults[2 * i];
125 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
127 value = jsUndefined();
128 array->initializeIndexWithoutBarrier(scope, i, value, ArrayWithContiguous);
134 inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset)
136 MatchResult ignoredResult;
137 return createRegExpMatchesArray(globalObject->vm(), globalObject, string, string->value(exec), regExp, startOffset, ignoredResult);
139 JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*);
140 Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*);
141 Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*);