Skip to content

Commit 2403444

Browse files
committed
VM: Optimize RegExp.matchAsPrefix(...) by generating a sticky RegExp specialization.
This is the same as a sticky RegExp flag in ES2015. Overlay some RegExp fields on top of each other - given that they should never be used simultaneously. BUG=http://dartbug.com/27810 R=rmacnak@google.com Review URL: https://codereview.chromium.org/2510783002 .
1 parent 547b8f4 commit 2403444

23 files changed

+249
-100
lines changed

runtime/lib/regexp.cc

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,34 @@ DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 1) {
7878
}
7979

8080

81-
DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
82-
// This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
81+
static RawObject* ExecuteMatch(Zone* zone,
82+
NativeArguments* arguments,
83+
bool sticky) {
8384
const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
8485
ASSERT(!regexp.IsNull());
8586
GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
8687
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
8788

88-
if (FLAG_interpret_irregexp || FLAG_precompiled_runtime) {
89+
if (FLAG_interpret_irregexp) {
8990
return BytecodeRegExpMacroAssembler::Interpret(regexp, subject, start_index,
90-
zone);
91+
/*sticky=*/sticky, zone);
9192
}
9293

93-
return IRRegExpMacroAssembler::Execute(regexp, subject, start_index, zone);
94+
return IRRegExpMacroAssembler::Execute(regexp, subject, start_index,
95+
/*sticky=*/sticky, zone);
9496
}
9597

98+
99+
DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
100+
// This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
101+
return ExecuteMatch(zone, arguments, /*sticky=*/false);
102+
}
103+
104+
105+
DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatchSticky, 3) {
106+
// This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatchSticky.
107+
return ExecuteMatch(zone, arguments, /*sticky=*/true);
108+
}
109+
110+
96111
} // namespace dart

runtime/lib/regexp_patch.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,8 @@ class _RegExp implements RegExp {
160160
if (start < 0 || start > string.length) {
161161
throw new RangeError.range(start, 0, string.length);
162162
}
163-
// Inefficient check that searches for a later match too.
164-
// Change this when possible.
165-
List<int> list = _ExecuteMatch(string, start);
163+
List<int> list = _ExecuteMatchSticky(string, start);
166164
if (list == null) return null;
167-
if (list[0] != start) return null;
168165
return new _RegExpMatch(this, string, list);
169166
}
170167

@@ -238,6 +235,9 @@ class _RegExp implements RegExp {
238235

239236
List _ExecuteMatch(String str, int start_index)
240237
native "RegExp_ExecuteMatch";
238+
239+
List _ExecuteMatchSticky(String str, int start_index)
240+
native "RegExp_ExecuteMatchSticky";
241241
}
242242

243243
class _AllMatchesIterable extends IterableBase<Match> {

runtime/vm/bootstrap_natives.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ namespace dart {
112112
V(RegExp_getIsCaseSensitive, 1) \
113113
V(RegExp_getGroupCount, 1) \
114114
V(RegExp_ExecuteMatch, 3) \
115+
V(RegExp_ExecuteMatchSticky, 3) \
115116
V(List_allocate, 2) \
116117
V(List_getIndexed, 2) \
117118
V(List_setIndexed, 3) \

runtime/vm/intrinsifier.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,16 @@ bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) {
11601160

11611161
return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound);
11621162
}
1163+
1164+
1165+
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
1166+
IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/false);
1167+
}
1168+
1169+
1170+
void Intrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler) {
1171+
IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/true);
1172+
}
11631173
#endif // !defined(TARGET_ARCH_DBC)
11641174

11651175

runtime/vm/intrinsifier.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class Intrinsifier : public AllStatic {
5656
GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
5757

5858
#undef DECLARE_FUNCTION
59+
60+
static void IntrinsifyRegExpExecuteMatch(Assembler* assembler, bool sticky);
5961
#endif
6062
};
6163

runtime/vm/intrinsifier_arm.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2218,7 +2218,8 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
22182218
}
22192219

22202220

