public void translateDesynthesized(ClassGenerator classGen, MethodGenerator methodGen) { final Type tleft = _left.getType(); final InstructionList il = methodGen.getInstructionList(); if (tleft instanceof BooleanType) { _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IF_ICMPNE(null) : (BranchInstruction) new IF_ICMPEQ(null))); } else if (tleft instanceof NumberType) { _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); if (tleft instanceof RealType) { il.append(DCMPG); _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IFNE(null) : (BranchInstruction) new IFEQ(null))); } else { _falseList.add( il.append( _op == Operators.EQ ? (BranchInstruction) new IF_ICMPNE(null) : (BranchInstruction) new IF_ICMPEQ(null))); } } else { translate(classGen, methodGen); desynthesize(classGen, methodGen); } }
/** * Translate the code required for getting the node for which the QName, local-name or namespace * URI should be extracted. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); il.append(methodGen.loadDOM()); // Function was called with no parameters if (argumentCount() == 0) { il.append(methodGen.loadContextNode()); } // Function was called with node parameter else if (_paramType == Type.Node) { _param.translate(classGen, methodGen); } else if (_paramType == Type.Reference) { _param.translate(classGen, methodGen); il.append( new INVOKESTATIC( cpg.addMethodref( BASIS_LIBRARY_CLASS, "referenceToNodeSet", "(" + OBJECT_SIG + ")" + NODE_ITERATOR_SIG))); il.append(methodGen.nextNode()); } // Function was called with node-set parameter else { _param.translate(classGen, methodGen); _param.startIterator(classGen, methodGen); il.append(methodGen.nextNode()); } }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { if (elementCount() == 1) { final Expression exp = (Expression) elementAt(0); exp.translate(classGen, methodGen); } else { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final int initBuffer = cpg.addMethodref(STRING_BUFFER_CLASS, "<init>", "()V"); final Instruction append = new INVOKEVIRTUAL( cpg.addMethodref( STRING_BUFFER_CLASS, "append", "(" + STRING_SIG + ")" + STRING_BUFFER_SIG)); final int toString = cpg.addMethodref(STRING_BUFFER_CLASS, "toString", "()" + STRING_SIG); il.append(new NEW(cpg.addClass(STRING_BUFFER_CLASS))); il.append(DUP); il.append(new INVOKESPECIAL(initBuffer)); // StringBuffer is on the stack final Iterator<SyntaxTreeNode> elements = elements(); while (elements.hasNext()) { final Expression exp = (Expression) elements.next(); exp.translate(classGen, methodGen); il.append(append); } il.append(new INVOKEVIRTUAL(toString)); } }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final InstructionList il = methodGen.getInstructionList(); _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); switch (_op) { case PLUS: il.append(_type.ADD()); break; case MINUS: il.append(_type.SUB()); break; case TIMES: il.append(_type.MUL()); break; case DIV: il.append(_type.DIV()); break; case MOD: il.append(_type.REM()); break; default: ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_BINARY_OP_ERR, this); getParser().reportError(Constants.ERROR, msg); } }
/** * 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); } }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); _right.translate(classGen, methodGen); il.append(new CHECKCAST(cpg.addClass(_className))); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Push the this pointer on the stack... il.append(methodGen.loadDOM()); // ...then the entity name... _entity.translate(classGen, methodGen); // ...to get the URI from the DOM object. il.append( new INVOKEINTERFACE( cpg.addInterfaceMethodref( DOM_INTF, GET_UNPARSED_ENTITY_URI, GET_UNPARSED_ENTITY_URI_SIG), 2)); }
/** * Compiles code that instantiates a SortingIterator object. This object's constructor needs * referencdes to the current iterator and a node sort record producing objects as its parameters. */ public static void translateSortIterator( ClassGenerator classGen, MethodGenerator methodGen, Expression nodeSet, Vector sortObjects) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // SortingIterator.SortingIterator(NodeIterator,NodeSortRecordFactory); final int init = cpg.addMethodref( SORT_ITERATOR, "<init>", "(" + NODE_ITERATOR_SIG + NODE_SORT_FACTORY_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. LocalVariableGen nodesTemp = methodGen.addLocalVariable("sort_tmp1", Util.getJCRefType(NODE_ITERATOR_SIG), null, null); LocalVariableGen sortRecordFactoryTemp = methodGen.addLocalVariable( "sort_tmp2", Util.getJCRefType(NODE_SORT_FACTORY_SIG), null, null); // Get the current node iterator if (nodeSet == null) { // apply-templates default final int children = cpg.addInterfaceMethodref(DOM_INTF, "getAxisIterator", "(I)" + NODE_ITERATOR_SIG); il.append(methodGen.loadDOM()); il.append(new PUSH(cpg, Axis.CHILD)); il.append(new INVOKEINTERFACE(children, 2)); } else { nodeSet.translate(classGen, methodGen); } nodesTemp.setStart(il.append(new ASTORE(nodesTemp.getIndex()))); // Compile the code for the NodeSortRecord producing class and pass // that as the last argument to the SortingIterator constructor. compileSortRecordFactory(sortObjects, classGen, methodGen); sortRecordFactoryTemp.setStart(il.append(new ASTORE(sortRecordFactoryTemp.getIndex()))); il.append(new NEW(cpg.addClass(SORT_ITERATOR))); il.append(DUP); nodesTemp.setEnd(il.append(new ALOAD(nodesTemp.getIndex()))); sortRecordFactoryTemp.setEnd(il.append(new ALOAD(sortRecordFactoryTemp.getIndex()))); il.append(new INVOKESPECIAL(init)); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Save current node and current iterator on the stack il.append(methodGen.loadCurrentNode()); il.append(methodGen.loadIterator()); // Collect sort objects associated with this instruction final Vector sortObjects = new Vector(); Enumeration children = elements(); while (children.hasMoreElements()) { final Object child = children.nextElement(); if (child instanceof Sort) { sortObjects.addElement(child); } } if ((_type != null) && (_type instanceof ResultTreeType)) { // Store existing DOM on stack - must be restored when loop is done il.append(methodGen.loadDOM()); // <xsl:sort> cannot be applied to a result tree - issue warning if (sortObjects.size() > 0) { ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR, this); getParser().reportError(WARNING, msg); } // Put the result tree on the stack (DOM) _select.translate(classGen, methodGen); // Get an iterator for the whole DOM - excluding the root node _type.translateTo(classGen, methodGen, Type.NodeSet); // Store the result tree as the default DOM il.append(SWAP); il.append(methodGen.storeDOM()); } else { // Compile node iterator if (sortObjects.size() > 0) { Sort.translateSortIterator(classGen, methodGen, _select, sortObjects); } else { _select.translate(classGen, methodGen); } if (_type instanceof ReferenceType == false) { il.append(methodGen.loadContextNode()); il.append(methodGen.setStartNode()); } } // 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())); il.append(methodGen.nextNode()); il.append(DUP); il.append(methodGen.storeCurrentNode()); il.append(new IFGT(loop)); // Restore current DOM (if result tree was used instead for this loop) if ((_type != null) && (_type instanceof ResultTreeType)) { il.append(methodGen.storeDOM()); } // Restore current node and current iterator from the stack il.append(methodGen.storeIterator()); il.append(methodGen.storeCurrentNode()); }
/** * This method compiles code for the select expression for this xsl:sort element. The method is * called from the static code-generating methods in this class. */ public void translateSelect(ClassGenerator classGen, MethodGenerator methodGen) { _select.translate(classGen, methodGen); }
/** * Create a new "Filter" class implementing <code>CurrentNodeListFilter</code>. Allocate registers * for local variables and local parameters passed in the closure to test(). Notice that local * variables need to be "unboxed". */ private void compileFilter(ClassGenerator classGen, MethodGenerator methodGen) { TestGenerator testGen; LocalVariableGen local; FilterGenerator filterGen; _className = getXSLTC().getHelperClassName(); filterGen = new FilterGenerator( _className, "java.lang.Object", toString(), ACC_PUBLIC | ACC_SUPER, new String[] {CURRENT_NODE_LIST_FILTER}, classGen.getStylesheet()); final ConstantPoolGen cpg = filterGen.getConstantPool(); final int length = (_closureVars == null) ? 0 : _closureVars.size(); // Add a new instance variable for each var in closure for (int i = 0; i < length; i++) { VariableBase var = ((VariableRefBase) _closureVars.get(i)).getVariable(); filterGen.addField( new Field( ACC_PUBLIC, cpg.addUtf8(var.getEscapedName()), cpg.addUtf8(var.getType().toSignature()), null, cpg.getConstantPool())); } final InstructionList il = new InstructionList(); testGen = new TestGenerator( ACC_PUBLIC | ACC_FINAL, org.apache.bcel.generic.Type.BOOLEAN, new org.apache.bcel.generic.Type[] { org.apache.bcel.generic.Type.INT, org.apache.bcel.generic.Type.INT, org.apache.bcel.generic.Type.INT, org.apache.bcel.generic.Type.INT, Util.getJCRefType(TRANSLET_SIG), Util.getJCRefType(NODE_ITERATOR_SIG) }, new String[] {"node", "position", "last", "current", "translet", "iterator"}, "test", _className, il, cpg); // Store the dom in a local variable local = testGen.addLocalVariable("document", Util.getJCRefType(DOM_INTF_SIG), null, null); final String className = classGen.getClassName(); il.append(filterGen.loadTranslet()); il.append(new CHECKCAST(cpg.addClass(className))); il.append(new GETFIELD(cpg.addFieldref(className, DOM_FIELD, DOM_INTF_SIG))); local.setStart(il.append(new ASTORE(local.getIndex()))); // Store the dom index in the test generator testGen.setDomIndex(local.getIndex()); _exp.translate(filterGen, testGen); il.append(IRETURN); filterGen.addEmptyConstructor(ACC_PUBLIC); filterGen.addMethod(testGen); getXSLTC().dumpClass(filterGen.getJavaClass()); }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final Type tleft = _left.getType(); Type tright = _right.getType(); if (tleft instanceof BooleanType || tleft instanceof NumberType) { translateDesynthesized(classGen, methodGen); synthesize(classGen, methodGen); return; } if (tleft instanceof StringType) { final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z"); _left.translate(classGen, methodGen); _right.translate(classGen, methodGen); il.append(new INVOKEVIRTUAL(equals)); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } BranchHandle truec, falsec; if (tleft instanceof ResultTreeType) { if (tright instanceof BooleanType) { _right.translate(classGen, methodGen); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tright instanceof RealType) { _left.translate(classGen, methodGen); tleft.translateTo(classGen, methodGen, Type.Real); _right.translate(classGen, methodGen); il.append(DCMPG); falsec = il.append( _op == Operators.EQ ? (BranchInstruction) new IFNE(null) : (BranchInstruction) new IFEQ(null)); il.append(ICONST_1); truec = il.append(new GOTO(null)); falsec.setTarget(il.append(ICONST_0)); truec.setTarget(il.append(NOP)); return; } // Next, result-tree/string and result-tree/result-tree comparisons _left.translate(classGen, methodGen); tleft.translateTo(classGen, methodGen, Type.String); _right.translate(classGen, methodGen); if (tright instanceof ResultTreeType) { tright.translateTo(classGen, methodGen, Type.String); } final int equals = cpg.addMethodref(STRING_CLASS, "equals", "(" + OBJECT_SIG + ")Z"); il.append(new INVOKEVIRTUAL(equals)); if (_op == Operators.NE) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tleft instanceof NodeSetType && tright instanceof BooleanType) { _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); Type.NodeSet.translateTo(classGen, methodGen, Type.Boolean); _right.translate(classGen, methodGen); il.append(IXOR); // x != y <-> x xor y if (_op == Operators.EQ) { il.append(ICONST_1); il.append(IXOR); // not x <-> x xor 1 } return; } if (tleft instanceof NodeSetType && tright instanceof StringType) { _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); // needed ? _right.translate(classGen, methodGen); il.append(new PUSH(cpg, _op)); il.append(methodGen.loadDOM()); final int cmp = cpg.addMethodref( BASIS_LIBRARY_CLASS, "compare", "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z"); il.append(new INVOKESTATIC(cmp)); return; } // Next, node-set/t for t in {real, string, node-set, result-tree} _left.translate(classGen, methodGen); _left.startIterator(classGen, methodGen); _right.translate(classGen, methodGen); _right.startIterator(classGen, methodGen); // Cast a result tree to a string to use an existing compare if (tright instanceof ResultTreeType) { tright.translateTo(classGen, methodGen, Type.String); tright = Type.String; } // Call the appropriate compare() from the BasisLibrary il.append(new PUSH(cpg, _op)); il.append(methodGen.loadDOM()); final int compare = cpg.addMethodref( BASIS_LIBRARY_CLASS, "compare", "(" + tleft.toSignature() + tright.toSignature() + "I" + DOM_INTF_SIG + ")Z"); il.append(new INVOKESTATIC(compare)); }
/** * Translate a function call. The compiled code will leave the function's return value on the * JVM's stack. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final int n = argumentCount(); final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final boolean isSecureProcessing = classGen.getParser().getXSLTC().isSecureProcessing(); int index; // Translate calls to methods in the BasisLibrary if (isStandard() || isExtension()) { for (int i = 0; i < n; i++) { final Expression exp = argument(i); exp.translate(classGen, methodGen); exp.startIterator(classGen, methodGen); } // append "F" to the function's name final String name = _fname.toString().replace('-', '_') + "F"; String args = Constants.EMPTYSTRING; // Special precautions for some method calls if (name.equals("sumF")) { args = DOM_INTF_SIG; il.append(methodGen.loadDOM()); } else if (name.equals("normalize_spaceF")) { if (_chosenMethodType.toSignature(args).equals("()Ljava/lang/String;")) { args = "I" + DOM_INTF_SIG; il.append(methodGen.loadContextNode()); il.append(methodGen.loadDOM()); } } // Invoke the method in the basis library index = cpg.addMethodref(BASIS_LIBRARY_CLASS, name, _chosenMethodType.toSignature(args)); il.append(new INVOKESTATIC(index)); } // Add call to BasisLibrary.unresolved_externalF() to generate // run-time error message for unsupported external functions else if (unresolvedExternal) { index = cpg.addMethodref(BASIS_LIBRARY_CLASS, "unresolved_externalF", "(Ljava/lang/String;)V"); il.append(new PUSH(cpg, _fname.toString())); il.append(new INVOKESTATIC(index)); } else if (_isExtConstructor) { if (isSecureProcessing) translateUnallowedExtension(cpg, il); final String clazz = _chosenConstructor.getDeclaringClass().getName(); Class[] paramTypes = _chosenConstructor.getParameterTypes(); LocalVariableGen[] paramTemp = new LocalVariableGen[n]; // 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. for (int i = 0; i < n; i++) { final Expression exp = argument(i); Type expType = exp.getType(); exp.translate(classGen, methodGen); // Convert the argument to its Java type exp.startIterator(classGen, methodGen); expType.translateTo(classGen, methodGen, paramTypes[i]); paramTemp[i] = methodGen.addLocalVariable( "function_call_tmp" + i, expType.toJCType(), il.getEnd(), null); il.append(expType.STORE(paramTemp[i].getIndex())); } il.append(new NEW(cpg.addClass(_className))); il.append(InstructionConstants.DUP); for (int i = 0; i < n; i++) { final Expression arg = argument(i); il.append(arg.getType().LOAD(paramTemp[i].getIndex())); } final StringBuffer buffer = new StringBuffer(); buffer.append('('); for (int i = 0; i < paramTypes.length; i++) { buffer.append(getSignature(paramTypes[i])); } buffer.append(')'); buffer.append("V"); index = cpg.addMethodref(clazz, "<init>", buffer.toString()); il.append(new INVOKESPECIAL(index)); // Convert the return type back to our internal type (Type.Object).translateFrom(classGen, methodGen, _chosenConstructor.getDeclaringClass()); } // Invoke function calls that are handled in separate classes else { if (isSecureProcessing) translateUnallowedExtension(cpg, il); final String clazz = _chosenMethod.getDeclaringClass().getName(); Class[] paramTypes = _chosenMethod.getParameterTypes(); // Push "this" if it is an instance method if (_thisArgument != null) { _thisArgument.translate(classGen, methodGen); } for (int i = 0; i < n; i++) { final Expression exp = argument(i); exp.translate(classGen, methodGen); // Convert the argument to its Java type exp.startIterator(classGen, methodGen); exp.getType().translateTo(classGen, methodGen, paramTypes[i]); } final StringBuffer buffer = new StringBuffer(); buffer.append('('); for (int i = 0; i < paramTypes.length; i++) { buffer.append(getSignature(paramTypes[i])); } buffer.append(')'); buffer.append(getSignature(_chosenMethod.getReturnType())); if (_thisArgument != null && _clazz.isInterface()) { index = cpg.addInterfaceMethodref(clazz, _fname.getLocalPart(), buffer.toString()); il.append(new INVOKEINTERFACE(index, n + 1)); } else { index = cpg.addMethodref(clazz, _fname.getLocalPart(), buffer.toString()); il.append( _thisArgument != null ? (InvokeInstruction) new INVOKEVIRTUAL(index) : (InvokeInstruction) new INVOKESTATIC(index)); } // Convert the return type back to our internal type _type.translateFrom(classGen, methodGen, _chosenMethod.getReturnType()); } }