You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by mo...@apache.org on 2001/06/29 16:58:56 UTC

cvs commit: xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util MethodGenerator.java

morten      01/06/29 07:58:56

  Modified:    java/src/org/apache/xalan/xsltc/compiler ForEach.java
                        Param.java Variable.java
               java/src/org/apache/xalan/xsltc/compiler/util
                        MethodGenerator.java
  Log:
  Added a fix for local variables inside nested xsl:for-each elements.
  Local variables are usually not initialized to any default value (such as
  with general Java classes), because code compiled for <xsl:variable>
  elements always assign values to variable slots before they are accessed.
  But the code structure generated by nested <xsl:for-each> elements is too
  much for the JVMs verifier to get around, so we have to initialize all
  local variables inside such loops to zero, false, null, whatever.
  This takes care some of our runtime-errors caused by apparent corrupt code.
  (The JVMs verifier thinks that it is corrupt, but it isn't really.)
  PR:		none
  Obtained from:	n/a
  Submitted by:	morten@xml.apache.org
  Reviewed by:	morten@xml.apache.org
  
  Revision  Changes    Path
  1.7       +34 -2     xml-xalan/java/src/org/apache/xalan/xsltc/compiler/ForEach.java
  
  Index: ForEach.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/ForEach.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- ForEach.java	2001/06/17 12:23:28	1.6
  +++ ForEach.java	2001/06/29 14:58:55	1.7
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: ForEach.java,v 1.6 2001/06/17 12:23:28 curcuru Exp $
  + * @(#)$Id: ForEach.java,v 1.7 2001/06/29 14:58:55 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -148,9 +148,12 @@
   	// Overwrite current iterator
   	il.append(methodGen.storeIterator());
   
  +	// Give local variables (if any) default values before starting loop
  +	initializeVariables(classGen, methodGen);
  +
   	final BranchHandle nextNode = il.append(new GOTO(null));
   	final InstructionHandle loop = il.append(NOP);
  -		    
  +
   	translateContents(classGen, methodGen);
   		    
   	nextNode.setTarget(il.append(methodGen.loadIterator()));
  @@ -163,4 +166,33 @@
   	il.append(methodGen.storeIterator());
   	il.append(methodGen.storeCurrentNode());
       }
  +
  +    /**
  +     * The code that is generated by nested for-each loops can appear to some
  +     * JVMs as if it is accessing un-initialized variables. We must add some
  +     * code that pushes the default variable value on the stack and pops it
  +     * into the variable slot. This is done by the Variable.initialize()
  +     * method. The code that we compile for this loop looks like this:
  +     *
  +     *           initialize iterator
  +     *           initialize variables <-- HERE!!!
  +     *           goto   Iterate
  +     *  Loop:    :
  +     *           : (code for <xsl:for-each> contents)
  +     *           :
  +     *  Iterate: node = iterator.next();
  +     *           if (node != END) goto Loop
  +     */
  +    public void initializeVariables(ClassGenerator classGen,
  +				   MethodGenerator methodGen) {
  +	final int n = elementCount();
  +	for (int i = 0; i < n; i++) {
  +	    final Object child = getContents().elementAt(i);
  +	    if (child instanceof Variable) {
  +		Variable var = (Variable)child;
  +		var.initialize(classGen, methodGen);
  +	    }
  +	}
  +    }
  +
   }
  
  
  
  1.6       +5 -2      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Param.java
  
  Index: Param.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Param.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Param.java	2001/06/19 10:44:10	1.5
  +++ Param.java	2001/06/29 14:58:55	1.6
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Param.java,v 1.5 2001/06/19 10:44:10 morten Exp $
  + * @(#)$Id: Param.java,v 1.6 2001/06/29 14:58:55 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -242,8 +242,10 @@
   	_compiled = true;
   
   	if (isLocal()) {
  +
   	    il.append(classGen.loadTranslet());
   	    il.append(new PUSH(cpg, name));
  +
   	    if (_select == null) {
   		if (hasContents()) {
   		    compileResultTree(classGen, methodGen);	
  @@ -269,7 +271,8 @@
   		_local = null;
   	    }
   	    else {		// normal case
  -		_local = methodGen.addLocalVariable2(name, _type.toJCType(),
  +		_local = methodGen.addLocalVariable2(name,
  +						     _type.toJCType(),
   						     il.getEnd());
   		// Cache the result of addParameter() in a local variable
   		il.append(_type.STORE(_local.getIndex()));
  
  
  
  1.7       +38 -4     xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Variable.java
  
  Index: Variable.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/Variable.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- Variable.java	2001/06/19 10:44:13	1.6
  +++ Variable.java	2001/06/29 14:58:55	1.7
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: Variable.java,v 1.6 2001/06/19 10:44:13 morten Exp $
  + * @(#)$Id: Variable.java,v 1.7 2001/06/29 14:58:55 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -350,6 +350,38 @@
   	il.append(methodGen.storeHandler());
       }
   
  +    /**
  +     * This method is part of a little trick that is needed to use local
  +     * variables inside nested for-each loops. See the initializeVariables()
  +     * method in the ForEach class for an explanation
  +     */
  +    public void initialize(ClassGenerator classGen, MethodGenerator methodGen) {
  +	final ConstantPoolGen cpg = classGen.getConstantPool();
  +	final InstructionList il = methodGen.getInstructionList();
  +
  +	// This is only done for local variables that are actually used
  +	if (isLocal() && !_refs.isEmpty()) {
  +	    // Create a variable slot if none is allocated
  +	    if (_local == null) {
  +		final String name = _name.getLocalPart();
  +		_local = methodGen.addLocalVariable2(name,
  +						     _type.toJCType(),
  +						     il.getEnd());
  +	    }
  +	    // Push the default value on the JVM's stack
  +	    if ((_type instanceof IntType) ||
  +		(_type instanceof NodeType) ||
  +		(_type instanceof BooleanType))
  +		il.append(new ICONST(0)); // 0 for node-id, integer and boolean
  +	    else if (_type instanceof RealType)
  +		il.append(new FCONST(0)); // 0.0 for floating point numbers
  +	    else
  +		il.append(new ACONST_NULL()); // and 'null' for anything else
  +	    il.append(_type.STORE(_local.getIndex()));
  +	}
  +    }
  +
  +
       public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
   	final ConstantPoolGen cpg = classGen.getConstantPool();
   	final InstructionList il = methodGen.getInstructionList();
  @@ -397,9 +429,11 @@
   		_local = null;
   	    }
   	    else {		// normal case
  -		_local = methodGen.addLocalVariable2(name,
  -						     _type.toJCType(),
  -						     il.getEnd());
  +		if (_local == null) {
  +		    _local = methodGen.addLocalVariable2(name,
  +							 _type.toJCType(),
  +							 il.getEnd());
  +		}
   		il.append(_type.STORE(_local.getIndex()));
   	    }
   
  
  
  
  1.4       +2 -9      xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java
  
  Index: MethodGenerator.java
  ===================================================================
  RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/xsltc/compiler/util/MethodGenerator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- MethodGenerator.java	2001/06/28 15:36:31	1.3
  +++ MethodGenerator.java	2001/06/29 14:58:56	1.4
  @@ -1,5 +1,5 @@
   /*
  - * @(#)$Id: MethodGenerator.java,v 1.3 2001/06/28 15:36:31 morten Exp $
  + * @(#)$Id: MethodGenerator.java,v 1.4 2001/06/29 14:58:56 morten Exp $
    *
    * The Apache Software License, Version 1.1
    *
  @@ -172,23 +172,17 @@
   					     InstructionHandle start,
   					     InstructionHandle end) {
   	
  -	//System.out.println("OLD addLocalVariable " + name);
   	return super.addLocalVariable(name, type, start, end);
       }
       
       public LocalVariableGen addLocalVariable2(String name, Type type,
   					      InstructionHandle start) {
  -	
  -	//System.out.println("addLocalVariable " + name);
  -	
   	return super.addLocalVariable(name, type,
   				      _slotAllocator.allocateSlot(type),
   				      start, null);
       }
   
       public void removeLocalVariable(LocalVariableGen lvg) {
  -	//final int slot = lvg.getIndex();
  -	//System.out.println("removing local " + slot);
   	_slotAllocator.releaseSlot(lvg);
   	super.removeLocalVariable(lvg);
       }
  @@ -335,8 +329,6 @@
       }
   
       public LocalVariableGen getLocalVariable(String name) {
  -	//	System.out.println("getLocalVariable " + name);
  -	
   	final LocalVariableGen[] vars = getLocalVariables();
   	for (int i = 0; i < vars.length; i++)
   	    if (vars[i].getName().equals(name))
  @@ -362,4 +354,5 @@
   
   	super.setMaxLocals(maxLocals);
       }
  +
   }
  
  
  

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