Skip to content

Instantly share code, notes, and snippets.

@mraleph
Last active November 15, 2016 15:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mraleph/2e57e391d6d32136e5cb71e402c3aa7a to your computer and use it in GitHub Desktop.
Save mraleph/2e57e391d6d32136e5cb71e402c3aa7a to your computer and use it in GitHub Desktop.
VM patch adds `RegExp.matchAsPrefixEx` which allows to match anchored regexps at a particular position (essentially redefining what hat `^` means).
diff --git a/lib/less.dart b/lib/less.dart
index 14996ef..d947709 100644
--- a/lib/less.dart
+++ b/lib/less.dart
@@ -127,7 +127,9 @@ class Less {
Future parseLessFile(String data){
Parser parser = new Parser(_options);
+ final stopwatch = new Stopwatch()..start();
return parser.parse(data).then((Ruleset tree){
+ print('Parsed in ${stopwatch.elapsedMilliseconds}');
RenderResult result;
if (tree == null) return new Future.value(currentErrorCode);
diff --git a/lib/src/parser/entities.dart b/lib/src/parser/entities.dart
index 2ae2769..29138c6 100644
--- a/lib/src/parser/entities.dart
+++ b/lib/src/parser/entities.dart
@@ -451,12 +451,10 @@ class Entities {
if (parserInput.currentChar() == '#'
&& (rgb = parserInput.$reMatch(r'^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})')) != null) {
-
// strip colons, brackets, whitespaces and other characters that should not
// definitely be part of color string
- Match colorCandidateMatch = new RegExp(r'^#([\w]+).*').firstMatch(rgb.input);
+ Match colorCandidateMatch = new RegExp(r'^#([\w]+).*').matchAsPrefixEx(rgb.input, rgb.start);
String colorCandidateString = colorCandidateMatch[1];
-
// verify if candidate consists only of allowed HEX characters
if (new RegExp(r'^[A-Fa-f0-9]+$').firstMatch(colorCandidateString) == null) {
parserInput.error('Invalid HEX color code');
diff --git a/lib/src/parser/parser_input.dart b/lib/src/parser/parser_input.dart
index 5813c73..c65fb0b 100644
--- a/lib/src/parser/parser_input.dart
+++ b/lib/src/parser/parser_input.dart
@@ -7,15 +7,11 @@ class ParserInput {
Contexts context;
bool autoCommentAbsorb = true;
- List<String> chunks; // chunkified input
List<CommentPointer> commentStore = [];
- String current; // current chunk
- int currentPos = 0; // index of current chunk, in `input`. current[0] == input[currentPos]
int i = 0; // current index in `input`
bool finished = false;
int furthest = 0; // furthest index the parser has gone to
String furthestPossibleErrorMessage; // if this is furthest we got to, this is the probably cause
- int j = 0; // current chunk in chunks[j]
List saveStack = []; // holds state for backtracking
ParserInput(String this.input, Contexts this.context) {
@@ -24,11 +20,7 @@ class ParserInput {
///
//Not used in 2.2.0
- bool get notEmpty => current.length > 0;
-
- String currentForward(int pos) {
- return (pos > current.length - 1) ? '' : current.substring(pos);
- }
+ bool get notEmpty => i < input.length;
///
String charAt(int pos) {
@@ -55,8 +47,7 @@ class ParserInput {
/// save input pointers in stack
///
void save() {
- currentPos = i;
- saveStack.add(new StackItem(current, i, j));
+ saveStack.add(i);
}
///
@@ -70,22 +61,7 @@ class ParserInput {
furthestPossibleErrorMessage = possibleErrorMessage;
}
- StackItem state = saveStack.removeLast();
- current = state.current;
- currentPos = i = state.i;
- j = state.j;
-
-//2.2.0
-// parserInput.restore = function(possibleErrorMessage) {
-// if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
-// furthest = parserInput.i;
-// furthestPossibleErrorMessage = possibleErrorMessage;
-// }
-// var state = saveStack.pop();
-// current = state.current;
-// currentPos = parserInput.i = state.i;
-// j = state.j;
-// };
+ i = saveStack.removeLast();
}
///
@@ -138,12 +114,7 @@ class ParserInput {
reg = tok;
}
- if (i > currentPos) {
- current = current.substring(i - currentPos);
- currentPos = i;
- }
-
- Match m = reg.firstMatch(current);
+ Match m = reg.matchAsPrefixEx(input, i);
if (m == null) return null;
skipWhitespace(m[0].length);
@@ -157,24 +128,6 @@ class ParserInput {
return resultList;
}
-// function $re(tok) {
-// if (i > currentPos) {
-// current = current.slice(i - currentPos);
-// currentPos = i;
-// }
-// var m = tok.exec(current);
-// if (!m) {
-// return null;
-// }
-//
-// skipWhitespace(m[0].length);
-// if(typeof m === "string") {
-// return m;
-// }
-//
-// return m.length === 1 ? m[0] : m;
-// }
-
///
/// Same as $re, but returns first match.
/// Parse from a RegExp and returns Match.
@@ -185,12 +138,7 @@ class ParserInput {
Match $reMatch(String tok, [bool caseSensitive = true]) {
RegExp reg = new RegExp(tok, caseSensitive: caseSensitive);
- if (i > currentPos) {
- current = current.substring(i - currentPos);
- currentPos = i;
- }
-
- Match m = reg.firstMatch(current);
+ Match m = reg.matchAsPrefixEx(input, i);
if (m == null) return null;
skipWhitespace(m[0].length);
@@ -304,9 +252,7 @@ class ParserInput {
///
bool skipWhitespace(int length) {
int oldi = i;
- int oldj = j;
- int curr = i - currentPos;
- int endIndex = i + current.length - curr;
+ int endIndex = input.length;
int mem = (i += length);
int c; //char
String nextChar;
@@ -343,141 +289,11 @@ class ParserInput {
&& (c != Charcode.TAB_9) && (c != Charcode.CR_13)) break;
}
- current = currentForward(length + i - mem + curr);
- currentPos = i;
-
- if (current.isEmpty) {
- if (j < chunks.length - 1) {
- current = chunks[++j];
- skipWhitespace(0); // skip space at the beginning of a chunk
- return true; // things changed
- }
+ if (i == endIndex) {
finished = true;
}
- return (oldi != i || oldj != j);
-
-//2.4.0 20150315 1345
-// var skipWhitespace = function(length) {
-// var oldi = parserInput.i, oldj = j,
-// curr = parserInput.i - currentPos,
-// endIndex = parserInput.i + current.length - curr,
-// mem = (parserInput.i += length),
-// inp = input,
-// c, nextChar, comment;
-//
-// for (; parserInput.i < endIndex; parserInput.i++) {
-// c = inp.charCodeAt(parserInput.i);
-//
-// if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
-// nextChar = inp.charAt(parserInput.i + 1);
-// if (nextChar === '/') {
-// comment = {index: parserInput.i, isLineComment: true};
-// var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
-// if (nextNewLine < 0) {
-// nextNewLine = endIndex;
-// }
-// parserInput.i = nextNewLine;
-// comment.text = inp.substr(comment.i, parserInput.i - comment.i);
-// parserInput.commentStore.push(comment);
-// continue;
-// } else if (nextChar === '*') {
-// var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
-// if (nextStarSlash >= 0) {
-// comment = {
-// index: parserInput.i,
-// text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
-// isLineComment: false
-// };
-// parserInput.i += comment.text.length - 1;
-// parserInput.commentStore.push(comment);
-// continue;
-// }
-// }
-// break;
-// }
-//
-// if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
-// break;
-// }
-// }
-//
-// current = current.slice(length + parserInput.i - mem + curr);
-// currentPos = parserInput.i;
-//
-// if (!current.length) {
-// if (j < chunks.length - 1)
-// {
-// current = chunks[++j];
-// skipWhitespace(0); // skip space at the beginning of a chunk
-// return true; // things changed
-// }
-// parserInput.finished = true;
-// }
-//
-// return oldi !== parserInput.i || oldj !== j;
-// };
-//2.2.0
-// var skipWhitespace = function(length) {
-// var oldi = parserInput.i, oldj = j,
-// curr = parserInput.i - currentPos,
-// endIndex = parserInput.i + current.length - curr,
-// mem = (parserInput.i += length),
-// inp = input,
-// c, nextChar, comment;
-//
-// for (; parserInput.i < endIndex; parserInput.i++) {
-// c = inp.charCodeAt(parserInput.i);
-//
-// if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
-// nextChar = inp.charAt(parserInput.i + 1);
-// if (nextChar === '/') {
-// comment = {index: parserInput.i, isLineComment: true};
-// var nextNewLine = inp.indexOf("\n", parserInput.i + 1);
-// if (nextNewLine < 0) {
-// nextNewLine = endIndex;
-// }
-// parserInput.i = nextNewLine;
-// comment.text = inp.substr(comment.i, parserInput.i - comment.i);
-// parserInput.commentStore.push(comment);
-// continue;
-// } else if (nextChar === '*') {
-// var haystack = inp.substr(parserInput.i);
-// var comment_search_result = haystack.match(/^\/\*(?:[^*]|\*+[^\/*])*\*+\//);
-// if (comment_search_result) {
-// comment = {
-// index: parserInput.i,
-// text: comment_search_result[0],
-// isLineComment: false
-// };
-// parserInput.i += comment.text.length - 1;
-// parserInput.commentStore.push(comment);
-// continue;
-// }
-// }
-// break;
-// }
-//
-// if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
-// break;
-// }
-// }
-//
-// current = current.slice(length + parserInput.i - mem + curr);
-// currentPos = parserInput.i;
-//
-// if (!current.length) {
-// if (j < chunks.length - 1)
-// {
-// current = chunks[++j];
-// skipWhitespace(0); // skip space at the beginning of a chunk
-// return true; // things changed
-// }
-// parserInput.finished = true;
-// }
-//
-// return oldi !== parserInput.i || oldj !== j;
-// };
+ return oldi != i;
}
///
@@ -562,23 +378,9 @@ class ParserInput {
// https://jsperf.com/string-startswith/21
return input.startsWith(tok, i);
} else {
- RegExp r = (tok as RegExp);
- return r.hasMatch(current);
+ RegExp r = tok;
+ return r.matchAsPrefixEx(input, i) != null;
}
-
-//2.4.0 20150315-1729
-// parserInput.peek = function(tok) {
-// if (typeof tok === 'string') {
-// for (var i = 0; i < tok.length; i++) {
-// if (input.charAt(parserInput.i + i) !== tok.charAt(i)) {
-// return false;
-// }
-// }
-// return true;
-// } else {
-// return tok.test(current);
-// }
-// };
}
///
@@ -620,34 +422,12 @@ class ParserInput {
/// in the case it causes too much performance issues.
///
void start(String str, bool chunkInput){
- i = j = currentPos = furthest = 0;
-
+ i = furthest = 0;
if (chunkInput) {
- chunks = new Chunker(str, context).getChunks();
- } else {
- chunks = [str];
+ throw "String stuff is not supported";
}
-
- current = chunks[0];
-
+ input = str;
skipWhitespace(0);
-
-//2.2.0
-// parserInput.start = function(str, chunkInput, failFunction) {
-// input = str;
-// parserInput.i = j = currentPos = furthest = 0;
-//
-//
-// if (chunkInput) {
-// chunks = chunker(str, failFunction);
-// } else {
-// chunks = [str];
-// }
-//
-// current = chunks[0];
-//
-// skipWhitespace(0);
-// };
}
///
@@ -770,10 +550,3 @@ class ParserStatus {
this.furthestReachedEnd, this.furthestChar});
}
-class StackItem {
- String current;
- int i;
- int j;
-
- StackItem(String this.current, int this.i, int this.j);
-}
diff --git a/lib/src/tree/ruleset.dart b/lib/src/tree/ruleset.dart
index 709fc4c..66d6220 100644
--- a/lib/src/tree/ruleset.dart
+++ b/lib/src/tree/ruleset.dart
@@ -509,6 +509,7 @@ class Ruleset extends Node with VariableMixin implements GetIsReferencedNode, Ma
ruleNodes.add(rule);
}
}
+ // Strange code: charsetRuleNodes is always empty.
ruleNodes.insertAll(0, charsetRuleNodes);
// If this is the root node, we don't render
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 7a50561..1bbdcf0 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -78,19 +78,21 @@ DEFINE_NATIVE_ENTRY(RegExp_getGroupCount, 1) {
}
-DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
+DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 4) {
// This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
+ GET_NON_NULL_NATIVE_ARGUMENT(Smi, hat_index, arguments->NativeArgAt(2));
if (FLAG_interpret_irregexp || FLAG_precompiled_runtime) {
return BytecodeRegExpMacroAssembler::Interpret(regexp, subject, start_index,
zone);
}
- return IRRegExpMacroAssembler::Execute(regexp, subject, start_index, zone);
+ return IRRegExpMacroAssembler::Execute(
+ regexp, subject, start_index, hat_index, zone);
}
} // namespace dart
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index a9ccd55..b1c6a5b 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -138,7 +138,7 @@ class _RegExp implements RegExp {
Match firstMatch(String str) {
if (str is! String) throw new ArgumentError(str);
- List match = _ExecuteMatch(str, 0);
+ List match = _ExecuteMatch(str, 0, 0);
if (match == null) {
return null;
}
@@ -154,6 +154,20 @@ class _RegExp implements RegExp {
return new _AllMatchesIterable(this, string, start);
}
+ Match matchAsPrefixEx(String string, [int start = 0]) {
+ if (string is! String) throw new ArgumentError(string);
+ if (start is! int) throw new ArgumentError(start);
+ if (start < 0 || start > string.length) {
+ throw new RangeError.range(start, 0, string.length);
+ }
+ // Inefficient check that searches for a later match too.
+ // Change this when possible.
+ List<int> list = _ExecuteMatch(string, start, start);
+ if (list == null) return null;
+ if (list[0] != start) return null;
+ return new _RegExpMatch(this, string, list);
+ }
+
Match matchAsPrefix(String string, [int start = 0]) {
if (string is! String) throw new ArgumentError(string);
if (start is! int) throw new ArgumentError(start);
@@ -162,7 +176,7 @@ class _RegExp implements RegExp {
}
// Inefficient check that searches for a later match too.
// Change this when possible.
- List<int> list = _ExecuteMatch(string, start);
+ List<int> list = _ExecuteMatch(string, start, 0);
if (list == null) return null;
if (list[0] != start) return null;
return new _RegExpMatch(this, string, list);
@@ -170,13 +184,13 @@ class _RegExp implements RegExp {
bool hasMatch(String str) {
if (str is! String) throw new ArgumentError(str);
- List match = _ExecuteMatch(str, 0);
+ List match = _ExecuteMatch(str, 0, 0);
return (match == null) ? false : true;
}
String stringMatch(String str) {
if (str is! String) throw new ArgumentError(str);
- List match = _ExecuteMatch(str, 0);
+ List match = _ExecuteMatch(str, 0, 0);
if (match == null) {
return null;
}
@@ -236,7 +250,7 @@ class _RegExp implements RegExp {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
- List _ExecuteMatch(String str, int start_index)
+ List _ExecuteMatch(String str, int start_index, int hat_index)
native "RegExp_ExecuteMatch";
}
@@ -263,7 +277,7 @@ class _AllMatchesIterator implements Iterator<Match> {
bool moveNext() {
if (_re == null) return false; // Cleared after a failed match.
if (_nextIndex <= _str.length) {
- var match = _re._ExecuteMatch(_str, _nextIndex);
+ var match = _re._ExecuteMatch(_str, _nextIndex, 0);
if (match != null) {
_current = new _RegExpMatch(_re, _str, match);
_nextIndex = _current.end;
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7ae1810..bea4a55 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -111,7 +111,7 @@ namespace dart {
V(RegExp_getIsMultiLine, 1) \
V(RegExp_getIsCaseSensitive, 1) \
V(RegExp_getGroupCount, 1) \
- V(RegExp_ExecuteMatch, 3) \
+ V(RegExp_ExecuteMatch, 4) \
V(List_allocate, 2) \
V(List_getIndexed, 2) \
V(List_setIndexed, 3) \
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index bc4a844..0a29337 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -735,6 +735,8 @@ CompileType ParameterInstr::ComputeType() const {
return CompileType::FromCid(function.string_specialization_cid());
case RegExpMacroAssembler::kParamStartOffsetIndex:
return CompileType::FromCid(kSmiCid);
+ case RegExpMacroAssembler::kParamHatOffsetIndex:
+ return CompileType::FromCid(kSmiCid);
default:
UNREACHABLE();
}
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index b888804..8082786 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -2195,9 +2195,9 @@ void Intrinsifier::TwoByteString_equality(Assembler* assembler) {
void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
if (FLAG_interpret_irregexp) return;
- static const intptr_t kRegExpParamOffset = 3 * kWordSize;
- static const intptr_t kStringParamOffset = 2 * kWordSize;
- // start_index smi is located at offset 1.
+ static const intptr_t kRegExpParamOffset = 4 * kWordSize;
+ static const intptr_t kStringParamOffset = 3 * kWordSize;
+ // start_index smi is located at offset 2.
// Incoming registers:
// RAX: Function. (Will be loaded with the specialized matcher function.)
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 580582f..ee7df7f 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -165,7 +165,7 @@ namespace dart {
V(_GrowableList, .withData, GrowableArray_Allocate, GrowableObjectArray, \
0x25a786de) \
V(_GrowableList, add, GrowableArray_add, Dynamic, 0x0d1358ed) \
- V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x6036d7fa) \
+ V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x74e38753) \
V(Object, ==, ObjectEquals, Bool, 0x11662ed8) \
V(Object, get:runtimeType, ObjectRuntimeType, Type, 0x00e7c26b) \
V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, Bool, 0x72aad7e2) \
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 19b88c5..0b15ff5 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -5060,6 +5060,10 @@ static void CreateSpecializedFunction(Thread* thread,
Object::dynamic_type());
fn.SetParameterNameAt(RegExpMacroAssembler::kParamStartOffsetIndex,
Symbols::start_index_param());
+ fn.SetParameterTypeAt(RegExpMacroAssembler::kParamHatOffsetIndex,
+ Object::dynamic_type());
+ fn.SetParameterNameAt(RegExpMacroAssembler::kParamHatOffsetIndex,
+ Symbols::hat_index_param());
fn.set_result_type(Type::Handle(zone, Type::ArrayType()));
// Cache the result.
diff --git a/runtime/vm/regexp_assembler.h b/runtime/vm/regexp_assembler.h
index 1a12789..4792869 100644
--- a/runtime/vm/regexp_assembler.h
+++ b/runtime/vm/regexp_assembler.h
@@ -92,6 +92,7 @@ class RegExpMacroAssembler : public ZoneAllocated {
kParamRegExpIndex = 0,
kParamStringIndex,
kParamStartOffsetIndex,
+ kParamHatOffsetIndex,
kParamCount
};
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index efb9d64..20c74b2 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -91,6 +91,7 @@ IRRegExpMacroAssembler::IRRegExpMacroAssembler(
string_param_(NULL),
string_param_length_(NULL),
start_index_param_(NULL),
+ hat_index_param_(NULL),
registers_count_(0),
saved_registers_count_((capture_count + 1) * 2),
stack_array_cell_(Array::ZoneHandle(zone, Array::New(1, Heap::kOld))),
@@ -175,6 +176,8 @@ void IRRegExpMacroAssembler::InitializeLocals() {
RegExpMacroAssembler::kParamStringIndex);
start_index_param_ = Parameter(Symbols::start_index_param(),
RegExpMacroAssembler::kParamStartOffsetIndex);
+ hat_index_param_ = Parameter(Symbols::hat_index_param(),
+ RegExpMacroAssembler::kParamHatOffsetIndex);
}
@@ -317,6 +320,7 @@ bool IRRegExpMacroAssembler::CanReadUnaligned() {
RawArray* IRRegExpMacroAssembler::Execute(const RegExp& regexp,
const String& input,
const Smi& start_offset,
+ const Smi& hat_offset,
Zone* zone) {
const intptr_t cid = input.GetClassId();
const Function& fun = Function::Handle(regexp.function(cid));
@@ -327,6 +331,7 @@ RawArray* IRRegExpMacroAssembler::Execute(const RegExp& regexp,
args.SetAt(RegExpMacroAssembler::kParamRegExpIndex, regexp);
args.SetAt(RegExpMacroAssembler::kParamStringIndex, input);
args.SetAt(RegExpMacroAssembler::kParamStartOffsetIndex, start_offset);
+ args.SetAt(RegExpMacroAssembler::kParamHatOffsetIndex, hat_offset);
// And finally call the generated code.
@@ -849,14 +854,15 @@ void IRRegExpMacroAssembler::CheckAtStart(BlockLabel* on_at_start) {
// Did we start the match at the start of the string at all?
BranchOrBacktrack(
- Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
+ Comparison(kNE, LoadLocal(start_index_param_),
+ LoadLocal(hat_index_param_)),
&not_at_start);
// If we did, are we still at the start of the input, i.e. is
// (offset == string_length * -1)?
- Definition* neg_len_def =
- InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
- PushLocal(string_param_length_));
+ PushArgumentInstr* start_index = PushLocal(start_index_param_);
+ PushArgumentInstr* length = PushLocal(string_param_length_);
+ Definition* neg_len_def = Sub(start_index, length);
Definition* offset_def = LoadLocal(current_position_);
BranchOrBacktrack(Comparison(kEQ, neg_len_def, offset_def), on_at_start);
@@ -869,14 +875,13 @@ void IRRegExpMacroAssembler::CheckNotAtStart(BlockLabel* on_not_at_start) {
// Did we start the match at the start of the string at all?
BranchOrBacktrack(
- Comparison(kNE, LoadLocal(start_index_param_), Uint64Constant(0)),
+ Comparison(kNE, LoadLocal(start_index_param_),
+ LoadLocal(hat_index_param_)),
on_not_at_start);
- // If we did, are we still at the start of the input, i.e. is
- // (offset == string_length * -1)?
- Definition* neg_len_def =
- InstanceCall(InstanceCallDescriptor::FromToken(Token::kNEGATE),
- PushLocal(string_param_length_));
+ PushArgumentInstr* start_index = PushLocal(start_index_param_);
+ PushArgumentInstr* length = PushLocal(string_param_length_);
+ Definition* neg_len_def = Sub(start_index, length);
Definition* offset_def = LoadLocal(current_position_);
BranchOrBacktrack(Comparison(kNE, neg_len_def, offset_def), on_not_at_start);
}
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index a08e05f..45a1006 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -40,6 +40,7 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler {
static RawArray* Execute(const RegExp& regexp,
const String& input,
const Smi& start_offset,
+ const Smi& hat_offset,
Zone* zone);
virtual bool IsClosed() const { return (current_instruction_ == NULL); }
@@ -406,6 +407,9 @@ class IRRegExpMacroAssembler : public RegExpMacroAssembler {
// The start index within the string, passed as a function parameter.
LocalVariable* start_index_param_;
+ // The start index within the string, passed as a function parameter.
+ LocalVariable* hat_index_param_;
+
// An assortment of utility variables.
LocalVariable* capture_length_;
LocalVariable* match_start_index_;
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index a728610..d332af7 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -389,6 +389,7 @@ class ObjectPointerVisitor;
V(position_registers, ":position_registers") \
V(string_param, ":string_param") \
V(start_index_param, ":start_index_param") \
+ V(hat_index_param, ":hat_index_param") \
V(clear, "clear") \
V(_wordCharacterMap, "_wordCharacterMap") \
V(print, "print") \
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment