You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sa...@apache.org on 2004/02/05 23:53:42 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler FilterExpr.java Predicate.java Step.java StepPattern.java

santiagopg    2004/02/05 14:53:42

  Modified:    java/src/org/apache/xalan/xsltc/compiler FilterExpr.java
                        Predicate.java Step.java StepPattern.java
  Log:
  Patch for Bugzilla 19194. I've made the following changes: (i) re-wrote Predicate.typeCheck() (ii) the predicate optimizations are turned off for FilterExpr, as they don't apply in all cases (iii) sync up Step, StepPattern and FilterExpr to accomodate the new changes. The interaction between these classes is non-trivial, and the code for some optimizations is brittle, to say the least. As part of this patch, I rolled back a patch to FilterExpr and fixed Bugzilla 25783 which wasn't really related despite what the bug report states. For the 2.0 work, it would be nice to place optimization code in separate classes so that it can be easily maintained and also easily deactivated via a command-line flag.
  
  Revision  Changes    Path
  1.10      +33 -39    xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java
  
  Index: FilterExpr.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- FilterExpr.java	19 Dec 2003 15:26:48 -0000	1.9
  +++ FilterExpr.java	5 Feb 2004 22:53:42 -0000	1.10
  @@ -80,7 +80,15 @@
   import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
   
   class FilterExpr extends Expression {
  +    
  +    /**
  +     * Primary expression of this filter. I.e., 'e' in '(e)[p1]...[pn]'.
  +     */
       private Expression   _primary;
  +    
  +    /**
  +     * Array of predicates in '(e)[p1]...[pn]'.
  +     */
       private final Vector _predicates;
   
       public FilterExpr(Expression primary, Vector predicates) {
  @@ -117,6 +125,8 @@
        * Type check a FilterParentPath. If the filter is not a node-set add a 
        * cast to node-set only if it is of reference type. This type coercion 
        * is needed for expressions like $x where $x is a parameter reference.
  +     * All optimizations are turned off before type checking underlying
  +     * predicates.
        */
       public Type typeCheck(SymbolTable stable) throws TypeCheckError {
   	Type ptype = _primary.typeCheck(stable);
  @@ -130,9 +140,11 @@
   	    }
   	}
   
  +        // Type check predicates and turn all optimizations off
   	int n = _predicates.size();
   	for (int i = 0; i < n; i++) {
  -	    Expression pred = (Expression)_predicates.elementAt(i);
  +	    Predicate pred = (Predicate) _predicates.elementAt(i);
  +            pred.dontOptimize();
   	    pred.typeCheck(stable);
   	}
   	return _type = Type.NodeSet;	
  @@ -148,26 +160,26 @@
   	}
   	else {
   	    _primary.translate(classGen, methodGen);
  -	    _primary.startIterator(classGen, methodGen);
   	}
       }
   
       /**
  -     * Translate a sequence of predicates.
  -     * Each predicate is translated by constructing an instance
  -     * of <code>CurrentNodeListIterator</code> which is initialized from
  -     * another iterator (recursive call), a filter and a closure
  -     * (call to translate on the predicate) and "this". 
  +     * Translate a sequence of predicates. Each predicate is translated 
  +     * by constructing an instance of <code>CurrentNodeListIterator</code> 
  +     * which is initialized from another iterator (recursive call), a 
  +     * filter and a closure (call to translate on the predicate) and "this". 
        */
       public void translatePredicates(ClassGenerator classGen,
   				    MethodGenerator methodGen) {
   	final ConstantPoolGen cpg = classGen.getConstantPool();
   	final InstructionList il = methodGen.getInstructionList();
   
  +        // If not predicates left, translate primary expression
   	if (_predicates.size() == 0) {
   	    translate(classGen, methodGen);
   	}
   	else {
  +            // Translate predicates from right to left
   	    final int initCNLI = cpg.addMethodref(CURRENT_NODE_LIST_ITERATOR,
   						  "<init>",
   						  "("+NODE_ITERATOR_SIG+"Z"+
  @@ -177,37 +189,19 @@
   	    Predicate predicate = (Predicate)_predicates.lastElement();
   	    _predicates.remove(predicate);
   
  -	    if (predicate.isNthPositionFilter()) {
  -		final int start = cpg.addInterfaceMethodref(NODE_ITERATOR,
  -							    "setStartNode", 
  -							    "(I)"+
  -							    NODE_ITERATOR_SIG);
  -		final int reset = cpg.addInterfaceMethodref(NODE_ITERATOR,
  -							    "reset",
  -							    "()"+
  -							    NODE_ITERATOR_SIG);
  -		translatePredicates(classGen, methodGen); // get the base itr.
  -		predicate.translate(classGen, methodGen); // get the position
  -		il.append(new INVOKEINTERFACE(start,2));
  -		il.append(new INVOKEINTERFACE(reset,1));
  -
  -		final int sngl = cpg.addMethodref(BASIS_LIBRARY_CLASS,
  -						  "getSingleNode",
  -						  "("+NODE_ITERATOR_SIG+")"+
  -						  NODE_ITERATOR_SIG);
  -		il.append(new INVOKESTATIC(sngl));
  -	    }
  -	    else {
  -		// create new CurrentNodeListIterator
  -		il.append(new NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  -		il.append(DUP);
  -		translatePredicates(classGen, methodGen); // recursive call
  -		il.append(ICONST_1);
  -		predicate.translate(classGen, methodGen);
  -		il.append(methodGen.loadCurrentNode());
  -		il.append(classGen.loadTranslet());
  -		il.append(new INVOKESPECIAL(initCNLI));
  -	    }
  +            // Create a CurrentNodeListIterator
  +            il.append(new NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  +            il.append(DUP);
  +            
  +            // Translate the rest of the predicates from right to left
  +            translatePredicates(classGen, methodGen);
  +            
  +            // Initialize CurrentNodeListIterator
  +            il.append(ICONST_1);
  +            predicate.translate(classGen, methodGen);
  +            il.append(methodGen.loadCurrentNode());
  +            il.append(classGen.loadTranslet());
  +            il.append(new INVOKESPECIAL(initCNLI));
   	}
       }
   }
  
  
  
  1.31      +157 -122  xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java
  
  Index: Predicate.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Predicate.java	15 Oct 2003 21:01:51 -0000	1.30
  +++ Predicate.java	5 Feb 2004 22:53:42 -0000	1.31
  @@ -92,36 +92,115 @@
   
   final class Predicate extends Expression implements Closure {
   
  -    private Expression _exp = null; // Expression to be compiled inside pred.
  +    /**
  +     * The predicate's expression.
  +     */
  +    private Expression _exp = null; 
  +    
  +    /**
  +     * This flag indicates if optimizations are turned on. The 
  +     * method <code>dontOptimize()</code> can be called to turn
  +     * optimizations off.
  +     */
  +    private boolean _canOptimize = true;
  +    
  +    /**
  +     * Flag indicatig if the nth position optimization is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthPositionFilter = false;
  +        
  +    /**
  +     * Flag indicatig if the nth position descendant is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthDescendant = false;
  -    private boolean _canOptimize = true;
  -    private int     _ptype = -1;
   
  +    /**
  +     * Cached node type of the expression that owns this predicate.
  +     */
  +    int _ptype = -1;
  +
  +    /**
  +     * Name of the inner class.
  +     */
       private String _className = null;
  +    
  +    /**
  +     * List of variables in closure.
  +     */
       private ArrayList _closureVars = null;
  +    
  +    /**
  +     * Reference to parent closure.
  +     */
       private Closure _parentClosure = null;
   
  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Expression _value = null;
  +    
  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Step _step = null;
  +
  +    /**
  +     * Initializes a predicate. 
  +     */
       public Predicate(Expression exp) {
  -	(_exp = exp).setParent(this);
  +        _exp = exp;
  +        _exp.setParent(this);
  +
       }
   
  +    /** 
  +     * Set the parser for this expression.
  +     */
       public void setParser(Parser parser) {
   	super.setParser(parser);
   	_exp.setParser(parser);
       }
   
  -    public boolean isNthDescendant() {
  -	return _nthDescendant;
  -    }
  -
  +    /**
  +     * Returns a boolean value indicating if the nth position optimization
  +     * is on. Must be call after type checking!
  +     */
       public boolean isNthPositionFilter() {
   	return _nthPositionFilter;
       }
   
  +    /**
  +     * Returns a boolean value indicating if the nth descendant optimization
  +     * is on. Must be call after type checking!
  +     */
  +    public boolean isNthDescendant() {
  +	return _nthDescendant;
  +    }
  +
  +    /**
  +     * Turns off all optimizations for this predicate.
  +     */
       public void dontOptimize() {
   	_canOptimize = false;
       }
  +    
  +    /**
  +     * Returns true if the expression in this predicate contains a call 
  +     * to position().
  +     */
  +    public boolean hasPositionCall() {
  +	return _exp.hasPositionCall();
  +    }
  +
  +    /**
  +     * Returns true if the expression in this predicate contains a call 
  +     * to last().
  +     */
  +    public boolean hasLastCall() {
  +	return _exp.hasLastCall();
  +    }
   
       // -- Begin Closure interface --------------------
   
  @@ -183,6 +262,10 @@
   
       // -- End Closure interface ----------------------
   
  +    /**
  +     * Returns the node type of the expression owning this predicate. The
  +     * return value is cached in <code>_ptype</code>.
  +     */
       public int getPosType() {
   	if (_ptype == -1) {
   	    SyntaxTreeNode parent = getParent();
  @@ -220,10 +303,7 @@
       }
   
       public String toString() {
  -	if (isNthPositionFilter())
  -	    return "pred([" + _exp + "],"+getPosType()+")";
  -	else
  -	    return "pred(" + _exp + ')';
  +        return "pred(" + _exp + ')';
       }
   	
       /**
  @@ -232,9 +312,12 @@
        * Note that if the expression is a parameter, we cannot distinguish
        * at compile time if its type is number or not. Hence, expressions of 
        * reference type are always converted to booleans.
  +     *
  +     * This method may be called twice, before and after calling
  +     * <code>dontOptimize()</code>. If so, the second time it should honor
  +     * the new value of <code>_canOptimize</code>.
        */
  -    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  -
  +    public Type typeCheck(SymbolTable stable) throws TypeCheckError {        
   	Type texp = _exp.typeCheck(stable);
   
   	// We need explicit type information for reference types - no good!
  @@ -253,96 +336,50 @@
   
   	// Numerical types will be converted to a position filter
   	if (texp instanceof NumberType) {
  -
   	    // Cast any numerical types to an integer
   	    if (texp instanceof IntType == false) {
   		_exp = new CastExpr(_exp, Type.Int);
   	    }
  -
  -	    SyntaxTreeNode parent = getParent();
  -        
  -	    // Expand [last()] into [position() = last()]
  -	    if ((_exp instanceof LastCall) ||
  -                //Fix for bug 22949, check for last() for any expression returns
  -                // NumberType            
  -                 _exp.hasLastCall()||
  -		(parent instanceof Pattern) ||
  -		(parent instanceof FilterExpr)) {
  -
  -		if (parent instanceof Pattern && !(_exp instanceof LastCall)) {
  - 		    _nthPositionFilter = _canOptimize;
  -		}
  -		else if (parent instanceof FilterExpr) {
  -		    FilterExpr filter = (FilterExpr)parent;
  -		    Expression fexp = filter.getExpr();
  -
  -		    if (fexp instanceof KeyCall)
  -			_canOptimize = false;
  -		    else if (fexp instanceof VariableRefBase)
  -		        _canOptimize = false;
  -		    else if (fexp instanceof ParentLocationPath)
  -			_canOptimize = false;
  -		    else if (fexp instanceof FilterParentPath)
  -			_canOptimize = false;
  -		    else if (fexp instanceof UnionPathExpr)
  -			_canOptimize = false;
  -		    else if (_exp.hasPositionCall() && _exp.hasLastCall())
  -			_canOptimize = false;
  -		    else if (filter.getParent() instanceof FilterParentPath)
  -			_canOptimize = false;
  -		    if (_canOptimize)
  -			_nthPositionFilter = true;
  -		}
  -
  -                // If this case can be optimized, leave the expression as
  -                // an integer.  Otherwise, turn it into a comparison with
  -                // the position() function.
  +                    
  +            if (_canOptimize) {
  +                // Nth position optimization. Expression must not depend on context
  +                _nthPositionFilter = 
  +                    !_exp.hasLastCall() && !_exp.hasPositionCall();
  +                
  +                // _nthDescendant optimization - only if _nthPositionFilter is on
                   if (_nthPositionFilter) {
  -                   return _type = Type.NodeSet;
  -                } else {
  -                   final QName position =
  -                                getParser().getQNameIgnoreDefaultNs("position");
  -
  -                   final PositionCall positionCall =
  -                                               new PositionCall(position);
  -                   positionCall.setParser(getParser());
  -                   positionCall.setParent(this);
  -
  -                   _exp = new EqualityExpr(EqualityExpr.EQ, positionCall,
  -                                            _exp);
  -                   if (_exp.typeCheck(stable) != Type.Boolean) {
  -                       _exp = new CastExpr(_exp, Type.Boolean);
  -                   }
  -
  -                   return _type = Type.Boolean;
  +                    SyntaxTreeNode parent = getParent();
  +                    _nthDescendant = (parent instanceof Step) &&
  +                        (parent.getParent() instanceof AbsoluteLocationPath);
  +                    return _type = Type.NodeSet;
                   }
  -	    }
  -	    // Use NthPositionIterator to handle [position()] or [a]
  -	    else {
  -		if ((parent != null) && (parent instanceof Step)) {
  -		    parent = parent.getParent();
  -		    if ((parent != null) &&
  -			(parent instanceof AbsoluteLocationPath)) {
  -			// TODO: Special case for "//*[n]" pattern....
  -			_nthDescendant = true;
  -			return _type = Type.NodeSet;
  -		    }
  -		}
  -		_nthPositionFilter = true;
  -		return _type = Type.NodeSet;
  -	    }
  -	}
  -	else if (texp instanceof BooleanType) {
  -	    if (_exp.hasPositionCall())
  -		_nthPositionFilter = true;
  +            }          
  +
  +           // Reset optimization flags
  +            _nthPositionFilter = _nthDescendant = false;
  +            
  +           // Otherwise, expand [e] to [position() = e]
  +           final QName position = 
  +                getParser().getQNameIgnoreDefaultNs("position");
  +           final PositionCall positionCall =
  +                new PositionCall(position);
  +           positionCall.setParser(getParser());
  +           positionCall.setParent(this);
  +
  +           _exp = new EqualityExpr(EqualityExpr.EQ, positionCall,
  +                                    _exp);
  +           if (_exp.typeCheck(stable) != Type.Boolean) {
  +               _exp = new CastExpr(_exp, Type.Boolean);
  +           }
  +           return _type = Type.Boolean;
   	}
  -	// All other types will be handled as boolean values
   	else {
  -	    _exp = new CastExpr(_exp, Type.Boolean);
  +            // All other types will be handled as boolean values
  +	    if (texp instanceof BooleanType == false) {
  +		_exp = new CastExpr(_exp, Type.Boolean);
  +            }
  +            return _type = Type.Boolean;
   	}
  -	_nthPositionFilter = false;
  -
  -	return _type = Type.Boolean;
       }
   	
       /**
  @@ -447,9 +484,6 @@
   	return (getStep() != null && getCompareValue() != null);
       }
   
  -    private Expression _value = null;
  -    private Step _step = null;
  -
       /**
        * Utility method for optimisation. See isNodeValueTest()
        */
  @@ -517,29 +551,6 @@
        * two references on the stack: a reference to a newly created
        * filter object and a reference to the predicate's closure.
        */
  -    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  -
  -	final ConstantPoolGen cpg = classGen.getConstantPool();
  -	final InstructionList il = methodGen.getInstructionList();
  -
  -	if (_nthPositionFilter || _nthDescendant) {
  -	    _exp.translate(classGen, methodGen);
  -	}
  -	else if (isNodeValueTest() && (getParent() instanceof Step)) {
  -	    _value.translate(classGen, methodGen);
  -	    il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  -	    il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  -	}
  -	else {
  -	    translateFilter(classGen, methodGen);
  -	}
  -    }
  -
  -    /**
  -     * Translate a predicate expression. This translation pushes
  -     * two references on the stack: a reference to a newly created
  -     * filter object and a reference to the predicate's closure.
  -     */
       public void translateFilter(ClassGenerator classGen,
   				MethodGenerator methodGen) 
       {
  @@ -588,6 +599,30 @@
   	    il.append(new PUTFIELD(
   		    cpg.addFieldref(_className, var.getVariable(), 
   			varType.toSignature())));
  +	}
  +    }
  +    
  +    /**
  +     * Translate a predicate expression. If non of the optimizations apply
  +     * then this translation pushes two references on the stack: a reference 
  +     * to a newly created filter object and a reference to the predicate's 
  +     * closure. See class <code>Step</code> for further details.
  +     */
  +    public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  +
  +	final ConstantPoolGen cpg = classGen.getConstantPool();
  +	final InstructionList il = methodGen.getInstructionList();
  +
  +	if (_nthPositionFilter || _nthDescendant) {
  +	    _exp.translate(classGen, methodGen);
  +	}
  +	else if (isNodeValueTest() && (getParent() instanceof Step)) {
  +	    _value.translate(classGen, methodGen);
  +	    il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  +	    il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  +	}
  +	else {
  +	    translateFilter(classGen, methodGen);
   	}
       }
   }
  
  
  
  1.44      +4 -3      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java
  
  Index: Step.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Step.java	1 Apr 2003 21:09:00 -0000	1.43
  +++ Step.java	5 Feb 2004 22:53:42 -0000	1.44
  @@ -417,11 +417,12 @@
   						GET_NODE_VALUE_ITERATOR,
   						GET_NODE_VALUE_ITERATOR_SIG);
   		il.append(new INVOKEINTERFACE(idx, 5));
  -	    }
  +	    }            
   	    // Handle '//*[n]' expression
   	    else if (predicate.isNthDescendant()) {
   		il.append(methodGen.loadDOM());
  -		il.append(new ICONST(NodeTest.ELEMENT));
  +		// il.append(new ICONST(NodeTest.ELEMENT));
  +		il.append(new ICONST(predicate.getPosType()));
   		predicate.translate(classGen, methodGen);
   		il.append(new ICONST(0));
   		idx = cpg.addInterfaceMethodref(DOM_INTF,
  
  
  
  1.23      +7 -4      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java
  
  Index: StepPattern.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- StepPattern.java	1 Apr 2003 21:09:00 -0000	1.22
  +++ StepPattern.java	5 Feb 2004 22:53:42 -0000	1.23
  @@ -202,9 +202,11 @@
   	final int n = _predicates.size();
   
   	for (int i = 0; i < n && noContext; i++) {
  -	    final Predicate pred = (Predicate)_predicates.elementAt(i);
  -	    if (pred.getExpr().hasPositionCall()
  -                || pred.isNthPositionFilter()) {
  +	    Predicate pred = (Predicate) _predicates.elementAt(i);
  +            if (pred.isNthPositionFilter() || 
  +                pred.hasPositionCall() || 
  +                pred.hasLastCall()) 
  +            {
   		noContext = false;
   	    }
   	}
  @@ -253,6 +255,7 @@
   
                   step = new Step(_axis, _nodeType, _predicates);
               }
  +            
               if (step != null) {
                   step.setParser(getParser());
                   step.typeCheck(stable);
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org


Re: cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler FilterExpr.java Predicate.java Step.java StepPattern.java

Posted by Igor Hersht <ig...@ca.ibm.com>.



> For the 2.0 work, it would be nice to place optimization code in
>separate classes so that it can be easily maintained and also easily
>deactivated via a command-line flag.

I think it an important idea. I was trying to suggest too.
That is how C++ compilers (I know) work. It is not only makes code
better, but also very important if we will have XSLTC debugger.
A debugger  cannot work properly if it has changed (optimized)
code. I think we should talk about this idea in our team.
We are doing a lot of 2.0 work (internally so far) and adapting
the idea could change our design.




Igor Hersht
XSLT Development
IBM Canada Ltd., 8200 Warden Avenue, Markham, Ontario L6G 1C7
Office D2-260, Phone (905)413-3240 ; FAX  (905)413-4839


                                                                           
             santiagopg@apache                                             
             .org                                                          
                                                                        To 
             02/05/2004 05:53          xml-xalan-cvs@apache.org            
             PM                                                         cc 
                                                                           
                                                                   Subject 
             Please respond to         cvs commit:                         
                 xalan-dev             xml-xalan/java/src/org/apache/xalan 
                                       /xsltc/compiler FilterExpr.java     
                                       Predicate.java Step.java            
                                       StepPattern.java                    
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




santiagopg    2004/02/05 14:53:42

  Modified:    java/src/org/apache/xalan/xsltc/compiler FilterExpr.java
                        Predicate.java Step.java StepPattern.java
  Log:
  Patch for Bugzilla 19194. I've made the following changes: (i) re-wrote
Predicate.typeCheck() (ii) the predicate optimizations are turned off for
FilterExpr, as they don't apply in all cases (iii) sync up Step,
StepPattern and FilterExpr to accomodate the new changes. The interaction
between these classes is non-trivial, and the code for some optimizations
is brittle, to say the least. As part of this patch, I rolled back a patch
to FilterExpr and fixed Bugzilla 25783 which wasn't really related despite
what the bug report states. For the 2.0 work, it would be nice to place
optimization code in separate classes so that it can be easily maintained
and also easily deactivated via a command-line flag.

  Revision  Changes    Path
  1.10      +33 -39
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java

  Index: FilterExpr.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java,v

  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- FilterExpr.java          19 Dec 2003 15:26:48 -0000          1.9
  +++ FilterExpr.java          5 Feb 2004 22:53:42 -0000           1.10
  @@ -80,7 +80,15 @@
   import org.apache.xalan.xsltc.compiler.util.TypeCheckError;

   class FilterExpr extends Expression {
  +
  +    /**
  +     * Primary expression of this filter. I.e., 'e' in '(e)[p1]...[pn]'.
  +     */
       private Expression   _primary;
  +
  +    /**
  +     * Array of predicates in '(e)[p1]...[pn]'.
  +     */
       private final Vector _predicates;

       public FilterExpr(Expression primary, Vector predicates) {
  @@ -117,6 +125,8 @@
        * Type check a FilterParentPath. If the filter is not a node-set
add a
        * cast to node-set only if it is of reference type. This type
coercion
        * is needed for expressions like $x where $x is a parameter
reference.
  +     * All optimizations are turned off before type checking underlying
  +     * predicates.
        */
       public Type typeCheck(SymbolTable stable) throws TypeCheckError {
             Type ptype = _primary.typeCheck(stable);
  @@ -130,9 +140,11 @@
                 }
             }

  +        // Type check predicates and turn all optimizations off
             int n = _predicates.size();
             for (int i = 0; i < n; i++) {
  -              Expression pred = (Expression)_predicates.elementAt(i);
  +              Predicate pred = (Predicate) _predicates.elementAt(i);
  +            pred.dontOptimize();
                 pred.typeCheck(stable);
             }
             return _type = Type.NodeSet;
  @@ -148,26 +160,26 @@
             }
             else {
                 _primary.translate(classGen, methodGen);
  -              _primary.startIterator(classGen, methodGen);
             }
       }

       /**
  -     * Translate a sequence of predicates.
  -     * Each predicate is translated by constructing an instance
  -     * of <code>CurrentNodeListIterator</code> which is initialized from
  -     * another iterator (recursive call), a filter and a closure
  -     * (call to translate on the predicate) and "this".
  +     * Translate a sequence of predicates. Each predicate is translated
  +     * by constructing an instance of
<code>CurrentNodeListIterator</code>
  +     * which is initialized from another iterator (recursive call), a
  +     * filter and a closure (call to translate on the predicate) and
"this".
        */
       public void translatePredicates(ClassGenerator classGen,
                                                     MethodGenerator
methodGen) {
             final ConstantPoolGen cpg = classGen.getConstantPool();
             final InstructionList il = methodGen.getInstructionList();

  +        // If not predicates left, translate primary expression
             if (_predicates.size() == 0) {
                 translate(classGen, methodGen);
             }
             else {
  +            // Translate predicates from right to left
                 final int initCNLI =
cpg.addMethodref(CURRENT_NODE_LIST_ITERATOR,

"<init>",

"("+NODE_ITERATOR_SIG+"Z"+
  @@ -177,37 +189,19 @@
                 Predicate predicate =
(Predicate)_predicates.lastElement();
                 _predicates.remove(predicate);

  -              if (predicate.isNthPositionFilter()) {
  -                      final int start =
cpg.addInterfaceMethodref(NODE_ITERATOR,
  -
           "setStartNode",
  -
           "(I)"+
  -
           NODE_ITERATOR_SIG);
  -                      final int reset =
cpg.addInterfaceMethodref(NODE_ITERATOR,
  -
           "reset",
  -
           "()"+
  -
           NODE_ITERATOR_SIG);
  -                      translatePredicates(classGen, methodGen); // get
the base itr.
  -                      predicate.translate(classGen, methodGen); // get
the position
  -                      il.append(new INVOKEINTERFACE(start,2));
  -                      il.append(new INVOKEINTERFACE(reset,1));
  -
  -                      final int sngl =
cpg.addMethodref(BASIS_LIBRARY_CLASS,
  -
"getSingleNode",
  -
"("+NODE_ITERATOR_SIG+")"+
  -
NODE_ITERATOR_SIG);
  -                      il.append(new INVOKESTATIC(sngl));
  -              }
  -              else {
  -                      // create new CurrentNodeListIterator
  -                      il.append(new
NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  -                      il.append(DUP);
  -                      translatePredicates(classGen, methodGen); //
recursive call
  -                      il.append(ICONST_1);
  -                      predicate.translate(classGen, methodGen);
  -                      il.append(methodGen.loadCurrentNode());
  -                      il.append(classGen.loadTranslet());
  -                      il.append(new INVOKESPECIAL(initCNLI));
  -              }
  +            // Create a CurrentNodeListIterator
  +            il.append(new
NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  +            il.append(DUP);
  +
  +            // Translate the rest of the predicates from right to left
  +            translatePredicates(classGen, methodGen);
  +
  +            // Initialize CurrentNodeListIterator
  +            il.append(ICONST_1);
  +            predicate.translate(classGen, methodGen);
  +            il.append(methodGen.loadCurrentNode());
  +            il.append(classGen.loadTranslet());
  +            il.append(new INVOKESPECIAL(initCNLI));
             }
       }
   }



  1.31      +157 -122
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java

  Index: Predicate.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java,v

  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Predicate.java           15 Oct 2003 21:01:51 -0000          1.30
  +++ Predicate.java           5 Feb 2004 22:53:42 -0000           1.31
  @@ -92,36 +92,115 @@

   final class Predicate extends Expression implements Closure {

  -    private Expression _exp = null; // Expression to be compiled inside
pred.
  +    /**
  +     * The predicate's expression.
  +     */
  +    private Expression _exp = null;
  +
  +    /**
  +     * This flag indicates if optimizations are turned on. The
  +     * method <code>dontOptimize()</code> can be called to turn
  +     * optimizations off.
  +     */
  +    private boolean _canOptimize = true;
  +
  +    /**
  +     * Flag indicatig if the nth position optimization is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthPositionFilter = false;
  +
  +    /**
  +     * Flag indicatig if the nth position descendant is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthDescendant = false;
  -    private boolean _canOptimize = true;
  -    private int     _ptype = -1;

  +    /**
  +     * Cached node type of the expression that owns this predicate.
  +     */
  +    int _ptype = -1;
  +
  +    /**
  +     * Name of the inner class.
  +     */
       private String _className = null;
  +
  +    /**
  +     * List of variables in closure.
  +     */
       private ArrayList _closureVars = null;
  +
  +    /**
  +     * Reference to parent closure.
  +     */
       private Closure _parentClosure = null;

  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Expression _value = null;
  +
  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Step _step = null;
  +
  +    /**
  +     * Initializes a predicate.
  +     */
       public Predicate(Expression exp) {
  -          (_exp = exp).setParent(this);
  +        _exp = exp;
  +        _exp.setParent(this);
  +
       }

  +    /**
  +     * Set the parser for this expression.
  +     */
       public void setParser(Parser parser) {
             super.setParser(parser);
             _exp.setParser(parser);
       }

  -    public boolean isNthDescendant() {
  -          return _nthDescendant;
  -    }
  -
  +    /**
  +     * Returns a boolean value indicating if the nth position
optimization
  +     * is on. Must be call after type checking!
  +     */
       public boolean isNthPositionFilter() {
             return _nthPositionFilter;
       }

  +    /**
  +     * Returns a boolean value indicating if the nth descendant
optimization
  +     * is on. Must be call after type checking!
  +     */
  +    public boolean isNthDescendant() {
  +          return _nthDescendant;
  +    }
  +
  +    /**
  +     * Turns off all optimizations for this predicate.
  +     */
       public void dontOptimize() {
             _canOptimize = false;
       }
  +
  +    /**
  +     * Returns true if the expression in this predicate contains a call
  +     * to position().
  +     */
  +    public boolean hasPositionCall() {
  +          return _exp.hasPositionCall();
  +    }
  +
  +    /**
  +     * Returns true if the expression in this predicate contains a call
  +     * to last().
  +     */
  +    public boolean hasLastCall() {
  +          return _exp.hasLastCall();
  +    }

       // -- Begin Closure interface --------------------

  @@ -183,6 +262,10 @@

       // -- End Closure interface ----------------------

  +    /**
  +     * Returns the node type of the expression owning this predicate.
The
  +     * return value is cached in <code>_ptype</code>.
  +     */
       public int getPosType() {
             if (_ptype == -1) {
                 SyntaxTreeNode parent = getParent();
  @@ -220,10 +303,7 @@
       }

       public String toString() {
  -          if (isNthPositionFilter())
  -              return "pred([" + _exp + "],"+getPosType()+")";
  -          else
  -              return "pred(" + _exp + ')';
  +        return "pred(" + _exp + ')';
       }

       /**
  @@ -232,9 +312,12 @@
        * Note that if the expression is a parameter, we cannot distinguish
        * at compile time if its type is number or not. Hence, expressions
of
        * reference type are always converted to booleans.
  +     *
  +     * This method may be called twice, before and after calling
  +     * <code>dontOptimize()</code>. If so, the second time it should
honor
  +     * the new value of <code>_canOptimize</code>.
        */
  -    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  -
  +    public Type typeCheck(SymbolTable stable) throws TypeCheckError {

             Type texp = _exp.typeCheck(stable);

             // We need explicit type information for reference types - no
good!
  @@ -253,96 +336,50 @@

             // Numerical types will be converted to a position filter
             if (texp instanceof NumberType) {
  -
                 // Cast any numerical types to an integer
                 if (texp instanceof IntType == false) {
                         _exp = new CastExpr(_exp, Type.Int);
                 }
  -
  -              SyntaxTreeNode parent = getParent();
  -
  -              // Expand [last()] into [position() = last()]
  -              if ((_exp instanceof LastCall) ||
  -                //Fix for bug 22949, check for last() for any expression
returns
  -                // NumberType
  -                 _exp.hasLastCall()||
  -                      (parent instanceof Pattern) ||
  -                      (parent instanceof FilterExpr)) {
  -
  -                      if (parent instanceof Pattern && !(_exp instanceof
LastCall)) {
  -                          _nthPositionFilter = _canOptimize;
  -                      }
  -                      else if (parent instanceof FilterExpr) {
  -                          FilterExpr filter = (FilterExpr)parent;
  -                          Expression fexp = filter.getExpr();
  -
  -                          if (fexp instanceof KeyCall)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof VariableRefBase)
  -                              _canOptimize = false;
  -                          else if (fexp instanceof ParentLocationPath)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof FilterParentPath)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof UnionPathExpr)
  -                                  _canOptimize = false;
  -                          else if (_exp.hasPositionCall() &&
_exp.hasLastCall())
  -                                  _canOptimize = false;
  -                          else if (filter.getParent() instanceof
FilterParentPath)
  -                                  _canOptimize = false;
  -                          if (_canOptimize)
  -                                  _nthPositionFilter = true;
  -                      }
  -
  -                // If this case can be optimized, leave the expression
as
  -                // an integer.  Otherwise, turn it into a comparison
with
  -                // the position() function.
  +
  +            if (_canOptimize) {
  +                // Nth position optimization. Expression must not depend
on context
  +                _nthPositionFilter =
  +                    !_exp.hasLastCall() && !_exp.hasPositionCall();
  +
  +                // _nthDescendant optimization - only if
_nthPositionFilter is on
                   if (_nthPositionFilter) {
  -                   return _type = Type.NodeSet;
  -                } else {
  -                   final QName position =
  -
getParser().getQNameIgnoreDefaultNs("position");
  -
  -                   final PositionCall positionCall =
  -                                               new
PositionCall(position);
  -                   positionCall.setParser(getParser());
  -                   positionCall.setParent(this);
  -
  -                   _exp = new EqualityExpr(EqualityExpr.EQ,
positionCall,
  -                                            _exp);
  -                   if (_exp.typeCheck(stable) != Type.Boolean) {
  -                       _exp = new CastExpr(_exp, Type.Boolean);
  -                   }
  -
  -                   return _type = Type.Boolean;
  +                    SyntaxTreeNode parent = getParent();
  +                    _nthDescendant = (parent instanceof Step) &&
  +                        (parent.getParent() instanceof
AbsoluteLocationPath);
  +                    return _type = Type.NodeSet;
                   }
  -              }
  -              // Use NthPositionIterator to handle [position()] or [a]
  -              else {
  -                      if ((parent != null) && (parent instanceof Step))
{
  -                          parent = parent.getParent();
  -                          if ((parent != null) &&
  -                                  (parent instanceof
AbsoluteLocationPath)) {
  -                                  // TODO: Special case for "//*[n]"
pattern....
  -                                  _nthDescendant = true;
  -                                  return _type = Type.NodeSet;
  -                          }
  -                      }
  -                      _nthPositionFilter = true;
  -                      return _type = Type.NodeSet;
  -              }
  -          }
  -          else if (texp instanceof BooleanType) {
  -              if (_exp.hasPositionCall())
  -                      _nthPositionFilter = true;
  +            }
  +
  +           // Reset optimization flags
  +            _nthPositionFilter = _nthDescendant = false;
  +
  +           // Otherwise, expand [e] to [position() = e]
  +           final QName position =
  +                getParser().getQNameIgnoreDefaultNs("position");
  +           final PositionCall positionCall =
  +                new PositionCall(position);
  +           positionCall.setParser(getParser());
  +           positionCall.setParent(this);
  +
  +           _exp = new EqualityExpr(EqualityExpr.EQ, positionCall,
  +                                    _exp);
  +           if (_exp.typeCheck(stable) != Type.Boolean) {
  +               _exp = new CastExpr(_exp, Type.Boolean);
  +           }
  +           return _type = Type.Boolean;
             }
  -          // All other types will be handled as boolean values
             else {
  -              _exp = new CastExpr(_exp, Type.Boolean);
  +            // All other types will be handled as boolean values
  +              if (texp instanceof BooleanType == false) {
  +                      _exp = new CastExpr(_exp, Type.Boolean);
  +            }
  +            return _type = Type.Boolean;
             }
  -          _nthPositionFilter = false;
  -
  -          return _type = Type.Boolean;
       }

       /**
  @@ -447,9 +484,6 @@
             return (getStep() != null && getCompareValue() != null);
       }

  -    private Expression _value = null;
  -    private Step _step = null;
  -
       /**
        * Utility method for optimisation. See isNodeValueTest()
        */
  @@ -517,29 +551,6 @@
        * two references on the stack: a reference to a newly created
        * filter object and a reference to the predicate's closure.
        */
  -    public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
  -
  -          final ConstantPoolGen cpg = classGen.getConstantPool();
  -          final InstructionList il = methodGen.getInstructionList();
  -
  -          if (_nthPositionFilter || _nthDescendant) {
  -              _exp.translate(classGen, methodGen);
  -          }
  -          else if (isNodeValueTest() && (getParent() instanceof Step)) {
  -              _value.translate(classGen, methodGen);
  -              il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  -              il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  -          }
  -          else {
  -              translateFilter(classGen, methodGen);
  -          }
  -    }
  -
  -    /**
  -     * Translate a predicate expression. This translation pushes
  -     * two references on the stack: a reference to a newly created
  -     * filter object and a reference to the predicate's closure.
  -     */
       public void translateFilter(ClassGenerator classGen,
                                                 MethodGenerator methodGen)

       {
  @@ -588,6 +599,30 @@
                 il.append(new PUTFIELD(
                             cpg.addFieldref(_className, var.getVariable(),

                                     varType.toSignature())));
  +          }
  +    }
  +
  +    /**
  +     * Translate a predicate expression. If non of the optimizations
apply
  +     * then this translation pushes two references on the stack: a
reference
  +     * to a newly created filter object and a reference to the
predicate's
  +     * closure. See class <code>Step</code> for further details.
  +     */
  +    public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
  +
  +          final ConstantPoolGen cpg = classGen.getConstantPool();
  +          final InstructionList il = methodGen.getInstructionList();
  +
  +          if (_nthPositionFilter || _nthDescendant) {
  +              _exp.translate(classGen, methodGen);
  +          }
  +          else if (isNodeValueTest() && (getParent() instanceof Step)) {
  +              _value.translate(classGen, methodGen);
  +              il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  +              il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  +          }
  +          else {
  +              translateFilter(classGen, methodGen);
             }
       }
   }



  1.44      +4 -3
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java

  Index: Step.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Step.java          1 Apr 2003 21:09:00 -0000           1.43
  +++ Step.java          5 Feb 2004 22:53:42 -0000           1.44
  @@ -417,11 +417,12 @@

