@Override public Constant createConstant(ConstantPoolGen cpg) { MethodRef method = getValue(); int i = cpg.addClass(method.getClassName()); int n = cpg.addNameAndType(method.getName(), method.getDescriptor().toString()); return new ConstantMethodref(i, n); }
/** * Creates the default, nameless, DecimalFormat object in AbstractTranslet's format_symbols * hashtable. This should be called for every stylesheet, and the entry may be overridden by later * nameless xsl:decimal-format instructions. */ public static void translateDefaultDFS(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name, which is empty, on the stack // for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, EMPTYSTRING)); // Manufacture a DecimalFormatSymbols on the stack for // call to addDecimalFormat(). Use the US Locale as the // default, as most of its settings are equivalent to // the default settings required of xsl:decimal-format - // except for the NaN and infinity attributes. il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }
/** * 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)); }
/** * 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); } }
/** * 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) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // Compile auxiliary class for filter compileFilter(classGen, methodGen); // Create new instance of filter il.append(new NEW(cpg.addClass(_className))); il.append(DUP); il.append(new INVOKESPECIAL(cpg.addMethodref(_className, "<init>", "()V"))); // Initialize closure variables final int length = (_closureVars == null) ? 0 : _closureVars.size(); for (int i = 0; i < length; i++) { VariableRefBase varRef = (VariableRefBase) _closureVars.get(i); VariableBase var = varRef.getVariable(); Type varType = var.getType(); il.append(DUP); // Find nearest closure implemented as an inner class Closure variableClosure = _parentClosure; while (variableClosure != null) { if (variableClosure.inInnerClass()) break; variableClosure = variableClosure.getParentClosure(); } // Use getfield if in an inner class if (variableClosure != null) { il.append(ALOAD_0); il.append( new GETFIELD( cpg.addFieldref( variableClosure.getInnerClassName(), var.getEscapedName(), varType.toSignature()))); } else { // Use a load of instruction if in translet class il.append(var.loadInstruction()); } // Store variable in new closure il.append( new PUTFIELD(cpg.addFieldref(_className, var.getEscapedName(), varType.toSignature()))); } }
/** * This method is called when the constructor is compiled in Stylesheet.compileConstructor() and * not as the syntax tree is traversed. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { ConstantPoolGen cpg = classGen.getConstantPool(); InstructionList il = methodGen.getInstructionList(); // DecimalFormatSymbols.<init>(Locale); // xsl:decimal-format - except for the NaN and infinity attributes. final int init = cpg.addMethodref(DFS_CLASS, "<init>", "(" + LOCALE_SIG + ")V"); // Push the format name on the stack for call to addDecimalFormat() il.append(classGen.loadTranslet()); il.append(new PUSH(cpg, _name.toString())); // Manufacture a DecimalFormatSymbols on the stack // for call to addDecimalFormat() // Use the US Locale as the default, as most of its settings // are equivalent to the default settings required of il.append(new NEW(cpg.addClass(DFS_CLASS))); il.append(DUP); il.append(new GETSTATIC(cpg.addFieldref(LOCALE_CLASS, "US", LOCALE_SIG))); il.append(new INVOKESPECIAL(init)); String tmp = getAttribute("NaN"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int nan = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "NaN")); il.append(new INVOKEVIRTUAL(nan)); } tmp = getAttribute("infinity"); if ((tmp == null) || (tmp.equals(EMPTYSTRING))) { int inf = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, "Infinity")); il.append(new INVOKEVIRTUAL(inf)); } final int nAttributes = _attributes.getLength(); for (int i = 0; i < nAttributes; i++) { final String name = _attributes.getQName(i); final String value = _attributes.getValue(i); boolean valid = true; int method = 0; if (name.equals("decimal-separator")) { // DecimalFormatSymbols.setDecimalSeparator(); method = cpg.addMethodref(DFS_CLASS, "setDecimalSeparator", "(C)V"); } else if (name.equals("grouping-separator")) { method = cpg.addMethodref(DFS_CLASS, "setGroupingSeparator", "(C)V"); } else if (name.equals("minus-sign")) { method = cpg.addMethodref(DFS_CLASS, "setMinusSign", "(C)V"); } else if (name.equals("percent")) { method = cpg.addMethodref(DFS_CLASS, "setPercent", "(C)V"); } else if (name.equals("per-mille")) { method = cpg.addMethodref(DFS_CLASS, "setPerMill", "(C)V"); } else if (name.equals("zero-digit")) { method = cpg.addMethodref(DFS_CLASS, "setZeroDigit", "(C)V"); } else if (name.equals("digit")) { method = cpg.addMethodref(DFS_CLASS, "setDigit", "(C)V"); } else if (name.equals("pattern-separator")) { method = cpg.addMethodref(DFS_CLASS, "setPatternSeparator", "(C)V"); } else if (name.equals("NaN")) { method = cpg.addMethodref(DFS_CLASS, "setNaN", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else if (name.equals("infinity")) { method = cpg.addMethodref(DFS_CLASS, "setInfinity", "(Ljava/lang/String;)V"); il.append(DUP); il.append(new PUSH(cpg, value)); il.append(new INVOKEVIRTUAL(method)); valid = false; } else { valid = false; } if (valid) { il.append(DUP); il.append(new PUSH(cpg, value.charAt(0))); il.append(new INVOKEVIRTUAL(method)); } } final int put = cpg.addMethodref(TRANSLET_CLASS, "addDecimalFormat", "(" + STRING_SIG + DFS_SIG + ")V"); il.append(new INVOKEVIRTUAL(put)); }
public static String compileSortRecordFactory( Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen, String sortRecordClass) { final XSLTC xsltc = ((Sort) sortObjects.firstElement()).getXSLTC(); final String className = xsltc.getHelperClassName(); final NodeSortRecordFactGenerator sortRecordFactory = new NodeSortRecordFactGenerator( className, NODE_SORT_FACTORY, className + ".java", ACC_PUBLIC | ACC_SUPER | ACC_FINAL, new String[] {}, classGen.getStylesheet()); ConstantPoolGen cpg = sortRecordFactory.getConstantPool(); // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); final ArrayList dups = new ArrayList(); for (int j = 0; j < nsorts; j++) { final Sort sort = (Sort) sortObjects.get(j); final int length = (sort._closureVars == null) ? 0 : sort._closureVars.size(); for (int i = 0; i < length; i++) { final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; final VariableBase var = varRef.getVariable(); sortRecordFactory.addField( new Field( ACC_PUBLIC, cpg.addUtf8(var.getEscapedName()), cpg.addUtf8(var.getType().toSignature()), null, cpg.getConstantPool())); dups.add(varRef); } } // Define a constructor for this class final org.apache.bcel.generic.Type[] argTypes = new org.apache.bcel.generic.Type[7]; argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); argTypes[1] = Util.getJCRefType(STRING_SIG); argTypes[2] = Util.getJCRefType(TRANSLET_INTF_SIG); argTypes[3] = Util.getJCRefType("[" + STRING_SIG); argTypes[4] = Util.getJCRefType("[" + STRING_SIG); argTypes[5] = Util.getJCRefType("[" + STRING_SIG); argTypes[6] = Util.getJCRefType("[" + STRING_SIG); final String[] argNames = new String[7]; argNames[0] = DOCUMENT_PNAME; argNames[1] = "className"; argNames[2] = TRANSLET_PNAME; argNames[3] = "order"; argNames[4] = "type"; argNames[5] = "lang"; argNames[6] = "case_order"; InstructionList il = new InstructionList(); final MethodGenerator constructor = new MethodGenerator( ACC_PUBLIC, org.apache.bcel.generic.Type.VOID, argTypes, argNames, "<init>", className, il, cpg); // Push all parameters onto the stack and called super.<init>() il.append(ALOAD_0); il.append(ALOAD_1); il.append(ALOAD_2); il.append(new ALOAD(3)); il.append(new ALOAD(4)); il.append(new ALOAD(5)); il.append(new ALOAD(6)); il.append(new ALOAD(7)); il.append( new INVOKESPECIAL( cpg.addMethodref( NODE_SORT_FACTORY, "<init>", "(" + DOM_INTF_SIG + STRING_SIG + TRANSLET_INTF_SIG + "[" + STRING_SIG + "[" + STRING_SIG + "[" + STRING_SIG + "[" + STRING_SIG + ")V"))); il.append(RETURN); // Override the definition of makeNodeSortRecord() il = new InstructionList(); final MethodGenerator makeNodeSortRecord = new MethodGenerator( ACC_PUBLIC, Util.getJCRefType(NODE_SORT_RECORD_SIG), new org.apache.bcel.generic.Type[] { org.apache.bcel.generic.Type.INT, org.apache.bcel.generic.Type.INT }, new String[] {"node", "last"}, "makeNodeSortRecord", className, il, cpg); il.append(ALOAD_0); il.append(ILOAD_1); il.append(ILOAD_2); il.append( new INVOKESPECIAL( cpg.addMethodref( NODE_SORT_FACTORY, "makeNodeSortRecord", "(II)" + NODE_SORT_RECORD_SIG))); il.append(DUP); il.append(new CHECKCAST(cpg.addClass(sortRecordClass))); // Initialize closure in record class final int ndups = dups.size(); for (int i = 0; i < ndups; i++) { final VariableRefBase varRef = (VariableRefBase) dups.get(i); final VariableBase var = varRef.getVariable(); final Type varType = var.getType(); il.append(DUP); // Get field from factory class il.append(ALOAD_0); il.append( new GETFIELD(cpg.addFieldref(className, var.getEscapedName(), varType.toSignature()))); // Put field in record class il.append( new PUTFIELD( cpg.addFieldref(sortRecordClass, var.getEscapedName(), varType.toSignature()))); } il.append(POP); il.append(ARETURN); constructor.setMaxLocals(); constructor.setMaxStack(); sortRecordFactory.addMethod(constructor); makeNodeSortRecord.setMaxLocals(); makeNodeSortRecord.setMaxStack(); sortRecordFactory.addMethod(makeNodeSortRecord); xsltc.dumpClass(sortRecordFactory.getJavaClass()); return className; }
/** * Compiles code that instantiates a NodeSortRecordFactory object which will produce * NodeSortRecord objects of a specific type. */ public static void compileSortRecordFactory( Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { String sortRecordClass = compileSortRecord(sortObjects, classGen, methodGen); boolean needsSortRecordFactory = false; final int nsorts = sortObjects.size(); for (int i = 0; i < nsorts; i++) { final Sort sort = (Sort) sortObjects.elementAt(i); needsSortRecordFactory |= sort._needsSortRecordFactory; } String sortRecordFactoryClass = NODE_SORT_FACTORY; if (needsSortRecordFactory) { sortRecordFactoryClass = compileSortRecordFactory(sortObjects, classGen, methodGen, sortRecordClass); } final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); // 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. // Compile code that initializes the static _sortOrder LocalVariableGen sortOrderTemp = methodGen.addLocalVariable( "sort_order_tmp", Util.getJCRefType("[" + STRING_SIG), null, null); il.append(new PUSH(cpg, nsorts)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int level = 0; level < nsorts; level++) { final Sort sort = (Sort) sortObjects.elementAt(level); il.append(DUP); il.append(new PUSH(cpg, level)); sort.translateSortOrder(classGen, methodGen); il.append(AASTORE); } sortOrderTemp.setStart(il.append(new ASTORE(sortOrderTemp.getIndex()))); LocalVariableGen sortTypeTemp = methodGen.addLocalVariable( "sort_type_tmp", Util.getJCRefType("[" + STRING_SIG), null, null); il.append(new PUSH(cpg, nsorts)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int level = 0; level < nsorts; level++) { final Sort sort = (Sort) sortObjects.elementAt(level); il.append(DUP); il.append(new PUSH(cpg, level)); sort.translateSortType(classGen, methodGen); il.append(AASTORE); } sortTypeTemp.setStart(il.append(new ASTORE(sortTypeTemp.getIndex()))); LocalVariableGen sortLangTemp = methodGen.addLocalVariable( "sort_lang_tmp", Util.getJCRefType("[" + STRING_SIG), null, null); il.append(new PUSH(cpg, nsorts)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int level = 0; level < nsorts; level++) { final Sort sort = (Sort) sortObjects.elementAt(level); il.append(DUP); il.append(new PUSH(cpg, level)); sort.translateLang(classGen, methodGen); il.append(AASTORE); } sortLangTemp.setStart(il.append(new ASTORE(sortLangTemp.getIndex()))); LocalVariableGen sortCaseOrderTemp = methodGen.addLocalVariable( "sort_case_order_tmp", Util.getJCRefType("[" + STRING_SIG), null, null); il.append(new PUSH(cpg, nsorts)); il.append(new ANEWARRAY(cpg.addClass(STRING))); for (int level = 0; level < nsorts; level++) { final Sort sort = (Sort) sortObjects.elementAt(level); il.append(DUP); il.append(new PUSH(cpg, level)); sort.translateCaseOrder(classGen, methodGen); il.append(AASTORE); } sortCaseOrderTemp.setStart(il.append(new ASTORE(sortCaseOrderTemp.getIndex()))); il.append(new NEW(cpg.addClass(sortRecordFactoryClass))); il.append(DUP); il.append(methodGen.loadDOM()); il.append(new PUSH(cpg, sortRecordClass)); il.append(classGen.loadTranslet()); sortOrderTemp.setEnd(il.append(new ALOAD(sortOrderTemp.getIndex()))); sortTypeTemp.setEnd(il.append(new ALOAD(sortTypeTemp.getIndex()))); sortLangTemp.setEnd(il.append(new ALOAD(sortLangTemp.getIndex()))); sortCaseOrderTemp.setEnd(il.append(new ALOAD(sortCaseOrderTemp.getIndex()))); il.append( new INVOKESPECIAL( cpg.addMethodref( sortRecordFactoryClass, "<init>", "(" + DOM_INTF_SIG + STRING_SIG + TRANSLET_INTF_SIG + "[" + STRING_SIG + "[" + STRING_SIG + "[" + STRING_SIG + "[" + STRING_SIG + ")V"))); // Initialize closure variables in sortRecordFactory final ArrayList dups = new ArrayList(); for (int j = 0; j < nsorts; j++) { final Sort sort = (Sort) sortObjects.get(j); final int length = (sort._closureVars == null) ? 0 : sort._closureVars.size(); for (int i = 0; i < length; i++) { VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; final VariableBase var = varRef.getVariable(); // Store variable in new closure il.append(DUP); il.append(var.loadInstruction()); il.append( new PUTFIELD( cpg.addFieldref( sortRecordFactoryClass, var.getEscapedName(), var.getType().toSignature()))); dups.add(varRef); } } }
/** * 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 Instruction createInstructionAnewarray(Element inst) { String classType = inst.getAttributeValue("elementType"); return new ANEWARRAY(_cp.addClass(classType)); }
public Instruction createInstructionCheckcast(Element inst) throws IllegalXMLVMException { String classType = inst.getAttributeValue("type"); return new CHECKCAST(_cp.addClass(classType)); }
/** * 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()); } }