Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Unified Diff: src/builtins/builtins-regexp.cc

Issue 2532403002: [regexp] Migrate @@split to TurboFan (Closed)
Patch Set: Address comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-regexp.cc
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
index dfca3151f2e73835ebc60d35028331cc19d36469..259449e6015e056aa800ad56a844c063cb4a508a 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -16,6 +16,7 @@ namespace internal {
typedef compiler::Node Node;
typedef CodeStubAssembler::Label CLabel;
typedef CodeStubAssembler::Variable CVariable;
+typedef CodeStubAssembler::ParameterMode ParameterMode;
typedef compiler::CodeAssemblerState CodeAssemblerState;
// -----------------------------------------------------------------------------
@@ -259,7 +260,7 @@ Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a,
Node* string) {
CLabel out(a);
- CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement(
match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0,
mode));
@@ -1180,8 +1181,7 @@ class GrowableFixedArray {
CodeStubAssembler* a = assembler_;
const WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER;
- const CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const length = var_length_.value();
Node* const capacity = var_capacity_.value();
@@ -1233,8 +1233,7 @@ class GrowableFixedArray {
CodeStubAssembler* a = assembler_;
const ElementsKind kind = FAST_ELEMENTS;
- const CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
static const int kInitialArraySize = 8;
Node* const capacity = a->IntPtrConstant(kInitialArraySize);
@@ -1262,7 +1261,7 @@ class GrowableFixedArray {
}
Node* GrowFixedArray(Node* const current_capacity, Node* const new_capacity,
- CodeStubAssembler::ParameterMode mode) {
+ ParameterMode mode) {
DCHECK(mode == CodeStubAssembler::INTPTR_PARAMETERS);
CodeStubAssembler* a = assembler_;
@@ -1360,8 +1359,7 @@ void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
// TODO(jgruber): We could optimize further here and in other
// methods (e.g. @@search) by bypassing RegExp result construction.
Node* const result_fixed_array = a->LoadElements(result);
- const CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
match =
a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
@@ -1380,8 +1378,7 @@ void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
// TODO(jgruber): We could optimize further here and in other
// methods (e.g. @@search) by bypassing RegExp result construction.
Node* const result_fixed_array = a->LoadElements(result);
- const CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const match =
a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
@@ -1598,346 +1595,322 @@ void Builtins::Generate_RegExpPrototypeSearch(CodeAssemblerState* state) {
namespace {
-MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
- Handle<Object> object,
- uint32_t* out) {
- if (object->IsUndefined(isolate)) {
- *out = kMaxUInt32;
- return object;
- }
-
- Handle<Object> number;
- ASSIGN_RETURN_ON_EXCEPTION(isolate, number, Object::ToNumber(object), Object);
- *out = NumberToUint32(*number);
- return object;
-}
+// Generates the fast path for @@split. {regexp} is an unmodified JSRegExp,
+// {string} is a String, and {limit} is a Smi.
+void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp,
+ Node* const string, Node* const limit,
+ Node* const context) {
+ Isolate* isolate = a->isolate();
-bool AtSurrogatePair(Isolate* isolate, Handle<String> string, int index) {
- if (index + 1 >= string->length()) return false;
- const uint16_t first = string->Get(index);
- if (first < 0xD800 || first > 0xDBFF) return false;
- const uint16_t second = string->Get(index + 1);
- return (second >= 0xDC00 && second <= 0xDFFF);
-}
+ Node* const null = a->NullConstant();
+ Node* const smi_zero = a->SmiConstant(0);
+ Node* const int_zero = a->IntPtrConstant(0);
+ Node* const int_limit = a->SmiUntag(limit);
-Handle<JSArray> NewJSArrayWithElements(Isolate* isolate,
- Handle<FixedArray> elems,
- int num_elems) {
- elems->Shrink(num_elems);
- return isolate->factory()->NewJSArrayWithElements(elems);
-}
+ const ElementsKind kind = FAST_ELEMENTS;
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
-MaybeHandle<JSArray> RegExpSplit(Isolate* isolate, Handle<JSRegExp> regexp,
- Handle<String> string,
- Handle<Object> limit_obj) {
- Factory* factory = isolate->factory();
+ Node* const allocation_site = nullptr;
+ Node* const native_context = a->LoadNativeContext(context);
+ Node* const array_map = a->LoadJSArrayElementsMap(kind, native_context);
- uint32_t limit;
- RETURN_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit), JSArray);
+ CLabel return_empty_array(a, CLabel::kDeferred);
- const int length = string->length();
+ // If limit is zero, return an empty array.
+ {
+ CLabel next(a), if_limitiszero(a, CLabel::kDeferred);
+ a->Branch(a->SmiEqual(limit, smi_zero), &return_empty_array, &next);
+ a->Bind(&next);
+ }
- if (limit == 0) return factory->NewJSArray(0);
+ Node* const string_length = a->LoadStringLength(string);
- Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
+ // If passed the empty {string}, return either an empty array or a singleton
+ // array depending on whether the {regexp} matches.
+ {
+ CLabel next(a), if_stringisempty(a, CLabel::kDeferred);
+ a->Branch(a->SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
- if (length == 0) {
- Handle<Object> match_indices;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, match_indices,
- RegExpImpl::Exec(regexp, string, 0, last_match_info), JSArray);
+ a->Bind(&if_stringisempty);
+ {
+ Node* const last_match_info = a->LoadContextElement(
+ native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
- if (!match_indices->IsNull(isolate)) return factory->NewJSArray(0);
+ Callable exec_callable = CodeFactory::RegExpExec(isolate);
+ Node* const match_indices = a->CallStub(
+ exec_callable, context, regexp, string, smi_zero, last_match_info);
- Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
- elems->set(0, *string);
- return factory->NewJSArrayWithElements(elems);
- }
+ CLabel return_singleton_array(a);
+ a->Branch(a->WordEqual(match_indices, null), &return_singleton_array,
+ &return_empty_array);
- int current_index = 0;
- int start_index = 0;
- int start_match = 0;
+ a->Bind(&return_singleton_array);
+ {
+ Node* const length = a->SmiConstant(1);
+ Node* const capacity = a->IntPtrConstant(1);
+ Node* const result = a->AllocateJSArray(kind, array_map, capacity,
+ length, allocation_site, mode);
- static const int kInitialArraySize = 8;
- Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
- int num_elems = 0;
+ Node* const fixed_array = a->LoadElements(result);
+ a->StoreFixedArrayElement(fixed_array, 0, string);
- while (true) {
- if (start_index == length) {
- Handle<String> substr =
- factory->NewSubString(string, current_index, length);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
- break;
+ a->Return(result);
+ }
}
- Handle<Object> match_indices_obj;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, match_indices_obj,
- RegExpImpl::Exec(regexp, string, start_index,
- isolate->regexp_last_match_info()),
- JSArray);
-
- if (match_indices_obj->IsNull(isolate)) {
- Handle<String> substr =
- factory->NewSubString(string, current_index, length);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
- break;
- }
+ a->Bind(&next);
+ }
- auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
+ // Loop preparations.
- start_match = match_indices->Capture(0);
+ GrowableFixedArray array(a);
- if (start_match == length) {
- Handle<String> substr =
- factory->NewSubString(string, current_index, length);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
- break;
- }
+ CVariable var_last_matched_until(a, MachineRepresentation::kTagged);
+ CVariable var_next_search_from(a, MachineRepresentation::kTagged);
- const int end_index = match_indices->Capture(1);
+ var_last_matched_until.Bind(smi_zero);
+ var_next_search_from.Bind(smi_zero);
- if (start_index == end_index && end_index == current_index) {
- const bool unicode = (regexp->GetFlags() & JSRegExp::kUnicode) != 0;
- if (unicode && AtSurrogatePair(isolate, string, start_index)) {
- start_index += 2;
- } else {
- start_index += 1;
- }
- continue;
- }
+ CVariable* vars[] = {array.var_array(), array.var_length(),
+ array.var_capacity(), &var_last_matched_until,
+ &var_next_search_from};
+ const int vars_count = sizeof(vars) / sizeof(vars[0]);
+ CLabel loop(a, vars_count, vars), push_suffix_and_out(a), out(a);
+ a->Goto(&loop);
+
+ a->Bind(&loop);
+ {
+ Node* const next_search_from = var_next_search_from.value();
+ Node* const last_matched_until = var_last_matched_until.value();
+ // We're done if we've reached the end of the string.
{
- Handle<String> substr =
- factory->NewSubString(string, current_index, start_match);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
+ CLabel next(a);
+ a->Branch(a->SmiEqual(next_search_from, string_length),
+ &push_suffix_and_out, &next);
+ a->Bind(&next);
}
- if (static_cast<uint32_t>(num_elems) == limit) break;
+ // Search for the given {regexp}.
- for (int i = 2; i < match_indices->NumberOfCaptureRegisters(); i += 2) {
- const int start = match_indices->Capture(i);
- const int end = match_indices->Capture(i + 1);
+ Node* const last_match_info = a->LoadContextElement(
+ native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
- if (end != -1) {
- Handle<String> substr = factory->NewSubString(string, start, end);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
- } else {
- elems = FixedArray::SetAndGrow(elems, num_elems++,
- factory->undefined_value());
- }
+ Callable exec_callable = CodeFactory::RegExpExec(isolate);
+ Node* const match_indices =
+ a->CallStub(exec_callable, context, regexp, string, next_search_from,
+ last_match_info);
- if (static_cast<uint32_t>(num_elems) == limit) {
- return NewJSArrayWithElements(isolate, elems, num_elems);
- }
+ // We're done if no match was found.
+ {
+ CLabel next(a);
+ a->Branch(a->WordEqual(match_indices, null), &push_suffix_and_out, &next);
+ a->Bind(&next);
}
- start_index = current_index = end_index;
- }
+ Node* const match_from = a->LoadFixedArrayElement(
+ match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
+ 0, mode);
- return NewJSArrayWithElements(isolate, elems, num_elems);
-}
+ // We're done if the match starts beyond the string.
+ {
+ CLabel next(a);
+ a->Branch(a->WordEqual(match_from, string_length), &push_suffix_and_out,
+ &next);
+ a->Bind(&next);
+ }
-// ES##sec-speciesconstructor
-// SpeciesConstructor ( O, defaultConstructor )
-MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor(
- Isolate* isolate, Handle<JSReceiver> recv,
- Handle<JSFunction> default_ctor) {
- Handle<Object> ctor_obj;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, ctor_obj,
- JSObject::GetProperty(recv, isolate->factory()->constructor_string()),
- Object);
-
- if (ctor_obj->IsUndefined(isolate)) return default_ctor;
-
- if (!ctor_obj->IsJSReceiver()) {
- THROW_NEW_ERROR(isolate,
- NewTypeError(MessageTemplate::kConstructorNotReceiver),
- Object);
- }
+ Node* const match_to = a->LoadFixedArrayElement(
+ match_indices,
+ a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
- Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
+ // Advance index and continue if the match is empty.
+ {
+ CLabel next(a);
- Handle<Object> species;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, species,
- JSObject::GetProperty(ctor, isolate->factory()->species_symbol()),
- Object);
+ a->GotoUnless(a->SmiEqual(match_to, next_search_from), &next);
+ a->GotoUnless(a->SmiEqual(match_to, last_matched_until), &next);
- if (species->IsNull(isolate) || species->IsUndefined(isolate)) {
- return default_ctor;
- }
+ Node* const is_unicode = FastFlagGetter(a, regexp, JSRegExp::kUnicode);
+ Node* const new_next_search_from =
+ AdvanceStringIndex(a, string, next_search_from, is_unicode);
+ var_next_search_from.Bind(new_next_search_from);
+ a->Goto(&loop);
- if (species->IsConstructor()) return species;
+ a->Bind(&next);
+ }
- THROW_NEW_ERROR(
- isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
-}
+ // A valid match was found, add the new substring to the array.
+ {
+ Node* const from = last_matched_until;
+ Node* const to = match_from;
-} // namespace
+ Node* const substr = a->SubString(context, string, from, to);
+ array.Push(substr);
-// ES#sec-regexp.prototype-@@split
-// RegExp.prototype [ @@split ] ( string, limit )
-BUILTIN(RegExpPrototypeSplit) {
- HandleScope scope(isolate);
- CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@split");
+ a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
+ }
- Factory* factory = isolate->factory();
+ // Add all captures to the array.
+ {
+ Node* const num_registers = a->LoadFixedArrayElement(
+ match_indices,
+ a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
+ Node* const int_num_registers = a->SmiUntag(num_registers);
- Handle<Object> string_obj = args.atOrUndefined(isolate, 1);
- Handle<Object> limit_obj = args.atOrUndefined(isolate, 2);
+ CVariable var_reg(a, MachineType::PointerRepresentation());
+ var_reg.Bind(a->IntPtrConstant(2));
- Handle<String> string;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
- Object::ToString(isolate, string_obj));
+ CVariable* vars[] = {array.var_array(), array.var_length(),
+ array.var_capacity(), &var_reg};
+ const int vars_count = sizeof(vars) / sizeof(vars[0]);
+ CLabel nested_loop(a, vars_count, vars), nested_loop_out(a);
+ a->Branch(a->IntPtrLessThan(var_reg.value(), int_num_registers),
+ &nested_loop, &nested_loop_out);
- if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) {
- RETURN_RESULT_OR_FAILURE(
- isolate,
- RegExpSplit(isolate, Handle<JSRegExp>::cast(recv), string, limit_obj));
- }
+ a->Bind(&nested_loop);
+ {
+ Node* const reg = var_reg.value();
+ Node* const from = a->LoadFixedArrayElement(
+ match_indices, reg,
+ RegExpMatchInfo::kFirstCaptureIndex * kPointerSize, mode);
+ Node* const to = a->LoadFixedArrayElement(
+ match_indices, reg,
+ (RegExpMatchInfo::kFirstCaptureIndex + 1) * kPointerSize, mode);
+
+ CLabel select_capture(a), select_undefined(a), store_value(a);
+ CVariable var_value(a, MachineRepresentation::kTagged);
+ a->Branch(a->SmiEqual(to, a->SmiConstant(-1)), &select_undefined,
+ &select_capture);
+
+ a->Bind(&select_capture);
+ {
+ Node* const substr = a->SubString(context, string, from, to);
+ var_value.Bind(substr);
+ a->Goto(&store_value);
+ }
- Handle<JSFunction> regexp_fun = isolate->regexp_function();
- Handle<Object> ctor;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun));
+ a->Bind(&select_undefined);
+ {
+ Node* const undefined = a->UndefinedConstant();
+ var_value.Bind(undefined);
+ a->Goto(&store_value);
+ }
- Handle<Object> flags_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, flags_obj, JSObject::GetProperty(recv, factory->flags_string()));
+ a->Bind(&store_value);
+ {
+ array.Push(var_value.value());
+ a->GotoIf(a->WordEqual(array.length(), int_limit), &out);
- Handle<String> flags;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags,
- Object::ToString(isolate, flags_obj));
+ Node* const new_reg = a->IntPtrAdd(reg, a->IntPtrConstant(2));
+ var_reg.Bind(new_reg);
- Handle<String> u_str = factory->LookupSingleCharacterStringFromCode('u');
- const bool unicode = (String::IndexOf(isolate, flags, u_str, 0) >= 0);
+ a->Branch(a->IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
+ &nested_loop_out);
+ }
+ }
- Handle<String> y_str = factory->LookupSingleCharacterStringFromCode('y');
- const bool sticky = (String::IndexOf(isolate, flags, y_str, 0) >= 0);
+ a->Bind(&nested_loop_out);
+ }
- Handle<String> new_flags = flags;
- if (!sticky) {
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, new_flags,
- factory->NewConsString(flags, y_str));
+ var_last_matched_until.Bind(match_to);
+ var_next_search_from.Bind(match_to);
+ a->Goto(&loop);
}
- Handle<JSReceiver> splitter;
+ a->Bind(&push_suffix_and_out);
{
- const int argc = 2;
+ Node* const from = var_last_matched_until.value();
+ Node* const to = string_length;
- ScopedVector<Handle<Object>> argv(argc);
- argv[0] = recv;
- argv[1] = new_flags;
+ Node* const substr = a->SubString(context, string, from, to);
+ array.Push(substr);
- Handle<JSFunction> ctor_fun = Handle<JSFunction>::cast(ctor);
- Handle<Object> splitter_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start()));
+ a->Goto(&out);
+ }
- splitter = Handle<JSReceiver>::cast(splitter_obj);
+ a->Bind(&out);
+ {
+ Node* const result = array.ToJSArray(context);
+ a->Return(result);
}
- uint32_t limit;
- RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit));
+ a->Bind(&return_empty_array);
+ {
+ Node* const length = smi_zero;
+ Node* const capacity = int_zero;
+ Node* const result = a->AllocateJSArray(kind, array_map, capacity, length,
+ allocation_site, mode);
+ a->Return(result);
+ }
+}
- const int length = string->length();
+} // namespace
- if (limit == 0) return *factory->NewJSArray(0);
+// ES#sec-regexp.prototype-@@split
+// RegExp.prototype [ @@split ] ( string, limit )
+void Builtins::Generate_RegExpPrototypeSplit(CodeAssemblerState* state) {
+ CodeStubAssembler a(state);
- if (length == 0) {
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
- factory->undefined_value()));
+ Isolate* const isolate = a.isolate();
- if (!result->IsNull(isolate)) return *factory->NewJSArray(0);
+ Node* const undefined = a.UndefinedConstant();
- Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
- elems->set(0, *string);
- return *factory->NewJSArrayWithElements(elems);
- }
+ Node* const maybe_receiver = a.Parameter(0);
+ Node* const maybe_string = a.Parameter(1);
+ Node* const maybe_limit = a.Parameter(2);
+ Node* const context = a.Parameter(5);
- // TODO(jgruber): Wrap this in a helper class.
- static const int kInitialArraySize = 8;
- Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
- int num_elems = 0;
+ // Ensure {maybe_receiver} is a JSReceiver.
+ Node* const map = ThrowIfNotJSReceiver(
+ &a, isolate, context, maybe_receiver,
+ MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.@@split");
+ Node* const receiver = maybe_receiver;
- int string_index = 0;
- int prev_string_index = 0;
- while (string_index < length) {
- RETURN_FAILURE_ON_EXCEPTION(
- isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index));
+ // Convert {maybe_string} to a String.
+ Node* const string = a.ToString(context, maybe_string);
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
- factory->undefined_value()));
+ CLabel fast_path(&a), slow_path(&a);
+ BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
- if (result->IsNull(isolate)) {
- string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
- string_index, unicode);
- continue;
- }
+ a.Bind(&fast_path);
+ {
+ // Convert {maybe_limit} to a uint32, capping at the maximal smi value.
+ CVariable var_limit(&a, MachineRepresentation::kTagged);
+ CLabel if_limitissmimax(&a), limit_done(&a);
- // TODO(jgruber): Extract toLength of some property into function.
- Handle<Object> last_index_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter));
+ a.GotoIf(a.WordEqual(maybe_limit, undefined), &if_limitissmimax);
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
- const int last_index = Handle<Smi>::cast(last_index_obj)->value();
-
- const int end = std::min(last_index, length);
- if (end == prev_string_index) {
- string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
- string_index, unicode);
- continue;
+ {
+ Node* const limit = a.ToUint32(context, maybe_limit);
+ a.GotoUnless(a.TaggedIsSmi(limit), &if_limitissmimax);
+
+ var_limit.Bind(limit);
+ a.Goto(&limit_done);
}
+ a.Bind(&if_limitissmimax);
{
- Handle<String> substr =
- factory->NewSubString(string, prev_string_index, string_index);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
- if (static_cast<uint32_t>(num_elems) == limit) {
- return *NewJSArrayWithElements(isolate, elems, num_elems);
- }
+ // TODO(jgruber): In this case, we can probably generation of limit checks
+ // in Generate_RegExpPrototypeSplitBody.
+ Node* const smi_max = a.SmiConstant(Smi::kMaxValue);
+ var_limit.Bind(smi_max);
+ a.Goto(&limit_done);
}
- prev_string_index = end;
-
- Handle<Object> num_captures_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, num_captures_obj,
- Object::GetProperty(result, isolate->factory()->length_string()));
-
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj));
- const int num_captures =
- std::max(Handle<Smi>::cast(num_captures_obj)->value(), 0);
-
- for (int i = 1; i < num_captures; i++) {
- Handle<Object> capture;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, capture, Object::GetElement(isolate, result, i));
- elems = FixedArray::SetAndGrow(elems, num_elems++, capture);
- if (static_cast<uint32_t>(num_elems) == limit) {
- return *NewJSArrayWithElements(isolate, elems, num_elems);
- }
+ a.Bind(&limit_done);
+ {
+ Node* const limit = var_limit.value();
+ Generate_RegExpPrototypeSplitBody(&a, receiver, string, limit, context);
}
-
- string_index = prev_string_index;
}
+ a.Bind(&slow_path);
{
- Handle<String> substr =
- factory->NewSubString(string, prev_string_index, length);
- elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
+ Node* const result = a.CallRuntime(Runtime::kRegExpSplit, context, receiver,
+ string, maybe_limit);
+ a.Return(result);
}
-
- return *NewJSArrayWithElements(isolate, elems, num_elems);
}
namespace {
@@ -1972,8 +1945,7 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
Node* const capacity = a->IntPtrConstant(16);
Node* const length = smi_zero;
Node* const allocation_site = nullptr;
- CodeStubAssembler::ParameterMode capacity_mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode capacity_mode = CodeStubAssembler::INTPTR_PARAMETERS;
result_array = a->AllocateJSArray(kind, array_map, capacity, length,
allocation_site, capacity_mode);
@@ -2001,7 +1973,7 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
Node* const res_elems = a->LoadElements(res);
CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE));
- CodeStubAssembler::ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const num_capture_registers = a->LoadFixedArrayElement(
last_match_info,
a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
@@ -2034,8 +2006,7 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
Node* const i = var_i.value();
a->GotoUnless(a->IntPtrLessThan(i, end), &create_result);
- CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const elem = a->LoadFixedArrayElement(res_elems, i, 0, mode);
CLabel if_issmi(a), if_isstring(a), loop_epilogue(a);
@@ -2102,8 +2073,7 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
a->Bind(&if_hasexplicitcaptures);
{
- CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const from = int_zero;
Node* const to = a->SmiUntag(res_length);
@@ -2220,8 +2190,7 @@ Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a, Node* context,
a->Bind(&if_matched);
{
- CodeStubAssembler::ParameterMode mode =
- CodeStubAssembler::INTPTR_PARAMETERS;
+ ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const subject_start = smi_zero;
Node* const match_start = a->LoadFixedArrayElement(
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698