GET_NODE_VALUE_ITERATOR,

GET_NODE_VALUE_ITERATOR_SIG);
                         il.append(new INVOKEINTERFACE(idx, 5));
  -              }
  +              }
                 // Handle '//*[n]' expression
                 else if (predicate.isNthDescendant()) {
                         il.append(methodGen.loadDOM());
  -                      il.append(new ICONST(NodeTest.ELEMENT));
  +                      // il.append(new ICONST(NodeTest.ELEMENT));
  +                      il.append(new ICONST(predicate.getPosType()));
                         predicate.translate(classGen, methodGen);
                         il.append(new ICONST(0));
                         idx = cpg.addInterfaceMethodref(DOM_INTF,



  1.23      +7 -4
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java

  Index: StepPattern.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java,v

  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- StepPattern.java         1 Apr 2003 21:09:00 -0000           1.22
  +++ StepPattern.java         5 Feb 2004 22:53:42 -0000           1.23
  @@ -202,9 +202,11 @@
             final int n = _predicates.size();

             for (int i = 0; i < n && noContext; i++) {
  -              final Predicate pred =
(Predicate)_predicates.elementAt(i);
  -              if (pred.getExpr().hasPositionCall()
  -                || pred.isNthPositionFilter()) {
  +              Predicate pred = (Predicate) _predicates.elementAt(i);
  +            if (pred.isNthPositionFilter() ||
  +                pred.hasPositionCall() ||
  +                pred.hasLastCall())
  +            {
                         noContext = false;
                 }
             }
  @@ -253,6 +255,7 @@

                   step = new Step(_axis, _nodeType, _predicates);
               }
  +
               if (step != null) {
                   step.setParser(getParser());
                   step.typeCheck(stable);




---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org





Re: cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler FilterExpr.java Predicate.java Step.java StepPattern.java

Posted by Igor Hersht <ig...@ca.ibm.com>.



> For the 2.0 work, it would be nice to place optimization code in
>separate classes so that it can be easily maintained and also easily
>deactivated via a command-line flag.

I think it an important idea. I was trying to suggest too.
That is how C++ compilers (I know) work. It is not only makes code
better, but also very important if we will have XSLTC debugger.
A debugger  cannot work properly if it has changed (optimized)
code. I think we should talk about this idea in our team.
We are doing a lot of 2.0 work (internally so far) and adapting
the idea could change our design.




Igor Hersht
XSLT Development
IBM Canada Ltd., 8200 Warden Avenue, Markham, Ontario L6G 1C7
Office D2-260, Phone (905)413-3240 ; FAX  (905)413-4839


                                                                           
             santiagopg@apache                                             
             .org                                                          
                                                                        To 
             02/05/2004 05:53          xml-xalan-cvs@apache.org            
             PM                                                         cc 
                                                                           
                                                                   Subject 
             Please respond to         cvs commit:                         
                 xalan-dev             xml-xalan/java/src/org/apache/xalan 
                                       /xsltc/compiler FilterExpr.java     
                                       Predicate.java Step.java            
                                       StepPattern.java                    
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           
                                                                           




santiagopg    2004/02/05 14:53:42

  Modified:    java/src/org/apache/xalan/xsltc/compiler FilterExpr.java
                        Predicate.java Step.java StepPattern.java
  Log:
  Patch for Bugzilla 19194. I've made the following changes: (i) re-wrote
Predicate.typeCheck() (ii) the predicate optimizations are turned off for
FilterExpr, as they don't apply in all cases (iii) sync up Step,
StepPattern and FilterExpr to accomodate the new changes. The interaction
between these classes is non-trivial, and the code for some optimizations
is brittle, to say the least. As part of this patch, I rolled back a patch
to FilterExpr and fixed Bugzilla 25783 which wasn't really related despite
what the bug report states. For the 2.0 work, it would be nice to place
optimization code in separate classes so that it can be easily maintained
and also easily deactivated via a command-line flag.

  Revision  Changes    Path
  1.10      +33 -39
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java

  Index: FilterExpr.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/FilterExpr.java,v

  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- FilterExpr.java          19 Dec 2003 15:26:48 -0000          1.9
  +++ FilterExpr.java          5 Feb 2004 22:53:42 -0000           1.10
  @@ -80,7 +80,15 @@
   import org.apache.xalan.xsltc.compiler.util.TypeCheckError;

   class FilterExpr extends Expression {
  +
  +    /**
  +     * Primary expression of this filter. I.e., 'e' in '(e)[p1]...[pn]'.
  +     */
       private Expression   _primary;
  +
  +    /**
  +     * Array of predicates in '(e)[p1]...[pn]'.
  +     */
       private final Vector _predicates;

       public FilterExpr(Expression primary, Vector predicates) {
  @@ -117,6 +125,8 @@
        * Type check a FilterParentPath. If the filter is not a node-set
add a
        * cast to node-set only if it is of reference type. This type
coercion
        * is needed for expressions like $x where $x is a parameter
reference.
  +     * All optimizations are turned off before type checking underlying
  +     * predicates.
        */
       public Type typeCheck(SymbolTable stable) throws TypeCheckError {
             Type ptype = _primary.typeCheck(stable);
  @@ -130,9 +140,11 @@
                 }
             }

  +        // Type check predicates and turn all optimizations off
             int n = _predicates.size();
             for (int i = 0; i < n; i++) {
  -              Expression pred = (Expression)_predicates.elementAt(i);
  +              Predicate pred = (Predicate) _predicates.elementAt(i);
  +            pred.dontOptimize();
                 pred.typeCheck(stable);
             }
             return _type = Type.NodeSet;
  @@ -148,26 +160,26 @@
             }
             else {
                 _primary.translate(classGen, methodGen);
  -              _primary.startIterator(classGen, methodGen);
             }
       }

       /**
  -     * Translate a sequence of predicates.
  -     * Each predicate is translated by constructing an instance
  -     * of <code>CurrentNodeListIterator</code> which is initialized from
  -     * another iterator (recursive call), a filter and a closure
  -     * (call to translate on the predicate) and "this".
  +     * Translate a sequence of predicates. Each predicate is translated
  +     * by constructing an instance of
<code>CurrentNodeListIterator</code>
  +     * which is initialized from another iterator (recursive call), a
  +     * filter and a closure (call to translate on the predicate) and
"this".
        */
       public void translatePredicates(ClassGenerator classGen,
                                                     MethodGenerator
methodGen) {
             final ConstantPoolGen cpg = classGen.getConstantPool();
             final InstructionList il = methodGen.getInstructionList();

  +        // If not predicates left, translate primary expression
             if (_predicates.size() == 0) {
                 translate(classGen, methodGen);
             }
             else {
  +            // Translate predicates from right to left
                 final int initCNLI =
cpg.addMethodref(CURRENT_NODE_LIST_ITERATOR,

"<init>",

"("+NODE_ITERATOR_SIG+"Z"+
  @@ -177,37 +189,19 @@
                 Predicate predicate =
(Predicate)_predicates.lastElement();
                 _predicates.remove(predicate);

  -              if (predicate.isNthPositionFilter()) {
  -                      final int start =
cpg.addInterfaceMethodref(NODE_ITERATOR,
  -
           "setStartNode",
  -
           "(I)"+
  -
           NODE_ITERATOR_SIG);
  -                      final int reset =
cpg.addInterfaceMethodref(NODE_ITERATOR,
  -
           "reset",
  -
           "()"+
  -
           NODE_ITERATOR_SIG);
  -                      translatePredicates(classGen, methodGen); // get
the base itr.
  -                      predicate.translate(classGen, methodGen); // get
the position
  -                      il.append(new INVOKEINTERFACE(start,2));
  -                      il.append(new INVOKEINTERFACE(reset,1));
  -
  -                      final int sngl =
cpg.addMethodref(BASIS_LIBRARY_CLASS,
  -
"getSingleNode",
  -
"("+NODE_ITERATOR_SIG+")"+
  -
NODE_ITERATOR_SIG);
  -                      il.append(new INVOKESTATIC(sngl));
  -              }
  -              else {
  -                      // create new CurrentNodeListIterator
  -                      il.append(new
NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  -                      il.append(DUP);
  -                      translatePredicates(classGen, methodGen); //
recursive call
  -                      il.append(ICONST_1);
  -                      predicate.translate(classGen, methodGen);
  -                      il.append(methodGen.loadCurrentNode());
  -                      il.append(classGen.loadTranslet());
  -                      il.append(new INVOKESPECIAL(initCNLI));
  -              }
  +            // Create a CurrentNodeListIterator
  +            il.append(new
NEW(cpg.addClass(CURRENT_NODE_LIST_ITERATOR)));
  +            il.append(DUP);
  +
  +            // Translate the rest of the predicates from right to left
  +            translatePredicates(classGen, methodGen);
  +
  +            // Initialize CurrentNodeListIterator
  +            il.append(ICONST_1);
  +            predicate.translate(classGen, methodGen);
  +            il.append(methodGen.loadCurrentNode());
  +            il.append(classGen.loadTranslet());
  +            il.append(new INVOKESPECIAL(initCNLI));
             }
       }
   }



  1.31      +157 -122
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java

  Index: Predicate.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Predicate.java,v

  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -r1.30 -r1.31
  --- Predicate.java           15 Oct 2003 21:01:51 -0000          1.30
  +++ Predicate.java           5 Feb 2004 22:53:42 -0000           1.31
  @@ -92,36 +92,115 @@

   final class Predicate extends Expression implements Closure {

  -    private Expression _exp = null; // Expression to be compiled inside
pred.
  +    /**
  +     * The predicate's expression.
  +     */
  +    private Expression _exp = null;
  +
  +    /**
  +     * This flag indicates if optimizations are turned on. The
  +     * method <code>dontOptimize()</code> can be called to turn
  +     * optimizations off.
  +     */
  +    private boolean _canOptimize = true;
  +
  +    /**
  +     * Flag indicatig if the nth position optimization is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthPositionFilter = false;
  +
  +    /**
  +     * Flag indicatig if the nth position descendant is on. It
  +     * is set in <code>typeCheck()</code>.
  +     */
       private boolean _nthDescendant = false;
  -    private boolean _canOptimize = true;
  -    private int     _ptype = -1;

  +    /**
  +     * Cached node type of the expression that owns this predicate.
  +     */
  +    int _ptype = -1;
  +
  +    /**
  +     * Name of the inner class.
  +     */
       private String _className = null;
  +
  +    /**
  +     * List of variables in closure.
  +     */
       private ArrayList _closureVars = null;
  +
  +    /**
  +     * Reference to parent closure.
  +     */
       private Closure _parentClosure = null;

  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Expression _value = null;
  +
  +    /**
  +     * Cached value of method <code>getCompareValue()</code>.
  +     */
  +    private Step _step = null;
  +
  +    /**
  +     * Initializes a predicate.
  +     */
       public Predicate(Expression exp) {
  -          (_exp = exp).setParent(this);
  +        _exp = exp;
  +        _exp.setParent(this);
  +
       }

  +    /**
  +     * Set the parser for this expression.
  +     */
       public void setParser(Parser parser) {
             super.setParser(parser);
             _exp.setParser(parser);
       }

  -    public boolean isNthDescendant() {
  -          return _nthDescendant;
  -    }
  -
  +    /**
  +     * Returns a boolean value indicating if the nth position
optimization
  +     * is on. Must be call after type checking!
  +     */
       public boolean isNthPositionFilter() {
             return _nthPositionFilter;
       }

  +    /**
  +     * Returns a boolean value indicating if the nth descendant
optimization
  +     * is on. Must be call after type checking!
  +     */
  +    public boolean isNthDescendant() {
  +          return _nthDescendant;
  +    }
  +
  +    /**
  +     * Turns off all optimizations for this predicate.
  +     */
       public void dontOptimize() {
             _canOptimize = false;
       }
  +
  +    /**
  +     * Returns true if the expression in this predicate contains a call
  +     * to position().
  +     */
  +    public boolean hasPositionCall() {
  +          return _exp.hasPositionCall();
  +    }
  +
  +    /**
  +     * Returns true if the expression in this predicate contains a call
  +     * to last().
  +     */
  +    public boolean hasLastCall() {
  +          return _exp.hasLastCall();
  +    }

       // -- Begin Closure interface --------------------

  @@ -183,6 +262,10 @@

       // -- End Closure interface ----------------------

  +    /**
  +     * Returns the node type of the expression owning this predicate.
The
  +     * return value is cached in <code>_ptype</code>.
  +     */
       public int getPosType() {
             if (_ptype == -1) {
                 SyntaxTreeNode parent = getParent();
  @@ -220,10 +303,7 @@
       }

       public String toString() {
  -          if (isNthPositionFilter())
  -              return "pred([" + _exp + "],"+getPosType()+")";
  -          else
  -              return "pred(" + _exp + ')';
  +        return "pred(" + _exp + ')';
       }

       /**
  @@ -232,9 +312,12 @@
        * Note that if the expression is a parameter, we cannot distinguish
        * at compile time if its type is number or not. Hence, expressions
of
        * reference type are always converted to booleans.
  +     *
  +     * This method may be called twice, before and after calling
  +     * <code>dontOptimize()</code>. If so, the second time it should
honor
  +     * the new value of <code>_canOptimize</code>.
        */
  -    public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  -
  +    public Type typeCheck(SymbolTable stable) throws TypeCheckError {

             Type texp = _exp.typeCheck(stable);

             // We need explicit type information for reference types - no
good!
  @@ -253,96 +336,50 @@

             // Numerical types will be converted to a position filter
             if (texp instanceof NumberType) {
  -
                 // Cast any numerical types to an integer
                 if (texp instanceof IntType == false) {
                         _exp = new CastExpr(_exp, Type.Int);
                 }
  -
  -              SyntaxTreeNode parent = getParent();
  -
  -              // Expand [last()] into [position() = last()]
  -              if ((_exp instanceof LastCall) ||
  -                //Fix for bug 22949, check for last() for any expression
returns
  -                // NumberType
  -                 _exp.hasLastCall()||
  -                      (parent instanceof Pattern) ||
  -                      (parent instanceof FilterExpr)) {
  -
  -                      if (parent instanceof Pattern && !(_exp instanceof
LastCall)) {
  -                          _nthPositionFilter = _canOptimize;
  -                      }
  -                      else if (parent instanceof FilterExpr) {
  -                          FilterExpr filter = (FilterExpr)parent;
  -                          Expression fexp = filter.getExpr();
  -
  -                          if (fexp instanceof KeyCall)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof VariableRefBase)
  -                              _canOptimize = false;
  -                          else if (fexp instanceof ParentLocationPath)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof FilterParentPath)
  -                                  _canOptimize = false;
  -                          else if (fexp instanceof UnionPathExpr)
  -                                  _canOptimize = false;
  -                          else if (_exp.hasPositionCall() &&
_exp.hasLastCall())
  -                                  _canOptimize = false;
  -                          else if (filter.getParent() instanceof
FilterParentPath)
  -                                  _canOptimize = false;
  -                          if (_canOptimize)
  -                                  _nthPositionFilter = true;
  -                      }
  -
  -                // If this case can be optimized, leave the expression
as
  -                // an integer.  Otherwise, turn it into a comparison
with
  -                // the position() function.
  +
  +            if (_canOptimize) {
  +                // Nth position optimization. Expression must not depend
on context
  +                _nthPositionFilter =
  +                    !_exp.hasLastCall() && !_exp.hasPositionCall();
  +
  +                // _nthDescendant optimization - only if
_nthPositionFilter is on
                   if (_nthPositionFilter) {
  -                   return _type = Type.NodeSet;
  -                } else {
  -                   final QName position =
  -
getParser().getQNameIgnoreDefaultNs("position");
  -
  -                   final PositionCall positionCall =
  -                                               new
PositionCall(position);
  -                   positionCall.setParser(getParser());
  -                   positionCall.setParent(this);
  -
  -                   _exp = new EqualityExpr(EqualityExpr.EQ,
positionCall,
  -                                            _exp);
  -                   if (_exp.typeCheck(stable) != Type.Boolean) {
  -                       _exp = new CastExpr(_exp, Type.Boolean);
  -                   }
  -
  -                   return _type = Type.Boolean;
  +                    SyntaxTreeNode parent = getParent();
  +                    _nthDescendant = (parent instanceof Step) &&
  +                        (parent.getParent() instanceof
AbsoluteLocationPath);
  +                    return _type = Type.NodeSet;
                   }
  -              }
  -              // Use NthPositionIterator to handle [position()] or [a]
  -              else {
  -                      if ((parent != null) && (parent instanceof Step))
{
  -                          parent = parent.getParent();
  -                          if ((parent != null) &&
  -                                  (parent instanceof
AbsoluteLocationPath)) {
  -                                  // TODO: Special case for "//*[n]"
pattern....
  -                                  _nthDescendant = true;
  -                                  return _type = Type.NodeSet;
  -                          }
  -                      }
  -                      _nthPositionFilter = true;
  -                      return _type = Type.NodeSet;
  -              }
  -          }
  -          else if (texp instanceof BooleanType) {
  -              if (_exp.hasPositionCall())
  -                      _nthPositionFilter = true;
  +            }
  +
  +           // Reset optimization flags
  +            _nthPositionFilter = _nthDescendant = false;
  +
  +           // Otherwise, expand [e] to [position() = e]
  +           final QName position =
  +                getParser().getQNameIgnoreDefaultNs("position");
  +           final PositionCall positionCall =
  +                new PositionCall(position);
  +           positionCall.setParser(getParser());
  +           positionCall.setParent(this);
  +
  +           _exp = new EqualityExpr(EqualityExpr.EQ, positionCall,
  +                                    _exp);
  +           if (_exp.typeCheck(stable) != Type.Boolean) {
  +               _exp = new CastExpr(_exp, Type.Boolean);
  +           }
  +           return _type = Type.Boolean;
             }
  -          // All other types will be handled as boolean values
             else {
  -              _exp = new CastExpr(_exp, Type.Boolean);
  +            // All other types will be handled as boolean values
  +              if (texp instanceof BooleanType == false) {
  +                      _exp = new CastExpr(_exp, Type.Boolean);
  +            }
  +            return _type = Type.Boolean;
             }
  -          _nthPositionFilter = false;
  -
  -          return _type = Type.Boolean;
       }

       /**
  @@ -447,9 +484,6 @@
             return (getStep() != null && getCompareValue() != null);
       }

  -    private Expression _value = null;
  -    private Step _step = null;
  -
       /**
        * Utility method for optimisation. See isNodeValueTest()
        */
  @@ -517,29 +551,6 @@
        * two references on the stack: a reference to a newly created
        * filter object and a reference to the predicate's closure.
        */
  -    public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
  -
  -          final ConstantPoolGen cpg = classGen.getConstantPool();
  -          final InstructionList il = methodGen.getInstructionList();
  -
  -          if (_nthPositionFilter || _nthDescendant) {
  -              _exp.translate(classGen, methodGen);
  -          }
  -          else if (isNodeValueTest() && (getParent() instanceof Step)) {
  -              _value.translate(classGen, methodGen);
  -              il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  -              il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  -          }
  -          else {
  -              translateFilter(classGen, methodGen);
  -          }
  -    }
  -
  -    /**
  -     * Translate a predicate expression. This translation pushes
  -     * two references on the stack: a reference to a newly created
  -     * filter object and a reference to the predicate's closure.
  -     */
       public void translateFilter(ClassGenerator classGen,
                                                 MethodGenerator methodGen)

       {
  @@ -588,6 +599,30 @@
                 il.append(new PUTFIELD(
                             cpg.addFieldref(_className, var.getVariable(),

                                     varType.toSignature())));
  +          }
  +    }
  +
  +    /**
  +     * Translate a predicate expression. If non of the optimizations
apply
  +     * then this translation pushes two references on the stack: a
reference
  +     * to a newly created filter object and a reference to the
predicate's
  +     * closure. See class <code>Step</code> for further details.
  +     */
  +    public void translate(ClassGenerator classGen, MethodGenerator
methodGen) {
  +
  +          final ConstantPoolGen cpg = classGen.getConstantPool();
  +          final InstructionList il = methodGen.getInstructionList();
  +
  +          if (_nthPositionFilter || _nthDescendant) {
  +              _exp.translate(classGen, methodGen);
  +          }
  +          else if (isNodeValueTest() && (getParent() instanceof Step)) {
  +              _value.translate(classGen, methodGen);
  +              il.append(new CHECKCAST(cpg.addClass(STRING_CLASS)));
  +              il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp()));
  +          }
  +          else {
  +              translateFilter(classGen, methodGen);
             }
       }
   }



  1.44      +4 -3
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java

  Index: Step.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Step.java,v
  retrieving revision 1.43
  retrieving revision 1.44
  diff -u -r1.43 -r1.44
  --- Step.java          1 Apr 2003 21:09:00 -0000           1.43
  +++ Step.java          5 Feb 2004 22:53:42 -0000           1.44
  @@ -417,11 +417,12 @@

