Last active
November 15, 2016 15:14
-
-
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).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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_)), | |
¬_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