diff options
author | Michaël Zasso <targos@protonmail.com> | 2019-03-12 09:01:49 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2019-03-14 18:49:21 +0100 |
commit | 7b48713334469818661fe276cf571de9c7899f2d (patch) | |
tree | 4dbda49ac88db76ce09dc330a0cb587e68e139ba /deps/v8/src/builtins/builtins-regexp-gen.cc | |
parent | 8549ac09b256666cf5275224ec58fab9939ff32e (diff) | |
download | android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.gz android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.bz2 android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.zip |
deps: update V8 to 7.3.492.25
PR-URL: https://github.com/nodejs/node/pull/25852
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/src/builtins/builtins-regexp-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-regexp-gen.cc | 425 |
1 files changed, 216 insertions, 209 deletions
diff --git a/deps/v8/src/builtins/builtins-regexp-gen.cc b/deps/v8/src/builtins/builtins-regexp-gen.cc index 30717f41de..08b8e0457c 100644 --- a/deps/v8/src/builtins/builtins-regexp-gen.cc +++ b/deps/v8/src/builtins/builtins-regexp-gen.cc @@ -58,8 +58,8 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult( // The folded allocation. - Node* result = Allocate(total_size); - Node* elements = InnerAllocate(result, kElementsOffset); + TNode<HeapObject> result = Allocate(total_size); + TNode<HeapObject> elements = InnerAllocate(result, kElementsOffset); // Initialize the JSRegExpResult. @@ -82,7 +82,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::AllocateRegExpResult( DCHECK(!IsDoubleElementsKind(elements_kind)); const RootIndex map_index = RootIndex::kFixedArrayMap; - DCHECK(Heap::RootIsImmortalImmovable(map_index)); + DCHECK(RootsTable::IsImmortalImmovable(map_index)); StoreMapNoWriteBarrier(elements, map_index); StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset, length); @@ -118,7 +118,7 @@ TNode<Object> RegExpBuiltinsAssembler::FastLoadLastIndex( TNode<JSRegExp> regexp) { // Load the in-object field. static const int field_offset = - JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; + JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kTaggedSize; return LoadObjectField(regexp, field_offset); } @@ -139,7 +139,7 @@ TNode<Object> RegExpBuiltinsAssembler::LoadLastIndex(TNode<Context> context, void RegExpBuiltinsAssembler::FastStoreLastIndex(Node* regexp, Node* value) { // Store the in-object field. static const int field_offset = - JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; + JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kTaggedSize; StoreObjectField(regexp, field_offset, value); } @@ -592,7 +592,7 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpExecInternal( TNode<Smi> smi_value = SmiFromInt32(value); StoreNoWriteBarrier(MachineRepresentation::kTagged, match_info, var_to_offset.value(), smi_value); - Increment(&var_to_offset, kPointerSize); + Increment(&var_to_offset, kTaggedSize); }, kInt32Size, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); } @@ -795,7 +795,7 @@ TNode<HeapObject> RegExpBuiltinsAssembler::RegExpPrototypeExecBody( } Node* RegExpBuiltinsAssembler::ThrowIfNotJSReceiver( - Node* context, Node* maybe_receiver, MessageTemplate::Template msg_template, + Node* context, Node* maybe_receiver, MessageTemplate msg_template, char const* method_name) { Label out(this), throw_exception(this, Label::kDeferred); VARIABLE(var_value_map, MachineRepresentation::kTagged); @@ -907,17 +907,17 @@ Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context, // We use a fairly coarse granularity for this and simply check whether both // the regexp itself is unmodified (i.e. its map has not changed), its // prototype is unmodified, and lastIndex is a non-negative smi. -void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context, - Node* const object, - Node* const map, - Label* const if_isunmodified, - Label* const if_ismodified) { +void RegExpBuiltinsAssembler::BranchIfFastRegExp( + Node* const context, Node* const object, Node* const map, + base::Optional<DescriptorIndexAndName> additional_property_to_check, + Label* const if_isunmodified, Label* const if_ismodified) { CSA_ASSERT(this, WordEqual(LoadMap(object), map)); GotoIfForceSlowPath(if_ismodified); - // TODO(ishell): Update this check once map changes for constant field - // tracking are landing. + // This should only be needed for String.p.(split||matchAll), but we are + // conservative here. + GotoIf(IsRegExpSpeciesProtectorCellInvalid(), if_ismodified); Node* const native_context = LoadNativeContext(context); Node* const regexp_fun = @@ -930,11 +930,19 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context, Node* const initial_proto_initial_map = LoadContextElement(native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX); - Node* const proto_map = LoadMap(LoadMapPrototype(map)); - Node* const proto_has_initialmap = - WordEqual(proto_map, initial_proto_initial_map); - GotoIfNot(proto_has_initialmap, if_ismodified); + DescriptorIndexAndName properties_to_check[2]; + int property_count = 0; + properties_to_check[property_count++] = DescriptorIndexAndName{ + JSRegExp::kExecFunctionDescriptorIndex, RootIndex::kexec_string}; + if (additional_property_to_check) { + properties_to_check[property_count++] = *additional_property_to_check; + } + + GotoIfInitialPrototypePropertiesModified( + CAST(map), CAST(initial_proto_initial_map), + Vector<DescriptorIndexAndName>(properties_to_check, property_count), + if_ismodified); // The smi check is required to omit ToLength(lastIndex) calls with possible // user-code execution on the fast path. @@ -947,8 +955,8 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context, Label* const if_isunmodified, Label* const if_ismodified) { CSA_ASSERT(this, TaggedIsNotSmi(object)); - BranchIfFastRegExp(context, object, LoadMap(object), if_isunmodified, - if_ismodified); + BranchIfFastRegExp(context, object, LoadMap(object), base::nullopt, + if_isunmodified, if_ismodified); } TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExp(SloppyTNode<Context> context, @@ -1194,20 +1202,20 @@ Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, } // ES#sec-isregexp IsRegExp ( argument ) -Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, - Node* const maybe_receiver) { +TNode<BoolT> RegExpBuiltinsAssembler::IsRegExp(TNode<Context> context, + TNode<Object> maybe_receiver) { Label out(this), if_isregexp(this); - VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(0)); + TVARIABLE(BoolT, var_result, Int32FalseConstant()); GotoIf(TaggedIsSmi(maybe_receiver), &out); - GotoIfNot(IsJSReceiver(maybe_receiver), &out); + GotoIfNot(IsJSReceiver(CAST(maybe_receiver)), &out); - Node* const receiver = maybe_receiver; + TNode<JSReceiver> receiver = CAST(maybe_receiver); // Check @@match. { - Node* const value = + TNode<Object> value = GetProperty(context, receiver, isolate()->factory()->match_symbol()); Label match_isundefined(this), match_isnotundefined(this); @@ -1217,11 +1225,26 @@ Node* RegExpBuiltinsAssembler::IsRegExp(Node* const context, Branch(IsJSRegExp(receiver), &if_isregexp, &out); BIND(&match_isnotundefined); - BranchIfToBooleanIsTrue(value, &if_isregexp, &out); + Label match_istrueish(this), match_isfalseish(this); + BranchIfToBooleanIsTrue(value, &match_istrueish, &match_isfalseish); + + // The common path. Symbol.match exists, equals the RegExpPrototypeMatch + // function (and is thus trueish), and the receiver is a JSRegExp. + BIND(&match_istrueish); + GotoIf(IsJSRegExp(receiver), &if_isregexp); + CallRuntime(Runtime::kIncrementUseCounter, context, + SmiConstant(v8::Isolate::kRegExpMatchIsTrueishOnNonJSRegExp)); + Goto(&if_isregexp); + + BIND(&match_isfalseish); + GotoIfNot(IsJSRegExp(receiver), &out); + CallRuntime(Runtime::kIncrementUseCounter, context, + SmiConstant(v8::Isolate::kRegExpMatchIsFalseishOnJSRegExp)); + Goto(&out); } BIND(&if_isregexp); - var_result.Bind(Int32Constant(1)); + var_result = Int32TrueConstant(); Goto(&out); BIND(&out); @@ -1263,7 +1286,8 @@ TF_BUILTIN(RegExpPrototypeFlagsGetter, RegExpBuiltinsAssembler) { TNode<JSReceiver> receiver = CAST(maybe_receiver); Label if_isfastpath(this), if_isslowpath(this, Label::kDeferred); - BranchIfFastRegExp(context, receiver, map, &if_isfastpath, &if_isslowpath); + BranchIfFastRegExp(context, receiver, map, base::nullopt, &if_isfastpath, + &if_isslowpath); BIND(&if_isfastpath); Return(FlagsGetter(context, receiver, true)); @@ -1290,7 +1314,7 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { Node* const regexp_function = LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - Node* const pattern_is_regexp = IsRegExp(context, pattern); + TNode<BoolT> pattern_is_regexp = IsRegExp(context, pattern); { Label next(this); @@ -1498,73 +1522,66 @@ TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { } // Fast-path implementation for flag checks on an unmodified JSRegExp instance. -Node* RegExpBuiltinsAssembler::FastFlagGetter(Node* const regexp, - JSRegExp::Flag flag) { - TNode<Smi> const flags = - CAST(LoadObjectField(regexp, JSRegExp::kFlagsOffset)); - TNode<Smi> const mask = SmiConstant(flag); - return SmiToInt32(SmiAnd(flags, mask)); +TNode<Int32T> RegExpBuiltinsAssembler::FastFlagGetter(TNode<JSRegExp> regexp, + JSRegExp::Flag flag) { + TNode<Smi> flags = CAST(LoadObjectField(regexp, JSRegExp::kFlagsOffset)); + TNode<Smi> mask = SmiConstant(flag); + return SmiToInt32(SmiShr(SmiAnd(flags, mask), JSRegExp::FlagShiftBits(flag))); } // Load through the GetProperty stub. -Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, - Node* const regexp, - JSRegExp::Flag flag) { - Factory* factory = isolate()->factory(); - +TNode<Int32T> RegExpBuiltinsAssembler::SlowFlagGetter(TNode<Context> context, + TNode<Object> regexp, + JSRegExp::Flag flag) { Label out(this); - VARIABLE(var_result, MachineRepresentation::kWord32); + TVARIABLE(Int32T, var_result); Handle<String> name; switch (flag) { case JSRegExp::kGlobal: - name = factory->global_string(); + name = isolate()->factory()->global_string(); break; case JSRegExp::kIgnoreCase: - name = factory->ignoreCase_string(); + name = isolate()->factory()->ignoreCase_string(); break; case JSRegExp::kMultiline: - name = factory->multiline_string(); + name = isolate()->factory()->multiline_string(); break; case JSRegExp::kDotAll: UNREACHABLE(); // Never called for dotAll. break; case JSRegExp::kSticky: - name = factory->sticky_string(); + name = isolate()->factory()->sticky_string(); break; case JSRegExp::kUnicode: - name = factory->unicode_string(); + name = isolate()->factory()->unicode_string(); break; default: UNREACHABLE(); } - Node* const value = GetProperty(context, regexp, name); + TNode<Object> value = GetProperty(context, regexp, name); Label if_true(this), if_false(this); BranchIfToBooleanIsTrue(value, &if_true, &if_false); BIND(&if_true); - { - var_result.Bind(Int32Constant(1)); - Goto(&out); - } + var_result = Int32Constant(1); + Goto(&out); BIND(&if_false); - { - var_result.Bind(Int32Constant(0)); - Goto(&out); - } + var_result = Int32Constant(0); + Goto(&out); BIND(&out); return var_result.value(); } -Node* RegExpBuiltinsAssembler::FlagGetter(Node* const context, - Node* const regexp, - JSRegExp::Flag flag, - bool is_fastpath) { - return is_fastpath ? FastFlagGetter(regexp, flag) +TNode<Int32T> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context, + TNode<Object> regexp, + JSRegExp::Flag flag, + bool is_fastpath) { + return is_fastpath ? FastFlagGetter(CAST(regexp), flag) : SlowFlagGetter(context, regexp, flag); } @@ -1582,7 +1599,7 @@ void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver, BIND(&if_isunmodifiedjsregexp); { // Refer to JSRegExp's flag property on the fast-path. - Node* const is_flag_set = FastFlagGetter(receiver, flag); + Node* const is_flag_set = FastFlagGetter(CAST(receiver), flag); Return(SelectBooleanConstant(is_flag_set)); } @@ -1846,7 +1863,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, if (is_fastpath) CSA_ASSERT(this, IsFastRegExp(context, regexp)); Node* const is_global = - FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); + FlagGetter(CAST(context), CAST(regexp), JSRegExp::kGlobal, is_fastpath); Label if_isglobal(this), if_isnotglobal(this); Branch(is_global, &if_isglobal, &if_isnotglobal); @@ -1862,8 +1879,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, BIND(&if_isglobal); { - Node* const is_unicode = - FlagGetter(context, regexp, JSRegExp::kUnicode, is_fastpath); + Node* const is_unicode = FlagGetter(CAST(context), CAST(regexp), + JSRegExp::kUnicode, is_fastpath); StoreLastIndex(context, regexp, SmiZero(), is_fastpath); @@ -1995,178 +2012,167 @@ TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { RegExpPrototypeMatchBody(context, receiver, string, false); } -TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator( - TNode<Context> context, TNode<Context> native_context, - TNode<Object> maybe_regexp, TNode<String> string, - TNode<BoolT> is_fast_regexp, char const* method_name) { - Label create_iterator(this), if_fast_regexp(this), - if_slow_regexp(this, Label::kDeferred), if_not_regexp(this); +void RegExpMatchAllAssembler::Generate(TNode<Context> context, + TNode<Context> native_context, + TNode<Object> receiver, + TNode<Object> maybe_string) { + // 1. Let R be the this value. + // 2. If Type(R) is not Object, throw a TypeError exception. + ThrowIfNotJSReceiver(context, receiver, + MessageTemplate::kIncompatibleMethodReceiver, + "RegExp.prototype.@@matchAll"); - // 1. Let S be ? ToString(O). - // Handled by the caller of MatchAllIterator. - CSA_ASSERT(this, IsString(string)); + // 3. Let S be ? ToString(O). + TNode<String> string = ToString_Inline(context, maybe_string); TVARIABLE(Object, var_matcher); TVARIABLE(Int32T, var_global); TVARIABLE(Int32T, var_unicode); + Label create_iterator(this), if_fast_regexp(this), + if_slow_regexp(this, Label::kDeferred); - // 2. If ? IsRegExp(R) is true, then - GotoIf(is_fast_regexp, &if_fast_regexp); - Branch(IsRegExp(context, maybe_regexp), &if_slow_regexp, &if_not_regexp); + BranchIfFastRegExp(context, receiver, &if_fast_regexp, &if_slow_regexp); BIND(&if_fast_regexp); { - CSA_ASSERT(this, IsFastRegExp(context, maybe_regexp)); - TNode<JSRegExp> fast_regexp = CAST(maybe_regexp); + TNode<JSRegExp> fast_regexp = CAST(receiver); TNode<Object> source = LoadObjectField(fast_regexp, JSRegExp::kSourceOffset); - TNode<String> flags = CAST(FlagsGetter(context, fast_regexp, true)); - // c. Let matcher be ? Construct(C, « R, flags »). + // 4. Let C be ? SpeciesConstructor(R, %RegExp%). + // 5. Let flags be ? ToString(? Get(R, "flags")). + // 6. Let matcher be ? Construct(C, « R, flags »). + TNode<String> flags = CAST(FlagsGetter(context, fast_regexp, true)); var_matcher = RegExpCreate(context, native_context, source, flags); CSA_ASSERT(this, IsFastRegExp(context, var_matcher.value())); - // d. Let global be ? ToBoolean(? Get(matcher, "global")). - var_global = UncheckedCast<Int32T>( - FastFlagGetter(var_matcher.value(), JSRegExp::kGlobal)); + // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). + // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). + FastStoreLastIndex(var_matcher.value(), FastLoadLastIndex(fast_regexp)); - // e. Let fullUnicode be ? ToBoolean(? Get(matcher, "unicode"). - var_unicode = UncheckedCast<Int32T>( - FastFlagGetter(var_matcher.value(), JSRegExp::kUnicode)); + // 9. If flags contains "g", let global be true. + // 10. Else, let global be false. + var_global = FastFlagGetter(CAST(var_matcher.value()), JSRegExp::kGlobal); - // f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). - // g. Perform ? Set(matcher, "lastIndex", lastIndex, true). - FastStoreLastIndex(var_matcher.value(), FastLoadLastIndex(fast_regexp)); + // 11. If flags contains "u", let fullUnicode be true. + // 12. Else, let fullUnicode be false. + var_unicode = FastFlagGetter(CAST(var_matcher.value()), JSRegExp::kUnicode); Goto(&create_iterator); } + BIND(&if_slow_regexp); { - // a. Let C be ? SpeciesConstructor(R, %RegExp%). - TNode<Object> regexp_fun = - LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX); - TNode<Object> species_constructor = - SpeciesConstructor(native_context, maybe_regexp, regexp_fun); + // 4. Let C be ? SpeciesConstructor(R, %RegExp%). + TNode<JSFunction> regexp_fun = CAST( + LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX)); + TNode<JSReceiver> species_constructor = + SpeciesConstructor(native_context, receiver, regexp_fun); - // b. Let flags be ? ToString(? Get(R, "flags")). - TNode<Object> flags = GetProperty(context, maybe_regexp, - isolate()->factory()->flags_string()); + // 5. Let flags be ? ToString(? Get(R, "flags")). + TNode<Object> flags = + GetProperty(context, receiver, isolate()->factory()->flags_string()); TNode<String> flags_string = ToString_Inline(context, flags); - // c. Let matcher be ? Construct(C, « R, flags »). + // 6. Let matcher be ? Construct(C, « R, flags »). var_matcher = - CAST(ConstructJS(CodeFactory::Construct(isolate()), context, - species_constructor, maybe_regexp, flags_string)); - - // d. Let global be ? ToBoolean(? Get(matcher, "global")). - var_global = UncheckedCast<Int32T>( - SlowFlagGetter(context, var_matcher.value(), JSRegExp::kGlobal)); - - // e. Let fullUnicode be ? ToBoolean(? Get(matcher, "unicode"). - var_unicode = UncheckedCast<Int32T>( - SlowFlagGetter(context, var_matcher.value(), JSRegExp::kUnicode)); + Construct(context, species_constructor, receiver, flags_string); - // f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). - TNode<Number> last_index = UncheckedCast<Number>( - ToLength_Inline(context, SlowLoadLastIndex(context, maybe_regexp))); + // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). + TNode<Number> last_index = + ToLength_Inline(context, SlowLoadLastIndex(context, receiver)); - // g. Perform ? Set(matcher, "lastIndex", lastIndex, true). + // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). SlowStoreLastIndex(context, var_matcher.value(), last_index); + // 9. If flags contains "g", let global be true. + // 10. Else, let global be false. + TNode<String> global_char_string = StringConstant("g"); + TNode<Smi> global_ix = + CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string, + global_char_string, SmiZero())); + var_global = + SelectInt32Constant(SmiEqual(global_ix, SmiConstant(-1)), 0, 1); + + // 11. If flags contains "u", let fullUnicode be true. + // 12. Else, let fullUnicode be false. + TNode<String> unicode_char_string = StringConstant("u"); + TNode<Smi> unicode_ix = + CAST(CallBuiltin(Builtins::kStringIndexOf, context, flags_string, + unicode_char_string, SmiZero())); + var_unicode = + SelectInt32Constant(SmiEqual(unicode_ix, SmiConstant(-1)), 0, 1); Goto(&create_iterator); } - // 3. Else, - BIND(&if_not_regexp); - { - // a. Let flags be "g". - // b. Let matcher be ? RegExpCreate(R, flags). - var_matcher = RegExpCreate(context, native_context, maybe_regexp, - StringConstant("g")); - - // c. Let global be true. - var_global = Int32Constant(1); - - // d. Let fullUnicode be false. - var_unicode = Int32Constant(0); - -#ifdef DEBUG - // Assert: ! Get(matcher, "lastIndex") is 0. - TNode<Object> last_index = SlowLoadLastIndex(context, var_matcher.value()); - CSA_ASSERT(this, WordEqual(SmiZero(), last_index)); -#endif // DEBUG - Goto(&create_iterator); - } - // 4. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). BIND(&create_iterator); { - TNode<Map> map = CAST(LoadContextElement( - native_context, - Context::INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX)); - - // 4. Let iterator be ObjectCreate(%RegExpStringIteratorPrototype%, « - // [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], - // [[Done]] »). - TNode<Object> iterator = CAST(Allocate(JSRegExpStringIterator::kSize)); - StoreMapNoWriteBarrier(iterator, map); - StoreObjectFieldRoot(iterator, - JSRegExpStringIterator::kPropertiesOrHashOffset, - RootIndex::kEmptyFixedArray); - StoreObjectFieldRoot(iterator, JSRegExpStringIterator::kElementsOffset, - RootIndex::kEmptyFixedArray); - - // 5. Set iterator.[[IteratingRegExp]] to R. - StoreObjectFieldNoWriteBarrier( - iterator, JSRegExpStringIterator::kIteratingRegExpOffset, - var_matcher.value()); - - // 6. Set iterator.[[IteratedString]] to S. - StoreObjectFieldNoWriteBarrier( - iterator, JSRegExpStringIterator::kIteratedStringOffset, string); + // 13. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). + TNode<Object> iterator = + CreateRegExpStringIterator(native_context, var_matcher.value(), string, + var_global.value(), var_unicode.value()); + Return(iterator); + } +} + +// ES#sec-createregexpstringiterator +// CreateRegExpStringIterator ( R, S, global, fullUnicode ) +TNode<Object> RegExpMatchAllAssembler::CreateRegExpStringIterator( + TNode<Context> native_context, TNode<Object> regexp, TNode<String> string, + TNode<Int32T> global, TNode<Int32T> full_unicode) { + TNode<Map> map = CAST(LoadContextElement( + native_context, + Context::INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX)); + + // 4. Let iterator be ObjectCreate(%RegExpStringIteratorPrototype%, « + // [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], + // [[Done]] »). + TNode<Object> iterator = Allocate(JSRegExpStringIterator::kSize); + StoreMapNoWriteBarrier(iterator, map); + StoreObjectFieldRoot(iterator, + JSRegExpStringIterator::kPropertiesOrHashOffset, + RootIndex::kEmptyFixedArray); + StoreObjectFieldRoot(iterator, JSRegExpStringIterator::kElementsOffset, + RootIndex::kEmptyFixedArray); + + // 5. Set iterator.[[IteratingRegExp]] to R. + StoreObjectFieldNoWriteBarrier( + iterator, JSRegExpStringIterator::kIteratingRegExpOffset, regexp); + + // 6. Set iterator.[[IteratedString]] to S. + StoreObjectFieldNoWriteBarrier( + iterator, JSRegExpStringIterator::kIteratedStringOffset, string); #ifdef DEBUG - // Verify global and unicode can be bitwise shifted without masking. - TNode<Int32T> zero = Int32Constant(0); - TNode<Int32T> one = Int32Constant(1); - CSA_ASSERT(this, Word32Or(Word32Equal(var_global.value(), zero), - Word32Equal(var_global.value(), one))); - CSA_ASSERT(this, Word32Or(Word32Equal(var_unicode.value(), zero), - Word32Equal(var_unicode.value(), one))); + // Verify global and full_unicode can be bitwise shifted without masking. + TNode<Int32T> zero = Int32Constant(0); + TNode<Int32T> one = Int32Constant(1); + CSA_ASSERT(this, + Word32Or(Word32Equal(global, zero), Word32Equal(global, one))); + CSA_ASSERT(this, Word32Or(Word32Equal(full_unicode, zero), + Word32Equal(full_unicode, one))); #endif // DEBUG - // 7. Set iterator.[[Global]] to global. - // 8. Set iterator.[[Unicode]] to fullUnicode. - // 9. Set iterator.[[Done]] to false. - TNode<Word32T> global_flag = Word32Shl( - var_global.value(), Int32Constant(JSRegExpStringIterator::kGlobalBit)); - TNode<Word32T> unicode_flag = - Word32Shl(var_unicode.value(), - Int32Constant(JSRegExpStringIterator::kUnicodeBit)); - TNode<Word32T> iterator_flags = Word32Or(global_flag, unicode_flag); - StoreObjectFieldNoWriteBarrier(iterator, - JSRegExpStringIterator::kFlagsOffset, - SmiFromInt32(Signed(iterator_flags))); + // 7. Set iterator.[[Global]] to global. + // 8. Set iterator.[[Unicode]] to fullUnicode. + // 9. Set iterator.[[Done]] to false. + TNode<Word32T> global_flag = + Word32Shl(global, Int32Constant(JSRegExpStringIterator::kGlobalBit)); + TNode<Word32T> unicode_flag = Word32Shl( + full_unicode, Int32Constant(JSRegExpStringIterator::kUnicodeBit)); + TNode<Word32T> iterator_flags = Word32Or(global_flag, unicode_flag); + StoreObjectFieldNoWriteBarrier(iterator, JSRegExpStringIterator::kFlagsOffset, + SmiFromInt32(Signed(iterator_flags))); - return iterator; - } + return iterator; } // https://tc39.github.io/proposal-string-matchall/ // RegExp.prototype [ @@matchAll ] ( string ) -TF_BUILTIN(RegExpPrototypeMatchAll, RegExpBuiltinsAssembler) { +TF_BUILTIN(RegExpPrototypeMatchAll, RegExpMatchAllAssembler) { TNode<Context> context = CAST(Parameter(Descriptor::kContext)); TNode<Context> native_context = LoadNativeContext(context); TNode<Object> receiver = CAST(Parameter(Descriptor::kReceiver)); - TNode<Object> string = CAST(Parameter(Descriptor::kString)); - - // 1. Let R be the this value. - // 2. If Type(R) is not Object, throw a TypeError exception. - ThrowIfNotJSReceiver(context, receiver, - MessageTemplate::kIncompatibleMethodReceiver, - "RegExp.prototype.@@matchAll"); - - // 3. Return ? MatchAllIterator(R, string). - Return(MatchAllIterator( - context, native_context, receiver, ToString_Inline(context, string), - IsFastRegExp(context, receiver), "RegExp.prototype.@@matchAll")); + TNode<Object> maybe_string = CAST(Parameter(Descriptor::kString)); + Generate(context, native_context, receiver, maybe_string); } // Helper that skips a few initial checks. and assumes... @@ -2330,7 +2336,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, TNode<String> string, TNode<Smi> const limit) { CSA_ASSERT(this, IsFastRegExp(context, regexp)); - CSA_ASSERT(this, Word32BinaryNot(FastFlagGetter(regexp, JSRegExp::kSticky))); + CSA_ASSERT(this, + Word32BinaryNot(FastFlagGetter(CAST(regexp), JSRegExp::kSticky))); TNode<IntPtrT> const int_limit = SmiUntag(limit); @@ -2339,7 +2346,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, Node* const allocation_site = nullptr; Node* const native_context = LoadNativeContext(context); - Node* const array_map = LoadJSArrayElementsMap(kind, native_context); + TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); Label return_empty_array(this, Label::kDeferred); @@ -2373,12 +2380,12 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&return_singleton_array); { - Node* const length = SmiConstant(1); - Node* const capacity = IntPtrConstant(1); - Node* const result = AllocateJSArray(kind, array_map, capacity, length, - allocation_site, mode); + TNode<Smi> length = SmiConstant(1); + TNode<IntPtrT> capacity = IntPtrConstant(1); + TNode<JSArray> result = AllocateJSArray(kind, array_map, capacity, + length, allocation_site, mode); - TNode<FixedArray> const fixed_array = CAST(LoadElements(result)); + TNode<FixedArray> fixed_array = CAST(LoadElements(result)); StoreFixedArrayElement(fixed_array, 0, string); Return(result); @@ -2452,7 +2459,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, GotoIfNot(SmiEqual(match_to, next_search_from), &next); GotoIfNot(SmiEqual(match_to, last_matched_until), &next); - Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); + Node* const is_unicode = FastFlagGetter(CAST(regexp), JSRegExp::kUnicode); Node* const new_next_search_from = AdvanceStringIndex(string, next_search_from, is_unicode, true); var_next_search_from = CAST(new_next_search_from); @@ -2490,10 +2497,10 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, Node* const reg = var_reg.value(); Node* const from = LoadFixedArrayElement( match_indices, reg, - RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode); + RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize, mode); TNode<Smi> const to = CAST(LoadFixedArrayElement( match_indices, reg, - (RegExpMatchInfo::kFirstCaptureIndex + 1) * kPointerSize, mode)); + (RegExpMatchInfo::kFirstCaptureIndex + 1) * kTaggedSize, mode)); Label select_capture(this), select_undefined(this), store_value(this); VARIABLE(var_value, MachineRepresentation::kTagged); @@ -2550,10 +2557,10 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, BIND(&return_empty_array); { - Node* const length = SmiZero(); - Node* const capacity = IntPtrZero(); - Node* const result = AllocateJSArray(kind, array_map, capacity, length, - allocation_site, mode); + TNode<Smi> length = SmiZero(); + TNode<IntPtrT> capacity = IntPtrZero(); + TNode<JSArray> result = AllocateJSArray(kind, array_map, capacity, length, + allocation_site, mode); Return(result); } } @@ -2675,7 +2682,7 @@ Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( Node* result_array; { ElementsKind kind = PACKED_ELEMENTS; - Node* const array_map = LoadJSArrayElementsMap(kind, native_context); + TNode<Map> array_map = LoadJSArrayElementsMap(kind, native_context); TNode<IntPtrT> capacity = IntPtrConstant(16); TNode<Smi> length = SmiZero(); Node* const allocation_site = nullptr; @@ -2875,10 +2882,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( if_nofurthermatches(this); // Is {regexp} global? - Node* const is_global = FastFlagGetter(regexp, JSRegExp::kGlobal); + Node* const is_global = FastFlagGetter(CAST(regexp), JSRegExp::kGlobal); GotoIfNot(is_global, &loop); - var_is_unicode.Bind(FastFlagGetter(regexp, JSRegExp::kUnicode)); + var_is_unicode.Bind(FastFlagGetter(CAST(regexp), JSRegExp::kUnicode)); FastStoreLastIndex(regexp, SmiZero()); Goto(&loop); |