📄 mode.java
字号:
methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Create a local variable to hold the current node final LocalVariableGen current; current = methodGen.addLocalVariable2("current", com.sun.org.apache.bcel.internal.generic.Type.INT, mainIL.getEnd()); _currentIndex = current.getIndex(); // Create the "body" instruction list that will eventually hold the // code for the entire method (other ILs will be appended). final InstructionList body = new InstructionList(); body.append(NOP); // Create an instruction list that contains the default next-node // iteration final InstructionList ilLoop = new InstructionList(); ilLoop.append(methodGen.loadIterator()); ilLoop.append(methodGen.nextNode()); ilLoop.append(DUP); ilLoop.append(new ISTORE(_currentIndex)); // The body of this code can get very large - large than can be handled // by a single IFNE(body.getStart()) instruction - need workaround: final BranchHandle ifeq = ilLoop.append(new IFLT(null)); final BranchHandle loop = ilLoop.append(new GOTO_W(null)); ifeq.setTarget(ilLoop.append(RETURN)); // applyTemplates() ends here! final InstructionHandle ihLoop = ilLoop.getStart(); // Compile default handling of elements (traverse children) InstructionList ilRecurse = compileDefaultRecursion(classGen, methodGen, ihLoop); InstructionHandle ihRecurse = ilRecurse.getStart(); // Compile default handling of text/attribute nodes (output text) InstructionList ilText = compileDefaultText(classGen, methodGen, ihLoop); InstructionHandle ihText = ilText.getStart(); // Distinguish attribute/element/namespace tests for further processing final int[] types = new int[DTM.NTYPES + names.size()]; for (int i = 0; i < types.length; i++) { types[i] = i; } // Initialize isAttribute[] and isNamespace[] arrays final boolean[] isAttribute = new boolean[types.length]; final boolean[] isNamespace = new boolean[types.length]; for (int i = 0; i < names.size(); i++) { final String name = (String)names.elementAt(i); isAttribute[i + DTM.NTYPES] = isAttributeName(name); isNamespace[i + DTM.NTYPES] = isNamespaceName(name); } // Compile all templates - regardless of pattern type compileTemplates(classGen, methodGen, ihLoop); // Handle template with explicit "*" pattern final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; InstructionHandle ihElem = ihRecurse; if (elemTest != null) ihElem = elemTest.compile(classGen, methodGen, ihRecurse); // Handle template with explicit "@*" pattern final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; InstructionHandle ihAttr = ihText; if (attrTest != null) ihAttr = attrTest.compile(classGen, methodGen, ihAttr); // Do tests for id() and key() patterns first InstructionList ilKey = null; if (_idxTestSeq != null) { loop.setTarget(_idxTestSeq.compile(classGen, methodGen, body.getStart())); ilKey = _idxTestSeq.getInstructionList(); } else { loop.setTarget(body.getStart()); } // If there is a match on node() we need to replace ihElem // and ihText if the priority of node() is higher if (_childNodeTestSeq != null) { // Compare priorities of node() and "*" double nodePrio = _childNodeTestSeq.getPriority(); int nodePos = _childNodeTestSeq.getPosition(); double elemPrio = (0 - Double.MAX_VALUE); int elemPos = Integer.MIN_VALUE; if (elemTest != null) { elemPrio = elemTest.getPriority(); elemPos = elemTest.getPosition(); } if (elemPrio == Double.NaN || elemPrio < nodePrio || (elemPrio == nodePrio && elemPos < nodePos)) { ihElem = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); } // Compare priorities of node() and text() final TestSeq textTest = _testSeq[DTM.TEXT_NODE]; double textPrio = (0 - Double.MAX_VALUE); int textPos = Integer.MIN_VALUE; if (textTest != null) { textPrio = textTest.getPriority(); textPos = textTest.getPosition(); } if (textPrio == Double.NaN || textPrio < nodePrio || (textPrio == nodePrio && textPos < nodePos)) { ihText = _childNodeTestSeq.compile(classGen, methodGen, ihLoop); _testSeq[DTM.TEXT_NODE] = _childNodeTestSeq; } } // Handle templates with "ns:*" pattern InstructionHandle elemNamespaceHandle = ihElem; InstructionList nsElem = compileNamespaces(classGen, methodGen, isNamespace, isAttribute, false, ihElem); if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); // Handle templates with "ns:@*" pattern InstructionHandle attrNamespaceHandle = ihAttr; InstructionList nsAttr = compileNamespaces(classGen, methodGen, isNamespace, isAttribute, true, ihAttr); if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); // Handle templates with "ns:elem" or "ns:@attr" pattern final InstructionHandle[] targets = new InstructionHandle[types.length]; for (int i = DTM.NTYPES; i < targets.length; i++) { final TestSeq testSeq = _testSeq[i]; // Jump straight to namespace tests ? if (isNamespace[i]) { if (isAttribute[i]) targets[i] = attrNamespaceHandle; else targets[i] = elemNamespaceHandle; } // Test first, then jump to namespace tests else if (testSeq != null) { if (isAttribute[i]) targets[i] = testSeq.compile(classGen, methodGen, attrNamespaceHandle); else targets[i] = testSeq.compile(classGen, methodGen, elemNamespaceHandle); } else { targets[i] = ihLoop; } } // Handle pattern with match on root node - default: traverse children targets[DTM.ROOT_NODE] = _rootPattern != null ? getTemplateInstructionHandle(_rootPattern.getTemplate()) : ihRecurse; // Handle pattern with match on root node - default: traverse children targets[DTM.DOCUMENT_NODE] = _rootPattern != null ? getTemplateInstructionHandle(_rootPattern.getTemplate()) : ihRecurse; // Handle any pattern with match on text nodes - default: output text targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null ? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) : ihText; // This DOM-type is not in use - default: process next node targets[DTM.NAMESPACE_NODE] = ihLoop; // Match unknown element in DOM - default: check for namespace match targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; // Match unknown attribute in DOM - default: check for namespace match targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; // Match on processing instruction - default: process next node InstructionHandle ihPI = ihLoop; if (_childNodeTestSeq != null) ihPI = ihElem; if (_testSeq[DTM.PROCESSING_INSTRUCTION_NODE] != null) targets[DTM.PROCESSING_INSTRUCTION_NODE] = _testSeq[DTM.PROCESSING_INSTRUCTION_NODE]. compile(classGen, methodGen, ihPI); else targets[DTM.PROCESSING_INSTRUCTION_NODE] = ihPI; // Match on comments - default: process next node InstructionHandle ihComment = ihLoop; if (_childNodeTestSeq != null) ihComment = ihElem; targets[DTM.COMMENT_NODE] = _testSeq[DTM.COMMENT_NODE] != null ? _testSeq[DTM.COMMENT_NODE].compile(classGen, methodGen, ihComment) : ihComment; // This DOM-type is not in use - default: process next node targets[DTM.CDATA_SECTION_NODE] = ihLoop; // This DOM-type is not in use - default: process next node targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; // This DOM-type is not in use - default: process next node targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; // This DOM-type is not in use - default: process next node targets[DTM.ENTITY_NODE] = ihLoop; // This DOM-type is not in use - default: process next node targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; // This DOM-type is not in use - default: process next node targets[DTM.NOTATION_NODE] = ihLoop; // Now compile test sequences for various match patterns: for (int i = DTM.NTYPES; i < targets.length; i++) { final TestSeq testSeq = _testSeq[i]; // Jump straight to namespace tests ? if ((testSeq == null) || (isNamespace[i])) { if (isAttribute[i]) targets[i] = attrNamespaceHandle; else targets[i] = elemNamespaceHandle; } // Match on node type else { if (isAttribute[i]) targets[i] = testSeq.compile(classGen, methodGen, attrNamespaceHandle); else targets[i] = testSeq.compile(classGen, methodGen, elemNamespaceHandle); } } if (ilKey != null) body.insert(ilKey); // Append first code in applyTemplates() - get type of current node final int getType = cpg.addInterfaceMethodref(DOM_INTF, "getExpandedTypeID", "(I)I"); body.append(methodGen.loadDOM()); body.append(new ILOAD(_currentIndex)); body.append(new INVOKEINTERFACE(getType, 2)); // Append switch() statement - main dispatch loop in applyTemplates() InstructionHandle disp = body.append(new SWITCH(types, targets, ihLoop)); // Append all the "case:" statements appendTestSequences(body); // Append the actual template code appendTemplateCode(body); // Append NS:* node tests (if any) if (nsElem != null) body.append(nsElem); // Append NS:@* node tests (if any) if (nsAttr != null) body.append(nsAttr); // Append default action for element and root nodes body.append(ilRecurse); // Append default action for text and attribute nodes body.append(ilText); // putting together constituent instruction lists mainIL.append(new GOTO_W(ihLoop)); mainIL.append(body); // fall through to ilLoop mainIL.append(ilLoop); peepHoleOptimization(methodGen); methodGen.stripAttributes(true); methodGen.setMaxLocals(); methodGen.setMaxStack(); methodGen.removeNOPs(); classGen.addMethod(methodGen.getMethod()); // Compile method(s) for <xsl:apply-imports/> for this mode if (_importLevels != null) { Enumeration levels = _importLevels.keys(); while (levels.hasMoreElements()) { Integer max = (Integer)levels.nextElement(); Integer min = (Integer)_importLevels.get(max); compileApplyImports(classGen, min.intValue(), max.intValue()); } } } 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); } } } } public void compileApplyImports(ClassGenerator classGen, int min, int max) { final XSLTC xsltc = classGen.getParser().getXSLTC(); final ConstantPoolGen cpg = classGen.getConstantPool(); final Vector names = xsltc.getNamesIndex(); // Clear some datastructures _namedTemplates = new Hashtable(); _neededTemplates = new Hashtable(); _templateIHs = new Hashtable(); _templateILs = new Hashtable(); _patternGroups = new Vector[32]; _rootPattern = null; // IMPORTANT: Save orignal & complete set of templates!!!! Vector oldTemplates = _templates; // Gather templates that are within the scope of this import _templates = new Vector(); final Enumeration templates = oldTemplates.elements(); while (templates.hasMoreElements()) { final Template template = (Template)templates.nextElement(); final int prec = template.getImportPrecedence(); if ((prec >= min) && (prec < max)) addTemplate(template); } // Process all patterns from those templates processPatterns(_keys); // Create the applyTemplates() method final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = new com.sun.org.apache.bcel.internal.generic.Type[4]; argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); argTypes[3] = com.sun.org.apache.bcel.internal.generic.Type.INT; final String[] argNames = new String[4]; argNames[0] = DOCUMENT_PNAME; argNames[1] = ITERATOR_PNAME; argNames[2] = TRANSLET_OUTPUT_PNAME; argNames[3] = NODE_PNAME; final InstructionList mainIL = new InstructionList(); final MethodGenerator methodGen = new MethodGenerator(ACC_PUBLIC | ACC_FINAL, com.sun.org.apache.bcel.internal.generic.Type.VOID, argTypes, argNames, functionName()+'_'+max, getClassName(), mainIL, classGen.getConstantPool()); methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); // Create the local variable to hold the current node final LocalVariableGen current; current = methodGen.addLocalVariable2("current", com.sun.org.apache.bcel.internal.generic.Type.INT, mainIL.getEnd()); _currentIndex = current.getIndex(); mainIL.append(new ILOAD(methodGen.getLocalIndex(NODE_PNAME))); mainIL.append(new ISTORE(_currentIndex)); // Create the "body" instruction list that will eventually hold the // code for the entire method (other ILs will be appended). final InstructionList body = new InstructionList(); body.append(NOP); // Create an instruction list that contains the default next-node // iteration final InstructionList ilLoop = new InstructionList();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -