diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc index 703f4d4c73..15e355b8f2 100644 --- a/src/builtins/builtins-regexp-gen.cc +++ b/src/builtins/builtins-regexp-gen.cc @@ -33,28 +33,23 @@ TNode RegExpBuiltinsAssembler::IntPtrZero() { // ----------------------------------------------------------------------------- // ES6 section 21.2 RegExp Objects -Node* RegExpBuiltinsAssembler::AllocateRegExpResult(Node* context, Node* length, - Node* index, Node* input) { - CSA_ASSERT(this, IsContext(context)); - CSA_ASSERT(this, TaggedIsSmi(index)); - CSA_ASSERT(this, TaggedIsSmi(length)); - CSA_ASSERT(this, IsString(input)); - +TNode RegExpBuiltinsAssembler::AllocateRegExpResult( + TNode context, TNode length, TNode index, + TNode input) { #ifdef DEBUG - TNode const max_length = - SmiConstant(JSArray::kInitialMaxFastElementArray); - CSA_ASSERT(this, SmiLessThanOrEqual(CAST(length), max_length)); + TNode max_length = SmiConstant(JSArray::kInitialMaxFastElementArray); + CSA_ASSERT(this, SmiLessThanOrEqual(length, max_length)); #endif // DEBUG // Allocate the JSRegExpResult together with its elements fixed array. // Initial preparations first. - Node* const length_intptr = SmiUntag(length); + TNode length_intptr = SmiUntag(length); const ElementsKind elements_kind = PACKED_ELEMENTS; - Node* const elements_size = GetFixedArrayAllocationSize( + TNode elements_size = GetFixedArrayAllocationSize( length_intptr, elements_kind, INTPTR_PARAMETERS); - Node* const total_size = + TNode total_size = IntPtrAdd(elements_size, IntPtrConstant(JSRegExpResult::kSize)); static const int kRegExpResultOffset = 0; @@ -63,14 +58,14 @@ Node* RegExpBuiltinsAssembler::AllocateRegExpResult(Node* context, Node* length, // The folded allocation. - Node* const result = Allocate(total_size); - Node* const elements = InnerAllocate(result, kElementsOffset); + Node* result = Allocate(total_size); + Node* elements = InnerAllocate(result, kElementsOffset); // Initialize the JSRegExpResult. - Node* const native_context = LoadNativeContext(context); - Node* const map = - LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); + TNode native_context = LoadNativeContext(context); + TNode map = CAST( + LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX)); StoreMapNoWriteBarrier(result, map); StoreObjectFieldNoWriteBarrier(result, JSArray::kPropertiesOrHashOffset, @@ -94,7 +89,7 @@ Node* RegExpBuiltinsAssembler::AllocateRegExpResult(Node* context, Node* length, FillFixedArrayWithValue(elements_kind, elements, IntPtrZero(), length_intptr, Heap::kUndefinedValueRootIndex); - return result; + return CAST(result); } TNode RegExpBuiltinsAssembler::RegExpCreate( @@ -163,21 +158,18 @@ void RegExpBuiltinsAssembler::StoreLastIndex(Node* context, Node* regexp, } } -Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( - Node* const context, Node* const regexp, Node* const match_info, - TNode const string) { - CSA_ASSERT(this, IsFixedArrayMap(LoadMap(match_info))); - CSA_ASSERT(this, IsJSRegExp(regexp)); - +TNode RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( + TNode context, TNode maybe_regexp, + TNode match_info, TNode string) { Label named_captures(this), out(this); TNode num_indices = SmiUntag(CAST(LoadFixedArrayElement( - CAST(match_info), RegExpMatchInfo::kNumberOfCapturesIndex))); - TNode const num_results = SmiTag(WordShr(num_indices, 1)); - Node* const start = LoadFixedArrayElement( - CAST(match_info), RegExpMatchInfo::kFirstCaptureIndex); - Node* const end = LoadFixedArrayElement( - CAST(match_info), RegExpMatchInfo::kFirstCaptureIndex + 1); + match_info, RegExpMatchInfo::kNumberOfCapturesIndex))); + TNode num_results = SmiTag(WordShr(num_indices, 1)); + TNode start = CAST( + LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex)); + TNode end = CAST(LoadFixedArrayElement( + match_info, RegExpMatchInfo::kFirstCaptureIndex + 1)); // Calculate the substring of the first match before creating the result array // to avoid an unnecessary write barrier storing the first result. @@ -185,9 +177,9 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( TNode first = CAST(CallBuiltin(Builtins::kSubString, context, string, start, end)); - Node* const result = + TNode result = AllocateRegExpResult(context, num_results, start, string); - TNode const result_elements = CAST(LoadElements(result)); + TNode result_elements = CAST(LoadElements(result)); StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); @@ -195,13 +187,12 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( GotoIf(SmiEqual(num_results, SmiConstant(1)), &out); // Store all remaining captures. - Node* const limit = IntPtrAdd( + TNode limit = IntPtrAdd( IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); - VARIABLE(var_from_cursor, MachineType::PointerRepresentation(), - IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); - VARIABLE(var_to_cursor, MachineType::PointerRepresentation(), - IntPtrConstant(1)); + TVARIABLE(IntPtrT, var_from_cursor, + IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); + TVARIABLE(IntPtrT, var_to_cursor, IntPtrConstant(1)); Variable* vars[] = {&var_from_cursor, &var_to_cursor}; Label loop(this, 2, vars); @@ -209,42 +200,42 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( Goto(&loop); BIND(&loop); { - Node* const from_cursor = var_from_cursor.value(); - Node* const to_cursor = var_to_cursor.value(); - TNode const start = - CAST(LoadFixedArrayElement(CAST(match_info), from_cursor)); + TNode from_cursor = var_from_cursor.value(); + TNode to_cursor = var_to_cursor.value(); + TNode start = CAST(LoadFixedArrayElement(match_info, from_cursor)); Label next_iter(this); GotoIf(SmiEqual(start, SmiConstant(-1)), &next_iter); - Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); - Node* const end = - LoadFixedArrayElement(CAST(match_info), from_cursor_plus1); + TNode from_cursor_plus1 = + IntPtrAdd(from_cursor, IntPtrConstant(1)); + TNode end = CAST(LoadFixedArrayElement(match_info, from_cursor_plus1)); - TNode const capture = + TNode capture = CAST(CallBuiltin(Builtins::kSubString, context, string, start, end)); StoreFixedArrayElement(result_elements, to_cursor, capture); Goto(&next_iter); BIND(&next_iter); - var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2))); - var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); + var_from_cursor = IntPtrAdd(from_cursor, IntPtrConstant(2)); + var_to_cursor = IntPtrAdd(to_cursor, IntPtrConstant(1)); Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &named_captures); } BIND(&named_captures); { + CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1))); + // We reach this point only if captures exist, implying that this is an // IRREGEXP JSRegExp. - CSA_ASSERT(this, IsJSRegExp(regexp)); - CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1))); + TNode regexp = CAST(maybe_regexp); // Preparations for named capture properties. Exit early if the result does // not have any named captures to minimize performance impact. - TNode const data = + TNode data = CAST(LoadObjectField(regexp, JSRegExp::kDataOffset)); CSA_ASSERT(this, SmiEqual(CAST(LoadFixedArrayElement(data, JSRegExp::kTagIndex)), @@ -252,7 +243,7 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( // The names fixed array associates names at even indices with a capture // index at odd indices. - TNode const maybe_names = + TNode maybe_names = LoadFixedArrayElement(data, JSRegExp::kIrregexpCaptureNameMapIndex); GotoIf(WordEqual(maybe_names, SmiZero()), &out); @@ -260,22 +251,23 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( // TODO(jgruber): Could be optimized by adding the object map to the heap // root list. - Node* const native_context = LoadNativeContext(context); - Node* const map = LoadContextElement( - native_context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP); - Node* const properties = + TNode native_context = LoadNativeContext(context); + TNode map = CAST(LoadContextElement( + native_context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP)); + TNode properties = AllocateNameDictionary(NameDictionary::kInitialCapacity); - Node* const group_object = AllocateJSObjectFromMap(map, properties); + TNode group_object = + CAST(AllocateJSObjectFromMap(map, properties)); StoreObjectField(result, JSRegExpResult::kGroupsOffset, group_object); // One or more named captures exist, add a property for each one. TNode names = CAST(maybe_names); - TNode const names_length = LoadAndUntagFixedArrayBaseLength(names); + TNode names_length = LoadAndUntagFixedArrayBaseLength(names); CSA_ASSERT(this, IntPtrGreaterThan(names_length, IntPtrZero())); - VARIABLE(var_i, MachineType::PointerRepresentation(), IntPtrZero()); + TVARIABLE(IntPtrT, var_i, IntPtrZero()); Variable* vars[] = {&var_i}; const int vars_count = sizeof(vars) / sizeof(vars[0]); @@ -284,14 +276,14 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( Goto(&loop); BIND(&loop); { - Node* const i = var_i.value(); - Node* const i_plus_1 = IntPtrAdd(i, IntPtrConstant(1)); - Node* const i_plus_2 = IntPtrAdd(i_plus_1, IntPtrConstant(1)); + TNode i = var_i.value(); + TNode i_plus_1 = IntPtrAdd(i, IntPtrConstant(1)); + TNode i_plus_2 = IntPtrAdd(i_plus_1, IntPtrConstant(1)); - Node* const name = LoadFixedArrayElement(names, i); - Node* const index = LoadFixedArrayElement(names, i_plus_1); - Node* const capture = - LoadFixedArrayElement(result_elements, SmiUntag(index)); + TNode name = CAST(LoadFixedArrayElement(names, i)); + TNode index = CAST(LoadFixedArrayElement(names, i_plus_1)); + TNode capture = + CAST(LoadFixedArrayElement(result_elements, SmiUntag(index))); // TODO(jgruber): Calling into runtime to create each property is slow. // Either we should create properties entirely in CSA (should be doable), @@ -299,7 +291,7 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( CallRuntime(Runtime::kCreateDataProperty, context, group_object, name, capture); - var_i.Bind(i_plus_2); + var_i = i_plus_2; Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, &loop); } @@ -653,10 +645,11 @@ TNode RegExpBuiltinsAssembler::RegExpExecInternal( // ES#sec-regexp.prototype.exec // RegExp.prototype.exec ( string ) // Implements the core of RegExp.prototype.exec but without actually -// constructing the JSRegExpResult. Returns either null (if the RegExp did not -// match) or a fixed array containing match indices as returned by -// RegExpExecStub. -TNode RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( +// constructing the JSRegExpResult. Returns a fixed array containing match +// indices as returned by RegExpExecStub on successful match, and jumps to +// if_didnotmatch otherwise. +TNode +RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( TNode context, TNode maybe_regexp, TNode string, Label* if_didnotmatch, const bool is_fastpath) { if (!is_fastpath) { @@ -722,7 +715,6 @@ TNode RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( BIND(&if_isoob); { StoreLastIndex(context, regexp, SmiZero(), is_fastpath); - var_result = NullConstant(); Goto(if_didnotmatch); } } @@ -771,32 +763,30 @@ TNode RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( } BIND(&out); - return var_result.value(); + return CAST(var_result.value()); } // ES#sec-regexp.prototype.exec // RegExp.prototype.exec ( string ) -Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBody( - Node* const context, Node* const regexp, TNode const string, - const bool is_fastpath) { - VARIABLE(var_result, MachineRepresentation::kTagged); +TNode RegExpBuiltinsAssembler::RegExpPrototypeExecBody( + TNode context, TNode maybe_regexp, + TNode string, const bool is_fastpath) { + TVARIABLE(HeapObject, var_result); Label if_didnotmatch(this), out(this); - TNode indices_or_null = RegExpPrototypeExecBodyWithoutResult( - CAST(context), CAST(regexp), string, &if_didnotmatch, is_fastpath); + TNode match_indices = RegExpPrototypeExecBodyWithoutResult( + context, maybe_regexp, string, &if_didnotmatch, is_fastpath); // Successful match. { - Node* const match_indices = indices_or_null; - Node* const result = - ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); - var_result.Bind(result); + var_result = ConstructNewResultFromMatchInfo(context, maybe_regexp, + match_indices, string); Goto(&out); } BIND(&if_didnotmatch); { - var_result.Bind(NullConstant()); + var_result = NullConstant(); Goto(&out); } @@ -997,9 +987,9 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* const context, // Slow path stub for RegExpPrototypeExec to decrease code size. TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) { - Node* const regexp = Parameter(Descriptor::kReceiver); - TNode const string = CAST(Parameter(Descriptor::kString)); - Node* const context = Parameter(Descriptor::kContext); + TNode regexp = CAST(Parameter(Descriptor::kReceiver)); + TNode string = CAST(Parameter(Descriptor::kString)); + TNode context = CAST(Parameter(Descriptor::kContext)); Return(RegExpPrototypeExecBody(context, regexp, string, false)); } @@ -1008,18 +998,15 @@ TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) { // and {match_info} is updated on success. // The slow path is implemented in RegExpImpl::AtomExec. TF_BUILTIN(RegExpExecAtom, RegExpBuiltinsAssembler) { - Node* const regexp = Parameter(Descriptor::kRegExp); - Node* const subject_string = Parameter(Descriptor::kString); - Node* const last_index = Parameter(Descriptor::kLastIndex); - TNode const match_info = CAST(Parameter(Descriptor::kMatchInfo)); - Node* const context = Parameter(Descriptor::kContext); + TNode regexp = CAST(Parameter(Descriptor::kRegExp)); + TNode subject_string = CAST(Parameter(Descriptor::kString)); + TNode last_index = CAST(Parameter(Descriptor::kLastIndex)); + TNode match_info = CAST(Parameter(Descriptor::kMatchInfo)); + TNode context = CAST(Parameter(Descriptor::kContext)); - CSA_ASSERT(this, IsJSRegExp(regexp)); - CSA_ASSERT(this, IsString(subject_string)); CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); - TNode const data = - CAST(LoadObjectField(regexp, JSRegExp::kDataOffset)); + TNode data = CAST(LoadObjectField(regexp, JSRegExp::kDataOffset)); CSA_ASSERT(this, SmiEqual(CAST(LoadFixedArrayElement(data, JSRegExp::kTagIndex)), SmiConstant(JSRegExp::ATOM))); @@ -1086,35 +1073,28 @@ TF_BUILTIN(RegExpExecInternal, RegExpBuiltinsAssembler) { // ES#sec-regexp.prototype.exec // RegExp.prototype.exec ( string ) TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { - Node* const maybe_receiver = Parameter(Descriptor::kReceiver); - Node* const maybe_string = Parameter(Descriptor::kString); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode maybe_string = CAST(Parameter(Descriptor::kString)); + TNode context = CAST(Parameter(Descriptor::kContext)); // Ensure {maybe_receiver} is a JSRegExp. ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); - Node* const receiver = maybe_receiver; + TNode receiver = CAST(maybe_receiver); // Convert {maybe_string} to a String. - TNode const string = ToString_Inline(context, maybe_string); + TNode string = ToString_Inline(context, maybe_string); Label if_isfastpath(this), if_isslowpath(this); Branch(IsFastRegExpNoPrototype(context, receiver), &if_isfastpath, &if_isslowpath); BIND(&if_isfastpath); - { - Node* const result = - RegExpPrototypeExecBody(context, receiver, string, true); - Return(result); - } + Return(RegExpPrototypeExecBody(context, receiver, string, true)); BIND(&if_isslowpath); - { - Node* const result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow, - context, receiver, string); - Return(result); - } + Return(CallBuiltin(Builtins::kRegExpPrototypeExecSlow, context, receiver, + string)); } Node* RegExpBuiltinsAssembler::FlagsGetter(Node* const context, @@ -1274,13 +1254,13 @@ Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, // ES #sec-get-regexp.prototype.flags TF_BUILTIN(RegExpPrototypeFlagsGetter, RegExpBuiltinsAssembler) { - Node* const maybe_receiver = Parameter(Descriptor::kReceiver); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode context = CAST(Parameter(Descriptor::kContext)); - Node* const map = ThrowIfNotJSReceiver(context, maybe_receiver, - MessageTemplate::kRegExpNonObject, - "RegExp.prototype.flags"); - Node* const receiver = maybe_receiver; + TNode map = CAST(ThrowIfNotJSReceiver(context, maybe_receiver, + MessageTemplate::kRegExpNonObject, + "RegExp.prototype.flags")); + TNode receiver = CAST(maybe_receiver); Label if_isfastpath(this), if_isslowpath(this, Label::kDeferred); BranchIfFastRegExp(context, receiver, map, &if_isfastpath, &if_isslowpath); @@ -1295,10 +1275,10 @@ TF_BUILTIN(RegExpPrototypeFlagsGetter, RegExpBuiltinsAssembler) { // ES#sec-regexp-pattern-flags // RegExp ( pattern, flags ) TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { - Node* const pattern = Parameter(Descriptor::kPattern); - Node* const flags = Parameter(Descriptor::kFlags); - Node* const new_target = Parameter(Descriptor::kJSNewTarget); - Node* const context = Parameter(Descriptor::kContext); + TNode pattern = CAST(Parameter(Descriptor::kPattern)); + TNode flags = CAST(Parameter(Descriptor::kFlags)); + TNode new_target = CAST(Parameter(Descriptor::kJSNewTarget)); + TNode context = CAST(Parameter(Descriptor::kContext)); Isolate* isolate = this->isolate(); @@ -1335,13 +1315,14 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { if_patternisslowregexp(this); GotoIf(TaggedIsSmi(pattern), &next); - GotoIf(IsJSRegExp(pattern), &if_patternisfastregexp); + GotoIf(IsJSRegExp(CAST(pattern)), &if_patternisfastregexp); Branch(pattern_is_regexp, &if_patternisslowregexp, &next); BIND(&if_patternisfastregexp); { - Node* const source = LoadObjectField(pattern, JSRegExp::kSourceOffset); + Node* const source = + LoadObjectField(CAST(pattern), JSRegExp::kSourceOffset); var_pattern.Bind(source); { @@ -1422,10 +1403,10 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) { // ES#sec-regexp.prototype.compile // RegExp.prototype.compile ( pattern, flags ) TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { - Node* const maybe_receiver = Parameter(Descriptor::kReceiver); - Node* const maybe_pattern = Parameter(Descriptor::kPattern); - Node* const maybe_flags = Parameter(Descriptor::kFlags); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode maybe_pattern = CAST(Parameter(Descriptor::kPattern)); + TNode maybe_flags = CAST(Parameter(Descriptor::kFlags)); + TNode context = CAST(Parameter(Descriptor::kContext)); ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.compile"); @@ -1439,7 +1420,7 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { Label next(this); GotoIf(TaggedIsSmi(maybe_pattern), &next); - GotoIfNot(IsJSRegExp(maybe_pattern), &next); + GotoIfNot(IsJSRegExp(CAST(maybe_pattern)), &next); Node* const pattern = maybe_pattern; @@ -1471,20 +1452,17 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) { // ES6 21.2.5.10. // ES #sec-get-regexp.prototype.source TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const context = Parameter(Descriptor::kContext); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode context = CAST(Parameter(Descriptor::kContext)); // Check whether we have an unmodified regexp instance. Label if_isjsregexp(this), if_isnotjsregexp(this, Label::kDeferred); GotoIf(TaggedIsSmi(receiver), &if_isnotjsregexp); - Branch(IsJSRegExp(receiver), &if_isjsregexp, &if_isnotjsregexp); + Branch(IsJSRegExp(CAST(receiver)), &if_isjsregexp, &if_isnotjsregexp); BIND(&if_isjsregexp); - { - Node* const source = LoadObjectField(receiver, JSRegExp::kSourceOffset); - Return(source); - } + Return(LoadObjectField(CAST(receiver), JSRegExp::kSourceOffset)); BIND(&if_isnotjsregexp); { @@ -1638,8 +1616,8 @@ void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver, // ES6 21.2.5.4. // ES #sec-get-regexp.prototype.global TF_BUILTIN(RegExpPrototypeGlobalGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); FlagGetter(context, receiver, JSRegExp::kGlobal, v8::Isolate::kRegExpPrototypeOldFlagGetter, "RegExp.prototype.global"); @@ -1648,8 +1626,8 @@ TF_BUILTIN(RegExpPrototypeGlobalGetter, RegExpBuiltinsAssembler) { // ES6 21.2.5.5. // ES #sec-get-regexp.prototype.ignorecase TF_BUILTIN(RegExpPrototypeIgnoreCaseGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); FlagGetter(context, receiver, JSRegExp::kIgnoreCase, v8::Isolate::kRegExpPrototypeOldFlagGetter, "RegExp.prototype.ignoreCase"); @@ -1658,8 +1636,8 @@ TF_BUILTIN(RegExpPrototypeIgnoreCaseGetter, RegExpBuiltinsAssembler) { // ES6 21.2.5.7. // ES #sec-get-regexp.prototype.multiline TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); FlagGetter(context, receiver, JSRegExp::kMultiline, v8::Isolate::kRegExpPrototypeOldFlagGetter, "RegExp.prototype.multiline"); @@ -1667,8 +1645,8 @@ TF_BUILTIN(RegExpPrototypeMultilineGetter, RegExpBuiltinsAssembler) { // ES #sec-get-regexp.prototype.dotAll TF_BUILTIN(RegExpPrototypeDotAllGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); static const int kNoCounter = -1; FlagGetter(context, receiver, JSRegExp::kDotAll, kNoCounter, "RegExp.prototype.dotAll"); @@ -1677,8 +1655,8 @@ TF_BUILTIN(RegExpPrototypeDotAllGetter, RegExpBuiltinsAssembler) { // ES6 21.2.5.12. // ES #sec-get-regexp.prototype.sticky TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); FlagGetter(context, receiver, JSRegExp::kSticky, v8::Isolate::kRegExpPrototypeStickyGetter, "RegExp.prototype.sticky"); @@ -1687,8 +1665,8 @@ TF_BUILTIN(RegExpPrototypeStickyGetter, RegExpBuiltinsAssembler) { // ES6 21.2.5.15. // ES #sec-get-regexp.prototype.unicode TF_BUILTIN(RegExpPrototypeUnicodeGetter, RegExpBuiltinsAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* receiver = Parameter(Descriptor::kReceiver); + TNode context = CAST(Parameter(Descriptor::kContext)); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); FlagGetter(context, receiver, JSRegExp::kUnicode, v8::Isolate::kRegExpPrototypeUnicodeGetter, "RegExp.prototype.unicode"); @@ -1876,8 +1854,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, BIND(&if_isnotglobal); { Node* const result = - is_fastpath ? RegExpPrototypeExecBody(context, regexp, string, true) - : RegExpExec(context, regexp, string); + is_fastpath + ? RegExpPrototypeExecBody(CAST(context), CAST(regexp), string, true) + : RegExpExec(context, regexp, string); Return(result); } @@ -1908,9 +1887,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, if (is_fastpath) { // On the fast path, grab the matching string from the raw match index // array. - TNode match_indices = - CAST(RegExpPrototypeExecBodyWithoutResult( - CAST(context), CAST(regexp), string, &if_didnotmatch, true)); + TNode match_indices = + RegExpPrototypeExecBodyWithoutResult(CAST(context), CAST(regexp), + string, &if_didnotmatch, true); Node* const match_from = LoadFixedArrayElement( match_indices, RegExpMatchInfo::kFirstCaptureIndex); @@ -1991,9 +1970,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, // ES#sec-regexp.prototype-@@match // RegExp.prototype [ @@match ] ( string ) TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { - Node* const maybe_receiver = Parameter(Descriptor::kReceiver); - Node* const maybe_string = Parameter(Descriptor::kString); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode maybe_string = CAST(Parameter(Descriptor::kString)); + TNode context = CAST(Parameter(Descriptor::kContext)); // Ensure {maybe_receiver} is a JSReceiver. ThrowIfNotJSReceiver(context, maybe_receiver, @@ -2194,9 +2173,9 @@ TF_BUILTIN(RegExpPrototypeMatchAll, RegExpBuiltinsAssembler) { // 1) receiver is a "fast" RegExp // 2) pattern is a string TF_BUILTIN(RegExpMatchFast, RegExpBuiltinsAssembler) { - Node* const receiver = Parameter(Descriptor::kReceiver); - TNode const string = CAST(Parameter(Descriptor::kPattern)); - Node* const context = Parameter(Descriptor::kContext); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode string = CAST(Parameter(Descriptor::kPattern)); + TNode context = CAST(Parameter(Descriptor::kContext)); RegExpPrototypeMatchBody(context, receiver, string, true); } @@ -2214,8 +2193,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( // Call exec. Label if_didnotmatch(this); - TNode match_indices = CAST(RegExpPrototypeExecBodyWithoutResult( - CAST(context), CAST(regexp), CAST(string), &if_didnotmatch, true)); + TNode match_indices = RegExpPrototypeExecBodyWithoutResult( + CAST(context), CAST(regexp), CAST(string), &if_didnotmatch, true); // Successful match. { @@ -2308,9 +2287,9 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( // ES#sec-regexp.prototype-@@search // RegExp.prototype [ @@search ] ( string ) TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { - Node* const maybe_receiver = Parameter(Descriptor::kReceiver); - Node* const maybe_string = Parameter(Descriptor::kString); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode maybe_string = CAST(Parameter(Descriptor::kString)); + TNode context = CAST(Parameter(Descriptor::kContext)); // Ensure {maybe_receiver} is a JSReceiver. ThrowIfNotJSReceiver(context, maybe_receiver, @@ -2337,9 +2316,9 @@ TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { // 1) receiver is a "fast" RegExp // 2) pattern is a string TF_BUILTIN(RegExpSearchFast, RegExpBuiltinsAssembler) { - Node* const receiver = Parameter(Descriptor::kReceiver); - Node* const string = Parameter(Descriptor::kPattern); - Node* const context = Parameter(Descriptor::kContext); + TNode receiver = CAST(Parameter(Descriptor::kReceiver)); + TNode string = CAST(Parameter(Descriptor::kPattern)); + TNode context = CAST(Parameter(Descriptor::kContext)); RegExpPrototypeSearchBodyFast(context, receiver, string); } @@ -2581,10 +2560,10 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, // Helper that skips a few initial checks. TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { - Node* const regexp = Parameter(Descriptor::kRegExp); - TNode const string = CAST(Parameter(Descriptor::kString)); - Node* const maybe_limit = Parameter(Descriptor::kLimit); - Node* const context = Parameter(Descriptor::kContext); + TNode regexp = CAST(Parameter(Descriptor::kRegExp)); + TNode string = CAST(Parameter(Descriptor::kString)); + TNode maybe_limit = CAST(Parameter(Descriptor::kLimit)); + TNode context = CAST(Parameter(Descriptor::kContext)); CSA_ASSERT(this, IsFastRegExp(context, regexp)); @@ -2640,14 +2619,14 @@ TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { const int kStringArg = 0; const int kLimitArg = 1; - Node* argc = + TNode argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* const maybe_receiver = args.GetReceiver(); - Node* const maybe_string = args.GetOptionalArgumentValue(kStringArg); - Node* const maybe_limit = args.GetOptionalArgumentValue(kLimitArg); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = args.GetReceiver(); + TNode maybe_string = args.GetOptionalArgumentValue(kStringArg); + TNode maybe_limit = args.GetOptionalArgumentValue(kLimitArg); + TNode context = CAST(Parameter(Descriptor::kContext)); // Ensure {maybe_receiver} is a JSReceiver. ThrowIfNotJSReceiver(context, maybe_receiver, @@ -2905,10 +2884,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( BIND(&loop); { - TNode var_match_indices = - CAST(RegExpPrototypeExecBodyWithoutResult(CAST(context), CAST(regexp), - string, &if_nofurthermatches, - kIsFastPath)); + TNode var_match_indices = + RegExpPrototypeExecBodyWithoutResult(CAST(context), CAST(regexp), + string, &if_nofurthermatches, + kIsFastPath); // Successful match. { @@ -2968,10 +2947,10 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( // Helper that skips a few initial checks. TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { - Node* const regexp = Parameter(Descriptor::kRegExp); - TNode const string = CAST(Parameter(Descriptor::kString)); - Node* const replace_value = Parameter(Descriptor::kReplaceValue); - Node* const context = Parameter(Descriptor::kContext); + TNode regexp = CAST(Parameter(Descriptor::kRegExp)); + TNode string = CAST(Parameter(Descriptor::kString)); + TNode replace_value = CAST(Parameter(Descriptor::kReplaceValue)); + TNode context = CAST(Parameter(Descriptor::kContext)); CSA_ASSERT(this, IsFastRegExp(context, regexp)); @@ -2980,7 +2959,7 @@ TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { // 2. Is {replace_value} callable? GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); - Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, + Branch(IsCallableMap(LoadMap(CAST(replace_value))), &if_iscallable, &checkreplacestring); // 3. Does ToString({replace_value}) contain '$'? @@ -3039,14 +3018,14 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { const int kStringArg = 0; const int kReplaceValueArg = 1; - Node* argc = + TNode argc = ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount)); CodeStubArguments args(this, argc); - Node* const maybe_receiver = args.GetReceiver(); - Node* const maybe_string = args.GetOptionalArgumentValue(kStringArg); - Node* const replace_value = args.GetOptionalArgumentValue(kReplaceValueArg); - Node* const context = Parameter(Descriptor::kContext); + TNode maybe_receiver = args.GetReceiver(); + TNode maybe_string = args.GetOptionalArgumentValue(kStringArg); + TNode replace_value = args.GetOptionalArgumentValue(kReplaceValueArg); + TNode context = CAST(Parameter(Descriptor::kContext)); // RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic: // @@ -3091,27 +3070,25 @@ TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) { // Simple string matching functionality for internal use which does not modify // the last match info. TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { - TNode const regexp = CAST(Parameter(Descriptor::kRegExp)); - TNode const string = CAST(Parameter(Descriptor::kString)); - Node* const context = Parameter(Descriptor::kContext); + TNode regexp = CAST(Parameter(Descriptor::kRegExp)); + TNode string = CAST(Parameter(Descriptor::kString)); + TNode context = CAST(Parameter(Descriptor::kContext)); - Node* const native_context = LoadNativeContext(context); - Node* const internal_match_info = LoadContextElement( - native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); - Node* const match_indices = - CallBuiltin(Builtins::kRegExpExecInternal, context, regexp, string, - SmiZero(), internal_match_info); - Node* const null = NullConstant(); + TNode native_context = LoadNativeContext(context); + TNode internal_match_info = CAST(LoadContextElement( + native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX)); + TNode maybe_match_indices = + CAST(CallBuiltin(Builtins::kRegExpExecInternal, context, regexp, string, + SmiZero(), internal_match_info)); + TNode null = NullConstant(); Label if_matched(this); - GotoIfNot(WordEqual(match_indices, null), &if_matched); + GotoIfNot(WordEqual(maybe_match_indices, null), &if_matched); Return(null); BIND(&if_matched); - { - Node* result = - ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); - Return(result); - } + TNode match_indices = CAST(maybe_match_indices); + Return( + ConstructNewResultFromMatchInfo(context, regexp, match_indices, string)); } class RegExpStringIteratorAssembler : public RegExpBuiltinsAssembler { @@ -3178,6 +3155,10 @@ TF_BUILTIN(RegExpStringIteratorPrototypeNext, RegExpStringIteratorAssembler) { TNode iterating_regexp = LoadObjectField(receiver, JSRegExpStringIterator::kIteratingRegExpOffset); + // TODO(jgruber): Verify that this is guaranteed. + CSA_CHECK(this, TaggedIsNotSmi(iterating_regexp)); + CSA_CHECK(this, IsJSReceiver(CAST(iterating_regexp))); + // 6. Let S be O.[[IteratedString]]. TNode iterating_string = CAST( LoadObjectField(receiver, JSRegExpStringIterator::kIteratedStringOffset)); @@ -3194,16 +3175,19 @@ TF_BUILTIN(RegExpStringIteratorPrototypeNext, RegExpStringIteratorAssembler) { { Label if_fast(this), if_slow(this, Label::kDeferred); BranchIfFastRegExp(context, iterating_regexp, &if_fast, &if_slow); + BIND(&if_fast); { - TNode indices_or_null = RegExpPrototypeExecBodyWithoutResult( - context, CAST(iterating_regexp), iterating_string, &if_no_match, - true); - var_match = CAST(ConstructNewResultFromMatchInfo( - context, iterating_regexp, indices_or_null, iterating_string)); + TNode match_indices = + RegExpPrototypeExecBodyWithoutResult(context, CAST(iterating_regexp), + iterating_string, &if_no_match, + true); + var_match = ConstructNewResultFromMatchInfo( + context, CAST(iterating_regexp), match_indices, iterating_string); var_is_fast_regexp = Int32TrueConstant(); Goto(&if_match); } + BIND(&if_slow); { var_match = CAST(RegExpExec(context, iterating_regexp, iterating_string)); diff --git a/src/builtins/builtins-regexp-gen.h b/src/builtins/builtins-regexp-gen.h index 91e41fbb33..fd0e4b6755 100644 --- a/src/builtins/builtins-regexp-gen.h +++ b/src/builtins/builtins-regexp-gen.h @@ -39,10 +39,11 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { // Allocate a RegExpResult with the given length (the number of captures, // including the match itself), index (the index where the match starts), - // and input string. |length| and |index| are expected to be tagged, and - // |input| must be a string. - Node* AllocateRegExpResult(Node* context, Node* length, Node* index, - Node* input); + // and input string. + TNode AllocateRegExpResult(TNode context, + TNode length, + TNode index, + TNode input); TNode FastLoadLastIndex(TNode regexp); TNode SlowLoadLastIndex(TNode context, TNode regexp); @@ -68,15 +69,17 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler { TNode last_index, TNode match_info); - Node* ConstructNewResultFromMatchInfo(Node* const context, Node* const regexp, - Node* const match_info, - TNode const string); + TNode ConstructNewResultFromMatchInfo( + TNode context, TNode maybe_regexp, + TNode match_info, TNode string); - TNode RegExpPrototypeExecBodyWithoutResult( + TNode RegExpPrototypeExecBodyWithoutResult( TNode context, TNode maybe_regexp, TNode string, Label* if_didnotmatch, const bool is_fastpath); - Node* RegExpPrototypeExecBody(Node* const context, Node* const regexp, - TNode string, const bool is_fastpath); + TNode RegExpPrototypeExecBody(TNode context, + TNode maybe_regexp, + TNode string, + const bool is_fastpath); Node* ThrowIfNotJSReceiver(Node* context, Node* maybe_receiver, MessageTemplate::Template msg_template, diff --git a/src/objects.h b/src/objects.h index f84f29a3a1..cda624f200 100644 --- a/src/objects.h +++ b/src/objects.h @@ -838,6 +838,7 @@ class ZoneForwardList; V(JSProxy) \ V(JSReceiver) \ V(JSRegExp) \ + V(JSRegExpResult) \ V(JSRegExpStringIterator) \ V(JSSet) \ V(JSSetIterator) \ @@ -987,6 +988,7 @@ class ZoneForwardList; V(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) \ V(JSPromise, JS_PROMISE_TYPE) \ V(JSRegExp, JS_REGEXP_TYPE) \ + V(JSRegExpResult, JS_ARRAY_TYPE) \ V(JSRegExpStringIterator, JS_REGEXP_STRING_ITERATOR_TYPE) \ V(JSSet, JS_SET_TYPE) \ V(JSStringIterator, JS_STRING_ITERATOR_TYPE) \