Skip to content

Commits on Source 23

jruby-joni (2.1.18-1) unstable; urgency=medium
* New upstream release
* debian/control
- set Standards-Version: 4.2.0 with no change
[ Thomas E. Enebo ]
* [maven-release-plugin] prepare for next development iteration
[ Marcin Mielzynski ]
* fix escape warning
* fix char class warning
* bump java since jcodings is already on 7
* remove unused settings
* move nameTable logic to scan environment
[ lopex ]
* don't use deprecated apis
* Fixes #35
[ Marcin Mielzynski ]
* bump jcodings
* move name table back to regex
* ability to pass null region
* remove USE_POSIX_API_REGION_OPTION
[ Marcin Mielzynski ]
* add matcherNoRegion byte[] version for consistency
[ Charles Oliver Nutter ]
* Provide a lighter-weight mechanism for interrupting.
-- Hideki Yamane <henrich@debian.org> Mon, 13 Aug 2018 17:07:26 +0900
jruby-joni (2.1.16-2) unstable; urgency=medium
* debian/rules
......
......@@ -13,7 +13,7 @@ Build-Depends-Indep:
libasm-java (>= 5.0.3),
libjcodings-java (>= 1.0.28),
maven-debian-helper (>= 2.0)
Standards-Version: 4.1.4
Standards-Version: 4.2.0
Vcs-Git: https://salsa.debian.org/java-team/jruby-joni.git
Vcs-Browser: https://salsa.debian.org/java-team/jruby-joni
Homepage: https://github.com/jruby/joni/
......
......@@ -4,7 +4,7 @@
<groupId>org.jruby.joni</groupId>
<artifactId>joni</artifactId>
<packaging>jar</packaging>
<version>2.1.16</version>
<version>2.1.18</version>
<name>Joni</name>
<description>
Java port of Oniguruma: http://www.geocities.jp/kosako3/oniguruma
......@@ -66,7 +66,7 @@
<dependency>
<groupId>org.jruby.jcodings</groupId>
<artifactId>jcodings</artifactId>
<version>1.0.28</version>
<version>1.0.30</version>
</dependency>
<dependency>
<groupId>junit</groupId>
......@@ -97,8 +97,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
......
......@@ -39,6 +39,7 @@ import org.joni.exception.InternalException;
class ByteCodeMachine extends StackMachine {
private static final int INTERRUPT_CHECK_EVERY = 30000;
int interruptCheckCounter = 0; // we modulos this to occasionally check for interrupts
volatile boolean interrupted = false;
private int bestLen; // return value
private int s = 0; // current char
......@@ -52,11 +53,15 @@ class ByteCodeMachine extends StackMachine {
private final int[]code; // byte code
private int ip; // instruction pointer
ByteCodeMachine(Regex regex, byte[]bytes, int p, int end) {
super(regex, bytes, p, end);
ByteCodeMachine(Regex regex, Region region, byte[]bytes, int p, int end) {
super(regex, region, bytes, p, end);
this.code = regex.code;
}
public void interrupt() {
interrupted = true;
}
protected int stkp; // a temporary
private boolean makeCaptureHistoryTree(CaptureTreeNode node) {
//CaptureTreeNode child;
......@@ -172,7 +177,7 @@ class ByteCodeMachine extends StackMachine {
Config.log.println(sb.toString());
}
protected final int matchAt(int _range, int _sstart, int _sprev) throws InterruptedException {
protected final int matchAt(int _range, int _sstart, int _sprev, boolean interrupt) throws InterruptedException {
range = _range;
sstart = _sstart;
sprev = _sprev;
......@@ -185,14 +190,15 @@ class ByteCodeMachine extends StackMachine {
bestLen = -1;
s = _sstart;
pkeep = _sstart;
return enc.isSingleByte() || (msaOptions & Option.CR_7_BIT) != 0 ? executeSb() : execute();
return enc.isSingleByte() || (msaOptions & Option.CR_7_BIT) != 0 ? executeSb(interrupt) : execute(interrupt);
}
private final int execute() throws InterruptedException {
private final int execute(boolean interrupt) throws InterruptedException {
Thread currentThread = Thread.currentThread();
final int[]code = this.code;
while (true) {
if (interruptCheckCounter++ % INTERRUPT_CHECK_EVERY == 0 && currentThread.isInterrupted()) {
if (interrupted ||
(interrupt && interruptCheckCounter++ % INTERRUPT_CHECK_EVERY == 0 && currentThread.isInterrupted())) {
currentThread.interrupted();
throw new InterruptedException();
}
......@@ -323,11 +329,12 @@ class ByteCodeMachine extends StackMachine {
} // main while
}
private final int executeSb() throws InterruptedException {
private final int executeSb(boolean interrupt) throws InterruptedException {
Thread currentThread = Thread.currentThread();
final int[]code = this.code;
while (true) {
if (interruptCheckCounter++ % INTERRUPT_CHECK_EVERY == 0 && currentThread.isInterrupted()) {
if ((!interrupt && interrupted) ||
(interrupt && interruptCheckCounter++ % INTERRUPT_CHECK_EVERY == 0 && currentThread.isInterrupted())) {
currentThread.interrupted();
throw new InterruptedException();
}
......@@ -501,21 +508,11 @@ class ByteCodeMachine extends StackMachine {
}
} else {
Region region = msaRegion;
if (Config.USE_POSIX_API_REGION_OPTION) {
if (!isPosixRegion(regex.options)) {
if (region != null) {
region.clear();
} else {
msaBegin = msaEnd = 0;
}
}
} else {
if (region != null) {
region.clear();
} else {
msaBegin = msaEnd = 0;
}
} // USE_POSIX_REGION_OPTION
}
// end_best_len:
/* default behavior: return first-matching result. */
......
......@@ -41,7 +41,6 @@ public interface Config extends org.jcodings.Config {
final boolean USE_CAPTURE_HISTORY = false;
final boolean USE_VARIABLE_META_CHARS = true;
final boolean USE_WORD_BEGIN_END = true; /* "\<": word-begin, "\>": word-end */
final boolean USE_POSIX_API_REGION_OPTION = true; /* needed for POSIX API support */
final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true;
final boolean USE_CEC = false;
final boolean USE_DYNAMIC_OPTION = false;
......@@ -52,19 +51,11 @@ public interface Config extends org.jcodings.Config {
final int MAX_REPEAT_NUM = 100000;
final int MAX_MULTI_BYTE_RANGES_NUM = 10000;
final boolean USE_WARN = true;
// internal config
final boolean USE_PARSE_TREE_NODE_RECYCLE = true;
final boolean USE_OP_PUSH_OR_JUMP_EXACT = true;
final boolean USE_QTFR_PEEK_NEXT = true;
final int INIT_MATCH_STACK_SIZE = 64;
final int DEFAULT_MATCH_STACK_LIMIT_SIZE = 0; /* unlimited */
final int NUMBER_OF_POOLED_STACKS = 4;
final boolean DONT_OPTIMIZE = false;
......
......@@ -27,6 +27,7 @@ import static org.joni.ast.QuantifierNode.isRepeatInfinite;
import org.jcodings.Ptr;
import org.jcodings.constants.CharacterType;
import org.jcodings.exception.CharacterPropertyException;
import org.jcodings.exception.EncodingError;
import org.joni.ast.QuantifierNode;
import org.joni.constants.AnchorType;
import org.joni.constants.MetaChar;
......@@ -34,12 +35,14 @@ import org.joni.constants.TokenType;
import org.joni.exception.ErrorMessages;
class Lexer extends ScannerSupport {
protected final Regex regex;
protected final ScanEnvironment env;
protected final Syntax syntax; // fast access to syntax
protected final Token token = new Token(); // current token
protected Lexer(Regex regex, Syntax syntax, byte[]bytes, int p, int end, WarnCallback warnings) {
super(regex.enc, bytes, p, end);
this.regex = regex;
this.env = new ScanEnvironment(regex, syntax, warnings);
this.syntax = env.syntax;
}
......@@ -944,7 +947,7 @@ class Lexer extends ScannerSupport {
token.setBackrefNum(1);
token.setBackrefRef1(backNum);
} else {
NameEntry e = env.reg.nameToGroupNumbers(bytes, last, nameEnd);
NameEntry e = regex.nameToGroupNumbers(bytes, last, nameEnd);
if (e == null) newValueException(UNDEFINED_NAME_REFERENCE, last, nameEnd);
if (syntax.strictCheckBackref()) {
......@@ -1009,6 +1012,7 @@ class Lexer extends ScannerSupport {
}
protected final void fetchToken() {
int src = p;
// mark(); // out
start:
while(true) {
......@@ -1236,8 +1240,9 @@ class Lexer extends ScannerSupport {
if (syntax.opBracketCC()) token.type = TokenType.CC_OPEN;
break;
case ']':
//if (*src > env->pattern) /* /].../ is allowed. */
//CLOSE_BRACKET_WITHOUT_ESC_WARN(env, (UChar* )"]");
if (src > getBegin()) { /* /].../ is allowed. */
env.closeBracketWithoutEscapeWarn("]");
}
break;
case '#':
if (Option.isExtend(env.option)) {
......@@ -1304,7 +1309,7 @@ class Lexer extends ScannerSupport {
if (c == '}') {
return enc.propertyNameToCType(bytes, _p, last);
} else if (c == '(' || c == ')' || c == '{' || c == '|') {
throw new CharacterPropertyException(ERR_INVALID_CHAR_PROPERTY_NAME, bytes, _p, last);
throw new CharacterPropertyException(EncodingError.ERR_INVALID_CHAR_PROPERTY_NAME, bytes, _p, last);
}
}
newInternalException(PARSER_BUG);
......@@ -1316,7 +1321,7 @@ class Lexer extends ScannerSupport {
}
protected final void syntaxWarn(String message) {
if (Config.USE_WARN) {
if (env.warnings != WarnCallback.NONE) {
env.warnings.warn(message + ": /" + new String(bytes, getBegin(), getEnd()) + "/");
}
}
......
......@@ -48,22 +48,23 @@ public abstract class Matcher extends IntHolder {
protected int msaBegin;
protected int msaEnd;
Matcher(Regex regex, byte[]bytes, int p, int end) {
Matcher(Regex regex, Region region, byte[]bytes, int p, int end) {
this.regex = regex;
this.enc = regex.enc;
this.bytes = bytes;
this.str = p;
this.end = end;
this.msaRegion = regex.numMem == 0 ? null : new Region(regex.numMem + 1);
this.msaRegion = region;
}
// main matching method
protected abstract int matchAt(int range, int sstart, int sprev) throws InterruptedException;
protected abstract int matchAt(int range, int sstart, int sprev, boolean interrupt) throws InterruptedException;
protected abstract void stateCheckBuffInit(int strLength, int offset, int stateNum);
protected abstract void stateCheckBuffClear();
public abstract void interrupt();
public final Region getRegion() {
return msaRegion;
}
......@@ -88,13 +89,17 @@ public abstract class Matcher extends IntHolder {
public final int match(int at, int range, int option) {
try {
return matchInterruptible(at, range, option);
return matchCommon(at, range, option, false);
} catch (InterruptedException ex) {
return INTERRUPTED;
}
}
public final int matchInterruptible(int at, int range, int option) throws InterruptedException {
return matchCommon(at, range, option, true);
}
private final int matchCommon(int at, int range, int option, boolean interrupt) throws InterruptedException {
msaInit(option, at);
if (Config.USE_CEC) {
......@@ -105,9 +110,9 @@ public abstract class Matcher extends IntHolder {
int prev = enc.prevCharHead(bytes, str, at, end);
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
return matchAt(end /*range*/, at, prev);
return matchAt(end /*range*/, at, prev, interrupt);
} else {
return matchAt(range /*range*/, at, prev);
return matchAt(range /*range*/, at, prev, interrupt);
}
}
......@@ -265,26 +270,26 @@ public abstract class Matcher extends IntHolder {
}
// MATCH_AND_RETURN_CHECK
private boolean matchCheck(int upperRange, int s, int prev) throws InterruptedException {
private boolean matchCheck(int upperRange, int s, int prev, boolean interrupt) throws InterruptedException {
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
//range = upperRange;
if (matchAt(upperRange, s, prev) != -1) {
if (matchAt(upperRange, s, prev, interrupt) != -1) {
if (!isFindLongest(regex.options)) return true;
}
} else {
//range = upperRange;
if (matchAt(upperRange, s, prev) != -1) return true;
if (matchAt(upperRange, s, prev, interrupt) != -1) return true;
}
} else {
if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
if (matchAt(end, s, prev) != -1) {
if (matchAt(end, s, prev, interrupt) != -1) {
//range = upperRange;
if (!isFindLongest(regex.options)) return true;
}
} else {
//range = upperRange;
if (matchAt(end, s, prev) != -1) return true;
if (matchAt(end, s, prev, interrupt) != -1) return true;
}
}
return false;
......@@ -292,13 +297,17 @@ public abstract class Matcher extends IntHolder {
public final int search(int start, int range, int option) {
try {
return searchInterruptible(start, range, option);
return searchCommon(start, range, option, false);
} catch (InterruptedException ex) {
return INTERRUPTED;
}
}
public final int searchInterruptible(int start, int range, int option) throws InterruptedException {
return searchCommon(start, range, option, true);
}
private final int searchCommon(int start, int range, int option, boolean interrupt) throws InterruptedException {
int s, prev;
int origStart = start;
int origRange = range;
......@@ -376,7 +385,7 @@ public abstract class Matcher extends IntHolder {
if (Config.USE_CEC) stateCheckBuffClear();
if (matchCheck(end, s, prev)) return match(s);
if (matchCheck(end, s, prev, interrupt)) return match(s);
return mismatch();
}
return FAILED; // goto mismatch_no_msa;
......@@ -418,7 +427,7 @@ public abstract class Matcher extends IntHolder {
prev = value;
}
while (s <= high) {
if (matchCheck(origRange, s, prev)) return match(s); // ???
if (matchCheck(origRange, s, prev, interrupt)) return match(s); // ???
prev = s;
s += enc.length(bytes, s, end);
}
......@@ -430,7 +439,7 @@ public abstract class Matcher extends IntHolder {
if ((regex.anchor & AnchorType.ANYCHAR_STAR) != 0) {
do {
if (matchCheck(origRange, s, prev)) return match(s);
if (matchCheck(origRange, s, prev, interrupt)) return match(s);
prev = s;
s += enc.length(bytes, s, end);
......@@ -447,13 +456,13 @@ public abstract class Matcher extends IntHolder {
}
do {
if (matchCheck(origRange, s, prev)) return match(s);
if (matchCheck(origRange, s, prev, interrupt)) return match(s);
prev = s;
s += enc.length(bytes, s, end);
} while (s < range);
if (s == range) { /* because empty match with /$/. */
if (matchCheck(origRange, s, prev)) return match(s);
if (matchCheck(origRange, s, prev, interrupt)) return match(s);
}
} else { /* backward search */
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
......@@ -477,7 +486,7 @@ public abstract class Matcher extends IntHolder {
if (s > high) s = high;
while (s != -1 && s >= low) {
prev = enc.prevCharHead(bytes, str, s, end);
if (matchCheck(origStart, s, prev)) return match(s);
if (matchCheck(origStart, s, prev, interrupt)) return match(s);
s = prev;
}
} while (s >= range);
......@@ -504,7 +513,7 @@ public abstract class Matcher extends IntHolder {
do {
prev = enc.prevCharHead(bytes, str, s, end);
if (matchCheck(origStart, s, prev)) return match(s);
if (matchCheck(origStart, s, prev, interrupt)) return match(s);
s = prev;
} while (s >= range);
......
......@@ -20,12 +20,12 @@
package org.joni;
abstract class MatcherFactory {
abstract Matcher create(Regex regex, byte[]bytes, int p, int end);
abstract Matcher create(Regex regex, Region region, byte[]bytes, int p, int end);
static final MatcherFactory DEFAULT = new MatcherFactory() {
@Override
Matcher create(Regex regex, byte[] bytes, int p, int end) {
return new ByteCodeMachine(regex, bytes, p, end);
Matcher create(Regex regex, Region region, byte[]bytes, int p, int end) {
return new ByteCodeMachine(regex, region, bytes, p, end);
}
};
}
......@@ -21,7 +21,7 @@ package org.joni;
abstract class NativeMachine extends Matcher {
protected NativeMachine(Regex regex, byte[]bytes, int p, int end) {
super(regex, bytes, p, end);
protected NativeMachine(Regex regex, Region region, byte[]bytes, int p, int end) {
super(regex, region, bytes, p, end);
}
}
......@@ -51,13 +51,11 @@ import org.joni.constants.NodeType;
import org.joni.constants.TokenType;
class Parser extends Lexer {
protected final Regex regex;
protected int returnCode; // return code used by parser methods (they itself return parsed nodes)
// this approach will not affect recursive calls
protected Parser(Regex regex, Syntax syntax, byte[]bytes, int p, int end, WarnCallback warnings) {
super(regex, syntax, bytes, p, end, warnings);
this.regex = regex;
}
private static final int POSIX_BRACKET_NAME_MIN_LEN = 4;
......
......@@ -23,6 +23,7 @@ import static org.joni.BitStatus.bsAt;
import static org.joni.Option.isCaptureGroup;
import static org.joni.Option.isDontCaptureGroup;
import java.util.Collections;
import java.util.Iterator;
import org.jcodings.Encoding;
......@@ -61,7 +62,7 @@ public final class Regex {
Object userObject;
final int caseFoldFlag;
BytesHash<NameEntry> nameTable; // named entries
private BytesHash<NameEntry> nameTable; // named entries
/* optimization info (string search, char-map and anchors) */
SearchAlgorithm searchAlgorithm; /* optimize flag */
......@@ -155,8 +156,16 @@ public final class Regex {
return matcher(bytes, 0, bytes.length);
}
public Matcher matcherNoRegion(byte[]bytes) {
return matcherNoRegion(bytes, 0, bytes.length);
}
public Matcher matcher(byte[]bytes, int p, int end) {
return factory.create(this, bytes, p, end);
return factory.create(this, numMem == 0 ? null : new Region(numMem + 1), bytes, p, end);
}
public Matcher matcherNoRegion(byte[]bytes, int p, int end) {
return factory.create(this, null, bytes, p, end);
}
public int numberOfCaptures() {
......@@ -175,20 +184,7 @@ public final class Regex {
}
}
String nameTableToString() {
StringBuilder sb = new StringBuilder();
if (nameTable != null) {
sb.append("name table\n");
for (NameEntry ne : nameTable) {
sb.append(" " + ne + "\n");
}
sb.append("\n");
}
return sb.toString();
}
NameEntry nameFind(byte[]name, int nameP, int nameEnd) {
private NameEntry nameFind(byte[]name, int nameP, int nameEnd) {
if (nameTable != null) return nameTable.get(name, nameP, nameEnd);
return null;
}
......@@ -207,10 +203,6 @@ public final class Regex {
}
}
public int numberOfNames() {
return nameTable == null ? 0 : nameTable.size();
}
void nameAdd(byte[]name, int nameP, int nameEnd, int backRef, Syntax syntax) {
if (nameEnd - nameP <= 0) throw new ValueException(ErrorMessages.EMPTY_GROUP_NAME);
......@@ -256,8 +248,25 @@ public final class Regex {
}
}
String nameTableToString() {
StringBuilder sb = new StringBuilder();
if (nameTable != null) {
sb.append("name table\n");
for (NameEntry ne : nameTable) {
sb.append(" " + ne + "\n");
}
sb.append("\n");
}
return sb.toString();
}
public Iterator<NameEntry> namedBackrefIterator() {
return nameTable.iterator();
return nameTable == null ? Collections.<NameEntry>emptyIterator() : nameTable.iterator();
}
public int numberOfNames() {
return nameTable == null ? 0 : nameTable.size();
}
public boolean noNameGroupIsActive(Syntax syntax) {
......
......@@ -20,23 +20,24 @@
package org.joni;
import org.jcodings.Encoding;
import org.jcodings.util.BytesHash;
import org.joni.ast.EncloseNode;
import org.joni.ast.Node;
import org.joni.constants.SyntaxProperties;
import org.joni.exception.ErrorMessages;
import org.joni.exception.InternalException;
import org.joni.exception.ValueException;
public final class ScanEnvironment {
public int option;
final int caseFoldFlag;
final public Encoding enc;
final public Syntax syntax;
public final Encoding enc;
public final Syntax syntax;
int captureHistory;
int btMemStart;
int btMemEnd;
int backrefedMem;
final public Regex reg;
public final WarnCallback warnings;
int numCall;
......@@ -57,16 +58,15 @@ public final class ScanEnvironment {
int numPrecReadNotNodes;
Node precReadNotNodes[];
public ScanEnvironment(Regex regex, Syntax syntax, WarnCallback warnings) {
this.reg = regex;
ScanEnvironment(Regex regex, Syntax syntax, WarnCallback warnings) {
this.syntax = syntax;
this.warnings = warnings;
option = reg.options;
caseFoldFlag = reg.caseFoldFlag;
enc = reg.enc;
option = regex.options;
caseFoldFlag = regex.caseFoldFlag;
enc = regex.enc;
}
public int addMemEntry() {
int addMemEntry() {
if (numMem >= Config.MAX_CAPTURE_GROUP_NUM) throw new InternalException(ErrorMessages.TOO_MANY_CAPTURE_GROUPS);
if (numMem++ == 0) {
memNodes = new EncloseNode[Config.SCANENV_MEMNODES_SIZE];
......@@ -79,7 +79,7 @@ public final class ScanEnvironment {
return numMem;
}
public void setMemNode(int num, EncloseNode node) {
void setMemNode(int num, EncloseNode node) {
if (numMem >= num) {
memNodes[num] = node;
} else {
......@@ -87,7 +87,8 @@ public final class ScanEnvironment {
}
}
public void pushPrecReadNotNode(Node node) {
void pushPrecReadNotNode(Node node) {
numPrecReadNotNodes++;
if (precReadNotNodes == null) {
precReadNotNodes = new Node[Config.SCANENV_MEMNODES_SIZE];
......@@ -99,21 +100,21 @@ public final class ScanEnvironment {
precReadNotNodes[numPrecReadNotNodes - 1] = node;
}
public void popPrecReadNotNode(Node node) {
void popPrecReadNotNode(Node node) {
if (precReadNotNodes != null && precReadNotNodes[numPrecReadNotNodes - 1] == node) {
precReadNotNodes[numPrecReadNotNodes - 1] = null;
numPrecReadNotNodes--;
}
}
public Node currentPrecReadNotNode() {
Node currentPrecReadNotNode() {
if (numPrecReadNotNodes > 0) {
return precReadNotNodes[numPrecReadNotNodes - 1];
}
return null;
}
public int convertBackslashValue(int c) {
int convertBackslashValue(int c) {
if (syntax.opEscControlChars()) {
switch (c) {
case 'n': return '\n';
......@@ -127,22 +128,28 @@ public final class ScanEnvironment {
if (syntax.op2EscVVtab()) return 11; // '\v'
break;
default:
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) ccEscWarn(String.valueOf((char)c));
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) unknownEscWarn(String.valueOf((char)c));
}
}
return c;
}
void ccEscWarn(String s) {
if (Config.USE_WARN) {
if (warnings != WarnCallback.NONE) {
if (syntax.warnCCOpNotEscaped() && syntax.backSlashEscapeInCC()) {
warnings.warn("character class has '" + s + "' without escape");
}
}
}
void unknownEscWarn(String s) {
if (warnings != WarnCallback.NONE) {
warnings.warn("Unknown escape \\" + s + " is ignored");
}
}
void closeBracketWithoutEscapeWarn(String s) {
if (Config.USE_WARN) {
if (warnings != WarnCallback.NONE) {
if (syntax.warnCCOpNotEscaped()) {
warnings.warn("regular expression has '" + s + "' without escape");
}
......
......@@ -38,8 +38,8 @@ abstract class StackMachine extends Matcher implements StackType {
protected byte[] stateCheckBuff; // CEC, move to int[] ?
protected int stateCheckBuffSize;
protected StackMachine(Regex regex, byte[]bytes, int p , int end) {
super(regex, bytes, p, end);
protected StackMachine(Regex regex, Region region, byte[]bytes, int p , int end) {
super(regex, region, bytes, p, end);
stack = regex.requireStack ? fetchStack() : null;
final int n;
if (Config.USE_SUBEXP_CALL) {
......