summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-08-14 16:28:54 -0400
committerLinus Groh <mail@linusgroh.de>2021-08-15 11:43:45 +0100
commitf1ce998d73979b80352675d6d3170399b2311913 (patch)
treeab15c8d1713571bbbf87591c7d3a8e1b0e7b5f58 /Userland/Libraries/LibJS/Runtime
parentfea181bde35b115de33adb5f80c3f6abe46cec72 (diff)
downloadserenity-f1ce998d73979b80352675d6d3170399b2311913.zip
LibRegex+LibJS: Combine named and unnamed capture groups in MatchState
Combining these into one list helps reduce the size of MatchState, and as a result, reduces the amount of memory consumed during execution of very large regex matches. Doing this also allows us to remove a few regex byte code instructions: ClearNamedCaptureGroup, SaveLeftNamedCaptureGroup, and NamedReference. Named groups now behave the same as unnamed groups for these operations. Note that SaveRightNamedCaptureGroup still exists to cache the matched group name. This also removes the recursion level from the MatchState, as it can exist as a local variable in Matcher::execute instead.
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime')
-rw-r--r--Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp22
1 files changed, 9 insertions, 13 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
index 7a5c4fad99..ca3f4593b5 100644
--- a/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
+++ b/Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
@@ -263,13 +263,16 @@ static Value regexp_builtin_exec(GlobalObject& global_object, RegExpObject& rege
return {};
}
- auto* array = Array::create(global_object, result.n_capture_groups + 1);
+ auto* array = Array::create(global_object, result.n_named_capture_groups + 1);
if (vm.exception())
return {};
Vector<Optional<Match>> indices { Match::create(match) };
HashMap<String, Match> group_names;
+ bool has_groups = result.n_named_capture_groups != 0;
+ Object* groups_object = has_groups ? Object::create(global_object, nullptr) : nullptr;
+
for (size_t i = 0; i < result.n_capture_groups; ++i) {
auto capture_value = js_undefined();
auto& capture = result.capture_group_matches[0][i + 1];
@@ -280,22 +283,15 @@ static Value regexp_builtin_exec(GlobalObject& global_object, RegExpObject& rege
indices.append(Match::create(capture));
}
array->create_data_property_or_throw(i + 1, capture_value);
- }
-
- bool has_groups = result.n_named_capture_groups > 0;
- Value groups = js_undefined();
- if (has_groups) {
- auto groups_object = Object::create(global_object, nullptr);
-
- for (auto& entry : result.named_capture_group_matches[0]) {
- groups_object->create_data_property_or_throw(entry.key, js_string(vm, entry.value.view.u16_view()));
- group_names.set(entry.key, Match::create(entry.value));
+ if (capture.capture_group_name.has_value()) {
+ auto group_name = capture.capture_group_name->to_string();
+ groups_object->create_data_property_or_throw(group_name, js_string(vm, capture.view.u16_view()));
+ group_names.set(move(group_name), Match::create(capture));
}
-
- groups = move(groups_object);
}
+ Value groups = has_groups ? groups_object : js_undefined();
array->create_data_property_or_throw(vm.names.groups, groups);
if (has_indices) {