Index: runtime/vm/regexp.cc |
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc |
index 19b88c5605940ceb7a33674b3970fa2061a5911d..7f8890925c8fd56e1c7a28411ea679c6bf4871e1 100644 |
--- a/runtime/vm/regexp.cc |
+++ b/runtime/vm/regexp.cc |
@@ -4824,6 +4824,7 @@ RegExpEngine::CompilationResult RegExpEngine::CompileIR( |
const Function& function = parsed_function->function(); |
const intptr_t specialization_cid = function.string_specialization_cid(); |
+ const intptr_t is_sticky = function.is_sticky_specialization(); |
const bool is_one_byte = (specialization_cid == kOneByteStringCid || |
specialization_cid == kExternalOneByteStringCid); |
RegExp& regexp = RegExp::Handle(zone, function.regexp()); |
@@ -4851,12 +4852,12 @@ RegExpEngine::CompilationResult RegExpEngine::CompileIR( |
RegExpCapture::ToNode(data->tree, 0, &compiler, compiler.accept()); |
RegExpNode* node = captured_body; |
- bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
- bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
+ const bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
+ const bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
intptr_t max_length = data->tree->max_match(); |
- if (!is_start_anchored) { |
+ if (!is_start_anchored && !is_sticky) { |
// Add a .*? at the beginning, outside the body capture, unless |
rmacnak
2016/11/17 00:49:52
Not sure I see why this property is called sticky,
erikcorry
2016/11/17 13:56:17
From es-discuss (!):
I believe the y actually com
|
- // this expression is anchored at the beginning. |
+ // this expression is anchored at the beginning or is sticky. |
RegExpNode* loop_node = RegExpQuantifier::ToNode( |
0, RegExpTree::kInfinity, false, new (zone) RegExpCharacterClass('*'), |
&compiler, captured_body, data->contains_anchor); |
@@ -4927,6 +4928,7 @@ RegExpEngine::CompilationResult RegExpEngine::CompileBytecode( |
RegExpCompileData* data, |
const RegExp& regexp, |
bool is_one_byte, |
+ bool is_sticky, |
Zone* zone) { |
ASSERT(FLAG_interpret_irregexp); |
const String& pattern = String::Handle(zone, regexp.pattern()); |
@@ -4956,7 +4958,7 @@ RegExpEngine::CompilationResult RegExpEngine::CompileBytecode( |
bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
intptr_t max_length = data->tree->max_match(); |
- if (!is_start_anchored) { |
+ if (!is_start_anchored && !is_sticky) { |
// Add a .*? at the beginning, outside the body capture, unless |
// this expression is anchored at the beginning. |
RegExpNode* loop_node = RegExpQuantifier::ToNode( |
@@ -5029,6 +5031,7 @@ static void CreateSpecializedFunction(Thread* thread, |
Zone* zone, |
const RegExp& regexp, |
intptr_t specialization_cid, |
+ bool sticky, |
const Object& owner) { |
const intptr_t kParamCount = RegExpMacroAssembler::kParamCount; |
@@ -5063,9 +5066,9 @@ static void CreateSpecializedFunction(Thread* thread, |
fn.set_result_type(Type::Handle(zone, Type::ArrayType())); |
// Cache the result. |
- regexp.set_function(specialization_cid, fn); |
+ regexp.set_function(specialization_cid, sticky, fn); |
- fn.SetRegExpData(regexp, specialization_cid); |
+ fn.SetRegExpData(regexp, specialization_cid, sticky); |
fn.set_is_debuggable(false); |
// The function is compiled lazily during the first call. |
@@ -5098,12 +5101,13 @@ RawRegExp* RegExpEngine::CreateRegExp(Thread* thread, |
const Class& owner = |
Class::Handle(zone, lib.LookupClass(Symbols::RegExp())); |
- CreateSpecializedFunction(thread, zone, regexp, kOneByteStringCid, owner); |
- CreateSpecializedFunction(thread, zone, regexp, kTwoByteStringCid, owner); |
- CreateSpecializedFunction(thread, zone, regexp, kExternalOneByteStringCid, |
- owner); |
- CreateSpecializedFunction(thread, zone, regexp, kExternalTwoByteStringCid, |
- owner); |
+ for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid; |
+ cid++) { |
+ CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/false, |
+ owner); |
+ CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/true, |
+ owner); |
+ } |
} |
return regexp.raw(); |