提交 0be10227 编写于 作者: H hannesw

8012359: Increase code coverage in Joni

Reviewed-by: jlaskey, lagergren
上级 31e7995e
...@@ -305,6 +305,8 @@ ...@@ -305,6 +305,8 @@
<include name="**/codegen/*Test.class"/> <include name="**/codegen/*Test.class"/>
<include name="**/parser/*Test.class"/> <include name="**/parser/*Test.class"/>
<include name="**/runtime/*Test.class"/> <include name="**/runtime/*Test.class"/>
<include name="**/runtime/regexp/*Test.class"/>
<include name="**/runtime/regexp/joni/*Test.class"/>
<include name="**/framework/*Test.class"/> <include name="**/framework/*Test.class"/>
</fileset> </fileset>
......
...@@ -41,7 +41,7 @@ import java.util.regex.PatternSyntaxException; ...@@ -41,7 +41,7 @@ import java.util.regex.PatternSyntaxException;
* Note that this class is not thread-safe as it stores the current match result * Note that this class is not thread-safe as it stores the current match result
* and the string being matched in instance fields. * and the string being matched in instance fields.
*/ */
public class DefaultRegExp extends RegExp { public class JdkRegExp extends RegExp {
/** Java regexp pattern to use for match. We compile to one of these */ /** Java regexp pattern to use for match. We compile to one of these */
private Pattern pattern; private Pattern pattern;
...@@ -56,7 +56,7 @@ public class DefaultRegExp extends RegExp { ...@@ -56,7 +56,7 @@ public class DefaultRegExp extends RegExp {
* @param flags RegExp flag string * @param flags RegExp flag string
* @throws ParserException if flags is invalid or source string has syntax error. * @throws ParserException if flags is invalid or source string has syntax error.
*/ */
public DefaultRegExp(final String source, final String flags) throws ParserException { public JdkRegExp(final String source, final String flags) throws ParserException {
super(source, flags); super(source, flags);
int intFlags = 0; int intFlags = 0;
......
...@@ -113,7 +113,7 @@ public class JoniRegExp extends RegExp { ...@@ -113,7 +113,7 @@ public class JoniRegExp extends RegExp {
public static class Factory extends RegExpFactory { public static class Factory extends RegExpFactory {
@Override @Override
protected RegExp compile(final String pattern, final String flags) throws ParserException { public RegExp compile(final String pattern, final String flags) throws ParserException {
return new JoniRegExp(pattern, flags); return new JoniRegExp(pattern, flags);
} }
......
...@@ -29,7 +29,7 @@ import jdk.nashorn.internal.runtime.ParserException; ...@@ -29,7 +29,7 @@ import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.options.Options; import jdk.nashorn.internal.runtime.options.Options;
/** /**
* Factory class for regular expressions. This class creates instances of {@link DefaultRegExp}. * Factory class for regular expressions. This class creates instances of {@link JdkRegExp}.
* An alternative factory can be installed using the {@code nashorn.regexp.impl} system property. * An alternative factory can be installed using the {@code nashorn.regexp.impl} system property.
*/ */
public class RegExpFactory { public class RegExpFactory {
...@@ -62,8 +62,8 @@ public class RegExpFactory { ...@@ -62,8 +62,8 @@ public class RegExpFactory {
* @return new RegExp * @return new RegExp
* @throws ParserException if flags is invalid or pattern string has syntax error. * @throws ParserException if flags is invalid or pattern string has syntax error.
*/ */
protected RegExp compile(final String pattern, final String flags) throws ParserException { public RegExp compile(final String pattern, final String flags) throws ParserException {
return new DefaultRegExp(pattern, flags); return new JdkRegExp(pattern, flags);
} }
/** /**
......
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode;
final class AsmCompiler extends AsmCompilerSupport {
public AsmCompiler(Analyser analyser) {
super(analyser);
}
@Override
protected void prepare() {
REG_NUM++;
prepareMachine();
prepareMachineInit();
prepareMachineMatch();
prepareFactory();
prepareFactoryInit();
}
@Override
protected void finish() {
setupFactoryInit();
setupMachineInit();
setupMachineMatch();
setupClasses();
}
@Override
protected void compileAltNode(ConsAltNode node) {
}
@Override
protected void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase) {
String template = installTemplate(chars, p, strLength);
}
@Override
protected void compileCClassNode(CClassNode node) {
if (node.bs != null) {
String bitsetName = installBitSet(node.bs.bits);
}
}
@Override
protected void compileCTypeNode(CTypeNode node) {
}
@Override
protected void compileAnyCharNode() {
}
@Override
protected void compileBackrefNode(BackRefNode node) {
}
@Override
protected void compileCallNode(CallNode node) {
}
@Override
protected void compileCECQuantifierNode(QuantifierNode node) {
}
@Override
protected void compileNonCECQuantifierNode(QuantifierNode node) {
}
@Override
protected void compileOptionNode(EncloseNode node) {
}
@Override
protected void compileEncloseNode(EncloseNode node) {
}
@Override
protected void compileAnchorNode(AnchorNode node) {
}
}
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
import java.io.FileOutputStream;
import java.io.IOException;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.internal.org.objectweb.asm.Opcodes;
abstract class AsmCompilerSupport extends Compiler implements Opcodes, AsmConstants {
protected ClassWriter factory; // matcher allocator, also bit set, code rage and string template container
protected MethodVisitor factoryInit;// factory constructor
protected String factoryName;
protected ClassWriter machine; // matcher
protected MethodVisitor machineInit;// matcher constructor
protected MethodVisitor match; // actual matcher implementation (the matchAt method)
protected String machineName;
// we will? try to manage visitMaxs ourselves for efficiency
protected int maxStack = 1;
protected int maxVars = LAST_INDEX;
// for field generation
protected int bitsets, ranges, templates;
// simple class name postfix scheme for now
static int REG_NUM = 0;
// dummy class loader for now
private static final class DummyClassLoader extends ClassLoader {
public Class<?> defineClass(String name, byte[] bytes) {
return super.defineClass(name, bytes, 0, bytes.length);
}
};
private static final DummyClassLoader loader = new DummyClassLoader();
AsmCompilerSupport(Analyser analyser) {
super(analyser);
}
protected final void prepareFactory() {
factory = new ClassWriter(ClassWriter.COMPUTE_MAXS);
factoryName = "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory" + REG_NUM;
factory.visit(V1_4, ACC_PUBLIC + ACC_FINAL, factoryName, null, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", null);
MethodVisitor create = factory.visitMethod(ACC_SYNTHETIC, "create", "(Lorg/joni/Regex;[BII)Lorg/joni/Matcher;", null, null);
create.visitTypeInsn(NEW, machineName);
create.visitInsn(DUP); // instance
create.visitVarInsn(ALOAD, 1); // Regex
create.visitVarInsn(ALOAD, 2); // bytes[]
create.visitVarInsn(ILOAD, 3); // p
create.visitVarInsn(ILOAD, 4); // end
create.visitMethodInsn(INVOKESPECIAL, machineName, "<init>", "(Lorg/joni/Regex;[BII)V");
create.visitInsn(ARETURN);
create.visitMaxs(0, 0);
//create.visitMaxs(6, 5);
create.visitEnd();
}
protected final void prepareFactoryInit() {
factoryInit = factory.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
factoryInit.visitVarInsn(ALOAD, 0);
factoryInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", "<init>", "()V");
}
protected final void setupFactoryInit() {
factoryInit.visitInsn(RETURN);
factoryInit.visitMaxs(0, 0);
//init.visitMaxs(1, 1);
factoryInit.visitEnd();
}
protected final void prepareMachine() {
machine = new ClassWriter(ClassWriter.COMPUTE_MAXS);
machineName = "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine" + REG_NUM;
}
protected final void prepareMachineInit() {
machine.visit(V1_4, ACC_PUBLIC + ACC_FINAL, machineName, null, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", null);
machineInit = machine.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/joni/Regex;[BII)V", null, null);
machineInit.visitVarInsn(ALOAD, THIS); // this
machineInit.visitVarInsn(ALOAD, 1); // Regex
machineInit.visitVarInsn(ALOAD, 2); // bytes[]
machineInit.visitVarInsn(ILOAD, 3); // p
machineInit.visitVarInsn(ILOAD, 4); // end
machineInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", "<init>", "(Lorg/joni/Regex;[BII)V");
}
protected final void setupMachineInit() {
if (bitsets + ranges + templates > 0) { // ok, some of these are in use, we'd like to cache the factory
machine.visitField(ACC_PRIVATE + ACC_FINAL, "factory", "L" + factoryName + ";", null, null);
machineInit.visitVarInsn(ALOAD, THIS); // this
machineInit.visitVarInsn(ALOAD, 1); // this, Regex
machineInit.visitFieldInsn(GETFIELD, "jdk/nashorn/internal/runtime/regexp/joni/Regex", "factory", "Lorg/joni/MatcherFactory;"); // this, factory
machineInit.visitTypeInsn(CHECKCAST, factoryName);
machineInit.visitFieldInsn(PUTFIELD, machineName, "factory", "L" + factoryName + ";"); // []
}
machineInit.visitInsn(RETURN);
machineInit.visitMaxs(0, 0);
//init.visitMaxs(5, 5);
machineInit.visitEnd();
}
protected final void prepareMachineMatch() {
match = machine.visitMethod(ACC_SYNTHETIC, "matchAt", "(III)I", null, null);
move(S, SSTART); // s = sstart
load("bytes", "[B"); //
astore(BYTES); // byte[]bytes = this.bytes
}
protected final void setupMachineMatch() {
match.visitInsn(ICONST_M1);
match.visitInsn(IRETURN);
match.visitMaxs(maxStack, maxVars);
match.visitEnd();
}
protected final void setupClasses() {
byte[]factoryCode = factory.toByteArray();
byte[]machineCode = machine.toByteArray();
if (Config.DEBUG_ASM) {
try {
FileOutputStream fos;
fos = new FileOutputStream(factoryName.substring(factoryName.lastIndexOf('/') + 1) + ".class");
fos.write(factoryCode);
fos.close();
fos = new FileOutputStream(machineName.substring(machineName.lastIndexOf('/') + 1) + ".class");
fos.write(machineCode);
fos.close();
} catch (IOException ioe) {
ioe.printStackTrace(Config.err);
}
}
loader.defineClass(machineName.replace('/', '.'), machineCode);
Class<?> cls = loader.defineClass(factoryName.replace('/', '.'), factoryCode);
try {
regex.factory = (MatcherFactory)cls.newInstance();
} catch(Exception e) {
e.printStackTrace(Config.err);
}
}
protected final void aload(int var) {
match.visitVarInsn(ALOAD, var);
}
protected final void astore(int var) {
match.visitVarInsn(ASTORE, var);
}
protected final void loadThis() {
match.visitVarInsn(ALOAD, THIS);
}
protected final void load(int var) {
match.visitVarInsn(ILOAD, var);
}
protected final void store(int var) {
match.visitVarInsn(ISTORE, var);
}
protected final void move(int to, int from) {
load(from);
store(to);
}
protected final void load(String field, String singature) {
loadThis();
match.visitFieldInsn(GETFIELD, machineName, field, singature);
}
protected final void load(String field) {
load(field, "I");
}
protected final void store(String field, String singature) {
loadThis();
match.visitFieldInsn(PUTFIELD, machineName, field, singature);
}
protected final void store(String field) {
store(field, "I");
}
protected final String installTemplate(char[] arr, int p, int length) {
String templateName = TEMPLATE + ++templates;
installArray(templateName, arr, p, length);
return templateName;
}
protected final String installCodeRange(int[]arr) {
String coreRangeName = CODERANGE + ++ranges;
installArray(coreRangeName, arr);
return coreRangeName;
}
protected final String installBitSet(int[]arr) {
String bitsetName = BITSET + ++bitsets;
installArray(bitsetName, arr);
return bitsetName;
}
private void installArray(String name, int[]arr) {
factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[I", null, null);
factoryInit.visitVarInsn(ALOAD, THIS); // this;
loadInt(factoryInit, arr.length); // this, length
factoryInit.visitIntInsn(NEWARRAY, T_INT); // this, arr
for (int i=0;i < arr.length; i++) buildArray(i, arr[i], IASTORE);
factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[I");
}
private void installArray(String name, char[]arr, int p, int length) {
factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[B", null, null);
factoryInit.visitVarInsn(ALOAD, THIS); // this;
loadInt(factoryInit, arr.length); // this, length
factoryInit.visitIntInsn(NEWARRAY, T_BYTE); // this, arr
for (int i=p, j=0; i < p + length; i++, j++) buildArray(j, arr[i] & 0xff, BASTORE);
factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[B");
}
private void buildArray(int index, int value, int type) {
factoryInit.visitInsn(DUP); // ... arr, arr
loadInt(factoryInit, index); // ... arr, arr, index
loadInt(factoryInit, value); // ... arr, arr, index, value
factoryInit.visitInsn(type); // ... arr
}
private void loadInt(MethodVisitor mv, int value) {
if (value >= -1 && value <= 5) {
mv.visitInsn(value + ICONST_0); // ICONST_0 == 3
} else if (value >= 6 && value <= 127 || value >= -128 && value <= -2) {
mv.visitIntInsn(BIPUSH, value);
} else if (value >= 128 && value <= 32767 || value >= -32768 && value <= -129) {
mv.visitIntInsn(SIPUSH, value);
} else {
mv.visitLdcInsn(new Integer(value));
}
}
}
...@@ -51,10 +51,6 @@ public final class BitSet { ...@@ -51,10 +51,6 @@ public final class BitSet {
bits[pos >>> ROOM_SHIFT] &= ~bit(pos); bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
} }
public void invert(int pos) {
bits[pos >>> ROOM_SHIFT] ^= bit(pos);
}
public void clear() { public void clear() {
for (int i=0; i<BITSET_SIZE; i++) bits[i]=0; for (int i=0; i<BITSET_SIZE; i++) bits[i]=0;
} }
...@@ -70,10 +66,6 @@ public final class BitSet { ...@@ -70,10 +66,6 @@ public final class BitSet {
for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i); for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i);
} }
public void setAll() {
for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~0;
}
public void invert() { public void invert() {
for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i]; for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i];
} }
......
...@@ -25,12 +25,15 @@ final class BitStatus { ...@@ -25,12 +25,15 @@ final class BitStatus {
public static int bsClear() { public static int bsClear() {
return 0; return 0;
} }
public static int bsAll() { public static int bsAll() {
return -1; return -1;
} }
public static boolean bsAt(int stats, int n) { public static boolean bsAt(int stats, int n) {
return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0; return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0;
} }
public static int bsOnAt(int stats, int n) { public static int bsOnAt(int stats, int n) {
if (n < BIT_STATUS_BITS_NUM) { if (n < BIT_STATUS_BITS_NUM) {
stats |= (1 << n); stats |= (1 << n);
...@@ -39,10 +42,6 @@ final class BitStatus { ...@@ -39,10 +42,6 @@ final class BitStatus {
} }
return stats; return stats;
} }
public static int bsOnAtSimple(int stats, int n) {
if (n < BIT_STATUS_BITS_NUM) stats |= (1 << n);
return stats;
}
public static int bsOnOff(int v, int f, boolean negative) { public static int bsOnOff(int v, int f, boolean negative) {
if (negative) { if (negative) {
......
...@@ -53,56 +53,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -53,56 +53,6 @@ class ByteCodeMachine extends StackMachine {
this.code = regex.code; this.code = regex.code;
} }
protected int stkp; // a temporary
private boolean makeCaptureHistoryTree(CaptureTreeNode node) {
//CaptureTreeNode child;
int k = stkp;
//int k = kp;
while (k < stk) {
StackEntry e = stack[k];
if (e.type == MEM_START) {
int n = e.getMemNum();
if (n <= Config.MAX_CAPTURE_HISTORY_GROUP && bsAt(regex.captureHistory, n)) {
CaptureTreeNode child = new CaptureTreeNode();
child.group = n;
child.beg = e.getMemPStr() - str;
node.addChild(child);
stkp = k + 1;
if (makeCaptureHistoryTree(child)) return true;
k = stkp;
child.end = e.getMemPStr() - str;
}
} else if (e.type == MEM_END) {
if (e.getMemNum() == node.group) {
node.end = e.getMemPStr() - str;
stkp = k;
return false;
}
}
}
return true; /* 1: root node ending. */
}
private void checkCaptureHistory(Region region) {
CaptureTreeNode node;
if (region.historyRoot == null) {
node = region.historyRoot = new CaptureTreeNode();
} else {
node = region.historyRoot;
node.clear();
}
// was clear ???
node.group = 0;
node.beg = sstart - str;
node.end = s - str;
stkp = 0;
makeCaptureHistoryTree(region.historyRoot);
}
private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) { private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) {
int s2 = ps2.value; int s2 = ps2.value;
...@@ -175,13 +125,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -175,13 +125,6 @@ class ByteCodeMachine extends StackMachine {
case OPCode.EXACT5: opExact5(); continue; case OPCode.EXACT5: opExact5(); continue;
case OPCode.EXACTN: opExactN(); continue; case OPCode.EXACTN: opExactN(); continue;
case OPCode.EXACTMB2N1: opExactMB2N1(); break;
case OPCode.EXACTMB2N2: opExactMB2N2(); continue;
case OPCode.EXACTMB2N3: opExactMB2N3(); continue;
case OPCode.EXACTMB2N: opExactMB2N(); continue;
case OPCode.EXACTMB3N: opExactMB3N(); continue;
case OPCode.EXACTMBN: opExactMBN(); continue;
case OPCode.EXACT1_IC: opExact1IC(); break; case OPCode.EXACT1_IC: opExact1IC(); break;
case OPCode.EXACTN_IC: opExactNIC(); continue; case OPCode.EXACTN_IC: opExactNIC(); continue;
...@@ -199,8 +142,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -199,8 +142,6 @@ class ByteCodeMachine extends StackMachine {
case OPCode.ANYCHAR_ML_STAR: opAnyCharMLStar(); break; case OPCode.ANYCHAR_ML_STAR: opAnyCharMLStar(); break;
case OPCode.ANYCHAR_STAR_PEEK_NEXT: opAnyCharStarPeekNext(); break; case OPCode.ANYCHAR_STAR_PEEK_NEXT: opAnyCharStarPeekNext(); break;
case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT: opAnyCharMLStarPeekNext(); break; case OPCode.ANYCHAR_ML_STAR_PEEK_NEXT: opAnyCharMLStarPeekNext(); break;
case OPCode.STATE_CHECK_ANYCHAR_STAR: opStateCheckAnyCharStar(); break;
case OPCode.STATE_CHECK_ANYCHAR_ML_STAR:opStateCheckAnyCharMLStar();break;
case OPCode.WORD: opWord(); break; case OPCode.WORD: opWord(); break;
case OPCode.NOT_WORD: opNotWord(); break; case OPCode.NOT_WORD: opNotWord(); break;
...@@ -239,11 +180,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -239,11 +180,6 @@ class ByteCodeMachine extends StackMachine {
case OPCode.JUMP: opJump(); continue; case OPCode.JUMP: opJump(); continue;
case OPCode.PUSH: opPush(); continue; case OPCode.PUSH: opPush(); continue;
// CEC
case OPCode.STATE_CHECK_PUSH: opStateCheckPush(); continue;
case OPCode.STATE_CHECK_PUSH_OR_JUMP: opStateCheckPushOrJump(); continue;
case OPCode.STATE_CHECK: opStateCheck(); continue;
case OPCode.POP: opPop(); continue; case OPCode.POP: opPop(); continue;
case OPCode.PUSH_OR_JUMP_EXACT1: opPushOrJumpExact1(); continue; case OPCode.PUSH_OR_JUMP_EXACT1: opPushOrJumpExact1(); continue;
case OPCode.PUSH_IF_PEEK_NEXT: opPushIfPeekNext(); continue; case OPCode.PUSH_IF_PEEK_NEXT: opPushIfPeekNext(); continue;
...@@ -266,10 +202,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -266,10 +202,6 @@ class ByteCodeMachine extends StackMachine {
case OPCode.PUSH_LOOK_BEHIND_NOT: opPushLookBehindNot(); continue; case OPCode.PUSH_LOOK_BEHIND_NOT: opPushLookBehindNot(); continue;
case OPCode.FAIL_LOOK_BEHIND_NOT: opFailLookBehindNot(); continue; case OPCode.FAIL_LOOK_BEHIND_NOT: opFailLookBehindNot(); continue;
// USE_SUBEXP_CALL
case OPCode.CALL: opCall(); continue;
case OPCode.RETURN: opReturn(); continue;
case OPCode.FINISH: case OPCode.FINISH:
return finish(); return finish();
...@@ -322,9 +254,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -322,9 +254,6 @@ class ByteCodeMachine extends StackMachine {
} }
if (Config.USE_CAPTURE_HISTORY) {
if (regex.captureHistory != 0) checkCaptureHistory(region);
}
} else { } else {
msaBegin = sstart - str; msaBegin = sstart - str;
msaEnd = s - str; msaEnd = s - str;
...@@ -437,125 +366,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -437,125 +366,6 @@ class ByteCodeMachine extends StackMachine {
sprev = s - 1; sprev = s - 1;
} }
private void opExactMB2N1() {
if (s + 2 > range) {opFail(); return;}
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
sprev = sbegin; // break;
}
private void opExactMB2N2() {
if (s + 4 > range) {opFail(); return;}
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
sprev = s;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
}
private void opExactMB2N3() {
if (s + 6 > range) {opFail(); return;}
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
sprev = s;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
}
private void opExactMB2N() {
int tlen = code[ip++];
if (s + tlen * 2 > range) {opFail(); return;}
if (Config.USE_STRING_TEMPLATES) {
char[] bs = regex.templates[code[ip++]];
int ps = code[ip++];
while(tlen-- > 0) {
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
}
} else {
while(tlen-- > 0) {
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
}
}
sprev = s - 2;
}
private void opExactMB3N() {
int tlen = code[ip++];
if (s + tlen * 3 > range) {opFail(); return;}
if (Config.USE_STRING_TEMPLATES) {
char[] bs = regex.templates[code[ip++]];
int ps = code[ip++];
while (tlen-- > 0) {
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
}
} else {
while (tlen-- > 0) {
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
}
}
sprev = s - 3;
}
private void opExactMBN() {
int tlen = code[ip++]; /* mb-len */
int tlen2= code[ip++]; /* string len */
tlen2 *= tlen;
if (s + tlen2 > range) {opFail(); return;}
if (Config.USE_STRING_TEMPLATES) {
char[] bs = regex.templates[code[ip++]];
int ps = code[ip++];
while (tlen2-- > 0) {
if (bs[ps] != chars[s]) {opFail(); return;}
ps++; s++;
}
} else {
while (tlen2-- > 0) {
if (code[ip] != chars[s]) {opFail(); return;}
ip++; s++;
}
}
sprev = s - tlen;
}
private void opExact1IC() { private void opExact1IC() {
if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;} if (s >= range || code[ip] != Character.toLowerCase(chars[s++])) {opFail(); return;}
ip++; ip++;
...@@ -748,34 +558,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -748,34 +558,6 @@ class ByteCodeMachine extends StackMachine {
sprev = sbegin; // break; sprev = sbegin; // break;
} }
// CEC
private void opStateCheckAnyCharStar() {
int mem = code[ip++];
final char[] chars = this.chars;
while (s < range) {
if (stateCheckVal(s, mem)) {opFail(); return;}
pushAltWithStateCheck(ip, s, sprev, mem);
if (chars[s] == EncodingHelper.NEW_LINE) {opFail(); return;}
sprev = s;
s++;
}
sprev = sbegin; // break;
}
// CEC
private void opStateCheckAnyCharMLStar() {
int mem = code[ip++];
while (s < range) {
if (stateCheckVal(s, mem)) {opFail(); return;}
pushAltWithStateCheck(ip, s, sprev, mem);
sprev = s;
s++;
}
sprev = sbegin; // break;
}
private void opWord() { private void opWord() {
if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;} if (s >= range || !EncodingHelper.isWord(chars[s])) {opFail(); return;}
s++; s++;
...@@ -1223,33 +1005,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -1223,33 +1005,6 @@ class ByteCodeMachine extends StackMachine {
pushAlt(ip + addr, s, sprev); pushAlt(ip + addr, s, sprev);
} }
// CEC
private void opStateCheckPush() {
int mem = code[ip++];
if (stateCheckVal(s, mem)) {opFail(); return;}
int addr = code[ip++];
pushAltWithStateCheck(ip + addr, s, sprev, mem);
}
// CEC
private void opStateCheckPushOrJump() {
int mem = code[ip++];
int addr= code[ip++];
if (stateCheckVal(s, mem)) {
ip += addr;
} else {
pushAltWithStateCheck(ip + addr, s, sprev, mem);
}
}
// CEC
private void opStateCheck() {
int mem = code[ip++];
if (stateCheckVal(s, mem)) {opFail(); return;}
pushStateCheck(s, mem);
}
private void opPop() { private void opPop() {
popOne(); popOne();
} }
...@@ -1425,17 +1180,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -1425,17 +1180,6 @@ class ByteCodeMachine extends StackMachine {
opFail(); opFail();
} }
private void opCall() {
int addr = code[ip++];
pushCallFrame(ip);
ip = addr; // absolute address
}
private void opReturn() {
ip = sreturn();
pushReturn();
}
private void opFail() { private void opFail() {
if (stack == null) { if (stack == null) {
ip = regex.codeLength - 1; ip = regex.codeLength - 1;
...@@ -1447,13 +1191,6 @@ class ByteCodeMachine extends StackMachine { ...@@ -1447,13 +1191,6 @@ class ByteCodeMachine extends StackMachine {
ip = e.getStatePCode(); ip = e.getStatePCode();
s = e.getStatePStr(); s = e.getStatePStr();
sprev = e.getStatePStrPrev(); sprev = e.getStatePStrPrev();
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.getStateCheck() != 0) {
e.type = STATE_CHECK_MARK;
stk++;
}
}
} }
private int finish() { private int finish() {
......
...@@ -34,6 +34,239 @@ class ByteCodePrinter { ...@@ -34,6 +34,239 @@ class ByteCodePrinter {
int operantCount; int operantCount;
WarnCallback warnings; WarnCallback warnings;
private final static String OpCodeNames[] = new String[] {
"finish", /*OP_FINISH*/
"end", /*OP_END*/
"exact1", /*OP_EXACT1*/
"exact2", /*OP_EXACT2*/
"exact3", /*OP_EXACT3*/
"exact4", /*OP_EXACT4*/
"exact5", /*OP_EXACT5*/
"exactn", /*OP_EXACTN*/
"exactmb2-n1", /*OP_EXACTMB2N1*/
"exactmb2-n2", /*OP_EXACTMB2N2*/
"exactmb2-n3", /*OP_EXACTMB2N3*/
"exactmb2-n", /*OP_EXACTMB2N*/
"exactmb3n", /*OP_EXACTMB3N*/
"exactmbn", /*OP_EXACTMBN*/
"exact1-ic", /*OP_EXACT1_IC*/
"exactn-ic", /*OP_EXACTN_IC*/
"cclass", /*OP_CCLASS*/
"cclass-mb", /*OP_CCLASS_MB*/
"cclass-mix", /*OP_CCLASS_MIX*/
"cclass-not", /*OP_CCLASS_NOT*/
"cclass-mb-not", /*OP_CCLASS_MB_NOT*/
"cclass-mix-not", /*OP_CCLASS_MIX_NOT*/
"cclass-node", /*OP_CCLASS_NODE*/
"anychar", /*OP_ANYCHAR*/
"anychar-ml", /*OP_ANYCHAR_ML*/
"anychar*", /*OP_ANYCHAR_STAR*/
"anychar-ml*", /*OP_ANYCHAR_ML_STAR*/
"anychar*-peek-next", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
"anychar-ml*-peek-next", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
"word", /*OP_WORD*/
"not-word", /*OP_NOT_WORD*/
"word-bound", /*OP_WORD_BOUND*/
"not-word-bound", /*OP_NOT_WORD_BOUND*/
"word-begin", /*OP_WORD_BEGIN*/
"word-end", /*OP_WORD_END*/
"begin-buf", /*OP_BEGIN_BUF*/
"end-buf", /*OP_END_BUF*/
"begin-line", /*OP_BEGIN_LINE*/
"end-line", /*OP_END_LINE*/
"semi-end-buf", /*OP_SEMI_END_BUF*/
"begin-position", /*OP_BEGIN_POSITION*/
"backref1", /*OP_BACKREF1*/
"backref2", /*OP_BACKREF2*/
"backrefn", /*OP_BACKREFN*/
"backrefn-ic", /*OP_BACKREFN_IC*/
"backref_multi", /*OP_BACKREF_MULTI*/
"backref_multi-ic", /*OP_BACKREF_MULTI_IC*/
"backref_at_level", /*OP_BACKREF_AT_LEVEL*/
"mem-start", /*OP_MEMORY_START*/
"mem-start-push", /*OP_MEMORY_START_PUSH*/
"mem-end-push", /*OP_MEMORY_END_PUSH*/
"mem-end-push-rec", /*OP_MEMORY_END_PUSH_REC*/
"mem-end", /*OP_MEMORY_END*/
"mem-end-rec", /*OP_MEMORY_END_REC*/
"fail", /*OP_FAIL*/
"jump", /*OP_JUMP*/
"push", /*OP_PUSH*/
"pop", /*OP_POP*/
"push-or-jump-e1", /*OP_PUSH_OR_JUMP_EXACT1*/
"push-if-peek-next", /*OP_PUSH_IF_PEEK_NEXT*/
"repeat", /*OP_REPEAT*/
"repeat-ng", /*OP_REPEAT_NG*/
"repeat-inc", /*OP_REPEAT_INC*/
"repeat-inc-ng", /*OP_REPEAT_INC_NG*/
"repeat-inc-sg", /*OP_REPEAT_INC_SG*/
"repeat-inc-ng-sg", /*OP_REPEAT_INC_NG_SG*/
"null-check-start", /*OP_NULL_CHECK_START*/
"null-check-end", /*OP_NULL_CHECK_END*/
"null-check-end-memst", /*OP_NULL_CHECK_END_MEMST*/
"null-check-end-memst-push", /*OP_NULL_CHECK_END_MEMST_PUSH*/
"push-pos", /*OP_PUSH_POS*/
"pop-pos", /*OP_POP_POS*/
"push-pos-not", /*OP_PUSH_POS_NOT*/
"fail-pos", /*OP_FAIL_POS*/
"push-stop-bt", /*OP_PUSH_STOP_BT*/
"pop-stop-bt", /*OP_POP_STOP_BT*/
"look-behind", /*OP_LOOK_BEHIND*/
"push-look-behind-not", /*OP_PUSH_LOOK_BEHIND_NOT*/
"fail-look-behind-not", /*OP_FAIL_LOOK_BEHIND_NOT*/
"call", /*OP_CALL*/
"return", /*OP_RETURN*/
"state-check-push", /*OP_STATE_CHECK_PUSH*/
"state-check-push-or-jump", /*OP_STATE_CHECK_PUSH_OR_JUMP*/
"state-check", /*OP_STATE_CHECK*/
"state-check-anychar*", /*OP_STATE_CHECK_ANYCHAR_STAR*/
"state-check-anychar-ml*", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
"set-option-push", /*OP_SET_OPTION_PUSH*/
"set-option", /*OP_SET_OPTION*/
// single byte versions
"anychar-sb", /*OP_ANYCHAR*/
"anychar-ml-sb", /*OP_ANYCHAR_ML*/
"anychar*-sb", /*OP_ANYCHAR_STAR*/
"anychar-ml*-sb", /*OP_ANYCHAR_ML_STAR*/
"anychar*-peek-next-sb", /*OP_ANYCHAR_STAR_PEEK_NEXT*/
"anychar-ml*-peek-next-sb", /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
"state-check-anychar*-sb", /*OP_STATE_CHECK_ANYCHAR_STAR*/
"state-check-anychar-ml*-sb", /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
"cclass-sb", /*OP_CCLASS*/
"cclass-not-sb", /*OP_CCLASS_NOT*/
"word-sb", /*OP_WORD*/
"not-word-sb", /*OP_NOT_WORD*/
"word-bound-sb", /*OP_WORD_BOUND*/
"not-word-bound-sb", /*OP_NOT_WORD_BOUND*/
"word-begin-sb", /*OP_WORD_BEGIN*/
"word-end-sb", /*OP_WORD_END*/
"look-behind-sb", /*OP_LOOK_BEHIND*/
"exact1-ic-sb", /*OP_EXACT1_IC*/
"exactn-ic-sb", /*OP_EXACTN_IC*/
};
private final static int OpCodeArgTypes[] = new int[] {
Arguments.NON, /*OP_FINISH*/
Arguments.NON, /*OP_END*/
Arguments.SPECIAL, /*OP_EXACT1*/
Arguments.SPECIAL, /*OP_EXACT2*/
Arguments.SPECIAL, /*OP_EXACT3*/
Arguments.SPECIAL, /*OP_EXACT4*/
Arguments.SPECIAL, /*OP_EXACT5*/
Arguments.SPECIAL, /*OP_EXACTN*/
Arguments.SPECIAL, /*OP_EXACTMB2N1*/
Arguments.SPECIAL, /*OP_EXACTMB2N2*/
Arguments.SPECIAL, /*OP_EXACTMB2N3*/
Arguments.SPECIAL, /*OP_EXACTMB2N*/
Arguments.SPECIAL, /*OP_EXACTMB3N*/
Arguments.SPECIAL, /*OP_EXACTMBN*/
Arguments.SPECIAL, /*OP_EXACT1_IC*/
Arguments.SPECIAL, /*OP_EXACTN_IC*/
Arguments.SPECIAL, /*OP_CCLASS*/
Arguments.SPECIAL, /*OP_CCLASS_MB*/
Arguments.SPECIAL, /*OP_CCLASS_MIX*/
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
Arguments.SPECIAL, /*OP_CCLASS_MB_NOT*/
Arguments.SPECIAL, /*OP_CCLASS_MIX_NOT*/
Arguments.SPECIAL, /*OP_CCLASS_NODE*/
Arguments.NON, /*OP_ANYCHAR*/
Arguments.NON, /*OP_ANYCHAR_ML*/
Arguments.NON, /*OP_ANYCHAR_STAR*/
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
Arguments.NON, /*OP_WORD*/
Arguments.NON, /*OP_NOT_WORD*/
Arguments.NON, /*OP_WORD_BOUND*/
Arguments.NON, /*OP_NOT_WORD_BOUND*/
Arguments.NON, /*OP_WORD_BEGIN*/
Arguments.NON, /*OP_WORD_END*/
Arguments.NON, /*OP_BEGIN_BUF*/
Arguments.NON, /*OP_END_BUF*/
Arguments.NON, /*OP_BEGIN_LINE*/
Arguments.NON, /*OP_END_LINE*/
Arguments.NON, /*OP_SEMI_END_BUF*/
Arguments.NON, /*OP_BEGIN_POSITION*/
Arguments.NON, /*OP_BACKREF1*/
Arguments.NON, /*OP_BACKREF2*/
Arguments.MEMNUM, /*OP_BACKREFN*/
Arguments.SPECIAL, /*OP_BACKREFN_IC*/
Arguments.SPECIAL, /*OP_BACKREF_MULTI*/
Arguments.SPECIAL, /*OP_BACKREF_MULTI_IC*/
Arguments.SPECIAL, /*OP_BACKREF_AT_LEVEL*/
Arguments.MEMNUM, /*OP_MEMORY_START*/
Arguments.MEMNUM, /*OP_MEMORY_START_PUSH*/
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH*/
Arguments.MEMNUM, /*OP_MEMORY_END_PUSH_REC*/
Arguments.MEMNUM, /*OP_MEMORY_END*/
Arguments.MEMNUM, /*OP_MEMORY_END_REC*/
Arguments.NON, /*OP_FAIL*/
Arguments.RELADDR, /*OP_JUMP*/
Arguments.RELADDR, /*OP_PUSH*/
Arguments.NON, /*OP_POP*/
Arguments.SPECIAL, /*OP_PUSH_OR_JUMP_EXACT1*/
Arguments.SPECIAL, /*OP_PUSH_IF_PEEK_NEXT*/
Arguments.SPECIAL, /*OP_REPEAT*/
Arguments.SPECIAL, /*OP_REPEAT_NG*/
Arguments.MEMNUM, /*OP_REPEAT_INC*/
Arguments.MEMNUM, /*OP_REPEAT_INC_NG*/
Arguments.MEMNUM, /*OP_REPEAT_INC_SG*/
Arguments.MEMNUM, /*OP_REPEAT_INC_NG_SG*/
Arguments.MEMNUM, /*OP_NULL_CHECK_START*/
Arguments.MEMNUM, /*OP_NULL_CHECK_END*/
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST*/
Arguments.MEMNUM, /*OP_NULL_CHECK_END_MEMST_PUSH*/
Arguments.NON, /*OP_PUSH_POS*/
Arguments.NON, /*OP_POP_POS*/
Arguments.RELADDR, /*OP_PUSH_POS_NOT*/
Arguments.NON, /*OP_FAIL_POS*/
Arguments.NON, /*OP_PUSH_STOP_BT*/
Arguments.NON, /*OP_POP_STOP_BT*/
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
Arguments.SPECIAL, /*OP_PUSH_LOOK_BEHIND_NOT*/
Arguments.NON, /*OP_FAIL_LOOK_BEHIND_NOT*/
Arguments.ABSADDR, /*OP_CALL*/
Arguments.NON, /*OP_RETURN*/
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH*/
Arguments.SPECIAL, /*OP_STATE_CHECK_PUSH_OR_JUMP*/
Arguments.STATE_CHECK, /*OP_STATE_CHECK*/
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
Arguments.OPTION, /*OP_SET_OPTION_PUSH*/
Arguments.OPTION, /*OP_SET_OPTION*/
// single byte versions
Arguments.NON, /*OP_ANYCHAR*/
Arguments.NON, /*OP_ANYCHAR_ML*/
Arguments.NON, /*OP_ANYCHAR_STAR*/
Arguments.NON, /*OP_ANYCHAR_ML_STAR*/
Arguments.SPECIAL, /*OP_ANYCHAR_STAR_PEEK_NEXT*/
Arguments.SPECIAL, /*OP_ANYCHAR_ML_STAR_PEEK_NEXT*/
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_STAR*/
Arguments.STATE_CHECK, /*OP_STATE_CHECK_ANYCHAR_ML_STAR*/
Arguments.SPECIAL, /*OP_CCLASS*/
Arguments.SPECIAL, /*OP_CCLASS_NOT*/
Arguments.NON, /*OP_WORD*/
Arguments.NON, /*OP_NOT_WORD*/
Arguments.NON, /*OP_WORD_BOUND*/
Arguments.NON, /*OP_NOT_WORD_BOUND*/
Arguments.NON, /*OP_WORD_BEGIN*/
Arguments.NON, /*OP_WORD_END*/
Arguments.SPECIAL, /*OP_LOOK_BEHIND*/
Arguments.SPECIAL, /*OP_EXACT1_IC*/
Arguments.SPECIAL, /*OP_EXACTN_IC*/
};
public ByteCodePrinter(Regex regex) { public ByteCodePrinter(Regex regex) {
code = regex.code; code = regex.code;
codeLength = regex.codeLength; codeLength = regex.codeLength;
...@@ -76,8 +309,8 @@ class ByteCodePrinter { ...@@ -76,8 +309,8 @@ class ByteCodePrinter {
CClassNode cc; CClassNode cc;
int tm, idx; int tm, idx;
sb.append("[" + OPCode.OpCodeNames[code[bp]]); sb.append("[" + OpCodeNames[code[bp]]);
int argType = OPCode.OpCodeArgTypes[code[bp]]; int argType = OpCodeArgTypes[code[bp]];
int ip = bp; int ip = bp;
if (argType != Arguments.SPECIAL) { if (argType != Arguments.SPECIAL) {
bp++; bp++;
......
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
public class CaptureTreeNode {
int group;
int beg;
int end;
// int allocated;
int numChildren;
CaptureTreeNode[]children;
CaptureTreeNode() {
beg = Region.REGION_NOTPOS;
end = Region.REGION_NOTPOS;
group = -1;
}
static final int HISTORY_TREE_INIT_ALLOC_SIZE = 8;
void addChild(CaptureTreeNode child) {
if (children == null) {
children = new CaptureTreeNode[HISTORY_TREE_INIT_ALLOC_SIZE];
} else if (numChildren >= children.length) {
CaptureTreeNode[]tmp = new CaptureTreeNode[children.length << 1];
System.arraycopy(children, 0, tmp, 0, children.length);
children = tmp;
}
children[numChildren] = child;
numChildren++;
}
void clear() {
for (int i=0; i<numChildren; i++) {
children[i] = null; // ???
}
numChildren = 0;
beg = end = Region.REGION_NOTPOS;
group = -1;
}
CaptureTreeNode cloneTree() {
CaptureTreeNode clone = new CaptureTreeNode();
clone.beg = beg;
clone.end = end;
for (int i=0; i<numChildren; i++) {
CaptureTreeNode child = children[i].cloneTree();
clone.addChild(child);
}
return clone;
}
}
...@@ -22,8 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni; ...@@ -22,8 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node; import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
...@@ -56,7 +54,7 @@ abstract class Compiler implements ErrorMessages { ...@@ -56,7 +54,7 @@ abstract class Compiler implements ErrorMessages {
private void compileStringRawNode(StringNode sn) { private void compileStringRawNode(StringNode sn) {
if (sn.length() <= 0) return; if (sn.length() <= 0) return;
addCompileString(sn.chars, sn.p, 1 /*sb*/, sn.length(), false); addCompileString(sn.chars, sn.p, sn.length(), false);
} }
private void compileStringNode(StringNode node) { private void compileStringNode(StringNode node) {
...@@ -76,17 +74,14 @@ abstract class Compiler implements ErrorMessages { ...@@ -76,17 +74,14 @@ abstract class Compiler implements ErrorMessages {
slen++; slen++;
p++; p++;
} }
addCompileString(chars, prev, 1, slen, ambig); addCompileString(chars, prev, slen, ambig);
} }
protected abstract void addCompileString(char[] chars, int p, int mbLength, int strLength, boolean ignoreCase); protected abstract void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase);
protected abstract void compileCClassNode(CClassNode node); protected abstract void compileCClassNode(CClassNode node);
protected abstract void compileCTypeNode(CTypeNode node);
protected abstract void compileAnyCharNode(); protected abstract void compileAnyCharNode();
protected abstract void compileCallNode(CallNode node);
protected abstract void compileBackrefNode(BackRefNode node); protected abstract void compileBackrefNode(BackRefNode node);
protected abstract void compileCECQuantifierNode(QuantifierNode node);
protected abstract void compileNonCECQuantifierNode(QuantifierNode node); protected abstract void compileNonCECQuantifierNode(QuantifierNode node);
protected abstract void compileOptionNode(EncloseNode node); protected abstract void compileOptionNode(EncloseNode node);
protected abstract void compileEncloseNode(EncloseNode node); protected abstract void compileEncloseNode(EncloseNode node);
...@@ -118,10 +113,6 @@ abstract class Compiler implements ErrorMessages { ...@@ -118,10 +113,6 @@ abstract class Compiler implements ErrorMessages {
compileCClassNode((CClassNode)node); compileCClassNode((CClassNode)node);
break; break;
case NodeType.CTYPE:
compileCTypeNode((CTypeNode)node);
break;
case NodeType.CANY: case NodeType.CANY:
compileAnyCharNode(); compileAnyCharNode();
break; break;
...@@ -130,19 +121,8 @@ abstract class Compiler implements ErrorMessages { ...@@ -130,19 +121,8 @@ abstract class Compiler implements ErrorMessages {
compileBackrefNode((BackRefNode)node); compileBackrefNode((BackRefNode)node);
break; break;
case NodeType.CALL:
if (Config.USE_SUBEXP_CALL) {
compileCallNode((CallNode)node);
break;
} // USE_SUBEXP_CALL
break;
case NodeType.QTFR: case NodeType.QTFR:
if (Config.USE_COMBINATION_EXPLOSION_CHECK) { compileNonCECQuantifierNode((QuantifierNode)node);
compileCECQuantifierNode((QuantifierNode)node);
} else {
compileNonCECQuantifierNode((QuantifierNode)node);
}
break; break;
case NodeType.ENCLOSE: case NodeType.ENCLOSE:
......
...@@ -31,10 +31,6 @@ public interface Config { ...@@ -31,10 +31,6 @@ public interface Config {
final int ENC_CASE_FOLD_DEFAULT = ENC_CASE_FOLD_MIN; final int ENC_CASE_FOLD_DEFAULT = ENC_CASE_FOLD_MIN;
final boolean USE_CRNL_AS_LINE_TERMINATOR = false; final boolean USE_CRNL_AS_LINE_TERMINATOR = false;
final boolean USE_NAMED_GROUP = true;
final boolean USE_SUBEXP_CALL = true;
final boolean USE_BACKREF_WITH_LEVEL = true; /* \k<name+n>, \k<name-n> */
final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */ final boolean USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT = true; /* /(?:()|())*\2/ */
final boolean USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE = true; /* /\n$/ =~ "\n" */ final boolean USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE = true; /* /\n$/ =~ "\n" */
final boolean USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR = false; final boolean USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR = false;
...@@ -42,12 +38,10 @@ public interface Config { ...@@ -42,12 +38,10 @@ public interface Config {
final boolean CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS = true; final boolean CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS = true;
final boolean USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE = false; final boolean USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE = false;
final boolean USE_CAPTURE_HISTORY = false;
final boolean USE_VARIABLE_META_CHARS = true; final boolean USE_VARIABLE_META_CHARS = true;
final boolean USE_WORD_BEGIN_END = true; /* "\<": word-begin, "\>": word-end */ 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_POSIX_API_REGION_OPTION = false; /* needed for POSIX API support */
final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true; final boolean USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE = true;
final boolean USE_COMBINATION_EXPLOSION_CHECK = false;
final int NREGION = 10; final int NREGION = 10;
final int MAX_BACKREF_NUM = 1000; final int MAX_BACKREF_NUM = 1000;
...@@ -73,13 +67,6 @@ public interface Config { ...@@ -73,13 +67,6 @@ public interface Config {
final boolean USE_STRING_TEMPLATES = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array final boolean USE_STRING_TEMPLATES = true; // use embeded string templates in Regex object as byte arrays instead of compiling them into int bytecode array
final int MAX_CAPTURE_HISTORY_GROUP = 31;
final int CHECK_STRING_THRESHOLD_LEN = 7;
final int CHECK_BUFF_MAX_SIZE = 0x4000;
final boolean NON_UNICODE_SDW = true; final boolean NON_UNICODE_SDW = true;
...@@ -95,6 +82,4 @@ public interface Config { ...@@ -95,6 +82,4 @@ public interface Config {
final boolean DEBUG_COMPILE_BYTE_CODE_INFO = DEBUG_ALL; final boolean DEBUG_COMPILE_BYTE_CODE_INFO = DEBUG_ALL;
final boolean DEBUG_SEARCH = DEBUG_ALL; final boolean DEBUG_SEARCH = DEBUG_ALL;
final boolean DEBUG_MATCH = DEBUG_ALL; final boolean DEBUG_MATCH = DEBUG_ALL;
final boolean DEBUG_ASM = true;
final boolean DEBUG_ASM_EXEC = true;
} }
...@@ -95,20 +95,6 @@ public class EncodingHelper { ...@@ -95,20 +95,6 @@ public class EncodingHelper {
return s; return s;
} }
/* onigenc_with_ascii_strncmp */
public static int strNCmp(char[] chars1, int p1, int end, char[] chars2, int p2, int n) {
while (n-- > 0) {
if (p1 >= end) return chars2[p2];
int c = chars1[p1];
int x = chars2[p2] - c;
if (x != 0) return x;
p2++;
p1++;
}
return 0;
}
public static int mbcToCode(byte[] bytes, int p, int end) { public static int mbcToCode(byte[] bytes, int p, int end) {
int code = 0; int code = 0;
for (int i = p; i < end; i++) { for (int i = p; i < end; i++) {
......
...@@ -27,10 +27,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; ...@@ -27,10 +27,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar; import jdk.nashorn.internal.runtime.regexp.joni.constants.MetaChar;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TokenType; import jdk.nashorn.internal.runtime.regexp.joni.constants.TokenType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType; import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
class Lexer extends ScannerSupport { class Lexer extends ScannerSupport {
protected final ScanEnvironment env; protected final ScanEnvironment env;
...@@ -215,198 +212,6 @@ class Lexer extends ScannerSupport { ...@@ -215,198 +212,6 @@ class Lexer extends ScannerSupport {
\k<-num+n>, \k<-num-n> \k<-num+n>, \k<-num-n>
*/ */
// value implicit (rnameEnd)
private boolean fetchNameWithLevel(int startCode, Ptr rbackNum, Ptr rlevel) {
int src = p;
boolean existLevel = false;
int isNum = 0;
int sign = 1;
int endCode = nameEndCodePoint(startCode);
int pnumHead = p;
int nameEnd = stop;
String err = null;
if (!left()) {
newValueException(ERR_EMPTY_GROUP_NAME);
} else {
fetch();
if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
if (Character.isDigit(c)) {
isNum = 1;
} else if (c == '-') {
isNum = 2;
sign = -1;
pnumHead = p;
} else if (!EncodingHelper.isWord(c)) {
err = ERR_INVALID_GROUP_NAME;
}
}
while (left()) {
nameEnd = p;
fetch();
if (c == endCode || c == ')' || c == '+' || c == '-') {
if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
break;
}
if (isNum != 0) {
if (EncodingHelper.isDigit(c)) {
isNum = 1;
} else {
err = ERR_INVALID_GROUP_NAME;
// isNum = 0;
}
} else if (!EncodingHelper.isWord(c)) {
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
}
}
boolean isEndCode = false;
if (err == null && c != endCode) {
if (c == '+' || c == '-') {
int flag = c == '-' ? -1 : 1;
fetch();
if (!EncodingHelper.isDigit(c)) newValueException(ERR_INVALID_GROUP_NAME, src, stop);
unfetch();
int level = scanUnsignedNumber();
if (level < 0) newValueException(ERR_TOO_BIG_NUMBER);
rlevel.p = level * flag;
existLevel = true;
fetch();
isEndCode = c == endCode;
}
if (!isEndCode) {
err = ERR_INVALID_GROUP_NAME;
nameEnd = stop;
}
}
if (err == null) {
if (isNum != 0) {
mark();
p = pnumHead;
int backNum = scanUnsignedNumber();
restore();
if (backNum < 0) {
newValueException(ERR_TOO_BIG_NUMBER);
} else if (backNum == 0) {
newValueException(ERR_INVALID_GROUP_NAME, src, stop);
}
rbackNum.p = backNum * sign;
}
value = nameEnd;
return existLevel;
} else {
newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
return false; // not reached
}
}
// USE_NAMED_GROUP
// ref: 0 -> define name (don't allow number name)
// 1 -> reference name (allow number name)
private int fetchNameForNamedGroup(int startCode, boolean ref) {
int src = p;
value = 0;
int isNum = 0;
int sign = 1;
int endCode = nameEndCodePoint(startCode);
int pnumHead = p;
int nameEnd = stop;
String err = null;
if (!left()) {
newValueException(ERR_EMPTY_GROUP_NAME);
} else {
fetch();
if (c == endCode) newValueException(ERR_EMPTY_GROUP_NAME);
if (EncodingHelper.isDigit(c)) {
if (ref) {
isNum = 1;
} else {
err = ERR_INVALID_GROUP_NAME;
// isNum = 0;
}
} else if (c == '-') {
if (ref) {
isNum = 2;
sign = -1;
pnumHead = p;
} else {
err = ERR_INVALID_GROUP_NAME;
// isNum = 0;
}
} else if (!EncodingHelper.isWord(c)) {
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
}
}
if (err == null) {
while (left()) {
nameEnd = p;
fetch();
if (c == endCode || c == ')') {
if (isNum == 2) err = ERR_INVALID_GROUP_NAME;
break;
}
if (isNum != 0) {
if (EncodingHelper.isDigit(c)) {
isNum = 1;
} else {
if (!EncodingHelper.isWord(c)) {
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
} else {
err = ERR_INVALID_GROUP_NAME;
}
// isNum = 0;
}
} else {
if (!EncodingHelper.isWord(c)) {
err = ERR_INVALID_CHAR_IN_GROUP_NAME;
}
}
}
if (c != endCode) {
err = ERR_INVALID_GROUP_NAME;
nameEnd = stop;
}
int backNum = 0;
if (isNum != 0) {
mark();
p = pnumHead;
backNum = scanUnsignedNumber();
restore();
if (backNum < 0) {
newValueException(ERR_TOO_BIG_NUMBER);
} else if (backNum == 0) {
newValueException(ERR_INVALID_GROUP_NAME, src, nameEnd);
}
backNum *= sign;
}
value = nameEnd;
return backNum;
} else {
while (left()) {
nameEnd = p;
fetch();
if (c == endCode || c == ')') break;
}
if (!left()) nameEnd = stop;
newValueException(err, src, nameEnd);
return 0; // not reached
}
}
// #else USE_NAMED_GROUP // #else USE_NAMED_GROUP
// make it return nameEnd! // make it return nameEnd!
private final int fetchNameForNoNamedGroup(int startCode, boolean ref) { private final int fetchNameForNoNamedGroup(int startCode, boolean ref) {
...@@ -472,11 +277,7 @@ class Lexer extends ScannerSupport { ...@@ -472,11 +277,7 @@ class Lexer extends ScannerSupport {
} }
protected final int fetchName(int startCode, boolean ref) { protected final int fetchName(int startCode, boolean ref) {
if (Config.USE_NAMED_GROUP) { return fetchNameForNoNamedGroup(startCode, ref);
return fetchNameForNamedGroup(startCode, ref);
} else {
return fetchNameForNoNamedGroup(startCode, ref);
}
} }
private boolean strExistCheckWithEsc(int[]s, int n, int bad) { private boolean strExistCheckWithEsc(int[]s, int n, int bad) {
...@@ -519,26 +320,6 @@ class Lexer extends ScannerSupport { ...@@ -519,26 +320,6 @@ class Lexer extends ScannerSupport {
token.setPropNot(flag); token.setPropNot(flag);
} }
private void fetchTokenInCCFor_p() {
int c2 = peek(); // !!! migrate to peekIs
if (c2 == '{' && syntax.op2EscPBraceCharProperty()) {
inc();
token.type = TokenType.CHAR_PROPERTY;
token.setPropNot(c == 'P');
if (syntax.op2EscPBraceCircumflexNot()) {
c2 = fetchTo();
if (c2 == '^') {
token.setPropNot(!token.getPropNot());
} else {
unfetch();
}
}
} else {
syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
}
}
private void fetchTokenInCCFor_x() { private void fetchTokenInCCFor_x() {
if (!left()) return; if (!left()) return;
int last = p; int last = p;
...@@ -604,30 +385,6 @@ class Lexer extends ScannerSupport { ...@@ -604,30 +385,6 @@ class Lexer extends ScannerSupport {
} }
} }
private void fetchTokenInCCFor_posixBracket() {
if (syntax.opPosixBracket() && peekIs(':')) {
token.backP = p; /* point at '[' is readed */
inc();
if (strExistCheckWithEsc(send, send.length, ']')) {
token.type = TokenType.POSIX_BRACKET_OPEN;
} else {
unfetch();
// remove duplication, goto cc_in_cc;
if (syntax.op2CClassSetOp()) {
token.type = TokenType.CC_CC_OPEN;
} else {
env.ccEscWarn("[");
}
}
} else { // cc_in_cc:
if (syntax.op2CClassSetOp()) {
token.type = TokenType.CC_CC_OPEN;
} else {
env.ccEscWarn("[");
}
}
}
private void fetchTokenInCCFor_and() { private void fetchTokenInCCFor_and() {
if (syntax.op2CClassSetOp() && left() && peekIs('&')) { if (syntax.op2CClassSetOp() && left() && peekIs('&')) {
inc(); inc();
...@@ -683,10 +440,6 @@ class Lexer extends ScannerSupport { ...@@ -683,10 +440,6 @@ class Lexer extends ScannerSupport {
case 'H': case 'H':
if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT); if (syntax.op2EscHXDigit()) fetchTokenInCCFor_charType(true, CharacterType.XDIGIT);
break; break;
case 'p':
case 'P':
fetchTokenInCCFor_p();
break;
case 'x': case 'x':
fetchTokenInCCFor_x(); fetchTokenInCCFor_x();
break; break;
...@@ -714,18 +467,12 @@ class Lexer extends ScannerSupport { ...@@ -714,18 +467,12 @@ class Lexer extends ScannerSupport {
break; break;
} // switch } // switch
} else if (c == '[') {
fetchTokenInCCFor_posixBracket();
} else if (c == '&') { } else if (c == '&') {
fetchTokenInCCFor_and(); fetchTokenInCCFor_and();
} }
return token.type; return token.type;
} }
protected final int backrefRelToAbs(int relNo) {
return env.numMem + 1 + relNo;
}
private void fetchTokenFor_repeat(int lower, int upper) { private void fetchTokenFor_repeat(int lower, int upper) {
token.type = TokenType.OP_REPEAT; token.type = TokenType.OP_REPEAT;
token.setRepeatLower(lower); token.setRepeatLower(lower);
...@@ -815,7 +562,6 @@ class Lexer extends ScannerSupport { ...@@ -815,7 +562,6 @@ class Lexer extends ScannerSupport {
token.setBackrefNum(1); token.setBackrefNum(1);
token.setBackrefRef1(num); token.setBackrefRef1(num);
token.setBackrefByName(false); token.setBackrefByName(false);
if (Config.USE_BACKREF_WITH_LEVEL) token.setBackrefExistLevel(false);
return; return;
} }
...@@ -845,76 +591,6 @@ class Lexer extends ScannerSupport { ...@@ -845,76 +591,6 @@ class Lexer extends ScannerSupport {
} }
} }
private void fetchTokenFor_namedBackref() {
if (syntax.op2EscKNamedBackref()) {
if (left()) {
fetch();
if (c =='<' || c == '\'') {
int last = p;
int backNum;
if (Config.USE_BACKREF_WITH_LEVEL) {
Ptr rbackNum = new Ptr();
Ptr rlevel = new Ptr();
token.setBackrefExistLevel(fetchNameWithLevel(c, rbackNum, rlevel));
token.setBackrefLevel(rlevel.p);
backNum = rbackNum.p;
} else {
backNum = fetchName(c, true);
} // USE_BACKREF_AT_LEVEL
int nameEnd = value; // set by fetchNameWithLevel/fetchName
if (backNum != 0) {
if (backNum < 0) {
backNum = backrefRelToAbs(backNum);
if (backNum <= 0) newValueException(ERR_INVALID_BACKREF);
}
if (syntax.strictCheckBackref() && (backNum > env.numMem || env.memNodes == null)) {
newValueException(ERR_INVALID_BACKREF);
}
token.type = TokenType.BACKREF;
token.setBackrefByName(false);
token.setBackrefNum(1);
token.setBackrefRef1(backNum);
} else {
NameEntry e = env.reg.nameToGroupNumbers(chars, last, nameEnd);
if (e == null) newValueException(ERR_UNDEFINED_NAME_REFERENCE, last, nameEnd);
if (syntax.strictCheckBackref()) {
if (e.backNum == 1) {
if (e.backRef1 > env.numMem ||
env.memNodes == null ||
env.memNodes[e.backRef1] == null) newValueException(ERR_INVALID_BACKREF);
} else {
for (int i=0; i<e.backNum; i++) {
if (e.backRefs[i] > env.numMem ||
env.memNodes == null ||
env.memNodes[e.backRefs[i]] == null) newValueException(ERR_INVALID_BACKREF);
}
}
}
token.type = TokenType.BACKREF;
token.setBackrefByName(true);
if (e.backNum == 1) {
token.setBackrefNum(1);
token.setBackrefRef1(e.backRef1);
} else {
token.setBackrefNum(e.backNum);
token.setBackrefRefs(e.backRefs);
}
}
} else {
unfetch();
syntaxWarn(Warnings.INVALID_BACKREFERENCE);
}
} else {
syntaxWarn(Warnings.INVALID_BACKREFERENCE);
}
}
}
private void fetchTokenFor_subexpCall() { private void fetchTokenFor_subexpCall() {
if (syntax.op2EscGSubexpCall()) { if (syntax.op2EscGSubexpCall()) {
if (left()) { if (left()) {
...@@ -937,25 +613,6 @@ class Lexer extends ScannerSupport { ...@@ -937,25 +613,6 @@ class Lexer extends ScannerSupport {
} }
} }
private void fetchTokenFor_charProperty() {
if (peekIs('{') && syntax.op2EscPBraceCharProperty()) {
inc();
token.type = TokenType.CHAR_PROPERTY;
token.setPropNot(c == 'P');
if (syntax.op2EscPBraceCircumflexNot()) {
fetch();
if (c == '^') {
token.setPropNot(!token.getPropNot());
} else {
unfetch();
}
}
} else {
syntaxWarn(Warnings.INVALID_UNICODE_PROPERTY, (char)c);
}
}
private void fetchTokenFor_metaChars() { private void fetchTokenFor_metaChars() {
if (c == syntax.metaCharTable.anyChar) { if (c == syntax.metaCharTable.anyChar) {
token.type = TokenType.ANYCHAR; token.type = TokenType.ANYCHAR;
...@@ -1091,19 +748,6 @@ class Lexer extends ScannerSupport { ...@@ -1091,19 +748,6 @@ class Lexer extends ScannerSupport {
case '0': case '0':
fetchTokenFor_zero(); fetchTokenFor_zero();
break; break;
case 'k':
if (Config.USE_NAMED_GROUP) fetchTokenFor_namedBackref();
break;
case 'g':
if (Config.USE_SUBEXP_CALL) fetchTokenFor_subexpCall();
break;
case 'Q':
if (syntax.op2EscCapitalQQuote()) token.type = TokenType.QUOTE_OPEN;
break;
case 'p':
case 'P':
fetchTokenFor_charProperty();
break;
default: default:
unfetch(); unfetch();
...@@ -1244,24 +888,6 @@ class Lexer extends ScannerSupport { ...@@ -1244,24 +888,6 @@ class Lexer extends ScannerSupport {
} }
} }
protected final int fetchCharPropertyToCType() {
mark();
while (left()) {
int last = p;
fetch();
if (c == '}') {
String name = new String(chars, _p, last - _p);
return PosixBracket.propertyNameToCType(name);
} else if (c == '(' || c == ')' || c == '{' || c == '|') {
String name = new String(chars, _p, last - _p);
throw new JOniException(ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
}
}
newInternalException(ERR_PARSER_BUG);
return 0; // not reached
}
protected final void syntaxWarn(String message, char c) { protected final void syntaxWarn(String message, char c) {
syntaxWarn(message.replace("<%n>", Character.toString(c))); syntaxWarn(message.replace("<%n>", Character.toString(c)));
} }
......
...@@ -58,17 +58,10 @@ public abstract class Matcher extends IntHolder { ...@@ -58,17 +58,10 @@ public abstract class Matcher extends IntHolder {
// main matching method // main matching method
protected abstract int matchAt(int range, int sstart, int sprev); protected abstract int matchAt(int range, int sstart, int sprev);
protected abstract void stateCheckBuffInit(int strLength, int offset, int stateNum);
protected abstract void stateCheckBuffClear();
public final Region getRegion() { public final Region getRegion() {
return msaRegion; return msaRegion;
} }
public final Region getEagerRegion() {
return msaRegion != null ? msaRegion : new Region(msaBegin, msaEnd);
}
public final int getBegin() { public final int getBegin() {
return msaBegin; return msaBegin;
} }
...@@ -86,11 +79,6 @@ public abstract class Matcher extends IntHolder { ...@@ -86,11 +79,6 @@ public abstract class Matcher extends IntHolder {
public final int match(int at, int range, int option) { public final int match(int at, int range, int option) {
msaInit(option, at); msaInit(option, at);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
int offset = at = str;
stateCheckBuffInit(end - str, offset, regex.numCombExpCheck); // move it to construction?
} // USE_COMBINATION_EXPLOSION_CHECK
int prev = EncodingHelper.prevCharHead(str, at); int prev = EncodingHelper.prevCharHead(str, at);
if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) { if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
...@@ -377,8 +365,6 @@ public abstract class Matcher extends IntHolder { ...@@ -377,8 +365,6 @@ public abstract class Matcher extends IntHolder {
prev = -1; prev = -1;
msaInit(option, start); msaInit(option, start);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) stateCheckBuffClear();
if (matchCheck(end, s, prev)) return match(s); if (matchCheck(end, s, prev)) return match(s);
return mismatch(); return mismatch();
} }
...@@ -393,10 +379,6 @@ public abstract class Matcher extends IntHolder { ...@@ -393,10 +379,6 @@ public abstract class Matcher extends IntHolder {
} }
msaInit(option, origStart); msaInit(option, origStart);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
int offset = Math.min(start, range) - str;
stateCheckBuffInit(end - str, offset, regex.numCombExpCheck);
}
s = start; s = start;
if (range > start) { /* forward search */ if (range > start) { /* forward search */
......
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
public final class NameEntry {
static final int INIT_NAME_BACKREFS_ALLOC_NUM = 8;
public final char[] name;
public final int nameP;
public final int nameEnd;
int backNum;
int backRef1;
int backRefs[];
public NameEntry(char[] chars, int p, int end) {
name = chars;
nameP = p;
nameEnd = end;
}
public int[] getBackRefs() {
switch (backNum) {
case 0:
return new int[]{};
case 1:
return new int[]{backRef1};
default:
int[]result = new int[backNum];
System.arraycopy(backRefs, 0, result, 0, backNum);
return result;
}
}
private void alloc() {
backRefs = new int[INIT_NAME_BACKREFS_ALLOC_NUM];
}
private void ensureSize() {
if (backNum > backRefs.length) {
int[]tmp = new int[backRefs.length << 1];
System.arraycopy(backRefs, 0, tmp, 0, backRefs.length);
backRefs = tmp;
}
}
public void addBackref(int backRef) {
backNum++;
switch (backNum) {
case 1:
backRef1 = backRef;
break;
case 2:
alloc();
backRefs[0] = backRef1;
backRefs[1] = backRef;
break;
default:
ensureSize();
backRefs[backNum - 1] = backRef;
}
}
public String toString() {
StringBuilder buff = new StringBuilder(new String(name, nameP, nameEnd - nameP) + " ");
if (backNum == 0) {
buff.append("-");
} else if (backNum == 1){
buff.append(backRef1);
} else {
for (int i=0; i<backNum; i++){
if (i > 0) buff.append(", ");
buff.append(backRefs[i]);
}
}
return buff.toString();
}
}
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
public abstract class NativeMachine extends Matcher {
protected NativeMachine(Regex regex, char[] chars, int p, int end) {
super(regex, chars, p, end);
}
}
...@@ -19,20 +19,15 @@ ...@@ -19,20 +19,15 @@
*/ */
package jdk.nashorn.internal.runtime.regexp.joni; package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnAtSimple;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff; import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsOnOff;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isIgnoreCase;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType; import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.PosixBracket;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.Ptr;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.AnyCharNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CTypeNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.CallNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.ConsAltNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode; import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node; import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
...@@ -66,65 +61,6 @@ class Parser extends Lexer { ...@@ -66,65 +61,6 @@ class Parser extends Lexer {
return root; return root;
} }
private static final int POSIX_BRACKET_NAME_MIN_LEN = 4;
private static final int POSIX_BRACKET_CHECK_LIMIT_LENGTH = 20;
private static final char BRACKET_END[] = ":]".toCharArray();
private boolean parsePosixBracket(CClassNode cc) {
mark();
boolean not;
if (peekIs('^')) {
inc();
not = true;
} else {
not = false;
}
if (stop - p >= POSIX_BRACKET_NAME_MIN_LEN + 3) { // else goto not_posix_bracket
char[][] pbs = PosixBracket.PBSNamesLower;
for (int i=0; i<pbs.length; i++) {
char[] name = pbs[i];
// hash lookup here ?
if (EncodingHelper.strNCmp(chars, p, stop, name, 0, name.length) == 0) {
p += name.length;
if (EncodingHelper.strNCmp(chars, p, stop, BRACKET_END, 0, BRACKET_END.length) != 0) {
newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
}
cc.addCType(PosixBracket.PBSValues[i], not, env, this);
inc();
inc();
return false;
}
}
}
// not_posix_bracket:
c = 0;
int i= 0;
while (left() && ((c=peek()) != ':') && c != ']') {
inc();
if (++i > POSIX_BRACKET_CHECK_LIMIT_LENGTH) break;
}
if (c == ':' && left()) {
inc();
if (left()) {
fetch();
if (c == ']') newSyntaxException(ERR_INVALID_POSIX_BRACKET_TYPE);
}
}
restore();
return true; /* 1: is not POSIX bracket, but no error. */
}
private CClassNode parseCharProperty() {
int ctype = fetchCharPropertyToCType();
CClassNode n = new CClassNode();
n.addCType(ctype, false, env, this);
if (token.getPropNot()) n.setNot();
return n;
}
private boolean codeExistCheck(int code, boolean ignoreEscaped) { private boolean codeExistCheck(int code, boolean ignoreEscaped) {
mark(); mark();
...@@ -225,29 +161,11 @@ class Parser extends Lexer { ...@@ -225,29 +161,11 @@ class Parser extends Lexer {
parseCharClassValEntry(cc, arg); // val_entry:, val_entry2 parseCharClassValEntry(cc, arg); // val_entry:, val_entry2
break; break;
case POSIX_BRACKET_OPEN:
if (parsePosixBracket(cc)) { /* true: is not POSIX bracket */
env.ccEscWarn("[");
p = token.backP;
arg.v = token.getC();
arg.vIsRaw = false;
parseCharClassValEntry(cc, arg); // goto val_entry
break;
}
cc.nextStateClass(arg, env); // goto next_class
break;
case CHAR_TYPE: case CHAR_TYPE:
cc.addCType(token.getPropCType(), token.getPropNot(), env, this); cc.addCType(token.getPropCType(), token.getPropNot(), env, this);
cc.nextStateClass(arg, env); // next_class: cc.nextStateClass(arg, env); // next_class:
break; break;
case CHAR_PROPERTY:
int ctype = fetchCharPropertyToCType();
cc.addCType(ctype, token.getPropNot(), env, this);
cc.nextStateClass(arg, env); // goto next_class
break;
case CC_RANGE: case CC_RANGE:
if (arg.state == CCSTATE.VALUE) { if (arg.state == CCSTATE.VALUE) {
fetchTokenInCC(); fetchTokenInCC();
...@@ -413,15 +331,6 @@ class Parser extends Lexer { ...@@ -413,15 +331,6 @@ class Parser extends Lexer {
node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose node = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
break; break;
case '\'': case '\'':
if (Config.USE_NAMED_GROUP) {
if (syntax.op2QMarkLtNamedGroup()) {
listCapture = false; // goto named_group1
node = parseEncloseNamedGroup2(listCapture);
break;
} else {
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
}
} // USE_NAMED_GROUP
break; break;
case '<': /* look behind (?<=...), (?<!...) */ case '<': /* look behind (?<=...), (?<!...) */
fetch(); fetch();
...@@ -430,36 +339,12 @@ class Parser extends Lexer { ...@@ -430,36 +339,12 @@ class Parser extends Lexer {
} else if (c == '!') { } else if (c == '!') {
node = new AnchorNode(AnchorType.LOOK_BEHIND_NOT); node = new AnchorNode(AnchorType.LOOK_BEHIND_NOT);
} else { } else {
if (Config.USE_NAMED_GROUP) { newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
if (syntax.op2QMarkLtNamedGroup()) {
unfetch();
c = '<';
listCapture = false; // named_group1:
node = parseEncloseNamedGroup2(listCapture); // named_group2:
break;
} else {
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
}
} else { // USE_NAMED_GROUP
newSyntaxException(ERR_UNDEFINED_GROUP_OPTION);
} // USE_NAMED_GROUP
} }
break; break;
case '@': case '@':
if (syntax.op2AtMarkCaptureHistory()) { if (syntax.op2AtMarkCaptureHistory()) {
if (Config.USE_NAMED_GROUP) { EncloseNode en = new EncloseNode(); // node_new_enclose_memory
if (syntax.op2QMarkLtNamedGroup()) {
fetch();
if (c == '<' || c == '\'') {
listCapture = true;
node = parseEncloseNamedGroup2(listCapture); // goto named_group2 /* (?@<name>...) */
}
unfetch();
}
} // USE_NAMED_GROUP
EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory
int num = env.addMemEntry(); int num = env.addMemEntry();
if (num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY); if (num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
en.regNum = num; en.regNum = num;
...@@ -546,7 +431,7 @@ class Parser extends Lexer { ...@@ -546,7 +431,7 @@ class Parser extends Lexer {
returnCode = 1; /* group */ returnCode = 1; /* group */
return node; return node;
} }
EncloseNode en = new EncloseNode(env.option, false); // node_new_enclose_memory EncloseNode en = new EncloseNode(); // node_new_enclose_memory
int num = env.addMemEntry(); int num = env.addMemEntry();
en.regNum = num; en.regNum = num;
node = en; node = en;
...@@ -570,48 +455,6 @@ class Parser extends Lexer { ...@@ -570,48 +455,6 @@ class Parser extends Lexer {
return node; // ?? return node; // ??
} }
private Node parseEncloseNamedGroup2(boolean listCapture) {
int nm = p;
int num = fetchName(c, false);
int nameEnd = value;
num = env.addMemEntry();
if (listCapture && num >= BitStatus.BIT_STATUS_BITS_NUM) newValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
regex.nameAdd(chars, nm, nameEnd, num, syntax);
EncloseNode en = new EncloseNode(env.option, true); // node_new_enclose_memory
en.regNum = num;
Node node = en;
if (listCapture) env.captureHistory = bsOnAtSimple(env.captureHistory, num);
env.numNamed++;
return node;
}
private int findStrPosition(int[]s, int n, int from, int to, Ptr nextChar) {
int x;
int q;
int p = from;
int i = 0;
while (p < to) {
x = chars[p];
q = p + 1;
if (x == s[0]) {
for (i=1; i<n && q<to; i++) {
x = chars[q];
if (x != s[i]) break;
q++;
}
if (i >= n) {
if (chars[nextChar.p] != 0) nextChar.p = q; // we may need zero term semantics...
return p;
}
}
p = q;
}
return -1;
}
private Node parseExp(TokenType term) { private Node parseExp(TokenType term) {
if (token.type == term) return StringNode.EMPTY; // goto end_of_token if (token.type == term) return StringNode.EMPTY; // goto end_of_token
...@@ -656,16 +499,6 @@ class Parser extends Lexer { ...@@ -656,16 +499,6 @@ class Parser extends Lexer {
node = new StringNode(buf, 0, 1); node = new StringNode(buf, 0, 1);
break; break;
case QUOTE_OPEN:
int[] endOp = new int[] {syntax.metaCharTable.esc, 'E'};
int qstart = p;
Ptr nextChar = new Ptr();
int qend = findStrPosition(endOp, endOp.length, qstart, stop, nextChar);
if (qend == -1) nextChar.p = qend = stop;
node = new StringNode(chars, qstart, qend);
p = nextChar.p;
break;
case CHAR_TYPE: case CHAR_TYPE:
switch(token.getPropCType()) { switch(token.getPropCType()) {
case CharacterType.D: case CharacterType.D:
...@@ -679,10 +512,6 @@ class Parser extends Lexer { ...@@ -679,10 +512,6 @@ class Parser extends Lexer {
} }
break; break;
case CharacterType.WORD:
node = new CTypeNode(token.getPropCType(), token.getPropNot());
break;
case CharacterType.SPACE: case CharacterType.SPACE:
case CharacterType.DIGIT: case CharacterType.DIGIT:
case CharacterType.XDIGIT: case CharacterType.XDIGIT:
...@@ -699,10 +528,6 @@ class Parser extends Lexer { ...@@ -699,10 +528,6 @@ class Parser extends Lexer {
} // inner switch } // inner switch
break; break;
case CHAR_PROPERTY:
node = parseCharProperty();
break;
case CC_CC_OPEN: case CC_CC_OPEN:
CClassNode cc = parseCharClass(); CClassNode cc = parseCharClass();
node = cc; node = cc;
...@@ -735,20 +560,6 @@ class Parser extends Lexer { ...@@ -735,20 +560,6 @@ class Parser extends Lexer {
token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL token.getBackrefExistLevel(), // #ifdef USE_BACKREF_AT_LEVEL
token.getBackrefLevel(), // ... token.getBackrefLevel(), // ...
env); env);
break;
case CALL:
if (Config.USE_SUBEXP_CALL) {
int gNum = token.getCallGNum();
if (gNum < 0) {
gNum = backrefRelToAbs(gNum);
if (gNum <= 0) newValueException(ERR_INVALID_BACKREF);
}
node = new CallNode(chars, token.getCallNameP(), token.getCallNameEnd(), gNum);
env.numCall++;
} // USE_SUBEXP_CALL
break; break;
case ANCHOR: case ANCHOR:
......
...@@ -23,9 +23,11 @@ import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; ...@@ -23,9 +23,11 @@ import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isCaptureGroup;
import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup; import static jdk.nashorn.internal.runtime.regexp.joni.Option.isDontCaptureGroup;
import java.nio.file.Files;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType; import jdk.nashorn.internal.runtime.regexp.joni.constants.AnchorType;
import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState; import jdk.nashorn.internal.runtime.regexp.joni.constants.RegexState;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
...@@ -44,7 +46,6 @@ public final class Regex implements RegexState { ...@@ -44,7 +46,6 @@ public final class Regex implements RegexState {
int numMem; /* used memory(...) num counted from 1 */ int numMem; /* used memory(...) num counted from 1 */
int numRepeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */ int numRepeat; /* OP_REPEAT/OP_REPEAT_NG id-counter */
int numNullCheck; /* OP_NULL_CHECK_START/END id counter */ int numNullCheck; /* OP_NULL_CHECK_START/END id counter */
int numCombExpCheck; /* combination explosion check */
int numCall; /* number of subexp call */ int numCall; /* number of subexp call */
int captureHistory; /* (?@...) flag (1-31) */ int captureHistory; /* (?@...) flag (1-31) */
int btMemStart; /* need backtrack flag */ int btMemStart; /* need backtrack flag */
...@@ -57,7 +58,7 @@ public final class Regex implements RegexState { ...@@ -57,7 +58,7 @@ public final class Regex implements RegexState {
WarnCallback warnings; WarnCallback warnings;
MatcherFactory factory; MatcherFactory factory;
private Analyser analyser; protected Analyser analyser;
int options; int options;
int userOptions; int userOptions;
...@@ -65,8 +66,6 @@ public final class Regex implements RegexState { ...@@ -65,8 +66,6 @@ public final class Regex implements RegexState {
//final Syntax syntax; //final Syntax syntax;
final int caseFoldFlag; final int caseFoldFlag;
HashMap<String,NameEntry> nameTable; // named entries
/* optimization info (string search, char-map and anchors) */ /* optimization info (string search, char-map and anchors) */
SearchAlgorithm searchAlgorithm; /* optimize flag */ SearchAlgorithm searchAlgorithm; /* optimize flag */
int thresholdLength; /* search str-length for apply optimize */ int thresholdLength; /* search str-length for apply optimize */
...@@ -172,112 +171,6 @@ public final class Regex implements RegexState { ...@@ -172,112 +171,6 @@ public final class Regex implements RegexState {
return numMem; return numMem;
} }
public int numberOfCaptureHistories() {
if (Config.USE_CAPTURE_HISTORY) {
int n = 0;
for (int i=0; i<=Config.MAX_CAPTURE_HISTORY_GROUP; i++) {
if (bsAt(captureHistory, i)) n++;
}
return n;
} else {
return 0;
}
}
String nameTableToString() {
StringBuilder sb = new StringBuilder();
if (nameTable != null) {
sb.append("name table\n");
for (NameEntry ne : nameTable.values()) {
sb.append(" " + ne + "\n");
}
sb.append("\n");
}
return sb.toString();
}
NameEntry nameFind(char[] name, int nameP, int nameEnd) {
if (nameTable != null) return nameTable.get(new String(name, nameP, nameEnd - nameP));
return null;
}
void renumberNameTable(int[]map) {
if (nameTable != null) {
for (NameEntry e : nameTable.values()) {
if (e.backNum > 1) {
for (int i=0; i<e.backNum; i++) {
e.backRefs[i] = map[e.backRefs[i]];
}
} else if (e.backNum == 1) {
e.backRef1 = map[e.backRef1];
}
}
}
}
public int numberOfNames() {
return nameTable == null ? 0 : nameTable.size();
}
void nameAdd(char[] name, int nameP, int nameEnd, int backRef, Syntax syntax) {
if (nameEnd - nameP <= 0) throw new ValueException(ErrorMessages.ERR_EMPTY_GROUP_NAME);
NameEntry e = null;
if (nameTable == null) {
nameTable = new HashMap<String,NameEntry>(); // 13, oni defaults to 5
} else {
e = nameFind(name, nameP, nameEnd);
}
if (e == null) {
// dup the name here as oni does ?, what for ? (it has to manage it, we don't)
e = new NameEntry(name, nameP, nameEnd);
nameTable.put(new String(name, nameP, nameEnd - nameP), e);
} else if (e.backNum >= 1 && !syntax.allowMultiplexDefinitionName()) {
throw new ValueException(ErrorMessages.ERR_MULTIPLEX_DEFINED_NAME, new String(name, nameP, nameEnd - nameP));
}
e.addBackref(backRef);
}
NameEntry nameToGroupNumbers(char[] name, int nameP, int nameEnd) {
return nameFind(name, nameP, nameEnd);
}
public int nameToBackrefNumber(char[] name, int nameP, int nameEnd, Region region) {
NameEntry e = nameToGroupNumbers(name, nameP, nameEnd);
if (e == null) throw new ValueException(ErrorMessages.ERR_UNDEFINED_NAME_REFERENCE,
new String(name, nameP, nameEnd - nameP));
switch(e.backNum) {
case 0:
throw new InternalException(ErrorMessages.ERR_PARSER_BUG);
case 1:
return e.backRef1;
default:
if (region != null) {
for (int i = e.backNum - 1; i >= 0; i--) {
if (region.beg[e.backRefs[i]] != Region.REGION_NOTPOS) return e.backRefs[i];
}
}
return e.backRefs[e.backNum - 1];
}
}
public Iterator<NameEntry> namedBackrefIterator() {
return nameTable.values().iterator();
}
public boolean noNameGroupIsActive(Syntax syntax) {
if (isDontCaptureGroup(options)) return false;
if (Config.USE_NAMED_GROUP) {
if (numberOfNames() > 0 && syntax.captureOnlyNamedGroup() && !isCaptureGroup(options)) return false;
}
return true;
}
/* set skip map for Boyer-Moor search */ /* set skip map for Boyer-Moor search */
void setupBMSkipMap() { void setupBMSkipMap() {
char[] chars = exact; char[] chars = exact;
...@@ -353,16 +246,6 @@ public final class Regex implements RegexState { ...@@ -353,16 +246,6 @@ public final class Regex implements RegexState {
exactP = exactEnd = 0; exactP = exactEnd = 0;
} }
public String encStringToString(byte[]bytes, int p, int end) {
StringBuilder sb = new StringBuilder("\nPATTERN: /");
while (p < end) {
sb.append(new String(new byte[]{bytes[p]}));
p++;
}
return sb.append("/").toString();
}
public String optimizeInfoToString() { public String optimizeInfoToString() {
String s = ""; String s = "";
s += "optimize: " + searchAlgorithm.getName() + "\n"; s += "optimize: " + searchAlgorithm.getName() + "\n";
...@@ -410,19 +293,13 @@ public final class Regex implements RegexState { ...@@ -410,19 +293,13 @@ public final class Regex implements RegexState {
return options; return options;
} }
public void setUserOptions(int options) { public String dumpTree() {
this.userOptions = options; return analyser == null ? null : analyser.root.toString();
}
public int getUserOptions() {
return userOptions;
} }
public void setUserObject(Object object) { public String dumpByteCode() {
this.userObject = object; compile();
return new ByteCodePrinter(this).byteCodeListToString();
} }
public Object getUserObject() {
return userObject;
}
} }
...@@ -25,7 +25,6 @@ public final class Region { ...@@ -25,7 +25,6 @@ public final class Region {
public final int numRegs; public final int numRegs;
public final int[]beg; public final int[]beg;
public final int[]end; public final int[]end;
public CaptureTreeNode historyRoot;
public Region(int num) { public Region(int num) {
this.numRegs = num; this.numRegs = num;
...@@ -33,20 +32,6 @@ public final class Region { ...@@ -33,20 +32,6 @@ public final class Region {
this.end = new int[num]; this.end = new int[num];
} }
public Region(int begin, int end) {
this.numRegs = 1;
this.beg = new int[]{begin};
this.end = new int[]{end};
}
public Region clone() {
Region region = new Region(numRegs);
System.arraycopy(beg, 0, region.beg, 0, beg.length);
System.arraycopy(end, 0, region.end, 0, end.length);
if (historyRoot != null) region.historyRoot = historyRoot.cloneTree();
return region;
}
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Region: \n"); sb.append("Region: \n");
...@@ -54,10 +39,6 @@ public final class Region { ...@@ -54,10 +39,6 @@ public final class Region {
return sb.toString(); return sb.toString();
} }
CaptureTreeNode getCaptureTree() {
return historyRoot;
}
void clear() { void clear() {
for (int i=0; i<beg.length; i++) { for (int i=0; i<beg.length; i++) {
beg[i] = end[i] = REGION_NOTPOS; beg[i] = end[i] = REGION_NOTPOS;
......
...@@ -40,16 +40,10 @@ public final class ScanEnvironment { ...@@ -40,16 +40,10 @@ public final class ScanEnvironment {
final public Regex reg; final public Regex reg;
int numCall; int numCall;
UnsetAddrList unsetAddrList; // USE_SUBEXP_CALL
public int numMem; public int numMem;
int numNamed; // USE_NAMED_GROUP
public Node memNodes[]; public Node memNodes[];
// USE_COMBINATION_EXPLOSION_CHECK
int numCombExpCheck;
int combExpMaxRegNum;
int currMaxRegNum; int currMaxRegNum;
boolean hasRecursion; boolean hasRecursion;
...@@ -69,12 +63,8 @@ public final class ScanEnvironment { ...@@ -69,12 +63,8 @@ public final class ScanEnvironment {
numCall = 0; numCall = 0;
numMem = 0; numMem = 0;
numNamed = 0;
memNodes = null; memNodes = null;
numCombExpCheck = 0;
combExpMaxRegNum = 0;
currMaxRegNum = 0; currMaxRegNum = 0;
hasRecursion = false; hasRecursion = false;
} }
......
...@@ -37,6 +37,8 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages { ...@@ -37,6 +37,8 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
private final int end; // pattern end position for reset() support private final int end; // pattern end position for reset() support
protected int _p; // used by mark()/restore() to mark positions protected int _p; // used by mark()/restore() to mark positions
private final static int INT_SIGN_BIT = 1 << 31;
protected ScannerSupport(char[] chars, int p, int end) { protected ScannerSupport(char[] chars, int p, int end) {
this.chars = chars; this.chars = chars;
this.begin = p; this.begin = p;
...@@ -53,8 +55,6 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages { ...@@ -53,8 +55,6 @@ abstract class ScannerSupport extends IntHolder implements ErrorMessages {
return end; return end;
} }
private final int INT_SIGN_BIT = 1 << 31;
protected final int scanUnsignedNumber() { protected final int scanUnsignedNumber() {
int last = c; int last = c;
int num = 0; // long ??? int num = 0; // long ???
......
...@@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni; ...@@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni;
import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt; import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Arrays;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType; import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
...@@ -36,10 +35,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -36,10 +35,6 @@ abstract class StackMachine extends Matcher implements StackType {
protected final int[]repeatStk; protected final int[]repeatStk;
protected final int memStartStk, memEndStk; protected final int memStartStk, memEndStk;
// CEC
protected byte[] stateCheckBuff; // move to int[] ?
int stateCheckBuffSize;
protected StackMachine(Regex regex, char[] chars, int p , int end) { protected StackMachine(Regex regex, char[] chars, int p , int end) {
super(regex, chars, p, end); super(regex, chars, p, end);
...@@ -104,67 +99,12 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -104,67 +99,12 @@ abstract class StackMachine extends Matcher implements StackType {
stk++; stk++;
} }
// CEC
// STATE_CHECK_POS
private int stateCheckPos(int s, int snum) {
return (s - str) * regex.numCombExpCheck + (snum - 1);
}
// STATE_CHECK_VAL
protected final boolean stateCheckVal(int s, int snum) {
if (stateCheckBuff != null) {
int x = stateCheckPos(s, snum);
return (stateCheckBuff[x / 8] & (1 << (x % 8))) != 0;
}
return false;
}
// ELSE_IF_STATE_CHECK_MARK
private void stateCheckMark() {
StackEntry e = stack[stk];
int x = stateCheckPos(e.getStatePStr(), e.getStateCheck());
stateCheckBuff[x / 8] |= (1 << (x % 8));
}
// STATE_CHECK_BUFF_INIT
private static final int STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE = 16;
protected final void stateCheckBuffInit(int strLength, int offset, int stateNum) {
if (stateNum > 0 && strLength >= Config.CHECK_STRING_THRESHOLD_LEN) {
int size = ((strLength + 1) * stateNum + 7) >>> 3;
offset = (offset * stateNum) >>> 3;
if (size > 0 && offset < size && size < Config.CHECK_BUFF_MAX_SIZE) {
if (size >= STATE_CHECK_BUFF_MALLOC_THRESHOLD_SIZE) {
stateCheckBuff = new byte[size];
} else {
// same impl, reduce...
stateCheckBuff = new byte[size];
}
Arrays.fill(stateCheckBuff, offset, (size - offset), (byte)0);
stateCheckBuffSize = size;
} else {
stateCheckBuff = null; // reduce
stateCheckBuffSize = 0;
}
} else {
stateCheckBuff = null; // reduce
stateCheckBuffSize = 0;
}
}
protected final void stateCheckBuffClear() {
stateCheckBuff = null;
stateCheckBuffSize = 0;
}
private void push(int type, int pat, int s, int prev) { private void push(int type, int pat, int s, int prev) {
StackEntry e = ensure1(); StackEntry e = ensure1();
e.type = type; e.type = type;
e.setStatePCode(pat); e.setStatePCode(pat);
e.setStatePStr(s); e.setStatePStr(s);
e.setStatePStrPrev(prev); e.setStatePStrPrev(prev);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
stk++; stk++;
} }
...@@ -172,30 +112,9 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -172,30 +112,9 @@ abstract class StackMachine extends Matcher implements StackType {
StackEntry e = stack[stk]; StackEntry e = stack[stk];
e.type = type; e.type = type;
e.setStatePCode(pat); e.setStatePCode(pat);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(0);
stk++; stk++;
} }
protected final void pushAltWithStateCheck(int pat, int s, int sprev, int snum) {
StackEntry e = ensure1();
e.type = ALT;
e.setStatePCode(pat);
e.setStatePStr(s);
e.setStatePStrPrev(sprev);
if (Config.USE_COMBINATION_EXPLOSION_CHECK) e.setStateCheck(stateCheckBuff != null ? snum : 0);
stk++;
}
protected final void pushStateCheck(int s, int snum) {
if (stateCheckBuff != null) {
StackEntry e = ensure1();
e.type = STATE_CHECK_MARK;
e.setStatePStr(s);
e.setStateCheck(snum);
stk++;
}
}
protected final void pushAlt(int pat, int s, int prev) { protected final void pushAlt(int pat, int s, int prev) {
push(ALT, pat, s, prev); push(ALT, pat, s, prev);
} }
...@@ -294,19 +213,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -294,19 +213,6 @@ abstract class StackMachine extends Matcher implements StackType {
stk++; stk++;
} }
protected final void pushCallFrame(int pat) {
StackEntry e = ensure1();
e.type = CALL_FRAME;
e.setCallFrameRetAddr(pat);
stk++;
}
protected final void pushReturn() {
StackEntry e = ensure1();
e.type = RETURN;
stk++;
}
// stack debug routines here // stack debug routines here
// ... // ...
...@@ -331,8 +237,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -331,8 +237,6 @@ abstract class StackMachine extends Matcher implements StackType {
if ((e.type & MASK_POP_USED) != 0) { if ((e.type & MASK_POP_USED) != 0) {
return e; return e;
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.type == STATE_CHECK_MARK) stateCheckMark();
} }
} }
} }
...@@ -346,8 +250,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -346,8 +250,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_START) { } else if (e.type == MEM_START) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.type == STATE_CHECK_MARK) stateCheckMark();
} }
} }
} }
...@@ -368,8 +270,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -368,8 +270,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END) { } else if (e.type == MEM_END) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.type == STATE_CHECK_MARK) stateCheckMark();
} }
} }
} }
...@@ -391,8 +291,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -391,8 +291,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END){ } else if (e.type == MEM_END){
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemStart(); repeatStk[memEndStk + e.getMemNum()] = e.getMemStart();
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.type == STATE_CHECK_MARK) stateCheckMark();
} }
} }
} }
...@@ -414,8 +312,6 @@ abstract class StackMachine extends Matcher implements StackType { ...@@ -414,8 +312,6 @@ abstract class StackMachine extends Matcher implements StackType {
} else if (e.type == MEM_END) { } else if (e.type == MEM_END) {
repeatStk[memStartStk + e.getMemNum()] = e.getMemStart(); repeatStk[memStartStk + e.getMemNum()] = e.getMemStart();
repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd(); repeatStk[memEndStk + e.getMemNum()] = e.getMemEnd();
} else if (Config.USE_COMBINATION_EXPLOSION_CHECK) {
if (e.type == STATE_CHECK_MARK) stateCheckMark();
} }
} }
} }
......
...@@ -609,7 +609,7 @@ public final class Syntax implements SyntaxProperties{ ...@@ -609,7 +609,7 @@ public final class Syntax implements SyntaxProperties{
OP_ESC_CONTROL_CHARS | OP_ESC_C_CONTROL | OP_ESC_X_HEX2) OP_ESC_CONTROL_CHARS | OP_ESC_C_CONTROL | OP_ESC_X_HEX2)
& ~OP_ESC_LTGT_WORD_BEGIN_END ), & ~OP_ESC_LTGT_WORD_BEGIN_END ),
( OP2_QMARK_GROUP_EFFECT | OP2_CCLASS_SET_OP | ( OP2_QMARK_GROUP_EFFECT |
OP2_ESC_V_VTAB | OP2_ESC_U_HEX4 ), OP2_ESC_V_VTAB | OP2_ESC_U_HEX4 ),
( GNU_REGEX_BV | DIFFERENT_LEN_ALT_LOOK_BEHIND ), ( GNU_REGEX_BV | DIFFERENT_LEN_ALT_LOOK_BEHIND ),
......
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni;
import jdk.nashorn.internal.runtime.regexp.joni.ast.EncloseNode;
import jdk.nashorn.internal.runtime.regexp.joni.ast.Node;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
public final class UnsetAddrList {
int num;
Node[]targets;
int[]offsets;
public UnsetAddrList(int size) {
targets = new Node[size];
offsets = new int[size];
}
public void add(int offset, Node node) {
if (num >= offsets.length) {
Node []ttmp = new Node[targets.length << 1];
System.arraycopy(targets, 0, ttmp, 0, num);
targets = ttmp;
int[]otmp = new int[offsets.length << 1];
System.arraycopy(offsets, 0, otmp, 0, num);
offsets = otmp;
}
targets[num] = node;
offsets[num] = offset;
num++;
}
public void fix(Regex regex) {
for (int i=0; i<num; i++) {
EncloseNode en = (EncloseNode)targets[i];
if (!en.isAddrFixed()) new InternalException(ErrorMessages.ERR_PARSER_BUG);
regex.code[offsets[i]] = en.callAddr; // is this safe ?
}
}
public String toString() {
StringBuilder value = new StringBuilder();
if (num > 0) {
for (int i=0; i<num; i++) {
value.append("offset + " + offsets[i] + " target: " + targets[i].getAddressName());
}
}
return value.toString();
}
}
...@@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast; ...@@ -22,7 +22,6 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.*; import jdk.nashorn.internal.runtime.regexp.joni.*;
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE; import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE;
import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE; import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.AsciiTables;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType; import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder; import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages; import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
...@@ -40,6 +39,41 @@ public final class CClassNode extends Node { ...@@ -40,6 +39,41 @@ public final class CClassNode extends Node {
private int ctype; // for hashing purposes private int ctype; // for hashing purposes
private final static short AsciiCtypeTable[] = {
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
0x4008, 0x420c, 0x4209, 0x4208, 0x4208, 0x4208, 0x4008, 0x4008,
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008, 0x4008,
0x4284, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0, 0x78b0,
0x78b0, 0x78b0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x41a0,
0x41a0, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x7ca2, 0x74a2,
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2, 0x74a2,
0x74a2, 0x74a2, 0x74a2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x51a0,
0x41a0, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x78e2, 0x70e2,
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2, 0x70e2,
0x70e2, 0x70e2, 0x70e2, 0x41a0, 0x41a0, 0x41a0, 0x41a0, 0x4008,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
// node_new_cclass // node_new_cclass
public CClassNode() {} public CClassNode() {}
...@@ -330,13 +364,13 @@ public final class CClassNode extends Node { ...@@ -330,13 +364,13 @@ public final class CClassNode extends Node {
if (not) { if (not) {
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) { for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
// if (!ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c); // if (!ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c); if ((AsciiCtypeTable[c] & (1 << ctype)) == 0) bs.set(c);
} }
addAllMultiByteRange(); addAllMultiByteRange();
} else { } else {
for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) { for (int c = 0; c < BitSet.SINGLE_BYTE_SIZE; c++) {
// if (ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c); // if (ASCIIEncoding.INSTANCE.isCodeCType(c, ctype)) bs.set(c);
if ((AsciiTables.AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c); if ((AsciiCtypeTable[c] & (1 << ctype)) != 0) bs.set(c);
} }
} }
return; return;
......
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
public final class CTypeNode extends Node {
public int ctype;
public boolean not;
public CTypeNode(int type, boolean not) {
this.ctype= type;
this.not = not;
}
@Override
public int getType() {
return CTYPE;
}
@Override
public String getName() {
return "Character Type";
}
@Override
public String toString(int level) {
StringBuilder value = new StringBuilder();
value.append("\n ctype: " + ctype);
value.append("\n not: " + not);
return value.toString();
}
}
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.ast;
import java.util.Set;
import jdk.nashorn.internal.runtime.regexp.joni.UnsetAddrList;
import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
public final class CallNode extends StateNode {
public char[] name;
public int nameP;
public int nameEnd;
public int groupNum;
public Node target; // is it an EncloseNode always ?
public UnsetAddrList unsetAddrList;
public CallNode(char[] name, int nameP, int nameEnd, int gnum) {
this.name = name;
this.nameP = nameP;
this.nameEnd = nameEnd;
this.groupNum = gnum; /* call by number if gnum != 0 */
}
@Override
public int getType() {
return CALL;
}
@Override
protected void setChild(Node newChild) {
target = newChild;
}
@Override
protected Node getChild() {
return target;
}
public void setTarget(Node tgt) {
target = tgt;
tgt.parent = this;
}
@Override
public String getName() {
return "Call";
}
@Override
public void verifyTree(Set<Node> set, WarnCallback warnings) {
if (target == null || target.parent == this)
warnings.warn(this.getAddressName() + " doesn't point to a target or the target has been stolen");
// do not recurse here
}
@Override
public String toString(int level) {
StringBuilder value = new StringBuilder(super.toString(level));
value.append("\n name: " + new String(name, nameP, nameEnd - nameP));
value.append("\n groupNum: " + groupNum);
value.append("\n target: " + pad(target.getAddressName(), level + 1));
value.append("\n unsetAddrList: " + pad(unsetAddrList, level + 1));
return value.toString();
}
}
...@@ -25,7 +25,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType; ...@@ -25,7 +25,7 @@ import jdk.nashorn.internal.runtime.regexp.joni.constants.EncloseType;
public final class EncloseNode extends StateNode implements EncloseType { public final class EncloseNode extends StateNode implements EncloseType {
public int type; // enclose type public final int type; // enclose type
public int regNum; public int regNum;
public int option; public int option;
public Node target; /* EncloseNode : ENCLOSE_MEMORY */ public Node target; /* EncloseNode : ENCLOSE_MEMORY */
...@@ -42,10 +42,8 @@ public final class EncloseNode extends StateNode implements EncloseType { ...@@ -42,10 +42,8 @@ public final class EncloseNode extends StateNode implements EncloseType {
} }
// node_new_enclose_memory // node_new_enclose_memory
public EncloseNode(int option, boolean isNamed) { public EncloseNode() {
this(MEMORY); this(MEMORY);
if (isNamed) setNamedGroup();
if (Config.USE_SUBEXP_CALL) this.option = option;
} }
// node_new_option // node_new_option
...@@ -104,46 +102,14 @@ public final class EncloseNode extends StateNode implements EncloseType { ...@@ -104,46 +102,14 @@ public final class EncloseNode extends StateNode implements EncloseType {
return types.toString(); return types.toString();
} }
public void setEncloseStatus(int flag) {
state |= flag;
}
public void clearEncloseStatus(int flag) {
state &= ~flag;
}
public void clearMemory() {
type &= ~MEMORY;
}
public void setMemory() {
type |= MEMORY;
}
public boolean isMemory() { public boolean isMemory() {
return (type & MEMORY) != 0; return (type & MEMORY) != 0;
} }
public void clearOption() {
type &= ~OPTION;
}
public void setOption() {
type |= OPTION;
}
public boolean isOption() { public boolean isOption() {
return (type & OPTION) != 0; return (type & OPTION) != 0;
} }
public void clearStopBacktrack() {
type &= ~STOP_BACKTRACK;
}
public void setStopBacktrack() {
type |= STOP_BACKTRACK;
}
public boolean isStopBacktrack() { public boolean isStopBacktrack() {
return (type & STOP_BACKTRACK) != 0; return (type & STOP_BACKTRACK) != 0;
} }
......
...@@ -21,9 +21,10 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast; ...@@ -21,9 +21,10 @@ package jdk.nashorn.internal.runtime.regexp.joni.ast;
import jdk.nashorn.internal.runtime.regexp.joni.Config; import jdk.nashorn.internal.runtime.regexp.joni.Config;
import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment; import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
import jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce;
import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo; import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
public final class QuantifierNode extends StateNode { public final class QuantifierNode extends StateNode {
public Node target; public Node target;
...@@ -37,8 +38,33 @@ public final class QuantifierNode extends StateNode { ...@@ -37,8 +38,33 @@ public final class QuantifierNode extends StateNode {
public Node nextHeadExact; public Node nextHeadExact;
public boolean isRefered; /* include called node. don't eliminate even if {0} */ public boolean isRefered; /* include called node. don't eliminate even if {0} */
// USE_COMBINATION_EXPLOSION_CHECK enum ReduceType {
public int combExpCheckNum; /* 1,2,3...: check, 0: no check */ ASIS, /* as is */
DEL, /* delete parent */
A, /* to '*' */
AQ, /* to '*?' */
QQ, /* to '??' */
P_QQ, /* to '+)??' */
PQ_Q, /* to '+?)?' */
}
private final static ReduceType[][] REDUCE_TABLE = {
{DEL, A, A, QQ, AQ, ASIS}, /* '?' */
{DEL, DEL, DEL, P_QQ, P_QQ, DEL}, /* '*' */
{A, A, DEL, ASIS, P_QQ, DEL}, /* '+' */
{DEL, AQ, AQ, DEL, AQ, AQ}, /* '??' */
{DEL, DEL, DEL, DEL, DEL, DEL}, /* '*?' */
{ASIS, PQ_Q, DEL, AQ, AQ, DEL} /* '+?' */
};
private final static String PopularQStr[] = new String[] {
"?", "*", "+", "??", "*?", "+?"
};
private final static String ReduceQStr[]= new String[] {
"", "", "*", "*?", "??", "+ and ??", "+? and ?"
};
public QuantifierNode(int lower, int upper, boolean byNumber) { public QuantifierNode(int lower, int upper, boolean byNumber) {
this.lower = lower; this.lower = lower;
...@@ -92,7 +118,6 @@ public final class QuantifierNode extends StateNode { ...@@ -92,7 +118,6 @@ public final class QuantifierNode extends StateNode {
value.append("\n headExact: " + pad(headExact, level + 1)); value.append("\n headExact: " + pad(headExact, level + 1));
value.append("\n nextHeadExact: " + pad(nextHeadExact, level + 1)); value.append("\n nextHeadExact: " + pad(nextHeadExact, level + 1));
value.append("\n isRefered: " + isRefered); value.append("\n isRefered: " + isRefered);
value.append("\n combExpCheckNum: " + combExpCheckNum);
return value.toString(); return value.toString();
} }
...@@ -134,7 +159,6 @@ public final class QuantifierNode extends StateNode { ...@@ -134,7 +159,6 @@ public final class QuantifierNode extends StateNode {
headExact = other.headExact; headExact = other.headExact;
nextHeadExact = other.nextHeadExact; nextHeadExact = other.nextHeadExact;
isRefered = other.isRefered; isRefered = other.isRefered;
combExpCheckNum = other.combExpCheckNum;
} }
public void reduceNestedQuantifier(QuantifierNode other) { public void reduceNestedQuantifier(QuantifierNode other) {
...@@ -143,7 +167,7 @@ public final class QuantifierNode extends StateNode { ...@@ -143,7 +167,7 @@ public final class QuantifierNode extends StateNode {
if (pnum < 0 || cnum < 0) return; if (pnum < 0 || cnum < 0) return;
switch(Reduce.REDUCE_TABLE[cnum][pnum]) { switch(REDUCE_TABLE[cnum][pnum]) {
case DEL: case DEL:
// no need to set the parent here... // no need to set the parent here...
// swap ? // swap ?
...@@ -226,7 +250,7 @@ public final class QuantifierNode extends StateNode { ...@@ -226,7 +250,7 @@ public final class QuantifierNode extends StateNode {
if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) { if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) { if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
switch(Reduce.REDUCE_TABLE[targetQNum][nestQNum]) { switch(REDUCE_TABLE[targetQNum][nestQNum]) {
case ASIS: case ASIS:
break; break;
...@@ -237,9 +261,9 @@ public final class QuantifierNode extends StateNode { ...@@ -237,9 +261,9 @@ public final class QuantifierNode extends StateNode {
default: default:
env.reg.getWarnings().warn(new String(chars, p, end) + env.reg.getWarnings().warn(new String(chars, p, end) +
" nested repeat operator " + Reduce.PopularQStr[targetQNum] + " nested repeat operator " + PopularQStr[targetQNum] +
" and " + Reduce.PopularQStr[nestQNum] + " was replaced with '" + " and " + PopularQStr[nestQNum] + " was replaced with '" +
Reduce.ReduceQStr[Reduce.REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'"); ReduceQStr[REDUCE_TABLE[targetQNum][nestQNum].ordinal()] + "'");
} }
} }
} // USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR } // USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
......
...@@ -40,7 +40,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -40,7 +40,6 @@ public abstract class StateNode extends Node implements NodeStatus {
if (isRecursion()) states.append("RECURSION "); if (isRecursion()) states.append("RECURSION ");
if (isCalled()) states.append("CALLED "); if (isCalled()) states.append("CALLED ");
if (isAddrFixed()) states.append("ADDR_FIXED "); if (isAddrFixed()) states.append("ADDR_FIXED ");
if (isNamedGroup()) states.append("NAMED_GROUP ");
if (isNameRef()) states.append("NAME_REF "); if (isNameRef()) states.append("NAME_REF ");
if (isInRepeat()) states.append("IN_REPEAT "); if (isInRepeat()) states.append("IN_REPEAT ");
if (isNestLevel()) states.append("NEST_LEVEL "); if (isNestLevel()) states.append("NEST_LEVEL ");
...@@ -57,10 +56,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -57,10 +56,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MIN_FIXED; state |= NST_MIN_FIXED;
} }
public void clearMinFixed() {
state &= ~NST_MIN_FIXED;
}
public boolean isMaxFixed() { public boolean isMaxFixed() {
return (state & NST_MAX_FIXED) != 0; return (state & NST_MAX_FIXED) != 0;
} }
...@@ -69,10 +64,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -69,10 +64,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MAX_FIXED; state |= NST_MAX_FIXED;
} }
public void clearMaxFixed() {
state &= ~NST_MAX_FIXED;
}
public boolean isCLenFixed() { public boolean isCLenFixed() {
return (state & NST_CLEN_FIXED) != 0; return (state & NST_CLEN_FIXED) != 0;
} }
...@@ -81,10 +72,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -81,10 +72,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_CLEN_FIXED; state |= NST_CLEN_FIXED;
} }
public void clearCLenFixed() {
state &= ~NST_CLEN_FIXED;
}
public boolean isMark1() { public boolean isMark1() {
return (state & NST_MARK1) != 0; return (state & NST_MARK1) != 0;
} }
...@@ -93,10 +80,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -93,10 +80,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MARK1; state |= NST_MARK1;
} }
public void clearMark1() {
state &= ~NST_MARK1;
}
public boolean isMark2() { public boolean isMark2() {
return (state & NST_MARK2) != 0; return (state & NST_MARK2) != 0;
} }
...@@ -117,10 +100,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -117,10 +100,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_MEM_BACKREFED; state |= NST_MEM_BACKREFED;
} }
public void clearMemBackrefed() {
state &= ~NST_MEM_BACKREFED;
}
public boolean isStopBtSimpleRepeat() { public boolean isStopBtSimpleRepeat() {
return (state & NST_STOP_BT_SIMPLE_REPEAT) != 0; return (state & NST_STOP_BT_SIMPLE_REPEAT) != 0;
} }
...@@ -129,10 +108,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -129,10 +108,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_STOP_BT_SIMPLE_REPEAT; state |= NST_STOP_BT_SIMPLE_REPEAT;
} }
public void clearStopBtSimpleRepeat() {
state &= ~NST_STOP_BT_SIMPLE_REPEAT;
}
public boolean isRecursion() { public boolean isRecursion() {
return (state & NST_RECURSION) != 0; return (state & NST_RECURSION) != 0;
} }
...@@ -141,10 +116,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -141,10 +116,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_RECURSION; state |= NST_RECURSION;
} }
public void clearRecursion() {
state &= ~NST_RECURSION;
}
public boolean isCalled() { public boolean isCalled() {
return (state & NST_CALLED) != 0; return (state & NST_CALLED) != 0;
} }
...@@ -153,10 +124,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -153,10 +124,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_CALLED; state |= NST_CALLED;
} }
public void clearCAlled() {
state &= ~NST_CALLED;
}
public boolean isAddrFixed() { public boolean isAddrFixed() {
return (state & NST_ADDR_FIXED) != 0; return (state & NST_ADDR_FIXED) != 0;
} }
...@@ -165,22 +132,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -165,22 +132,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_ADDR_FIXED; state |= NST_ADDR_FIXED;
} }
public void clearAddrFixed() {
state &= ~NST_ADDR_FIXED;
}
public boolean isNamedGroup() {
return (state & NST_NAMED_GROUP) != 0;
}
public void setNamedGroup() {
state |= NST_NAMED_GROUP;
}
public void clearNamedGroup() {
state &= ~NST_NAMED_GROUP;
}
public boolean isNameRef() { public boolean isNameRef() {
return (state & NST_NAME_REF) != 0; return (state & NST_NAME_REF) != 0;
} }
...@@ -189,10 +140,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -189,10 +140,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_NAME_REF; state |= NST_NAME_REF;
} }
public void clearNameRef() {
state &= ~NST_NAME_REF;
}
public boolean isInRepeat() { public boolean isInRepeat() {
return (state & NST_IN_REPEAT) != 0; return (state & NST_IN_REPEAT) != 0;
} }
...@@ -201,10 +148,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -201,10 +148,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_IN_REPEAT; state |= NST_IN_REPEAT;
} }
public void clearInRepeat() {
state &= ~NST_IN_REPEAT;
}
public boolean isNestLevel() { public boolean isNestLevel() {
return (state & NST_NEST_LEVEL) != 0; return (state & NST_NEST_LEVEL) != 0;
} }
...@@ -213,10 +156,6 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -213,10 +156,6 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_NEST_LEVEL; state |= NST_NEST_LEVEL;
} }
public void clearNestLevel() {
state &= ~NST_NEST_LEVEL;
}
public boolean isByNumber() { public boolean isByNumber() {
return (state & NST_BY_NUMBER) != 0; return (state & NST_BY_NUMBER) != 0;
} }
...@@ -225,8 +164,4 @@ public abstract class StateNode extends Node implements NodeStatus { ...@@ -225,8 +164,4 @@ public abstract class StateNode extends Node implements NodeStatus {
state |= NST_BY_NUMBER; state |= NST_BY_NUMBER;
} }
public void clearByNumber() {
state &= ~NST_BY_NUMBER;
}
} }
package jdk.nashorn.internal.runtime.regexp.joni.bench;
import jdk.nashorn.internal.runtime.regexp.joni.Option;
import jdk.nashorn.internal.runtime.regexp.joni.Regex;
import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
public abstract class AbstractBench {
protected void bench(String _reg, String _str, int warmup, int times) throws Exception {
char[] reg = _reg.toCharArray();
char[] str = _str.toCharArray();
Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
for(int j=0;j<warmup;j++) {
long before = System.currentTimeMillis();
for(int i = 0; i < times; i++) {
p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
}
long time = System.currentTimeMillis() - before;
System.err.println(": " + time + "ms");
}
}
protected void benchBestOf(String _reg, String _str, int warmup, int times) throws Exception {
char[] reg = _reg.toCharArray();
char[] str = _str.toCharArray();
Regex p = new Regex(reg,0,reg.length,Option.DEFAULT,Syntax.DEFAULT);
System.err.println("::: /" + _reg + "/ =~ \"" + _str + "\", " + warmup + " * " + times + " times");
long best = Long.MAX_VALUE;
for(int j=0;j<warmup;j++) {
long before = System.currentTimeMillis();
for(int i = 0; i < times; i++) {
p.matcher(str, 0, str.length).search(0, str.length, Option.NONE);
}
long time = System.currentTimeMillis() - before;
if(time < best) {
best = time;
}
System.err.print(".");
}
System.err.println(": " + best + "ms");
}
}
package jdk.nashorn.internal.runtime.regexp.joni.bench;
public class BenchGreedyBacktrack extends AbstractBench {
public static void main(String[] args) throws Exception {
new BenchGreedyBacktrack().bench(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,1000000);
}
}
package jdk.nashorn.internal.runtime.regexp.joni.bench;
public class BenchRailsRegs extends AbstractBench {
public static void main(String[] args) throws Exception {
final String[][] regexps = {{"a.*?[b-z]{2,4}aaaaaa","afdgdsgderaabxxaaaaaaaaaaaaaaaaaaaaaaaa"},
{"://","/shop/viewCategory.shtml?category=DOGS"},
{"^\\w+\\://[^/]+(/.*|$)$","/shop/viewCategory.shtml?category=DOGS"},
{"\\A/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/signonForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/newAccountForm\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/newAccount\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/viewCart\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/index\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A/shop/viewCategory\\.shtml/?\\Z","/shop/viewCategory.shtml"},
{"\\A(?:::)?([A-Z]\\w*(?:::[A-Z]\\w*)*)\\z","CategoriesController"},
{"\\Ainsert","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7') LIMIT 1"},
{"\\A\\(?\\s*(select|show)","SELECT * FROM sessions WHERE (session_id = '1b341ffe23b5298676d535fcabd3d0d7') LIMIT 1"},
{".*?\n","1b341ffe23b5298676d535fcabd3d0d7"},
{"^find_(all_by|by)_([_a-zA-Z]\\w*)$","find_by_string_id"},
{"\\.rjs$","categories/show.rhtml"},
{"^[-a-z]+://","petstore.css"},
{"^get$",""},
{"^post$",""},
{"^[^:]+","www.example.com"},
{"(=|\\?|_before_type_cast)$", "updated_on"},
{"^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/"}};
for(String[] reg : regexps) {
new BenchRailsRegs().benchBestOf(reg[0],reg[1],10,1000000);
}
}
}
package jdk.nashorn.internal.runtime.regexp.joni.bench;
public class BenchSeveralRegexps extends AbstractBench {
public static void main(String[] args) throws Exception {
int BASE = 1000000;
new BenchSeveralRegexps().benchBestOf("a"," a",10,4*BASE);
new BenchSeveralRegexps().benchBestOf(".*?=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
new BenchSeveralRegexps().benchBestOf("^(.*?)=(.*?);","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,BASE);
new BenchSeveralRegexps().benchBestOf(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
new BenchSeveralRegexps().benchBestOf(".*=","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,4*BASE);
}
}
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.constants;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.A;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.AQ;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.ASIS;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.DEL;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.PQ_Q;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.P_QQ;
import static jdk.nashorn.internal.runtime.regexp.joni.constants.Reduce.ReduceType.QQ;
public interface Reduce {
enum ReduceType {
ASIS, /* as is */
DEL, /* delete parent */
A, /* to '*' */
AQ, /* to '*?' */
QQ, /* to '??' */
P_QQ, /* to '+)??' */
PQ_Q, /* to '+?)?' */
}
final ReduceType[][]REDUCE_TABLE = {
{DEL, A, A, QQ, AQ, ASIS}, /* '?' */
{DEL, DEL, DEL, P_QQ, P_QQ, DEL}, /* '*' */
{A, A, DEL, ASIS, P_QQ, DEL}, /* '+' */
{DEL, AQ, AQ, DEL, AQ, AQ}, /* '??' */
{DEL, DEL, DEL, DEL, DEL, DEL}, /* '*?' */
{ASIS, PQ_Q, DEL, AQ, AQ, DEL} /* '+?' */
};
final String PopularQStr[] = new String[] {
"?", "*", "+", "??", "*?", "+?"
};
String ReduceQStr[]= new String[] {
"", "", "*", "*?", "??", "+ and ??", "+? and ?"
};
}
...@@ -30,6 +30,5 @@ public final class ObjPtr<T> { ...@@ -30,6 +30,5 @@ public final class ObjPtr<T> {
public T p; public T p;
static final ObjPtr<Void> NULL = new ObjPtr<Void>();
} }
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS".toCharArray(), WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
import java.util.HashMap;
public class PosixBracket {
public static final char[][] PBSNamesLower = {
"alnum".toCharArray(),
"alpha".toCharArray(),
"blank".toCharArray(),
"cntrl".toCharArray(),
"digit".toCharArray(),
"graph".toCharArray(),
"lower".toCharArray(),
"print".toCharArray(),
"punct".toCharArray(),
"space".toCharArray(),
"upper".toCharArray(),
"xdigit".toCharArray(),
"ascii".toCharArray(),
"word".toCharArray()
};
public static final int PBSValues[] = {
CharacterType.ALNUM,
CharacterType.ALPHA,
CharacterType.BLANK,
CharacterType.CNTRL,
CharacterType.DIGIT,
CharacterType.GRAPH,
CharacterType.LOWER,
CharacterType.PRINT,
CharacterType.PUNCT,
CharacterType.SPACE,
CharacterType.UPPER,
CharacterType.XDIGIT,
CharacterType.ASCII,
CharacterType.WORD,
};
public static int propertyNameToCType(String name) {
name = name.toLowerCase();
if (!PBSTableUpper.containsKey(name)) {
throw new JOniException(ErrorMessages.ERR_INVALID_CHAR_PROPERTY_NAME.replaceAll("%n", name));
}
return PBSTableUpper.get(name);
}
private static final HashMap<String,Integer> PBSTableUpper = new HashMap<String,Integer>();
static {
for (int i=0; i<PBSValues.length; i++) PBSTableUpper.put(new String(PBSNamesLower[i]), PBSValues[i]);
}
}
/*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package jdk.nashorn.internal.runtime.regexp.joni.encoding;
public final class Ptr {
public Ptr() {
this(0);
}
public Ptr(int p) {
this.p = p;
}
public int p;
public static final Ptr NULL = new Ptr(0);
}
...@@ -30,8 +30,4 @@ public class ValueException extends SyntaxException{ ...@@ -30,8 +30,4 @@ public class ValueException extends SyntaxException{
super(message.replaceAll("%n", str)); super(message.replaceAll("%n", str));
} }
public ValueException(String message, byte[]bytes, int p, int end) {
this(message, new String(bytes, p, end - p));
}
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册