Remove excessive headers from JavaScriptCore
[WebKit-https.git] / Source / JavaScriptCore / runtime / RegExpMatchesArray.h
1 /*
2  *  Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
3  *
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.
8  *
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.
13  *
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
17  *
18  */
19
20 #pragma once
21
22 #include "ButterflyInlines.h"
23 #include "GCDeferralContextInlines.h"
24 #include "JSArray.h"
25 #include "JSCInlines.h"
26 #include "JSGlobalObject.h"
27 #include "RegExpInlines.h"
28 #include "RegExpObject.h"
29
30 namespace JSC {
31
32 static const PropertyOffset RegExpMatchesArrayIndexPropertyOffset = 100;
33 static const PropertyOffset RegExpMatchesArrayInputPropertyOffset = 101;
34
35 ALWAYS_INLINE JSArray* tryCreateUninitializedRegExpMatchesArray(ObjectInitializationScope& scope, GCDeferralContext* deferralContext, Structure* structure, unsigned initialLength)
36 {
37     VM& vm = scope.vm();
38     unsigned vectorLength = initialLength;
39     if (vectorLength > MAX_STORAGE_VECTOR_LENGTH)
40         return 0;
41
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)));
45     if (UNLIKELY(!temp))
46         return nullptr;
47     Butterfly* butterfly = Butterfly::fromBase(temp, 0, structure->outOfLineCapacity());
48     butterfly->setVectorLength(vectorLength);
49     butterfly->setPublicLength(initialLength);
50
51     unsigned i = (createUninitialized ? initialLength : 0);
52     for (; i < vectorLength; ++i)
53         butterfly->contiguous()[i].clear();
54
55     JSArray* result = JSArray::createWithButterfly(vm, deferralContext, structure, butterfly);
56     scope.notifyAllocated(result, createUninitialized);
57     return result;
58 }
59
60 ALWAYS_INLINE JSArray* createRegExpMatchesArray(
61     VM& vm, JSGlobalObject* globalObject, JSString* input, const String& inputValue,
62     RegExp* regExp, unsigned startOffset, MatchResult& result)
63 {
64     Vector<int, 32> subpatternResults;
65     int position = regExp->matchInline(vm, inputValue, startOffset, subpatternResults);
66     if (position == -1) {
67         result = MatchResult::failed();
68         return nullptr;
69     }
70
71     result.start = position;
72     result.end = subpatternResults[1];
73     
74     JSArray* array;
75
76     // FIXME: This should handle array allocation errors gracefully.
77     // https://bugs.webkit.org/show_bug.cgi?id=155144
78     
79     auto setProperties = [&] () {
80         array->putDirect(vm, RegExpMatchesArrayIndexPropertyOffset, jsNumber(result.start));
81         array->putDirect(vm, RegExpMatchesArrayInputPropertyOffset, input);
82     };
83     
84     unsigned numSubpatterns = regExp->numSubpatterns();
85     
86     GCDeferralContext deferralContext(vm.heap);
87     
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);
96
97         setProperties();
98         
99         array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start));
100         
101         for (unsigned i = 1; i <= numSubpatterns; ++i) {
102             int start = subpatternResults[2 * i];
103             JSValue value;
104             if (start >= 0)
105                 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
106             else
107                 value = jsUndefined();
108             array->initializeIndexWithoutBarrier(scope, i, value);
109         }
110     } else {
111         ObjectInitializationScope scope(vm);
112         array = tryCreateUninitializedRegExpMatchesArray(scope, &deferralContext, globalObject->regExpMatchesArrayStructure(), numSubpatterns + 1);
113         RELEASE_ASSERT(array);
114         
115         setProperties();
116         
117         // Now the object is safe to scan by GC.
118
119         array->initializeIndexWithoutBarrier(scope, 0, jsSubstringOfResolved(vm, &deferralContext, input, result.start, result.end - result.start), ArrayWithContiguous);
120         
121         for (unsigned i = 1; i <= numSubpatterns; ++i) {
122             int start = subpatternResults[2 * i];
123             JSValue value;
124             if (start >= 0)
125                 value = JSRopeString::createSubstringOfResolved(vm, &deferralContext, input, start, subpatternResults[2 * i + 1] - start);
126             else
127                 value = jsUndefined();
128             array->initializeIndexWithoutBarrier(scope, i, value, ArrayWithContiguous);
129         }
130     }
131     return array;
132 }
133
134 inline JSArray* createRegExpMatchesArray(ExecState* exec, JSGlobalObject* globalObject, JSString* string, RegExp* regExp, unsigned startOffset)
135 {
136     MatchResult ignoredResult;
137     return createRegExpMatchesArray(globalObject->vm(), globalObject, string, string->value(exec), regExp, startOffset, ignoredResult);
138 }
139 JSArray* createEmptyRegExpMatchesArray(JSGlobalObject*, JSString*, RegExp*);
140 Structure* createRegExpMatchesArrayStructure(VM&, JSGlobalObject*);
141 Structure* createRegExpMatchesArraySlowPutStructure(VM&, JSGlobalObject*);
142
143 } // namespace JSC