GET_NODE_VALUE_ITERATOR,

GET_NODE_VALUE_ITERATOR_SIG);
                         il.append(new INVOKEINTERFACE(idx, 5));
  -              }
  +              }
                 // Handle '//*[n]' expression
                 else if (predicate.isNthDescendant()) {
                         il.append(methodGen.loadDOM());
  -                      il.append(new ICONST(NodeTest.ELEMENT));
  +                      // il.append(new ICONST(NodeTest.ELEMENT));
  +                      il.append(new ICONST(predicate.getPosType()));
                         predicate.translate(classGen, methodGen);
                         il.append(new ICONST(0));
                         idx = cpg.addInterfaceMethodref(DOM_INTF,



  1.23      +7 -4
xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java

  Index: StepPattern.java
  ===================================================================
  RCS file:
/home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/StepPattern.java,v

  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- StepPattern.java         1 Apr 2003 21:09:00 -0000           1.22
  +++ StepPattern.java         5 Feb 2004 22:53:42 -0000           1.23
  @@ -202,9 +202,11 @@
             final int n = _predicates.size();

             for (int i = 0; i < n && noContext; i++) {
  -              final Predicate pred =
(Predicate)_predicates.elementAt(i);
  -              if (pred.getExpr().hasPositionCall()
  -                || pred.isNthPositionFilter()) {
  +              Predicate pred = (Predicate) _predicates.elementAt(i);
  +            if (pred.isNthPositionFilter() ||
  +                pred.hasPositionCall() ||
  +                pred.hasLastCall())
  +            {
                         noContext = false;
                 }
             }
  @@ -253,6 +255,7 @@

                   step = new Step(_axis, _nodeType, _predicates);
               }
  +
               if (step != null) {
                   step.setParser(getParser());
                   step.typeCheck(stable);




---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org





---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org