提交 f28c0a34 编写于 作者: J jlaskey

Merge

...@@ -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>
......
...@@ -23,26 +23,12 @@ ...@@ -23,26 +23,12 @@
* questions. * questions.
*/ */
package netscape.javascript; package jdk.nashorn.api.scripting;
import java.applet.Applet;
/** /**
* Stub for JSObject to get compilation going. * netscape.javascript.JSObject-like interface for nashorn script objects.
*/ */
public abstract class JSObject { public abstract class JSObject {
/**
* Get the window for an {@link Applet}. Not supported
* by Nashorn
*
* @param a applet
* @return the window instance
*/
public static JSObject getWindow(final Applet a) {
throw new UnsupportedOperationException("getWindow");
}
/** /**
* Call a JavaScript method * Call a JavaScript method
* *
......
...@@ -42,7 +42,6 @@ import jdk.nashorn.internal.runtime.Context; ...@@ -42,7 +42,6 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.ScriptRuntime;
import netscape.javascript.JSObject;
/** /**
* Mirror object that wraps a given ScriptObject instance. User can * Mirror object that wraps a given ScriptObject instance. User can
......
...@@ -261,19 +261,25 @@ final class Lower extends NodeOperatorVisitor { ...@@ -261,19 +261,25 @@ final class Lower extends NodeOperatorVisitor {
return throwNode; return throwNode;
} }
private static Node ensureUniqueLabelsIn(final Node node) { private static Node ensureUniqueNamesIn(final LexicalContext lc, final Node node) {
return node.accept(new NodeVisitor() { return node.accept(new NodeVisitor() {
@Override @Override
public Node leaveDefault(final Node labelledNode) { public Node leaveFunctionNode(final FunctionNode functionNode) {
return labelledNode.ensureUniqueLabels(getLexicalContext()); final String name = functionNode.getName();
} return functionNode.setName(getLexicalContext(), lc.getCurrentFunction().uniqueName(name));
}
@Override
public Node leaveDefault(final Node labelledNode) {
return labelledNode.ensureUniqueLabels(getLexicalContext());
}
}); });
} }
private static List<Statement> copyFinally(final Block finallyBody) { private static List<Statement> copyFinally(final LexicalContext lc, final Block finallyBody) {
final List<Statement> newStatements = new ArrayList<>(); final List<Statement> newStatements = new ArrayList<>();
for (final Statement statement : finallyBody.getStatements()) { for (final Statement statement : finallyBody.getStatements()) {
newStatements.add((Statement)ensureUniqueLabelsIn(statement)); newStatements.add((Statement)ensureUniqueNamesIn(lc, statement));
if (statement.hasTerminalFlags()) { if (statement.hasTerminalFlags()) {
return newStatements; return newStatements;
} }
...@@ -316,9 +322,9 @@ final class Lower extends NodeOperatorVisitor { ...@@ -316,9 +322,9 @@ final class Lower extends NodeOperatorVisitor {
* @return new try node after splicing finally code (same if nop) * @return new try node after splicing finally code (same if nop)
*/ */
private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) { private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
final int finish = tryNode.getFinish();
assert tryNode.getFinallyBody() == null; assert tryNode.getFinallyBody() == null;
final int finish = tryNode.getFinish();
final LexicalContext lc = getLexicalContext();
final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() { final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor() {
final List<Node> insideTry = new ArrayList<>(); final List<Node> insideTry = new ArrayList<>();
...@@ -338,7 +344,7 @@ final class Lower extends NodeOperatorVisitor { ...@@ -338,7 +344,7 @@ final class Lower extends NodeOperatorVisitor {
@Override @Override
public Node leaveThrowNode(final ThrowNode throwNode) { public Node leaveThrowNode(final ThrowNode throwNode) {
if (rethrows.contains(throwNode)) { if (rethrows.contains(throwNode)) {
final List<Statement> newStatements = copyFinally(finallyBody); final List<Statement> newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(throwNode); newStatements.add(throwNode);
} }
...@@ -372,7 +378,7 @@ final class Lower extends NodeOperatorVisitor { ...@@ -372,7 +378,7 @@ final class Lower extends NodeOperatorVisitor {
resultNode = null; resultNode = null;
} }
newStatements.addAll(copyFinally(finallyBody)); newStatements.addAll(copyFinally(lc, finallyBody));
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode)); newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
} }
...@@ -382,7 +388,7 @@ final class Lower extends NodeOperatorVisitor { ...@@ -382,7 +388,7 @@ final class Lower extends NodeOperatorVisitor {
private Node copy(final Statement endpoint, final Node targetNode) { private Node copy(final Statement endpoint, final Node targetNode) {
if (!insideTry.contains(targetNode)) { if (!insideTry.contains(targetNode)) {
final List<Statement> newStatements = copyFinally(finallyBody); final List<Statement> newStatements = copyFinally(lc, finallyBody);
if (!isTerminal(newStatements)) { if (!isTerminal(newStatements)) {
newStatements.add(endpoint); newStatements.add(endpoint);
} }
...@@ -548,7 +554,7 @@ final class Lower extends NodeOperatorVisitor { ...@@ -548,7 +554,7 @@ final class Lower extends NodeOperatorVisitor {
final FunctionNode currentFunction = getLexicalContext().getCurrentFunction(); final FunctionNode currentFunction = getLexicalContext().getCurrentFunction();
return callNode.setEvalArgs( return callNode.setEvalArgs(
new CallNode.EvalArgs( new CallNode.EvalArgs(
ensureUniqueLabelsIn(args.get(0)).accept(this), ensureUniqueNamesIn(getLexicalContext(), args.get(0)).accept(this),
compilerConstant(THIS), compilerConstant(THIS),
evalLocation(callee), evalLocation(callee),
currentFunction.isStrict())); currentFunction.isStrict()));
......
...@@ -250,6 +250,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -250,6 +250,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
final FunctionNode functionNode, final FunctionNode functionNode,
final long lastToken, final long lastToken,
final int flags, final int flags,
final String name,
final Type returnType, final Type returnType,
final CompileUnit compileUnit, final CompileUnit compileUnit,
final EnumSet<CompilationState> compilationState, final EnumSet<CompilationState> compilationState,
...@@ -260,6 +261,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -260,6 +261,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
super(functionNode); super(functionNode);
this.flags = flags; this.flags = flags;
this.name = name;
this.returnType = returnType; this.returnType = returnType;
this.compileUnit = compileUnit; this.compileUnit = compileUnit;
this.lastToken = lastToken; this.lastToken = lastToken;
...@@ -271,7 +273,6 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -271,7 +273,6 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
// the fields below never change - they are final and assigned in constructor // the fields below never change - they are final and assigned in constructor
this.source = functionNode.source; this.source = functionNode.source;
this.name = functionNode.name;
this.ident = functionNode.ident; this.ident = functionNode.ident;
this.namespace = functionNode.namespace; this.namespace = functionNode.namespace;
this.declaredSymbols = functionNode.declaredSymbols; this.declaredSymbols = functionNode.declaredSymbols;
...@@ -315,7 +316,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -315,7 +316,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.snapshot == null) { if (this.snapshot == null) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, null, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
} }
/** /**
...@@ -331,7 +332,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -331,7 +332,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (isProgram() || parameters.isEmpty()) { if (isProgram() || parameters.isEmpty()) {
return this; //never specialize anything that won't be recompiled return this; //never specialize anything that won't be recompiled
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, this, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
} }
/** /**
...@@ -389,7 +390,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -389,7 +390,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
} }
final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
newState.add(state); newState.add(state);
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, newState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
} }
/** /**
...@@ -410,7 +411,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -410,7 +411,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.hints == hints) { if (this.hints == hints) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
...@@ -463,7 +464,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -463,7 +464,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.flags == flags) { if (this.flags == flags) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
@Override @Override
...@@ -529,7 +530,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -529,7 +530,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
} }
/** /**
* Get the identifier for this function * Get the identifier for this function, this is its symbol.
* @return the identifier as an IdentityNode * @return the identifier as an IdentityNode
*/ */
public IdentNode getIdent() { public IdentNode getIdent() {
...@@ -572,7 +573,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -572,7 +573,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if(this.body == body) { if(this.body == body) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
...@@ -640,7 +641,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -640,7 +641,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.lastToken == lastToken) { if (this.lastToken == lastToken) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
...@@ -651,6 +652,20 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -651,6 +652,20 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
return name; return name;
} }
/**
* Set the internal name for this function
* @param lc lexical context
* @param name new name
* @return new function node if changed, otherwise the same
*/
public FunctionNode setName(final LexicalContext lc, final String name) {
if (this.name.equals(name)) {
return this;
}
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
}
/** /**
* Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and * Check if this function should have all its variables in its own scope. Scripts, split sub-functions, and
* functions having with and/or eval blocks are such. * functions having with and/or eval blocks are such.
...@@ -698,7 +713,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -698,7 +713,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.parameters == parameters) { if (this.parameters == parameters) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
...@@ -762,6 +777,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -762,6 +777,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
this, this,
lastToken, lastToken,
flags, flags,
name,
Type.widest(this.returnType, returnType.isObject() ? Type.widest(this.returnType, returnType.isObject() ?
Type.OBJECT : Type.OBJECT :
returnType), returnType),
...@@ -801,7 +817,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func ...@@ -801,7 +817,7 @@ public final class FunctionNode extends LexicalContextNode implements Flags<Func
if (this.compileUnit == compileUnit) { if (this.compileUnit == compileUnit) {
return this; return this;
} }
return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, returnType, compileUnit, compilationState, body, parameters, snapshot, hints)); return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
} }
/** /**
......
...@@ -38,7 +38,7 @@ import jdk.internal.dynalink.linker.LinkerServices; ...@@ -38,7 +38,7 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.JSType;
import netscape.javascript.JSObject; import jdk.nashorn.api.scripting.JSObject;
/** /**
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
......
...@@ -310,7 +310,34 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase { ...@@ -310,7 +310,34 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase {
Type.getMethodDescriptor(Type.VOID_TYPE), null, null)); Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR); mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getClassOverrides", GET_CLASS_INITIALIZER_DESCRIPTOR);
// Assign MethodHandle fields through invoking getHandle() final Label initGlobal;
if(samName != null) {
// If the class is a SAM, allow having a ScriptFunction passed as class overrides
final Label notAFunction = new Label();
mv.dup();
mv.instanceOf(SCRIPT_FUNCTION_TYPE);
mv.ifeq(notAFunction);
mv.checkcast(SCRIPT_FUNCTION_TYPE);
// Assign MethodHandle fields through invoking getHandle() for a ScriptFunction, only assigning the SAM
// method(s).
for (final MethodInfo mi : methodInfos) {
if(mi.getName().equals(samName)) {
mv.dup();
mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR);
} else {
mv.visitInsn(ACONST_NULL);
}
mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
}
initGlobal = new Label();
mv.goTo(initGlobal);
mv.visitLabel(notAFunction);
} else {
initGlobal = null;
}
// Assign MethodHandle fields through invoking getHandle() for a ScriptObject
for (final MethodInfo mi : methodInfos) { for (final MethodInfo mi : methodInfos) {
mv.dup(); mv.dup();
mv.aconst(mi.getName()); mv.aconst(mi.getName());
...@@ -319,6 +346,9 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase { ...@@ -319,6 +346,9 @@ final class JavaAdapterBytecodeGenerator extends JavaAdapterGeneratorBase {
mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR); mv.putstatic(generatedClassName, mi.methodHandleClassFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
} }
if(initGlobal != null) {
mv.visitLabel(initGlobal);
}
// Assign "staticGlobal = Context.getGlobal()" // Assign "staticGlobal = Context.getGlobal()"
invokeGetGlobalWithNullCheck(mv); invokeGetGlobalWithNullCheck(mv);
mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR); mv.putstatic(generatedClassName, STATIC_GLOBAL_FIELD_NAME, SCRIPT_OBJECT_TYPE_DESCRIPTOR);
......
...@@ -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;
public class BenchGreedyBacktrack extends AbstractBench {
public static void main(String[] args) throws Exception {
new BenchGreedyBacktrack().bench(".*_p","_petstore_session_id=1b341ffe23b5298676d535fcabd3d0d7; path=/",10,1000000);
}
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册