Skip to content

Commit 50fadbb

Browse files
balajirraogbrail
authored andcommitted
Introduce fast path for RegExp.prototype[Symbol.split]
1 parent d3b8320 commit 50fadbb

1 file changed

Lines changed: 92 additions & 5 deletions

File tree

rhino/src/main/java/org/mozilla/javascript/regexp/NativeRegExp.java

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3843,7 +3843,7 @@ private void setLastIndex(ScriptableObject thisObj, Object value) {
38433843
setLastIndex((Scriptable) thisObj, value);
38443844
}
38453845

3846-
private void setLastIndex(Scriptable thisObj, Object value) {
3846+
private static void setLastIndex(Scriptable thisObj, Object value) {
38473847
ScriptableObject.putProperty(thisObj, "lastIndex", value);
38483848
}
38493849

@@ -4404,13 +4404,10 @@ private Object js_SymbolSplit(Context cx, Scriptable scope, Scriptable rx, Objec
44044404

44054405
String flags = ScriptRuntime.toString(ScriptRuntime.getObjectProp(rx, "flags", cx));
44064406
boolean unicodeMatching = flags.indexOf('u') != -1 || flags.indexOf('v') != -1;
4407+
NativeArray a = (NativeArray) cx.newArray(scope, 0);
44074408
String newFlags = flags.indexOf('y') != -1 ? flags : (flags + "y");
4408-
44094409
Scriptable splitter = c.construct(cx, scope, new Object[] {rx, newFlags});
44104410

4411-
NativeArray a = (NativeArray) cx.newArray(scope, 0);
4412-
int lengthA = 0;
4413-
44144411
Object limit = args.length > 1 ? args[1] : Undefined.instance;
44154412
long lim;
44164413
if (Undefined.isUndefined(limit)) {
@@ -4422,6 +4419,30 @@ private Object js_SymbolSplit(Context cx, Scriptable scope, Scriptable rx, Objec
44224419
return a;
44234420
}
44244421

4422+
if (splitter instanceof NativeRegExp) {
4423+
var regexp = (NativeRegExp) splitter;
4424+
var exec = ScriptableObject.getProperty(regexp, "exec");
4425+
if ((regexp.lastIndexAttr & READONLY) == 0
4426+
&& exec instanceof IdFunctionObject
4427+
&& ((IdFunctionObject) exec).methodId() == Id_exec
4428+
&& ((IdFunctionObject) exec).getTag() == REGEXP_TAG)
4429+
return js_SymbolSplitFast(
4430+
cx, scope, (NativeRegExp) splitter, s, lim, unicodeMatching, a);
4431+
}
4432+
4433+
return js_SymbolSplitSlow(cx, scope, splitter, s, lim, unicodeMatching, a);
4434+
}
4435+
4436+
private static Object js_SymbolSplitSlow(
4437+
Context cx,
4438+
Scriptable scope,
4439+
Scriptable splitter,
4440+
String s,
4441+
long lim,
4442+
boolean unicodeMatching,
4443+
NativeArray a) {
4444+
int lengthA = 0;
4445+
44254446
if (s.isEmpty()) {
44264447
Object z = regExpExec(splitter, s, cx, scope);
44274448
if (z != null) {
@@ -4476,6 +4497,72 @@ private Object js_SymbolSplit(Context cx, Scriptable scope, Scriptable rx, Objec
44764497
return a;
44774498
}
44784499

4500+
private static Object js_SymbolSplitFast(
4501+
Context cx,
4502+
Scriptable scope,
4503+
NativeRegExp splitter,
4504+
String s,
4505+
long lim,
4506+
boolean unicodeMatching,
4507+
NativeArray a) {
4508+
int lengthA = 0;
4509+
4510+
int[] indexp = {0};
4511+
RegExpImpl reImpl = getImpl(cx);
4512+
if (s.isEmpty()) {
4513+
ExecResult result = splitter.executeRegExpInternal(cx, scope, reImpl, s, indexp, MATCH);
4514+
if (result != null) {
4515+
return a;
4516+
}
4517+
a.put(0, a, s);
4518+
return a;
4519+
}
4520+
4521+
int size = s.length();
4522+
long p = 0;
4523+
long q = p;
4524+
while (q < size) {
4525+
indexp[0] = (int) q;
4526+
ExecResult result = splitter.executeRegExpInternal(cx, scope, reImpl, s, indexp, MATCH);
4527+
4528+
if (result == null) {
4529+
q = ScriptRuntime.advanceStringIndex(s, q, unicodeMatching);
4530+
} else {
4531+
long e = indexp[0];
4532+
e = Math.min(e, size);
4533+
if (e == p) {
4534+
q = ScriptRuntime.advanceStringIndex(s, q, unicodeMatching);
4535+
} else {
4536+
String t = s.substring((int) p, (int) q);
4537+
a.put((int) a.getLength(), a, t);
4538+
lengthA++;
4539+
if (a.getLength() == lim) {
4540+
return a;
4541+
}
4542+
4543+
p = e;
4544+
int i = 0;
4545+
while (i < result.captures.size()) {
4546+
Object nextCapture = result.captures.get(i);
4547+
a.put(
4548+
(int) a.getLength(),
4549+
a,
4550+
nextCapture == null ? Undefined.instance : nextCapture);
4551+
i = i + 1;
4552+
lengthA++;
4553+
if (lengthA == lim) {
4554+
return a;
4555+
}
4556+
}
4557+
q = p;
4558+
}
4559+
}
4560+
}
4561+
String t = s.substring((int) p, size);
4562+
a.put((int) a.getLength(), a, t);
4563+
return a;
4564+
}
4565+
44794566
private static long getLastIndex(Context cx, Scriptable thisObj) {
44804567
return ScriptRuntime.toLength(ScriptRuntime.getObjectProp(thisObj, "lastIndex", cx));
44814568
}

0 commit comments

Comments
 (0)