2221-
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
2221+
void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
2222+
bool sticky) {
22222223
if (FLAG_interpret_irregexp) return;
22232224

22242225
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2237,7 +2238,8 @@ void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
22372238
__ LoadClassId(R1, R1);
22382239
__ AddImmediate(R1, R1, -kOneByteStringCid);
22392240
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
2240-
__ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
2241+
__ ldr(R0,
2242+
FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
22412243

22422244
// Registers are now set up for the lazy compile stub. It expects the function
22432245
// in R0, the argument descriptor in R4, and IC-Data in R9.

runtime/vm/intrinsifier_arm64.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,7 +2284,8 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
22842284
}
22852285

22862286

2287-
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
2287+
void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
2288+
bool sticky) {
22882289
if (FLAG_interpret_irregexp) return;
22892290

22902291
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2303,7 +2304,8 @@ void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
23032304
__ LoadClassId(R1, R1);
23042305
__ AddImmediate(R1, R1, -kOneByteStringCid);
23052306
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
2306-
__ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
2307+
__ ldr(R0,
2308+
FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
23072309

23082310
// Registers are now set up for the lazy compile stub. It expects the function
23092311
// in R0, the argument descriptor in R4, and IC-Data in R5.

runtime/vm/intrinsifier_ia32.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,7 +2230,8 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
22302230
}
22312231

22322232

2233-
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
2233+
void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
2234+
bool sticky) {
22342235
if (FLAG_interpret_irregexp) return;
22352236

22362237
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2248,8 +2249,8 @@ void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
22482249
__ movl(EDI, Address(ESP, kStringParamOffset));
22492250
__ LoadClassId(EDI, EDI);
22502251
__ SubImmediate(EDI, Immediate(kOneByteStringCid));
2251-
__ movl(EAX, FieldAddress(EBX, EDI, TIMES_4,
2252-
RegExp::function_offset(kOneByteStringCid)));
2252+
__ movl(EAX, FieldAddress(EBX, EDI, TIMES_4, RegExp::function_offset(
2253+
kOneByteStringCid, sticky)));
22532254

22542255
// Registers are now set up for the lazy compile stub. It expects the function
22552256
// in EAX, the argument descriptor in EDX, and IC-Data in ECX.

runtime/vm/intrinsifier_mips.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,8 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
23392339
}
23402340

23412341

2342-
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
2342+
void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
2343+
bool sticky) {
23432344
if (FLAG_interpret_irregexp) return;
23442345

23452346
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2359,7 +2360,8 @@ void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
23592360
__ AddImmediate(T2, -kOneByteStringCid);
23602361
__ sll(T2, T2, kWordSizeLog2);
23612362
__ addu(T2, T2, T1);
2362-
__ lw(T0, FieldAddress(T2, RegExp::function_offset(kOneByteStringCid)));
2363+
__ lw(T0,
2364+
FieldAddress(T2, RegExp::function_offset(kOneByteStringCid, sticky)));
23632365

23642366
// Registers are now set up for the lazy compile stub. It expects the function
23652367
// in T0, the argument descriptor in S4, and IC-Data in S5.

runtime/vm/intrinsifier_x64.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,7 +2192,8 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
21922192
}
21932193

21942194

2195-
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
2195+
void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
2196+
bool sticky) {
21962197
if (FLAG_interpret_irregexp) return;
21972198

21982199
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2210,8 +2211,8 @@ void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
22102211
__ movq(RDI, Address(RSP, kStringParamOffset));
22112212
__ LoadClassId(RDI, RDI);
22122213
__ SubImmediate(RDI, Immediate(kOneByteStringCid));
2213-
__ movq(RAX, FieldAddress(RBX, RDI, TIMES_8,
2214-
RegExp::function_offset(kOneByteStringCid)));
2214+
__ movq(RAX, FieldAddress(RBX, RDI, TIMES_8, RegExp::function_offset(
2215+
kOneByteStringCid, sticky)));
22152216

22162217
// Registers are now set up for the lazy compile stub. It expects the function
22172218
// in RAX, the argument descriptor in R10, and IC-Data in RCX.

0 commit comments

Comments
 (0)