StepPatternpublic class StepPattern extends RelativePathPattern
Fields Summary |
---|
private static final int | NO_CONTEXT | private static final int | SIMPLE_CONTEXT | private static final int | GENERAL_CONTEXT | protected final int | _axis | protected final int | _nodeType | protected Vector | _predicates | private Step | _step | private boolean | _isEpsilon | private int | _contextCase | private double | _priority |
Constructors Summary |
---|
public StepPattern(int axis, int nodeType, Vector predicates)
_axis = axis;
_nodeType = nodeType;
_predicates = predicates;
|
Methods Summary |
---|
private int | analyzeCases()
boolean noContext = true;
final int n = _predicates.size();
for (int i = 0; i < n && noContext; i++) {
Predicate pred = (Predicate) _predicates.elementAt(i);
if (pred.isNthPositionFilter() ||
pred.hasPositionCall() ||
pred.hasLastCall())
{
noContext = false;
}
}
if (noContext) {
return NO_CONTEXT;
}
else if (n == 1) {
return SIMPLE_CONTEXT;
}
return GENERAL_CONTEXT;
| public int | getAxis()
return _axis;
| public double | getDefaultPriority()
if (_priority != Double.MAX_VALUE) {
return _priority;
}
if (hasPredicates()) {
return 0.5;
}
else {
switch(_nodeType) {
case -1:
return -0.5; // node()
case 0:
return 0.0;
default:
return (_nodeType >= NodeTest.GTYPE) ? 0.0 : -0.5;
}
}
| public com.sun.org.apache.xalan.internal.xsltc.compiler.StepPattern | getKernelPattern()
return this;
| private java.lang.String | getNextFieldName()
return "__step_pattern_iter_" + getXSLTC().nextStepPatternSerial();
| public int | getNodeType()
return _nodeType;
| protected boolean | hasPredicates()
return _predicates != null && _predicates.size() > 0;
| public boolean | isWildcard()
return _isEpsilon && hasPredicates() == false;
| public void | reduceKernelPattern()
_isEpsilon = true;
| public void | setParser(com.sun.org.apache.xalan.internal.xsltc.compiler.Parser parser)
super.setParser(parser);
if (_predicates != null) {
final int n = _predicates.size();
for (int i = 0; i < n; i++) {
final Predicate exp = (Predicate)_predicates.elementAt(i);
exp.setParser(parser);
exp.setParent(this);
}
}
| public com.sun.org.apache.xalan.internal.xsltc.compiler.StepPattern | setPredicates(java.util.Vector predicates)
_predicates = predicates;
return(this);
| public void | setPriority(double priority)
_priority = priority;
| public java.lang.String | toString()
final StringBuffer buffer = new StringBuffer("stepPattern(\"");
buffer.append(Axis.getNames(_axis))
.append("\", ")
.append(_isEpsilon ?
("epsilon{" + Integer.toString(_nodeType) + "}") :
Integer.toString(_nodeType));
if (_predicates != null)
buffer.append(", ").append(_predicates.toString());
return buffer.append(')").toString();
| public void | translate(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
if (hasPredicates()) {
switch (_contextCase) {
case NO_CONTEXT:
translateNoContext(classGen, methodGen);
break;
case SIMPLE_CONTEXT:
translateSimpleContext(classGen, methodGen);
break;
default:
translateGeneralContext(classGen, methodGen);
break;
}
}
else if (isWildcard()) {
il.append(POP); // true list falls through
}
else {
translateKernel(classGen, methodGen);
}
| private void | translateGeneralContext(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
int iteratorIndex = 0;
BranchHandle ifBlock = null;
LocalVariableGen iter, node, node2;
final String iteratorName = getNextFieldName();
// Store node on the stack into a local variable
node = methodGen.addLocalVariable("step_pattern_tmp1",
Util.getJCRefType(NODE_SIG),
il.getEnd(), null);
il.append(new ISTORE(node.getIndex()));
// Create a new local to store the iterator
iter = methodGen.addLocalVariable("step_pattern_tmp2",
Util.getJCRefType(NODE_ITERATOR_SIG),
il.getEnd(), null);
// Add a new private field if this is the main class
if (!classGen.isExternal()) {
final Field iterator =
new Field(ACC_PRIVATE,
cpg.addUtf8(iteratorName),
cpg.addUtf8(NODE_ITERATOR_SIG),
null, cpg.getConstantPool());
classGen.addField(iterator);
iteratorIndex = cpg.addFieldref(classGen.getClassName(),
iteratorName,
NODE_ITERATOR_SIG);
il.append(classGen.loadTranslet());
il.append(new GETFIELD(iteratorIndex));
il.append(DUP);
il.append(new ASTORE(iter.getIndex()));
ifBlock = il.append(new IFNONNULL(null));
il.append(classGen.loadTranslet());
}
// Compile the step created at type checking time
_step.translate(classGen, methodGen);
il.append(new ASTORE(iter.getIndex()));
// If in the main class update the field too
if (!classGen.isExternal()) {
il.append(new ALOAD(iter.getIndex()));
il.append(new PUTFIELD(iteratorIndex));
ifBlock.setTarget(il.append(NOP));
}
// Get the parent of the node on the stack
il.append(methodGen.loadDOM());
il.append(new ILOAD(node.getIndex()));
int index = cpg.addInterfaceMethodref(DOM_INTF,
GET_PARENT, GET_PARENT_SIG);
il.append(new INVOKEINTERFACE(index, 2));
// Initialize the iterator with the parent
il.append(new ALOAD(iter.getIndex()));
il.append(SWAP);
il.append(methodGen.setStartNode());
/*
* Inline loop:
*
* int node2;
* while ((node2 = iter.next()) != NodeIterator.END
* && node2 < node);
* return node2 == node;
*/
BranchHandle skipNext;
InstructionHandle begin, next;
node2 = methodGen.addLocalVariable("step_pattern_tmp3",
Util.getJCRefType(NODE_SIG),
il.getEnd(), null);
skipNext = il.append(new GOTO(null));
next = il.append(new ALOAD(iter.getIndex()));
begin = il.append(methodGen.nextNode());
il.append(DUP);
il.append(new ISTORE(node2.getIndex()));
_falseList.add(il.append(new IFLT(null))); // NodeIterator.END
il.append(new ILOAD(node2.getIndex()));
il.append(new ILOAD(node.getIndex()));
il.append(new IF_ICMPLT(next));
il.append(new ILOAD(node2.getIndex()));
il.append(new ILOAD(node.getIndex()));
_falseList.add(il.append(new IF_ICMPNE(null)));
skipNext.setTarget(begin);
| private void | translateKernel(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
if (_nodeType == DTM.ELEMENT_NODE) {
final int check = cpg.addInterfaceMethodref(DOM_INTF,
"isElement", "(I)Z");
il.append(methodGen.loadDOM());
il.append(SWAP);
il.append(new INVOKEINTERFACE(check, 2));
// Need to allow for long jumps here
final BranchHandle icmp = il.append(new IFNE(null));
_falseList.add(il.append(new GOTO_W(null)));
icmp.setTarget(il.append(NOP));
}
else if (_nodeType == DTM.ATTRIBUTE_NODE) {
final int check = cpg.addInterfaceMethodref(DOM_INTF,
"isAttribute", "(I)Z");
il.append(methodGen.loadDOM());
il.append(SWAP);
il.append(new INVOKEINTERFACE(check, 2));
// Need to allow for long jumps here
final BranchHandle icmp = il.append(new IFNE(null));
_falseList.add(il.append(new GOTO_W(null)));
icmp.setTarget(il.append(NOP));
}
else {
// context node is on the stack
final int getEType = cpg.addInterfaceMethodref(DOM_INTF,
"getExpandedTypeID",
"(I)I");
il.append(methodGen.loadDOM());
il.append(SWAP);
il.append(new INVOKEINTERFACE(getEType, 2));
il.append(new PUSH(cpg, _nodeType));
// Need to allow for long jumps here
final BranchHandle icmp = il.append(new IF_ICMPEQ(null));
_falseList.add(il.append(new GOTO_W(null)));
icmp.setTarget(il.append(NOP));
}
| private void | translateNoContext(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
// Push current node on the stack
il.append(methodGen.loadCurrentNode());
il.append(SWAP);
// Overwrite current node with matching node
il.append(methodGen.storeCurrentNode());
// If pattern not reduced then check kernel
if (!_isEpsilon) {
il.append(methodGen.loadCurrentNode());
translateKernel(classGen, methodGen);
}
// Compile the expressions within the predicates
final int n = _predicates.size();
for (int i = 0; i < n; i++) {
Predicate pred = (Predicate)_predicates.elementAt(i);
Expression exp = pred.getExpr();
exp.translateDesynthesized(classGen, methodGen);
_trueList.append(exp._trueList);
_falseList.append(exp._falseList);
}
// Backpatch true list and restore current iterator/node
InstructionHandle restore;
restore = il.append(methodGen.storeCurrentNode());
backPatchTrueList(restore);
BranchHandle skipFalse = il.append(new GOTO(null));
// Backpatch false list and restore current iterator/node
restore = il.append(methodGen.storeCurrentNode());
backPatchFalseList(restore);
_falseList.add(il.append(new GOTO(null)));
// True list falls through
skipFalse.setTarget(il.append(NOP));
| private void | translateSimpleContext(com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator classGen, com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator methodGen)
int index;
final ConstantPoolGen cpg = classGen.getConstantPool();
final InstructionList il = methodGen.getInstructionList();
// Store matching node into a local variable
LocalVariableGen match;
match = methodGen.addLocalVariable("step_pattern_tmp1",
Util.getJCRefType(NODE_SIG),
il.getEnd(), null);
il.append(new ISTORE(match.getIndex()));
// If pattern not reduced then check kernel
if (!_isEpsilon) {
il.append(new ILOAD(match.getIndex()));
translateKernel(classGen, methodGen);
}
// Push current iterator and current node on the stack
il.append(methodGen.loadCurrentNode());
il.append(methodGen.loadIterator());
// Create a new matching iterator using the matching node
index = cpg.addMethodref(MATCHING_ITERATOR, "<init>",
"(I" + NODE_ITERATOR_SIG + ")V");
// Backwards branches are prohibited if an uninitialized object is
// on the stack by section 4.9.4 of the JVM Specification, 2nd Ed.
// We don't know whether this code might contain backwards branches,
// so we mustn't create the new object until after we've created
// the suspect arguments to its constructor. Instead we calculate
// the values of the arguments to the constructor first, store them
// in temporary variables, create the object and reload the
// arguments from the temporaries to avoid the problem.
_step.translate(classGen, methodGen);
LocalVariableGen stepIteratorTemp =
methodGen.addLocalVariable("step_pattern_tmp2",
Util.getJCRefType(NODE_ITERATOR_SIG),
il.getEnd(), null);
il.append(new ASTORE(stepIteratorTemp.getIndex()));
il.append(new NEW(cpg.addClass(MATCHING_ITERATOR)));
il.append(DUP);
il.append(new ILOAD(match.getIndex()));
il.append(new ALOAD(stepIteratorTemp.getIndex()));
il.append(new INVOKESPECIAL(index));
// Get the parent of the matching node
il.append(methodGen.loadDOM());
il.append(new ILOAD(match.getIndex()));
index = cpg.addInterfaceMethodref(DOM_INTF, GET_PARENT, GET_PARENT_SIG);
il.append(new INVOKEINTERFACE(index, 2));
// Start the iterator with the parent
il.append(methodGen.setStartNode());
// Overwrite current iterator and current node
il.append(methodGen.storeIterator());
il.append(new ILOAD(match.getIndex()));
il.append(methodGen.storeCurrentNode());
// Translate the expression of the predicate
Predicate pred = (Predicate) _predicates.elementAt(0);
Expression exp = pred.getExpr();
exp.translateDesynthesized(classGen, methodGen);
// Backpatch true list and restore current iterator/node
InstructionHandle restore = il.append(methodGen.storeIterator());
il.append(methodGen.storeCurrentNode());
exp.backPatchTrueList(restore);
BranchHandle skipFalse = il.append(new GOTO(null));
// Backpatch false list and restore current iterator/node
restore = il.append(methodGen.storeIterator());
il.append(methodGen.storeCurrentNode());
exp.backPatchFalseList(restore);
_falseList.add(il.append(new GOTO(null)));
// True list falls through
skipFalse.setTarget(il.append(NOP));
| public com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type | typeCheck(com.sun.org.apache.xalan.internal.xsltc.compiler.SymbolTable stable)
if (hasPredicates()) {
// Type check all the predicates (e -> position() = e)
final int n = _predicates.size();
for (int i = 0; i < n; i++) {
final Predicate pred = (Predicate)_predicates.elementAt(i);
pred.typeCheck(stable);
}
// Analyze context cases
_contextCase = analyzeCases();
Step step = null;
// Create an instance of Step to do the translation
if (_contextCase == SIMPLE_CONTEXT) {
Predicate pred = (Predicate)_predicates.elementAt(0);
if (pred.isNthPositionFilter()) {
_contextCase = GENERAL_CONTEXT;
step = new Step(_axis, _nodeType, _predicates);
} else {
step = new Step(_axis, _nodeType, null);
}
} else if (_contextCase == GENERAL_CONTEXT) {
final int len = _predicates.size();
for (int i = 0; i < len; i++) {
((Predicate)_predicates.elementAt(i)).dontOptimize();
}
step = new Step(_axis, _nodeType, _predicates);
}
if (step != null) {
step.setParser(getParser());
step.typeCheck(stable);
_step = step;
}
}
return _axis == Axis.CHILD ? Type.Element : Type.Attribute;
|
|