blob: 6dbe7fbdfcdb195741bc0dc6b2d78aa34df70de0 [file]
// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_REGEXP_REGEXP_H_
#define V8_REGEXP_REGEXP_H_
#include "vm/object.h"
#include "vm/regexp/base.h"
#include "vm/regexp/regexp-error.h"
#include "vm/regexp/regexp-flags.h"
#include "vm/regexp/zone-containers.h"
namespace dart {
class JSRegExp;
class RegExpCapture;
class RegExpData;
class IrRegExpData;
class AtomRegExpData;
class RegExpMatchInfo;
class RegExpNode;
class RegExpTree;
enum class RegExpCompilationTarget : int { kBytecode, kNative };
// TODO(jgruber): Do not expose in regexp.h.
// TODO(jgruber): Consider splitting between ParseData and CompileData.
struct RegExpCompileData {
// The parsed AST as produced by the RegExpParser.
RegExpTree* tree = nullptr;
// The compiled Node graph as produced by RegExpTree::ToNode methods.
RegExpNode* node = nullptr;
// Either the generated code as produced by the compiler or a trampoline
// to the interpreter.
Object* code;
// True, iff the pattern is a 'simple' atom with zero captures. In other
// words, the pattern consists of a string with no metacharacters and special
// regexp features, and can be implemented as a standard string search.
bool simple = true;
// True, iff the pattern is anchored at the start of the string with '^'.
bool contains_anchor = false;
// Only set if the pattern contains named captures.
// Note: the lifetime equals that of the parse/compile zone.
ZoneVector<RegExpCapture*>* named_captures = nullptr;
// The error message. Only used if an error occurred during parsing or
// compilation.
RegExpError error = RegExpError::kNone;
// The position at which the error was detected. Only used if an
// error occurred.
int error_pos = 0;
// The number of capture groups, without the global capture \0.
int capture_count = 0;
// The number of registers used by the generated code.
int register_count = 0;
// The compilation target (bytecode or native code).
RegExpCompilationTarget compilation_target;
};
class RegExpStatics final : public AllStatic {
public:
// Whether the irregexp engine generates interpreter bytecode.
static bool CanGenerateBytecode();
// Verify that the given flags combination is valid.
static bool VerifyFlags(RegExpFlags flags);
// Verify the given pattern, i.e. check that parsing succeeds. If
// verification fails, `regexp_error_out` is set.
template <class CharT>
static bool VerifySyntax(Zone* zone,
uintptr_t stack_limit,
const CharT* input,
int input_length,
RegExpFlags flags,
RegExpError* regexp_error_out);
// Parses the RegExp pattern and prepares the JSRegExp object with
// generic data and choice of implementation - as well as what
// the implementation wants to store in the data field.
// Returns false if compilation fails.
V8_WARN_UNUSED_RESULT static ObjectPtr Compile(Isolate* isolate,
const RegExp& re,
const String& pattern,
RegExpFlags flags,
uint32_t backtrack_limit);
// Ensures that a regexp is fully compiled and ready to be executed on a
// subject string. Returns true on success. Throw and return false on
// failure.
V8_WARN_UNUSED_RESULT static bool EnsureFullyCompiled(Isolate* isolate,
const RegExp& re_data,
const String& subject);
enum CallOrigin : int {
kFromRuntime = 0,
kFromJs = 1,
};
// See ECMA-262 section 15.10.6.2.
// This function calls the garbage collector if necessary.
V8_WARN_UNUSED_RESULT static std::optional<int> Exec(
Isolate* isolate,
RegExp& regexp,
const String& subject,
int index,
int32_t* result_offsets_vector,
uint32_t result_offsets_vector_length);
// As above, but passes the result through the old-style RegExpMatchInfo|Null
// interface. At most one match is returned.
V8_WARN_UNUSED_RESULT static ObjectPtr Exec_Single(Isolate* isolate,
RegExp& regexp,
const String& subject,
int index,
Object& last_match_info);
V8_WARN_UNUSED_RESULT static std::optional<int> ExperimentalOneshotExec(
Isolate* isolate,
RegExp& regexp,
const String& subject,
int index,
int32_t* result_offsets_vector,
uint32_t result_offsets_vector_length);
// Called directly from generated code through ExternalReference.
static intptr_t AtomExecRaw(Isolate* isolate,
uword /* AtomRegExpData */ data_address,
uword /* String */ subject_address,
int32_t index,
int32_t* result_offsets_vector,
int32_t result_offsets_vector_length);
// Integral return values used throughout regexp code layers.
static constexpr int kInternalRegExpFailure = 0;
static constexpr int kInternalRegExpSuccess = 1;
static constexpr int kInternalRegExpException = -1;
static constexpr int kInternalRegExpRetry = -2;
static constexpr int kInternalRegExpFallbackToExperimental = -3;
static constexpr int kInternalRegExpSmallestResult = -3;
enum IrregexpResult : int32_t {
RE_FAILURE = kInternalRegExpFailure,
RE_SUCCESS = kInternalRegExpSuccess,
RE_EXCEPTION = kInternalRegExpException,
RE_RETRY = kInternalRegExpRetry,
RE_FALLBACK_TO_EXPERIMENTAL = kInternalRegExpFallbackToExperimental,
};
// Set last match info. If match is nullptr, then setting captures is
// omitted.
static ObjectPtr SetLastMatchInfo(Isolate* isolate,
ObjectPtr last_match_info,
const String& subject,
int capture_count,
int32_t* match);
static bool CompileForTesting(Isolate* isolate,
Zone* zone,
RegExpCompileData* input,
RegExpFlags flags,
const String& pattern,
const String& sample_subject,
Object& re_data,
bool is_one_byte);
static void DotPrintForTesting(const char* label, RegExpNode* node);
static const int kRegExpTooLargeToOptimize = 20 * KB;
V8_WARN_UNUSED_RESULT
static ObjectPtr ThrowRegExpException(Isolate* isolate,
RegExpFlags flags,
const String& pattern,
RegExpError error);
static void ThrowRegExpException(Isolate* isolate,
const RegExp& re_data,
RegExpError error_text);
static bool IsUnmodifiedRegExp(Isolate* isolate, const RegExp& regexp);
static ArrayPtr CreateCaptureNameMap(
Isolate* isolate,
ZoneVector<RegExpCapture*>* named_captures);
static ObjectPtr Interpret(Thread* thread,
const RegExp& regexp,
const String& subject,
int start_index,
bool sticky);
};
} // namespace dart
#endif // V8_REGEXP_REGEXP_H_