v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
js-regexp.h
Go to the documentation of this file.
1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_OBJECTS_JS_REGEXP_H_
6#define V8_OBJECTS_JS_REGEXP_H_
7
8#include <optional>
9
10#include "include/v8-regexp.h"
14#include "torque-generated/bit-fields.h"
15
16// Has to be the last include (doesn't have include guards):
18
19namespace v8::internal {
20
21class RegExpData;
22
23#include "torque-generated/src/objects/js-regexp-tq.inc"
24
25class RegExpData;
26
27// Regular expressions
28class JSRegExp : public TorqueGeneratedJSRegExp<JSRegExp, JSObject> {
29 public:
30 DEFINE_TORQUE_GENERATED_JS_REG_EXP_FLAGS()
31
33 Isolate* isolate, DirectHandle<String> source, Flags flags,
34 uint32_t backtrack_limit = kNoBacktrackLimit);
35
38 uint32_t backtrack_limit = kNoBacktrackLimit);
41 DirectHandle<String> flags_string);
42
44
45 // Instance fields accessors.
46 inline Tagged<String> source() const;
47 inline Flags flags() const;
48
50
51 static constexpr Flag AsJSRegExpFlag(RegExpFlag f) {
52 return static_cast<Flag>(f);
53 }
54 static constexpr Flags AsJSRegExpFlags(RegExpFlags f) {
55 return Flags{static_cast<int>(f)};
56 }
57 static constexpr RegExpFlags AsRegExpFlags(Flags f) {
58 return RegExpFlags{static_cast<int>(f)};
59 }
60
61 static std::optional<RegExpFlag> FlagFromChar(char c) {
62 std::optional<RegExpFlag> f = TryRegExpFlagFromChar(c);
63 if (!f.has_value()) return f;
64 if (f.value() == RegExpFlag::kLinear &&
65 !v8_flags.enable_experimental_regexp_engine) {
66 return {};
67 }
68 return f;
69 }
70
71 static_assert(static_cast<int>(kNone) == v8::RegExp::kNone);
72#define V(_, Camel, ...) \
73 static_assert(static_cast<int>(k##Camel) == v8::RegExp::k##Camel); \
74 static_assert(static_cast<int>(k##Camel) == \
75 static_cast<int>(RegExpFlag::k##Camel));
77#undef V
78 static_assert(kFlagCount == v8::RegExp::kFlagCount);
79 static_assert(kFlagCount == kRegExpFlagCount);
80
81 static std::optional<Flags> FlagsFromString(Isolate* isolate,
82 DirectHandle<String> flags);
83
84 V8_EXPORT_PRIVATE static DirectHandle<String> StringFromFlags(
85 Isolate* isolate, Flags flags);
86
88
89 // Each capture (including the match itself) needs two registers.
90 static constexpr int RegistersForCaptureCount(int count) {
91 return (count + 1) * 2;
92 }
93 static constexpr int CaptureCountForRegisters(int register_count) {
94 DCHECK_EQ(register_count % 2, 0);
95 DCHECK_GE(register_count, 2);
96 return (register_count - 2) / 2;
97 }
98 // ATOM regexps don't have captures.
99 static constexpr int kAtomCaptureCount = 0;
100 static constexpr int kAtomRegisterCount = 2;
101
102 // Dispatched behavior.
105
106 /* This is already an in-object field. */
107 // TODO(v8:8944): improve handling of in-object fields
108 static constexpr int kLastIndexOffset = kHeaderSize;
109
110 // The initial value of the last_index field on a new JSRegExp instance.
111 static constexpr int kInitialLastIndexValue = 0;
112
113 // In-object fields.
114 static constexpr int kLastIndexFieldIndex = 0;
115 static constexpr int kInObjectFieldCount = 1;
116
117 // The actual object size including in-object fields.
118 static constexpr int kSize = kHeaderSize + kInObjectFieldCount * kTaggedSize;
119 static constexpr int Size() { return kSize; }
120
121 // Descriptor array index to important methods in the prototype.
122 static constexpr int kExecFunctionDescriptorIndex = 1;
123 static constexpr int kSymbolMatchFunctionDescriptorIndex = 15;
124 static constexpr int kSymbolMatchAllFunctionDescriptorIndex = 16;
125 static constexpr int kSymbolReplaceFunctionDescriptorIndex = 17;
126 static constexpr int kSymbolSearchFunctionDescriptorIndex = 18;
127 static constexpr int kSymbolSplitFunctionDescriptorIndex = 19;
128
129 // The uninitialized value for a regexp code object.
130 static constexpr int kUninitializedValue = -1;
131
132 // If the backtrack limit is set to this marker value, no limit is applied.
133 static constexpr uint32_t kNoBacktrackLimit = 0;
134
135 // The heuristic value for the length of the subject string for which we
136 // tier-up to the compiler immediately, instead of using the interpreter.
137 static constexpr int kTierUpForSubjectLengthValue = 1000;
138
139 // Maximum number of captures allowed.
140 static constexpr int kMaxCaptures = 1 << 16;
141
142 class BodyDescriptor;
143
144 private:
146 inline static const char* FlagsToString(Flags flags, FlagsBuffer* out_buffer);
147
148 friend class RegExpData;
149
151};
152
153DEFINE_OPERATORS_FOR_FLAGS(JSRegExp::Flags)
154
156
158 public:
159 enum class Type : uint8_t {
160 ATOM, // A simple string match.
161 IRREGEXP, // Compiled with Irregexp (code or bytecode).
162 EXPERIMENTAL, // Compiled to use the experimental linear time engine.
163 };
164
165 inline Type type_tag() const;
166 inline void set_type_tag(Type);
167
169
170 inline JSRegExp::Flags flags() const;
171 inline void set_flags(JSRegExp::Flags flags);
172
174
175 inline int capture_count() const;
176
177 static constexpr bool TypeSupportsCaptures(Type t) {
178 return t == Type::IRREGEXP || t == Type::EXPERIMENTAL;
179 }
180
182
185
186#define FIELD_LIST(V) \
187 V(kTypeTagOffset, kTaggedSize) \
188 V(kSourceOffset, kTaggedSize) \
189 V(kFlagsOffset, kTaggedSize) \
190 V(kWrapperOffset, kTaggedSize) \
191 V(kHeaderSize, 0) \
192 V(kSize, 0)
193
195
196#undef FIELD_LIST
197
198 class BodyDescriptor;
199
201};
202
203class RegExpDataWrapper : public Struct {
204 public:
206
209
210#define FIELD_LIST(V) \
211 V(kDataOffset, kTrustedPointerSize) \
212 V(kHeaderSize, 0) \
213 V(kSize, 0)
214
215 DEFINE_FIELD_OFFSET_CONSTANTS(Struct::kHeaderSize, FIELD_LIST)
216#undef FIELD_LIST
217
218 class BodyDescriptor;
219
221};
222
224 public:
226
229
230#define FIELD_LIST(V) \
231 V(kPatternOffset, kTaggedSize) \
232 V(kHeaderSize, 0) \
233 V(kSize, 0)
234
236
237#undef FIELD_LIST
238
239 class BodyDescriptor;
240
242};
243
244class IrRegExpData : public RegExpData {
245 public:
246 DECL_CODE_POINTER_ACCESSORS(latin1_code)
248 inline bool has_code(bool is_one_byte) const;
249 inline void set_code(bool is_one_byte, Tagged<Code> code);
250 inline Tagged<Code> code(IsolateForSandbox isolate, bool is_one_byte) const;
253 inline bool has_bytecode(bool is_one_byte) const;
254 inline void clear_bytecode(bool is_one_byte);
255 inline void set_bytecode(bool is_one_byte, Tagged<TrustedByteArray> bytecode);
256 inline Tagged<TrustedByteArray> bytecode(bool is_one_byte) const;
259 DECL_INT_ACCESSORS(max_register_count)
260 // Number of captures (without the match itself).
262 DECL_INT_ACCESSORS(ticks_until_tier_up)
263 DECL_INT_ACCESSORS(backtrack_limit)
264
265 bool CanTierUp();
266 bool MarkedForTierUp();
267 void ResetLastTierUpTick();
268 void TierUpTick();
271
273
274 // Sets the bytecode as well as initializing trampoline slots to the
275 // RegExpExperimentalTrampoline.
277 Tagged<TrustedByteArray> bytecode);
278
281
282#define FIELD_LIST(V) \
283 V(kLatin1BytecodeOffset, kProtectedPointerSize) \
284 V(kUc16BytecodeOffset, kProtectedPointerSize) \
285 V(kLatin1CodeOffset, kCodePointerSize) \
286 V(kUc16CodeOffset, kCodePointerSize) \
287 V(kCaptureNameMapOffset, kTaggedSize) \
288 V(kMaxRegisterCountOffset, kTaggedSize) \
289 V(kCaptureCountOffset, kTaggedSize) \
290 V(kTicksUntilTierUpOffset, kTaggedSize) \
291 V(kBacktrackLimitOffset, kTaggedSize) \
292 V(kHeaderSize, 0) \
293 V(kSize, 0)
294
296
297#undef FIELD_LIST
298
299 class BodyDescriptor;
300
302};
303
304// JSRegExpResult is just a JSArray with a specific initial map.
305// This initial map adds in-object properties for "index" and "input"
306// properties, as assigned by RegExp.prototype.exec, which allows
307// faster creation of RegExp exec results.
308// This class just holds constants used when creating the result.
309// After creation the result must be treated as a JSArray in all regards.
311 : public TorqueGeneratedJSRegExpResult<JSRegExpResult, JSArray> {
312 public:
313 // TODO(joshualitt): We would like to add printers and verifiers to
314 // JSRegExpResult, and maybe JSRegExpResultIndices, but both have the same
315 // instance type as JSArray.
316
317 // Indices of in-object properties.
318 static constexpr int kIndexIndex = 0;
319 static constexpr int kInputIndex = 1;
320 static constexpr int kGroupsIndex = 2;
321
322 // Private internal only fields.
323 static constexpr int kNamesIndex = 3;
324 static constexpr int kRegExpInputIndex = 4;
325 static constexpr int kRegExpLastIndex = 5;
326 static constexpr int kInObjectPropertyCount = 6;
327
328 static constexpr int kMapIndexInContext = Context::REGEXP_RESULT_MAP_INDEX;
329
331};
332
334 : public TorqueGeneratedJSRegExpResultWithIndices<JSRegExpResultWithIndices,
335 JSRegExpResult> {
336 public:
337 static_assert(
339 "JSRegExpResultWithIndices must be a subclass of JSRegExpResult");
340 static constexpr int kIndicesIndex = 6;
341 static constexpr int kInObjectPropertyCount = 7;
342
344};
345
346// JSRegExpResultIndices is just a JSArray with a specific initial map.
347// This initial map adds in-object properties for "group"
348// properties, as assigned by RegExp.prototype.exec, which allows
349// faster creation of RegExp exec results.
350// This class just holds constants used when creating the result.
351// After creation the result must be treated as a JSArray in all regards.
353 : public TorqueGeneratedJSRegExpResultIndices<JSRegExpResultIndices,
354 JSArray> {
355 public:
357 Isolate* isolate, DirectHandle<RegExpMatchInfo> match_info,
358 DirectHandle<Object> maybe_names);
359
360 // Indices of in-object properties.
361 static constexpr int kGroupsIndex = 0;
362 static constexpr int kInObjectPropertyCount = 1;
363
364 // Descriptor index of groups.
365 static constexpr int kGroupsDescriptorIndex = 1;
366
368};
369
370} // namespace v8::internal
371
373
374#endif // V8_OBJECTS_JS_REGEXP_H_
#define DEFINE_OPERATORS_FOR_FLAGS(Type)
Definition flags.h:100
static constexpr int kFlagCount
Definition v8-regexp.h:42
OBJECT_CONSTRUCTORS(AtomRegExpData, RegExpData)
static constexpr int kHeaderSize
void SetBytecodeForExperimental(Isolate *isolate, Tagged< TrustedByteArray > bytecode)
Definition js-regexp.cc:425
bool has_code(bool is_one_byte) const
void set_code(bool is_one_byte, Tagged< Code > code)
void set_bytecode(bool is_one_byte, Tagged< TrustedByteArray > bytecode)
bool has_bytecode(bool is_one_byte) const
void DiscardCompiledCodeForSerialization()
Definition js-regexp.cc:417
void set_capture_name_map(DirectHandle< FixedArray > capture_name_map)
OBJECT_CONSTRUCTORS(IrRegExpData, RegExpData)
void clear_bytecode(bool is_one_byte)
static DirectHandle< JSRegExpResultIndices > BuildIndices(Isolate *isolate, DirectHandle< RegExpMatchInfo > match_info, DirectHandle< Object > maybe_names)
Definition js-regexp.cc:18
static constexpr int kGroupsDescriptorIndex
Definition js-regexp.h:365
static constexpr int kInObjectPropertyCount
Definition js-regexp.h:362
static constexpr int kGroupsIndex
Definition js-regexp.h:361
static constexpr int kInObjectPropertyCount
Definition js-regexp.h:341
static constexpr int kInputIndex
Definition js-regexp.h:319
static constexpr int kNamesIndex
Definition js-regexp.h:323
static constexpr int kGroupsIndex
Definition js-regexp.h:320
static constexpr int kInObjectPropertyCount
Definition js-regexp.h:326
static constexpr int kRegExpInputIndex
Definition js-regexp.h:324
static constexpr int kRegExpLastIndex
Definition js-regexp.h:325
static constexpr int kIndexIndex
Definition js-regexp.h:318
static constexpr int kMapIndexInContext
Definition js-regexp.h:328
static const char * FlagsToString(Flags flags, FlagsBuffer *out_buffer)
static constexpr Flag AsJSRegExpFlag(RegExpFlag f)
Definition js-regexp.h:51
Tagged< String > source() const
static constexpr int kLastIndexFieldIndex
Definition js-regexp.h:114
static constexpr int Size()
Definition js-regexp.h:119
static MaybeDirectHandle< JSRegExp > Initialize(DirectHandle< JSRegExp > regexp, DirectHandle< String > source, Flags flags, uint32_t backtrack_limit=kNoBacktrackLimit)
Definition js-regexp.cc:328
static constexpr int kAtomRegisterCount
Definition js-regexp.h:100
static constexpr int kSymbolMatchAllFunctionDescriptorIndex
Definition js-regexp.h:124
static constexpr RegExpFlags AsRegExpFlags(Flags f)
Definition js-regexp.h:57
static constexpr uint32_t kNoBacktrackLimit
Definition js-regexp.h:133
static constexpr int kLastIndexOffset
Definition js-regexp.h:108
Tagged< String > EscapedPattern()
static constexpr int kSymbolReplaceFunctionDescriptorIndex
Definition js-regexp.h:125
static V8_EXPORT_PRIVATE DirectHandle< String > StringFromFlags(Isolate *isolate, Flags flags)
Definition js-regexp.cc:144
static V8_EXPORT_PRIVATE MaybeDirectHandle< JSRegExp > New(Isolate *isolate, DirectHandle< String > source, Flags flags, uint32_t backtrack_limit=kNoBacktrackLimit)
Definition js-regexp.cc:152
static constexpr int kMaxCaptures
Definition js-regexp.h:140
static constexpr int CaptureCountForRegisters(int register_count)
Definition js-regexp.h:93
static constexpr Flags AsJSRegExpFlags(RegExpFlags f)
Definition js-regexp.h:54
static std::optional< RegExpFlag > FlagFromChar(char c)
Definition js-regexp.h:61
static constexpr int kExecFunctionDescriptorIndex
Definition js-regexp.h:122
static constexpr int kUninitializedValue
Definition js-regexp.h:130
static constexpr int RegistersForCaptureCount(int count)
Definition js-regexp.h:90
static constexpr int kSymbolSearchFunctionDescriptorIndex
Definition js-regexp.h:126
static constexpr int kInObjectFieldCount
Definition js-regexp.h:115
static constexpr int kAtomCaptureCount
Definition js-regexp.h:99
static std::optional< Flags > FlagsFromString(Isolate *isolate, DirectHandle< String > flags)
Definition js-regexp.cc:123
static constexpr int kSize
Definition js-regexp.h:118
static constexpr int kTierUpForSubjectLengthValue
Definition js-regexp.h:137
static constexpr int kInitialLastIndexValue
Definition js-regexp.h:111
static constexpr int kSymbolSplitFunctionDescriptorIndex
Definition js-regexp.h:127
static constexpr int kSymbolMatchFunctionDescriptorIndex
Definition js-regexp.h:123
OBJECT_CONSTRUCTORS(RegExpDataWrapper, Struct)
JSRegExp::Flags flags() const
V8_EXPORT_PRIVATE bool HasCompiledCode() const
Definition js-regexp.cc:371
void set_flags(JSRegExp::Flags flags)
static constexpr bool TypeSupportsCaptures(Type t)
Definition js-regexp.h:177
OBJECT_CONSTRUCTORS(RegExpData, ExposedTrustedObject)
DirectHandle< FixedArray > capture_name_map
std::string pattern
#define FIELD_LIST(V)
constexpr std::optional< RegExpFlag > TryRegExpFlagFromChar(char c)
V8_EXPORT_PRIVATE base::Vector< Flag > Flags()
Definition flags.cc:300
constexpr int kTaggedSize
Definition globals.h:542
constexpr int kRegExpFlagCount
Tagged(T object) -> Tagged< T >
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DECL_ACCESSORS(name,...)
#define DECL_TRUSTED_POINTER_ACCESSORS(name, type)
#define DECL_CODE_POINTER_ACCESSORS(name)
#define DECL_VERIFIER(Name)
#define DECL_PROTECTED_POINTER_ACCESSORS(name, type)
#define DECL_PRINTER(Name)
#define DECL_INT_ACCESSORS(name)
#define TQ_OBJECT_CONSTRUCTORS(Type)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define DEFINE_FIELD_OFFSET_CONSTANTS(StartOffset, LIST_MACRO)
Definition utils.h:242