7887c34a29
Previously these functions would only contain a single CheckStackOverflowInstr
in a backtracking block and that CheckStackOverflowInstr would have a zero
loop_depth - which means it would not be considered eligable for OSR.
This change:
* adds CheckStackOverflowInstr with non-zero loop_depth in two other places
(Boyer-Moore lookahead skip loop and greedy loop) where loops arise in the
generated IL;
* sets non-zero loop depth on the CheckStackOverflowInstr in the backtracking
block;
* adds a flag on CheckStackOverflowInstr that allows optimizing compiler to
optimize away those checks that were inserted solely to serve as OSR entries.
* ensures that IR generated by IRRegExpMacroAssembler is OSR compatible:
* GraphEntryInstr has correct osr_id;
* GraphEntry and normal entry have different block ids (B0 and B1 - instead of B0 and B0);
* unreachable blocks are pruned and GraphEntry is rewired to point to OSR entry;
* IRRegExpMacroAssembler::GrowStack should not assume that stack_array_cell and :stack
are always in sync, because :stack can come from OSR or deoptimization why stack_array_cell
is a constant associated with a particular Code object.
* refactors the way the RegExp stack was growing: instead of having a special instruction
just emit a call to a Dart function;
* refactors the way block pruning for OSR is done by consolidating duplicated code
in a single function.
We allow the optimizing compiler to remove preemption checks from
non-backtracking loops in the regexp code because those loops
unlike backtracking have guaranteed O(input_length) time
complexity.
Performance Implications
------------------------
This change improves performance of regexps in cases where regexp spends a lot
of time in the first invocation (either due to backtracking or due to long non
matching prefix) by allowing VM to optimize the :matcher while :matcher is
running.
For example on regex-redux[1] benchmark it improves Dart performance by 3x
(from ~18s to ~6s on my Mac Book Pro).
CL history
----------
This relands commit d87cc52c3e.
Original code review: https://codereview.chromium.org/2950783003/
[1] https://benchmarksgame.alioth.debian.org/u64q/program.php?test=regexredux&lang=dart&id=2
R=erikcorry@google.com
Review-Url: https://codereview.chromium.org/2951053003 .
83 lines
2.5 KiB
Dart
83 lines
2.5 KiB
Dart
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'dart:core' hide Symbol;
|
|
import 'dart:typed_data' show Int32List;
|
|
|
|
@patch
|
|
List makeListFixedLength(List growableList)
|
|
native "Internal_makeListFixedLength";
|
|
|
|
@patch
|
|
List makeFixedListUnmodifiable(List fixedLengthList)
|
|
native "Internal_makeFixedListUnmodifiable";
|
|
|
|
class VMLibraryHooks {
|
|
// Example: "dart:isolate _Timer._factory"
|
|
static var timerFactory;
|
|
|
|
// Example: "dart:io _EventHandler._sendData"
|
|
static var eventHandlerSendData;
|
|
|
|
// A nullary closure that answers the current clock value in milliseconds.
|
|
// Example: "dart:io _EventHandler._timerMillisecondClock"
|
|
static var timerMillisecondClock;
|
|
|
|
// Implementation of Resource.readAsBytes.
|
|
static var resourceReadAsBytes;
|
|
|
|
// Implementation of package root/map provision.
|
|
static var packageRootString;
|
|
static var packageConfigString;
|
|
static var packageRootUriFuture;
|
|
static var packageConfigUriFuture;
|
|
static var resolvePackageUriFuture;
|
|
|
|
static var platformScript;
|
|
}
|
|
|
|
final bool is64Bit = _inquireIs64Bit();
|
|
|
|
bool _inquireIs64Bit() native "Internal_inquireIs64Bit";
|
|
|
|
bool _classRangeCheck(int cid, int lowerLimit, int upperLimit) {
|
|
return cid >= lowerLimit && cid <= upperLimit;
|
|
}
|
|
|
|
bool _classRangeCheckNegative(int cid, int lowerLimit, int upperLimit) {
|
|
return cid < lowerLimit || cid > upperLimit;
|
|
}
|
|
|
|
// Utility class now only used by the VM.
|
|
class Lists {
|
|
static void copy(List src, int srcStart, List dst, int dstStart, int count) {
|
|
if (srcStart < dstStart) {
|
|
for (int i = srcStart + count - 1, j = dstStart + count - 1;
|
|
i >= srcStart;
|
|
i--, j--) {
|
|
dst[j] = src[i];
|
|
}
|
|
} else {
|
|
for (int i = srcStart, j = dstStart; i < srcStart + count; i++, j++) {
|
|
dst[j] = src[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Prepend the parent type arguments (maybe null) to the function type
|
|
// arguments (may be null). The result is null if both input vectors are null
|
|
// or is a newly allocated and canonicalized vector of length 'len'.
|
|
_prependTypeArguments(functionTypeArguments, parentTypeArguments, len)
|
|
native "Internal_prependTypeArguments";
|
|
|
|
// Called by IRRegExpMacroAssembler::GrowStack.
|
|
Int32List _growRegExpStack(Int32List stack) {
|
|
final newStack = new Int32List(stack.length * 2);
|
|
for (int i = 0; i < stack.length; i++) {
|
|
newStack[i] = stack[i];
|
|
}
|
|
return newStack;
|
|
}
|