/** * Compiles the default handling for DOM elements: traverse all children */ private InstructionList compileDefaultRecursion(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle next) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final String applyTemplatesSig = classGen.getApplyTemplatesSig(); final int git = cpg.addInterfaceMethodref(DOM_INTF, GET_CHILDREN, GET_CHILDREN_SIG); final int applyTemplates = cpg.addMethodref(getClassName(), functionName(), applyTemplatesSig); il.append(classGen.loadTranslet()); il.append(methodGen.loadDOM()); il.append(methodGen.loadDOM()); il.append(new ILOAD(_currentIndex)); il.append(new INVOKEINTERFACE(git, 2)); il.append(methodGen.loadHandler()); il.append(new INVOKEVIRTUAL(applyTemplates)); il.append(new GOTO_W(next)); return il; }
/** * Compiles the default action for DOM text nodes and attribute nodes: * output the node's text value */ private InstructionList compileDefaultText(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle next) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = new InstructionList(); final int chars = cpg.addInterfaceMethodref(DOM_INTF, CHARACTERS, CHARACTERS_SIG); il.append(methodGen.loadDOM()); il.append(new ILOAD(_currentIndex)); il.append(methodGen.loadHandler()); il.append(new INVOKEINTERFACE(chars, 3)); il.append(new GOTO_W(next)); return il; }
private void compileTemplateCalls(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle next, int min, int max){ Enumeration templates = _neededTemplates.keys(); while (templates.hasMoreElements()) { final Template template = (Template)templates.nextElement(); final int prec = template.getImportPrecedence(); if ((prec >= min) && (prec < max)) { if (template.hasContents()) { InstructionList til = template.compile(classGen, methodGen); til.append(new GOTO_W(next)); _templateILs.put(template, til); _templateIHs.put(template, til.getStart()); } else { // empty template _templateIHs.put(template, next); } } } }
/** * Redirect the handles from oldList to newList. "This" flow list * is assumed to be relative to oldList. */ public FlowList copyAndRedirect(InstructionList oldList, InstructionList newList) { final FlowList result = new FlowList(); if (_elements == null) { return result; } final int n = _elements.size(); final Iterator oldIter = oldList.iterator(); final Iterator newIter = newList.iterator(); while (oldIter.hasNext()) { final InstructionHandle oldIh = (InstructionHandle) oldIter.next(); final InstructionHandle newIh = (InstructionHandle) newIter.next(); for (int i = 0; i < n; i++) { if (_elements.elementAt(i) == oldIh) { result.add(newIh); } } } return result; }
private void compileTemplateCalls(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle next, int min, int max){ _neededTemplates.keySet().stream().forEach((template) -> { final int prec = template.getImportPrecedence(); if ((prec >= min) && (prec < max)) { if (template.hasContents()) { InstructionList til = template.compile(classGen, methodGen); til.append(new GOTO_W(next)); _templateILs.put(template, til); _templateIHs.put(template, til.getStart()); } else { // empty template _templateIHs.put(template, next); } } }); }
public void start() { if (!_mg.isAbstract() && !_mg.isNative()) { for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih .getNext()) { final Instruction i = ih.getInstruction(); if (i instanceof BranchInstruction) { branch_map.put(i, ih); // memorize container } if (ih.hasTargeters()) { if (i instanceof BranchInstruction) { _out.println(" InstructionHandle ih_" + ih.getPosition() + ";"); } else { _out.print(" InstructionHandle ih_" + ih.getPosition() + " = "); } } else { _out.print(" "); } if (!visitInstruction(i)) { i.accept(this); } } updateBranchTargets(); updateExceptionHandlers(); } }
private void updateBranchTargets() { for (final BranchInstruction bi : branches) { final BranchHandle bh = (BranchHandle) branch_map.get(bi); final int pos = bh.getPosition(); final String name = bi.getName() + "_" + pos; int t_pos = bh.getTarget().getPosition(); _out.println(" " + name + ".setTarget(ih_" + t_pos + ");"); if (bi instanceof Select) { final InstructionHandle[] ihs = ((Select) bi).getTargets(); for (int j = 0; j < ihs.length; j++) { t_pos = ihs[j].getPosition(); _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");"); } } } }
private void compileTemplateCalls(ClassGenerator classGen, MethodGenerator methodGen, InstructionHandle next, int min, int max){ for (Template template : _neededTemplates.keySet()) { final int prec = template.getImportPrecedence(); if ((prec >= min) && (prec < max)) { if (template.hasContents()) { InstructionList til = template.compile(classGen, methodGen); til.append(new GOTO_W(next)); _templateILs.put(template, til); _templateIHs.put(template, til.getStart()); } else { // empty template _templateIHs.put(template, next); } } } }
/** * Back patch a flow list. All instruction handles must be branch handles. */ public void backPatch(InstructionHandle target) { if (_elements != null) { final int n = _elements.size(); for (int i = 0; i < n; i++) { BranchHandle bh = (BranchHandle)_elements.elementAt(i); bh.setTarget(target); } _elements.clear(); // avoid backpatching more than once } }
/** * Translate the "test" expression and contents of this element. * The contents will be ignored if we know the test will always fail. */ public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final InstructionList il = methodGen.getInstructionList(); _test.translateDesynthesized(classGen, methodGen); // remember end of condition final InstructionHandle truec = il.getEnd(); if (!_ignore) { translateContents(classGen, methodGen); } _test.backPatchFalseList(il.append(NOP)); _test.backPatchTrueList(truec.getNext()); }
/** * Peephole optimization: Remove sequences of [ALOAD, POP]. */ private void peepHoleOptimization(MethodGenerator methodGen) { final String pattern = "`aload'`pop'`instruction'"; final InstructionList il = methodGen.getInstructionList(); final InstructionFinder find = new InstructionFinder(il); for(Iterator iter=find.search(pattern); iter.hasNext(); ) { InstructionHandle[] match = (InstructionHandle[])iter.next(); try { il.delete(match[0], match[1]); } catch (TargetLostException e) { // TODO: move target down into the list } } }
public static void compileStripSpace(BranchHandle strip[], int sCount, InstructionList il) { final InstructionHandle target = il.append(ICONST_1); il.append(IRETURN); for (int i = 0; i < sCount; i++) { strip[i].setTarget(target); } }
public static void compilePreserveSpace(BranchHandle preserve[], int pCount, InstructionList il) { final InstructionHandle target = il.append(ICONST_0); il.append(IRETURN); for (int i = 0; i < pCount; i++) { preserve[i].setTarget(target); } }
/** * Allocates a local variable. If the slot allocator has already been * initialized, then call addLocalVariable2() so that the new variable * is known to the allocator. Failing to do this may cause the allocator * to return a slot that is already in use. */ public LocalVariableGen addLocalVariable(String name, Type type, InstructionHandle start, InstructionHandle end) { LocalVariableGen lvg; if (_allocatorInit) { lvg = addLocalVariable2(name, type, start); } else { lvg = super.addLocalVariable(name, type, start, end); getLocalVariableRegistry().registerLocalVariable(lvg); } return lvg; }
public LocalVariableGen addLocalVariable2(String name, Type type, InstructionHandle start) { LocalVariableGen lvg = super.addLocalVariable(name, type, _slotAllocator.allocateSlot(type), start, null); getLocalVariableRegistry().registerLocalVariable(lvg); return lvg; }
/** * Determines whether a particular variable is in use at a particular offset * in the byte code for this method. * <p><b>Preconditions:</b> * <ul> * <li>The {@link InstructionList#setPositions()} has been called for the * {@link InstructionList} associated with this {@link MethodGenerator}. * </li></ul></p> * @param lvg the {@link LocalVariableGen} for the variable * @param offset the position in the byte code * @return <code>true</code> if and only if the specified variable is in * use at the particular byte code offset. */ boolean offsetInLocalVariableGenRange(LocalVariableGen lvg, int offset) { InstructionHandle lvgStart = lvg.getStart(); InstructionHandle lvgEnd = lvg.getEnd(); // If no start handle is recorded for the LocalVariableGen, it is // assumed to be in use from the beginning of the method. if (lvgStart == null) { lvgStart = getInstructionList().getStart(); } // If no end handle is recorded for the LocalVariableGen, it is assumed // to be in use to the end of the method. if (lvgEnd == null) { lvgEnd = getInstructionList().getEnd(); } // Does the range of the instruction include the specified offset? // Note that the InstructionHandle.getPosition method returns the // offset of the beginning of an instruction. A LocalVariableGen's // range includes the end instruction itself, so that instruction's // length must be taken into consideration in computing whether the // varible is in range at a particular offset. return ((lvgStart.getPosition() <= offset) && (lvgEnd.getPosition() + lvgEnd.getInstruction().getLength() >= offset)); }
/** * <p>Get all {@link Method}s generated by this {@link MethodGenerator}. * The {@link MethodGen#getMethod()} only returns a single * <code>Method</code> object. This method takes into account the Java * Virtual Machine Specification limit of 64KB on the size of a method, and * may return more than one <code>Method</code>.</p> * <p>If the code associated with the <code>MethodGenerator</code> would * exceed the 64KB limit, this method will attempt to split the code in * the {@link InstructionList} associated with this * <code>MethodGenerator</code> into several methods.</p> * @param classGen the {@link ClassGenerator} of which these methods are * members * @return an array of all the <code>Method</code>s generated */ Method[] getGeneratedMethods(ClassGenerator classGen) { Method[] generatedMethods; InstructionList il = getInstructionList(); InstructionHandle last = il.getEnd(); il.setPositions(); int instructionListSize = last.getPosition() + last.getInstruction().getLength(); // Need to look for any branch target offsets that exceed the range // [-32768,32767] if (instructionListSize > MAX_BRANCH_TARGET_OFFSET) { boolean ilChanged = widenConditionalBranchTargetOffsets(); // If any branch instructions needed widening, recompute the size // of the byte code for the method if (ilChanged) { il.setPositions(); last = il.getEnd(); instructionListSize = last.getPosition() + last.getInstruction().getLength(); } } if (instructionListSize > MAX_METHOD_SIZE) { generatedMethods = outlineChunks(classGen, instructionListSize); } else { generatedMethods = new Method[] {getThisMethod()}; } return generatedMethods; }
public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final InstructionList il = methodGen.getInstructionList(); _left.translate(classGen, methodGen); final InstructionHandle gotot = il.append(new GOTO(null)); il.append(methodGen.loadContextNode()); _right.translate(classGen, methodGen); _left._trueList.backPatch(gotot); _left._falseList.backPatch(gotot.getNext()); _trueList.append(_right._trueList.add(gotot)); _falseList.append(_right._falseList); }