11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_BUILTINS_BUILTINS_REGEXP_GEN_H_ 61cb0ef41Sopenharmony_ci#define V8_BUILTINS_BUILTINS_REGEXP_GEN_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/optional.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/code-stub-assembler.h" 101cb0ef41Sopenharmony_ci#include "src/common/message-template.h" 111cb0ef41Sopenharmony_ci#include "src/regexp/regexp.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_cinamespace internal { 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciclass RegExpBuiltinsAssembler : public CodeStubAssembler { 171cb0ef41Sopenharmony_ci public: 181cb0ef41Sopenharmony_ci explicit RegExpBuiltinsAssembler(compiler::CodeAssemblerState* state) 191cb0ef41Sopenharmony_ci : CodeStubAssembler(state) {} 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_ci TNode<Smi> SmiZero(); 221cb0ef41Sopenharmony_ci TNode<IntPtrT> IntPtrZero(); 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci TNode<RawPtrT> LoadCodeObjectEntry(TNode<CodeT> code); 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci // Allocate either a JSRegExpResult or a JSRegExpResultWithIndices (depending 271cb0ef41Sopenharmony_ci // on has_indices) with the given length (the number of captures, including 281cb0ef41Sopenharmony_ci // the match itself), index (the index where the match starts), and input 291cb0ef41Sopenharmony_ci // string. 301cb0ef41Sopenharmony_ci TNode<JSRegExpResult> AllocateRegExpResult( 311cb0ef41Sopenharmony_ci TNode<Context> context, TNode<Smi> length, TNode<Smi> index, 321cb0ef41Sopenharmony_ci TNode<String> input, TNode<JSRegExp> regexp, TNode<Number> last_index, 331cb0ef41Sopenharmony_ci TNode<BoolT> has_indices, TNode<FixedArray>* elements_out = nullptr); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci TNode<Object> FastLoadLastIndexBeforeSmiCheck(TNode<JSRegExp> regexp); 361cb0ef41Sopenharmony_ci TNode<Smi> FastLoadLastIndex(TNode<JSRegExp> regexp) { 371cb0ef41Sopenharmony_ci return CAST(FastLoadLastIndexBeforeSmiCheck(regexp)); 381cb0ef41Sopenharmony_ci } 391cb0ef41Sopenharmony_ci TNode<Object> SlowLoadLastIndex(TNode<Context> context, TNode<Object> regexp); 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci void FastStoreLastIndex(TNode<JSRegExp> regexp, TNode<Smi> value); 421cb0ef41Sopenharmony_ci void SlowStoreLastIndex(TNode<Context> context, TNode<Object> regexp, 431cb0ef41Sopenharmony_ci TNode<Object> value); 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci // Loads {var_string_start} and {var_string_end} with the corresponding 461cb0ef41Sopenharmony_ci // offsets into the given {string_data}. 471cb0ef41Sopenharmony_ci void GetStringPointers(TNode<RawPtrT> string_data, TNode<IntPtrT> offset, 481cb0ef41Sopenharmony_ci TNode<IntPtrT> last_index, 491cb0ef41Sopenharmony_ci TNode<IntPtrT> string_length, 501cb0ef41Sopenharmony_ci String::Encoding encoding, 511cb0ef41Sopenharmony_ci TVariable<RawPtrT>* var_string_start, 521cb0ef41Sopenharmony_ci TVariable<RawPtrT>* var_string_end); 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci // Low level logic around the actual call into pattern matching code. 551cb0ef41Sopenharmony_ci TNode<HeapObject> RegExpExecInternal( 561cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSRegExp> regexp, TNode<String> string, 571cb0ef41Sopenharmony_ci TNode<Number> last_index, TNode<RegExpMatchInfo> match_info, 581cb0ef41Sopenharmony_ci RegExp::ExecQuirks exec_quirks = RegExp::ExecQuirks::kNone); 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci TNode<JSRegExpResult> ConstructNewResultFromMatchInfo( 611cb0ef41Sopenharmony_ci TNode<Context> context, TNode<JSRegExp> regexp, 621cb0ef41Sopenharmony_ci TNode<RegExpMatchInfo> match_info, TNode<String> string, 631cb0ef41Sopenharmony_ci TNode<Number> last_index); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci // Fast path check logic. 661cb0ef41Sopenharmony_ci // 671cb0ef41Sopenharmony_ci // Are you afraid? If not, you should be. 681cb0ef41Sopenharmony_ci // 691cb0ef41Sopenharmony_ci // It's complicated. Fast path checks protect certain assumptions, e.g. that 701cb0ef41Sopenharmony_ci // relevant properties on the regexp prototype (such as exec, @@split, global) 711cb0ef41Sopenharmony_ci // are unmodified. 721cb0ef41Sopenharmony_ci // 731cb0ef41Sopenharmony_ci // These assumptions differ by callsite. For example, RegExpPrototypeExec 741cb0ef41Sopenharmony_ci // cares whether the exec property has been modified; but it's totally fine 751cb0ef41Sopenharmony_ci // to modify other prototype properties. On the other hand, 761cb0ef41Sopenharmony_ci // StringPrototypeSplit does care very much whether @@split has been changed. 771cb0ef41Sopenharmony_ci // 781cb0ef41Sopenharmony_ci // We want to keep regexp execution on the fast path as much as possible. 791cb0ef41Sopenharmony_ci // Ideally, we could simply check if the regexp prototype has been modified; 801cb0ef41Sopenharmony_ci // yet common web frameworks routinely mutate it for various reasons. But most 811cb0ef41Sopenharmony_ci // of these mutations should happen in a way that still allows us to remain 821cb0ef41Sopenharmony_ci // on the fast path. To support this, the fast path check logic necessarily 831cb0ef41Sopenharmony_ci // becomes more involved. 841cb0ef41Sopenharmony_ci // 851cb0ef41Sopenharmony_ci // There are multiple knobs to twiddle for regexp fast path checks. We support 861cb0ef41Sopenharmony_ci // checks that completely ignore the prototype, checks that verify specific 871cb0ef41Sopenharmony_ci // properties on the prototype (the caller must ensure it passes in the right 881cb0ef41Sopenharmony_ci // ones), and strict checks that additionally ensure the prototype is 891cb0ef41Sopenharmony_ci // unchanged (we use these when we'd have to check multiple properties we 901cb0ef41Sopenharmony_ci // don't care too much about, e.g. all individual flag getters). 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci using DescriptorIndexNameValue = 931cb0ef41Sopenharmony_ci PrototypeCheckAssembler::DescriptorIndexNameValue; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci void BranchIfFastRegExp( 961cb0ef41Sopenharmony_ci TNode<Context> context, TNode<HeapObject> object, TNode<Map> map, 971cb0ef41Sopenharmony_ci PrototypeCheckAssembler::Flags prototype_check_flags, 981cb0ef41Sopenharmony_ci base::Optional<DescriptorIndexNameValue> additional_property_to_check, 991cb0ef41Sopenharmony_ci Label* if_isunmodified, Label* if_ismodified); 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci void BranchIfFastRegExpForSearch(TNode<Context> context, 1021cb0ef41Sopenharmony_ci TNode<HeapObject> object, 1031cb0ef41Sopenharmony_ci Label* if_isunmodified, 1041cb0ef41Sopenharmony_ci Label* if_ismodified); 1051cb0ef41Sopenharmony_ci void BranchIfFastRegExpForMatch(TNode<Context> context, 1061cb0ef41Sopenharmony_ci TNode<HeapObject> object, 1071cb0ef41Sopenharmony_ci Label* if_isunmodified, Label* if_ismodified); 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci // Strict: Does not tolerate any changes to the prototype map. 1101cb0ef41Sopenharmony_ci // Permissive: Allows changes to the prototype map except for the exec 1111cb0ef41Sopenharmony_ci // property. 1121cb0ef41Sopenharmony_ci void BranchIfFastRegExp_Strict(TNode<Context> context, 1131cb0ef41Sopenharmony_ci TNode<HeapObject> object, 1141cb0ef41Sopenharmony_ci Label* if_isunmodified, Label* if_ismodified); 1151cb0ef41Sopenharmony_ci void BranchIfFastRegExp_Permissive(TNode<Context> context, 1161cb0ef41Sopenharmony_ci TNode<HeapObject> object, 1171cb0ef41Sopenharmony_ci Label* if_isunmodified, 1181cb0ef41Sopenharmony_ci Label* if_ismodified); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci // Performs fast path checks on the given object itself, but omits prototype 1211cb0ef41Sopenharmony_ci // checks. 1221cb0ef41Sopenharmony_ci TNode<BoolT> IsFastRegExpNoPrototype(TNode<Context> context, 1231cb0ef41Sopenharmony_ci TNode<Object> object); 1241cb0ef41Sopenharmony_ci TNode<BoolT> IsFastRegExpNoPrototype(TNode<Context> context, 1251cb0ef41Sopenharmony_ci TNode<Object> object, TNode<Map> map); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci void BranchIfRegExpResult(const TNode<Context> context, 1281cb0ef41Sopenharmony_ci const TNode<Object> object, Label* if_isunmodified, 1291cb0ef41Sopenharmony_ci Label* if_ismodified); 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci TNode<String> FlagsGetter(TNode<Context> context, TNode<Object> regexp, 1321cb0ef41Sopenharmony_ci const bool is_fastpath); 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci TNode<BoolT> FastFlagGetter(TNode<JSRegExp> regexp, JSRegExp::Flag flag); 1351cb0ef41Sopenharmony_ci TNode<BoolT> FastFlagGetterGlobal(TNode<JSRegExp> regexp) { 1361cb0ef41Sopenharmony_ci return FastFlagGetter(regexp, JSRegExp::kGlobal); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci TNode<BoolT> FastFlagGetterUnicode(TNode<JSRegExp> regexp) { 1391cb0ef41Sopenharmony_ci return FastFlagGetter(regexp, JSRegExp::kUnicode); 1401cb0ef41Sopenharmony_ci } 1411cb0ef41Sopenharmony_ci TNode<BoolT> SlowFlagGetter(TNode<Context> context, TNode<Object> regexp, 1421cb0ef41Sopenharmony_ci JSRegExp::Flag flag); 1431cb0ef41Sopenharmony_ci TNode<BoolT> FlagGetter(TNode<Context> context, TNode<Object> regexp, 1441cb0ef41Sopenharmony_ci JSRegExp::Flag flag, bool is_fastpath); 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci TNode<Object> RegExpInitialize(const TNode<Context> context, 1471cb0ef41Sopenharmony_ci const TNode<JSRegExp> regexp, 1481cb0ef41Sopenharmony_ci const TNode<Object> maybe_pattern, 1491cb0ef41Sopenharmony_ci const TNode<Object> maybe_flags); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci TNode<Number> AdvanceStringIndex(TNode<String> string, TNode<Number> index, 1521cb0ef41Sopenharmony_ci TNode<BoolT> is_unicode, bool is_fastpath); 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci TNode<Smi> AdvanceStringIndexFast(TNode<String> string, TNode<Smi> index, 1551cb0ef41Sopenharmony_ci TNode<BoolT> is_unicode) { 1561cb0ef41Sopenharmony_ci return CAST(AdvanceStringIndex(string, index, is_unicode, true)); 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci TNode<Smi> AdvanceStringIndexSlow(TNode<String> string, TNode<Number> index, 1601cb0ef41Sopenharmony_ci TNode<BoolT> is_unicode) { 1611cb0ef41Sopenharmony_ci return CAST(AdvanceStringIndex(string, index, is_unicode, false)); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci TNode<JSArray> RegExpPrototypeSplitBody(TNode<Context> context, 1651cb0ef41Sopenharmony_ci TNode<JSRegExp> regexp, 1661cb0ef41Sopenharmony_ci const TNode<String> string, 1671cb0ef41Sopenharmony_ci const TNode<Smi> limit); 1681cb0ef41Sopenharmony_ci}; 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ciclass RegExpMatchAllAssembler : public RegExpBuiltinsAssembler { 1711cb0ef41Sopenharmony_ci public: 1721cb0ef41Sopenharmony_ci explicit RegExpMatchAllAssembler(compiler::CodeAssemblerState* state) 1731cb0ef41Sopenharmony_ci : RegExpBuiltinsAssembler(state) {} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci TNode<Object> CreateRegExpStringIterator(TNode<NativeContext> native_context, 1761cb0ef41Sopenharmony_ci TNode<Object> regexp, 1771cb0ef41Sopenharmony_ci TNode<String> string, 1781cb0ef41Sopenharmony_ci TNode<BoolT> global, 1791cb0ef41Sopenharmony_ci TNode<BoolT> full_unicode); 1801cb0ef41Sopenharmony_ci}; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci} // namespace internal 1831cb0ef41Sopenharmony_ci} // namespace v8 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci#endif // V8_BUILTINS_BUILTINS_REGEXP_GEN_H_ 186