// 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 "regexp/regexp-error.h" #include "regexp/regexp-shim.h" namespace v8 { namespace internal { 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 use if the pattern contains named captures. If so, this contains a // mapping of capture names to capture indices. Handle capture_name_map; // 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 RegExp final : public AllStatic { public: // Whether the irregexp engine generates interpreter bytecode. static bool CanGenerateBytecode() { return FLAG_regexp_interpret_all || FLAG_regexp_tier_up; } // 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 MaybeHandle Compile( Isolate* isolate, Handle re, Handle pattern, JSRegExp::Flags flags, uint32_t backtrack_limit); enum CallOrigin : int { kFromRuntime = 0, kFromJs = 1, }; // See ECMA-262 section 15.10.6.2. // This function calls the garbage collector if necessary. V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT static MaybeHandle Exec( Isolate* isolate, Handle regexp, Handle subject, int index, Handle last_match_info); // 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; enum IrregexpResult : int32_t { RE_FAILURE = kInternalRegExpFailure, RE_SUCCESS = kInternalRegExpSuccess, RE_EXCEPTION = kInternalRegExpException, }; // Prepare a RegExp for being executed one or more times (using // IrregexpExecOnce) on the subject. // This ensures that the regexp is compiled for the subject, and that // the subject is flat. // Returns the number of integer spaces required by IrregexpExecOnce // as its "registers" argument. If the regexp cannot be compiled, // an exception is set as pending, and this function returns negative. static int IrregexpPrepare(Isolate* isolate, Handle regexp, Handle subject); // Set last match info. If match is nullptr, then setting captures is // omitted. static Handle SetLastMatchInfo( Isolate* isolate, Handle last_match_info, Handle subject, int capture_count, int32_t* match); V8_EXPORT_PRIVATE static bool CompileForTesting(Isolate* isolate, Zone* zone, RegExpCompileData* input, JSRegExp::Flags flags, Handle pattern, Handle sample_subject, bool is_one_byte); V8_EXPORT_PRIVATE static void DotPrintForTesting(const char* label, RegExpNode* node); static const int kRegExpTooLargeToOptimize = 20 * KB; }; // Uses a special global mode of irregexp-generated code to perform a global // search and return multiple results at once. As such, this is essentially an // iterator over multiple results (retrieved batch-wise in advance). class RegExpGlobalCache final { public: RegExpGlobalCache(Handle regexp, Handle subject, Isolate* isolate); ~RegExpGlobalCache(); // Fetch the next entry in the cache for global regexp match results. // This does not set the last match info. Upon failure, nullptr is // returned. The cause can be checked with Result(). The previous result is // still in available in memory when a failure happens. int32_t* FetchNext(); int32_t* LastSuccessfulMatch(); bool HasException() { return num_matches_ < 0; } private: int AdvanceZeroLength(int last_index); int num_matches_; int max_matches_; int current_match_index_; int registers_per_match_; // Pointer to the last set of captures. int32_t* register_array_; int register_array_size_; Handle regexp_; Handle subject_; Isolate* isolate_; }; // Caches results for specific regexp queries on the isolate. At the time of // writing, this is used during global calls to RegExp.prototype.exec and // @@split. class RegExpResultsCache final : public AllStatic { public: enum ResultsCacheType { REGEXP_MULTIPLE_INDICES, STRING_SPLIT_SUBSTRINGS }; // Attempt to retrieve a cached result. On failure, 0 is returned as a Smi. // On success, the returned result is guaranteed to be a COW-array. static Object Lookup(Heap* heap, String key_string, Object key_pattern, FixedArray* last_match_out, ResultsCacheType type); // Attempt to add value_array to the cache specified by type. On success, // value_array is turned into a COW-array. static void Enter(Isolate* isolate, Handle key_string, Handle key_pattern, Handle value_array, Handle last_match_cache, ResultsCacheType type); static void Clear(FixedArray cache); static constexpr int kRegExpResultsCacheSize = 0x100; private: static constexpr int kStringOffset = 0; static constexpr int kPatternOffset = 1; static constexpr int kArrayOffset = 2; static constexpr int kLastMatchOffset = 3; static constexpr int kArrayEntriesPerCacheEntry = 4; }; } // namespace internal } // namespace v8 #endif // V8_REGEXP_REGEXP_H_