|
|
|
|
|
*/ |
|
/* |
|
* Licensed to the Apache Software Foundation (ASF) under one or more |
|
* contributor license agreements. See the NOTICE file distributed with |
|
* this work for additional information regarding copyright ownership. |
|
* The ASF licenses this file to You under the Apache License, Version 2.0 |
|
* (the "License"); you may not use this file except in compliance with |
|
* the License. You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
/* |
|
* $Id: Mode.java,v 1.2.4.1 2005/09/19 05:18:11 pvedula Exp $ |
|
*/ |
|
|
|
package com.sun.org.apache.xalan.internal.xsltc.compiler; |
|
|
|
import com.sun.org.apache.bcel.internal.generic.BranchHandle; |
|
import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; |
|
import com.sun.org.apache.bcel.internal.generic.DUP; |
|
import com.sun.org.apache.bcel.internal.generic.GOTO_W; |
|
import com.sun.org.apache.bcel.internal.generic.IFLT; |
|
import com.sun.org.apache.bcel.internal.generic.ILOAD; |
|
import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; |
|
import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; |
|
import com.sun.org.apache.bcel.internal.generic.ISTORE; |
|
import com.sun.org.apache.bcel.internal.generic.Instruction; |
|
import com.sun.org.apache.bcel.internal.generic.InstructionHandle; |
|
import com.sun.org.apache.bcel.internal.generic.InstructionList; |
|
import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; |
|
import com.sun.org.apache.bcel.internal.generic.SWITCH; |
|
import com.sun.org.apache.bcel.internal.generic.TargetLostException; |
|
import com.sun.org.apache.bcel.internal.util.InstructionFinder; |
|
import com.sun.org.apache.xalan.internal.xsltc.DOM; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NamedMethodGenerator; |
|
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; |
|
import com.sun.org.apache.xml.internal.dtm.Axis; |
|
import com.sun.org.apache.xml.internal.dtm.DTM; |
|
import java.util.ArrayList; |
|
import java.util.HashMap; |
|
import java.util.Iterator; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
final class Mode implements Constants { |
|
|
|
|
|
|
|
*/ |
|
private final QName _name; |
|
|
|
|
|
|
|
*/ |
|
private final Stylesheet _stylesheet; |
|
|
|
|
|
|
|
*/ |
|
private final String _methodName; |
|
|
|
|
|
|
|
*/ |
|
private List<Template> _templates; |
|
|
|
|
|
|
|
*/ |
|
private List<LocationPathPattern> _childNodeGroup = null; |
|
|
|
|
|
|
|
*/ |
|
private TestSeq _childNodeTestSeq = null; |
|
|
|
|
|
|
|
*/ |
|
private List<LocationPathPattern> _attribNodeGroup = null; |
|
|
|
|
|
|
|
*/ |
|
private TestSeq _attribNodeTestSeq = null; |
|
|
|
|
|
|
|
*/ |
|
private List<LocationPathPattern> _idxGroup = null; |
|
|
|
|
|
|
|
*/ |
|
private TestSeq _idxTestSeq = null; |
|
|
|
|
|
|
|
*/ |
|
private List<LocationPathPattern>[] _patternGroups; |
|
|
|
|
|
|
|
*/ |
|
private TestSeq[] _testSeq; |
|
|
|
|
|
|
|
|
|
*/ |
|
private Map<Template, Object> _neededTemplates = new HashMap<>(); |
|
|
|
|
|
|
|
*/ |
|
private Map<Template, Mode> _namedTemplates = new HashMap<>(); |
|
|
|
|
|
|
|
*/ |
|
private Map<Template, InstructionHandle> _templateIHs = new HashMap<>(); |
|
|
|
|
|
|
|
*/ |
|
private Map<Template, InstructionList> _templateILs = new HashMap<>(); |
|
|
|
|
|
|
|
*/ |
|
private LocationPathPattern _rootPattern = null; |
|
|
|
|
|
|
|
|
|
*/ |
|
private Map<Integer, Integer> _importLevels = null; |
|
|
|
|
|
|
|
*/ |
|
private Map<String, Key> _keys = null; |
|
|
|
|
|
|
|
*/ |
|
private int _currentIndex; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings({"rawtypes", "unchecked"}) |
|
public Mode(QName name, Stylesheet stylesheet, String suffix) { |
|
_name = name; |
|
_stylesheet = stylesheet; |
|
_methodName = APPLY_TEMPLATES + suffix; |
|
_templates = new ArrayList<>(); |
|
_patternGroups = (List<LocationPathPattern>[])new ArrayList[32]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public String functionName() { |
|
return _methodName; |
|
} |
|
|
|
public String functionName(int min, int max) { |
|
if (_importLevels == null) { |
|
_importLevels = new HashMap<>(); |
|
} |
|
_importLevels.put(max, min); |
|
return _methodName + '_' + max; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private String getClassName() { |
|
return _stylesheet.getClassName(); |
|
} |
|
|
|
public Stylesheet getStylesheet() { |
|
return _stylesheet; |
|
} |
|
|
|
public void addTemplate(Template template) { |
|
_templates.add(template); |
|
} |
|
|
|
private List<Template> quicksort(List<Template> templates, int p, int r) { |
|
if (p < r) { |
|
final int q = partition(templates, p, r); |
|
quicksort(templates, p, q); |
|
quicksort(templates, q + 1, r); |
|
} |
|
return templates; |
|
} |
|
|
|
private int partition(List<Template> templates, int p, int r) { |
|
final Template x = templates.get(p); |
|
int i = p - 1; |
|
int j = r + 1; |
|
while (true) { |
|
while (x.compareTo(templates.get(--j)) > 0); |
|
while (x.compareTo(templates.get(++i)) < 0); |
|
if (i < j) { |
|
templates.set(j, templates.set(i, templates.get(j))); |
|
} |
|
else { |
|
return j; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void processPatterns(Map<String, Key> keys) { |
|
_keys = keys; |
|
_templates = quicksort(_templates, 0, _templates.size() - 1); |
|
|
|
|
|
for (Template template : _templates) { |
|
|
|
|
|
|
|
|
|
*/ |
|
if (template.isNamed() && !template.disabled()) { |
|
_namedTemplates.put(template, this); |
|
} |
|
|
|
|
|
final Pattern pattern = template.getPattern(); |
|
if (pattern != null) { |
|
flattenAlternative(pattern, template, keys); |
|
} |
|
} |
|
prepareTestSequences(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void flattenAlternative(Pattern pattern, |
|
Template template, |
|
Map<String, Key> keys) { |
|
// Patterns on type id() and key() are special since they do not have |
|
// any kernel node type (it can be anything as long as the node is in |
|
|
|
if (pattern instanceof IdKeyPattern) { |
|
final IdKeyPattern idkey = (IdKeyPattern)pattern; |
|
idkey.setTemplate(template); |
|
if (_idxGroup == null) _idxGroup = new ArrayList<>(); |
|
_idxGroup.add((IdKeyPattern)pattern); |
|
} |
|
|
|
else if (pattern instanceof AlternativePattern) { |
|
final AlternativePattern alt = (AlternativePattern)pattern; |
|
flattenAlternative(alt.getLeft(), template, keys); |
|
flattenAlternative(alt.getRight(), template, keys); |
|
} |
|
|
|
else if (pattern instanceof LocationPathPattern) { |
|
final LocationPathPattern lpp = (LocationPathPattern)pattern; |
|
lpp.setTemplate(template); |
|
addPatternToGroup(lpp); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private void addPatternToGroup(final LocationPathPattern lpp) { |
|
|
|
if (lpp instanceof IdKeyPattern) { |
|
addPattern(-1, lpp); |
|
} |
|
|
|
else { |
|
|
|
final StepPattern kernel = lpp.getKernelPattern(); |
|
if (kernel != null) { |
|
addPattern(kernel.getNodeType(), lpp); |
|
} |
|
else if (_rootPattern == null || |
|
lpp.noSmallerThan(_rootPattern)) { |
|
_rootPattern = lpp; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void addPattern(int kernelType, LocationPathPattern pattern) { |
|
|
|
final int oldLength = _patternGroups.length; |
|
if (kernelType >= oldLength) { |
|
@SuppressWarnings({"rawtypes", "unchecked"}) |
|
List<LocationPathPattern>[] newGroups = |
|
(List<LocationPathPattern>[])new ArrayList[kernelType * 2]; |
|
|
|
System.arraycopy(_patternGroups, 0, newGroups, 0, oldLength); |
|
_patternGroups = newGroups; |
|
} |
|
|
|
|
|
List<LocationPathPattern> patterns; |
|
|
|
if (kernelType == DOM.NO_TYPE) { |
|
if (pattern.getAxis() == Axis.ATTRIBUTE) { |
|
patterns = (_attribNodeGroup == null) ? |
|
(_attribNodeGroup = new ArrayList<>(2)) : _attribNodeGroup; |
|
} |
|
else { |
|
patterns = (_childNodeGroup == null) ? |
|
(_childNodeGroup = new ArrayList<>(2)) : _childNodeGroup; |
|
} |
|
} |
|
else { |
|
patterns = (_patternGroups[kernelType] == null) ? |
|
(_patternGroups[kernelType] = new ArrayList<>(2)) : |
|
_patternGroups[kernelType]; |
|
} |
|
|
|
if (patterns.size() == 0) { |
|
patterns.add(pattern); |
|
} |
|
else { |
|
boolean inserted = false; |
|
for (int i = 0; i < patterns.size(); i++) { |
|
final LocationPathPattern lppToCompare = |
|
patterns.get(i); |
|
|
|
if (pattern.noSmallerThan(lppToCompare)) { |
|
inserted = true; |
|
patterns.add(i, pattern); |
|
break; |
|
} |
|
} |
|
if (inserted == false) { |
|
patterns.add(pattern); |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private void completeTestSequences(int nodeType, List<LocationPathPattern> patterns) { |
|
if (patterns != null) { |
|
if (_patternGroups[nodeType] == null) { |
|
_patternGroups[nodeType] = patterns; |
|
} |
|
else { |
|
final int m = patterns.size(); |
|
for (int j = 0; j < m; j++) { |
|
addPattern(nodeType, patterns.get(j)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private void prepareTestSequences() { |
|
final List<LocationPathPattern> starGroup = _patternGroups[DTM.ELEMENT_NODE]; |
|
final List<LocationPathPattern> atStarGroup = _patternGroups[DTM.ATTRIBUTE_NODE]; |
|
|
|
|
|
completeTestSequences(DTM.TEXT_NODE, _childNodeGroup); |
|
|
|
|
|
completeTestSequences(DTM.ELEMENT_NODE, _childNodeGroup); |
|
|
|
|
|
completeTestSequences(DTM.PROCESSING_INSTRUCTION_NODE, _childNodeGroup); |
|
|
|
|
|
completeTestSequences(DTM.COMMENT_NODE, _childNodeGroup); |
|
|
|
|
|
completeTestSequences(DTM.ATTRIBUTE_NODE, _attribNodeGroup); |
|
|
|
final List<String> names = _stylesheet.getXSLTC().getNamesIndex(); |
|
if (starGroup != null || atStarGroup != null || |
|
_childNodeGroup != null || _attribNodeGroup != null) |
|
{ |
|
final int n = _patternGroups.length; |
|
|
|
|
|
for (int i = DTM.NTYPES; i < n; i++) { |
|
if (_patternGroups[i] == null) continue; |
|
|
|
final String name = names.get(i - DTM.NTYPES); |
|
|
|
if (isAttributeName(name)) { |
|
|
|
completeTestSequences(i, atStarGroup); |
|
|
|
|
|
completeTestSequences(i, _attribNodeGroup); |
|
} |
|
else { |
|
|
|
completeTestSequences(i, starGroup); |
|
|
|
|
|
completeTestSequences(i, _childNodeGroup); |
|
} |
|
} |
|
} |
|
|
|
_testSeq = new TestSeq[DTM.NTYPES + names.size()]; |
|
|
|
final int n = _patternGroups.length; |
|
for (int i = 0; i < n; i++) { |
|
final List<LocationPathPattern> patterns = _patternGroups[i]; |
|
if (patterns != null) { |
|
final TestSeq testSeq = new TestSeq(patterns, i, this); |
|
|
|
testSeq.reduce(); |
|
_testSeq[i] = testSeq; |
|
testSeq.findTemplates(_neededTemplates); |
|
} |
|
} |
|
|
|
if (_childNodeGroup != null && _childNodeGroup.size() > 0) { |
|
_childNodeTestSeq = new TestSeq(_childNodeGroup, -1, this); |
|
_childNodeTestSeq.reduce(); |
|
_childNodeTestSeq.findTemplates(_neededTemplates); |
|
} |
|
|
|
/* |
|
if (_attribNodeGroup != null && _attribNodeGroup.size() > 0) { |
|
_attribNodeTestSeq = new TestSeq(_attribNodeGroup, -1, this); |
|
_attribNodeTestSeq.reduce(); |
|
_attribNodeTestSeq.findTemplates(_neededTemplates); |
|
} |
|
*/ |
|
|
|
if (_idxGroup != null && _idxGroup.size() > 0) { |
|
_idxTestSeq = new TestSeq(_idxGroup, this); |
|
_idxTestSeq.reduce(); |
|
_idxTestSeq.findTemplates(_neededTemplates); |
|
} |
|
|
|
if (_rootPattern != null) { |
|
|
|
_neededTemplates.put(_rootPattern.getTemplate(), this); |
|
} |
|
} |
|
|
|
private void compileNamedTemplate(Template template, |
|
ClassGenerator classGen) { |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
final InstructionList il = new InstructionList(); |
|
String methodName = Util.escape(template.getName().toString()); |
|
|
|
int numParams = 0; |
|
if (template.isSimpleNamedTemplate()) { |
|
List<Param> parameters = template.getParameters(); |
|
numParams = parameters.size(); |
|
} |
|
|
|
|
|
com.sun.org.apache.bcel.internal.generic.Type[] types = |
|
new com.sun.org.apache.bcel.internal.generic.Type[4 + numParams]; |
|
String[] names = new String[4 + numParams]; |
|
types[0] = Util.getJCRefType(DOM_INTF_SIG); |
|
types[1] = Util.getJCRefType(NODE_ITERATOR_SIG); |
|
types[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); |
|
types[3] = com.sun.org.apache.bcel.internal.generic.Type.INT; |
|
names[0] = DOCUMENT_PNAME; |
|
names[1] = ITERATOR_PNAME; |
|
names[2] = TRANSLET_OUTPUT_PNAME; |
|
names[3] = NODE_PNAME; |
|
|
|
// For simple named templates, the signature of the generated method |
|
// is not fixed. It depends on the number of parameters declared in the |
|
|
|
for (int i = 4; i < 4 + numParams; i++) { |
|
types[i] = Util.getJCRefType(OBJECT_SIG); |
|
names[i] = "param" + String.valueOf(i-4); |
|
} |
|
|
|
NamedMethodGenerator methodGen = |
|
new NamedMethodGenerator(ACC_PUBLIC, |
|
com.sun.org.apache.bcel.internal.generic.Type.VOID, |
|
types, names, methodName, |
|
getClassName(), il, cpg); |
|
|
|
il.append(template.compile(classGen, methodGen)); |
|
il.append(RETURN); |
|
|
|
classGen.addMethod(methodGen); |
|
} |
|
|
|
private void compileTemplates(ClassGenerator classGen, |
|
MethodGenerator methodGen, |
|
InstructionHandle next) |
|
{ |
|
Set<Template> templates = _namedTemplates.keySet(); |
|
for (Template template : templates) { |
|
compileNamedTemplate(template, classGen); |
|
} |
|
|
|
templates = _neededTemplates.keySet(); |
|
for (Template template : templates) { |
|
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 { |
|
|
|
_templateIHs.put(template, next); |
|
} |
|
} |
|
} |
|
|
|
private void appendTemplateCode(InstructionList body) { |
|
for (Template template : _neededTemplates.keySet()) { |
|
final InstructionList iList = _templateILs.get(template); |
|
if (iList != null) { |
|
body.append(iList); |
|
} |
|
|
|
} |
|
} |
|
|
|
private void appendTestSequences(InstructionList body) { |
|
final int n = _testSeq.length; |
|
for (int i = 0; i < n; i++) { |
|
final TestSeq testSeq = _testSeq[i]; |
|
if (testSeq != null) { |
|
InstructionList il = testSeq.getInstructionList(); |
|
if (il != null) |
|
body.append(il); |
|
// else trivial TestSeq |
|
} |
|
} |
|
} |
|
|
|
public static void compileGetChildren(ClassGenerator classGen, |
|
MethodGenerator methodGen, |
|
int node) { |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
final InstructionList il = methodGen.getInstructionList(); |
|
final int git = cpg.addInterfaceMethodref(DOM_INTF, |
|
GET_CHILDREN, |
|
GET_CHILDREN_SIG); |
|
il.append(methodGen.loadDOM()); |
|
il.append(new ILOAD(node)); |
|
il.append(new INVOKEINTERFACE(git, 2)); |
|
} |
|
|
|
|
|
|
|
*/ |
|
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; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
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 InstructionList compileNamespaces(ClassGenerator classGen, |
|
MethodGenerator methodGen, |
|
boolean[] isNamespace, |
|
boolean[] isAttribute, |
|
boolean attrFlag, |
|
InstructionHandle defaultTarget) { |
|
final XSLTC xsltc = classGen.getParser().getXSLTC(); |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
|
|
|
|
final List<String> namespaces = xsltc.getNamespaceIndex(); |
|
final List<String> names = xsltc.getNamesIndex(); |
|
final int namespaceCount = namespaces.size() + 1; |
|
final int namesCount = names.size(); |
|
|
|
final InstructionList il = new InstructionList(); |
|
final int[] types = new int[namespaceCount]; |
|
final InstructionHandle[] targets = new InstructionHandle[types.length]; |
|
|
|
if (namespaceCount > 0) { |
|
boolean compiled = false; |
|
|
|
|
|
for (int i = 0; i < namespaceCount; i++) { |
|
targets[i] = defaultTarget; |
|
types[i] = i; |
|
} |
|
|
|
|
|
for (int i = DTM.NTYPES; i < (DTM.NTYPES+namesCount); i++) { |
|
if ((isNamespace[i]) && (isAttribute[i] == attrFlag)) { |
|
String name = names.get(i-DTM.NTYPES); |
|
String namespace = name.substring(0,name.lastIndexOf(':')); |
|
final int type = xsltc.registerNamespace(namespace); |
|
|
|
if ((i < _testSeq.length) && |
|
(_testSeq[i] != null)) { |
|
targets[type] = |
|
(_testSeq[i]).compile(classGen, |
|
methodGen, |
|
defaultTarget); |
|
compiled = true; |
|
} |
|
} |
|
} |
|
|
|
|
|
if (!compiled) return(null); |
|
|
|
|
|
final int getNS = cpg.addInterfaceMethodref(DOM_INTF, |
|
"getNamespaceType", |
|
"(I)I"); |
|
il.append(methodGen.loadDOM()); |
|
il.append(new ILOAD(_currentIndex)); |
|
il.append(new INVOKEINTERFACE(getNS, 2)); |
|
il.append(new SWITCH(types, targets, defaultTarget)); |
|
return(il); |
|
} |
|
else { |
|
return(null); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public void compileApplyTemplates(ClassGenerator classGen) { |
|
final XSLTC xsltc = classGen.getParser().getXSLTC(); |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
final List<String> names = xsltc.getNamesIndex(); |
|
|
|
|
|
final com.sun.org.apache.bcel.internal.generic.Type[] argTypes = |
|
new com.sun.org.apache.bcel.internal.generic.Type[3]; |
|
argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); |
|
argTypes[1] = Util.getJCRefType(NODE_ITERATOR_SIG); |
|
argTypes[2] = Util.getJCRefType(TRANSLET_OUTPUT_SIG); |
|
|
|
final String[] argNames = new String[3]; |
|
argNames[0] = DOCUMENT_PNAME; |
|
argNames[1] = ITERATOR_PNAME; |
|
argNames[2] = TRANSLET_OUTPUT_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(), |
|
getClassName(), mainIL, |
|
classGen.getConstantPool()); |
|
methodGen.addException("com.sun.org.apache.xalan.internal.xsltc.TransletException"); |
|
// Insert an extra NOP just to keep "current" from appearing as if it |
|
|
|
mainIL.append(NOP); |
|
|
|
|
|
|
|
final LocalVariableGen current; |
|
current = methodGen.addLocalVariable2("current", |
|
com.sun.org.apache.bcel.internal.generic.Type.INT, |
|
null); |
|
_currentIndex = current.getIndex(); |
|
|
|
// Create the "body" instruction list that will eventually hold the |
|
|
|
final InstructionList body = new InstructionList(); |
|
body.append(NOP); |
|
|
|
// Create an instruction list that contains the default next-node |
|
|
|
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 |
|
|
|
final BranchHandle ifeq = ilLoop.append(new IFLT(null)); |
|
final BranchHandle loop = ilLoop.append(new GOTO_W(null)); |
|
ifeq.setTarget(ilLoop.append(RETURN)); |
|
final InstructionHandle ihLoop = ilLoop.getStart(); |
|
|
|
current.setStart(mainIL.append(new GOTO_W(ihLoop))); |
|
|
|
|
|
current.setEnd(loop); |
|
|
|
|
|
InstructionList ilRecurse = |
|
compileDefaultRecursion(classGen, methodGen, ihLoop); |
|
InstructionHandle ihRecurse = ilRecurse.getStart(); |
|
|
|
|
|
InstructionList ilText = |
|
compileDefaultText(classGen, methodGen, ihLoop); |
|
InstructionHandle ihText = ilText.getStart(); |
|
|
|
|
|
final int[] types = new int[DTM.NTYPES + names.size()]; |
|
for (int i = 0; i < types.length; i++) { |
|
types[i] = i; |
|
} |
|
|
|
|
|
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 = names.get(i); |
|
isAttribute[i + DTM.NTYPES] = isAttributeName(name); |
|
isNamespace[i + DTM.NTYPES] = isNamespaceName(name); |
|
} |
|
|
|
|
|
compileTemplates(classGen, methodGen, ihLoop); |
|
|
|
|
|
final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; |
|
InstructionHandle ihElem = ihRecurse; |
|
if (elemTest != null) |
|
ihElem = elemTest.compile(classGen, methodGen, ihRecurse); |
|
|
|
|
|
final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; |
|
InstructionHandle ihAttr = ihText; |
|
if (attrTest != null) |
|
ihAttr = attrTest.compile(classGen, methodGen, ihAttr); |
|
|
|
|
|
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 |
|
|
|
if (_childNodeTestSeq != null) { |
|
|
|
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); |
|
} |
|
|
|
|
|
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; |
|
} |
|
} |
|
|
|
|
|
InstructionHandle elemNamespaceHandle = ihElem; |
|
InstructionList nsElem = compileNamespaces(classGen, methodGen, |
|
isNamespace, isAttribute, |
|
false, ihElem); |
|
if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); |
|
|
|
|
|
InstructionHandle attrNamespaceHandle = ihAttr; |
|
InstructionList nsAttr = compileNamespaces(classGen, methodGen, |
|
isNamespace, isAttribute, |
|
true, ihAttr); |
|
if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); |
|
|
|
|
|
final InstructionHandle[] targets = new InstructionHandle[types.length]; |
|
for (int i = DTM.NTYPES; i < targets.length; i++) { |
|
final TestSeq testSeq = _testSeq[i]; |
|
|
|
if (isNamespace[i]) { |
|
if (isAttribute[i]) |
|
targets[i] = attrNamespaceHandle; |
|
else |
|
targets[i] = elemNamespaceHandle; |
|
} |
|
|
|
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; |
|
} |
|
} |
|
|
|
|
|
|
|
targets[DTM.ROOT_NODE] = _rootPattern != null |
|
? getTemplateInstructionHandle(_rootPattern.getTemplate()) |
|
: ihRecurse; |
|
|
|
|
|
targets[DTM.DOCUMENT_NODE] = _rootPattern != null |
|
? getTemplateInstructionHandle(_rootPattern.getTemplate()) |
|
: ihRecurse; |
|
|
|
|
|
targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null |
|
? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) |
|
: ihText; |
|
|
|
|
|
targets[DTM.NAMESPACE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; |
|
|
|
|
|
targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; |
|
|
|
|
|
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; |
|
|
|
|
|
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; |
|
|
|
|
|
targets[DTM.CDATA_SECTION_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ENTITY_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.NOTATION_NODE] = ihLoop; |
|
|
|
|
|
|
|
for (int i = DTM.NTYPES; i < targets.length; i++) { |
|
final TestSeq testSeq = _testSeq[i]; |
|
|
|
if ((testSeq == null) || (isNamespace[i])) { |
|
if (isAttribute[i]) |
|
targets[i] = attrNamespaceHandle; |
|
else |
|
targets[i] = elemNamespaceHandle; |
|
} |
|
|
|
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); |
|
|
|
|
|
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)); |
|
|
|
|
|
InstructionHandle disp = body.append(new SWITCH(types, targets, ihLoop)); |
|
|
|
|
|
appendTestSequences(body); |
|
|
|
appendTemplateCode(body); |
|
|
|
|
|
if (nsElem != null) body.append(nsElem); |
|
|
|
if (nsAttr != null) body.append(nsAttr); |
|
|
|
|
|
body.append(ilRecurse); |
|
|
|
body.append(ilText); |
|
|
|
|
|
mainIL.append(body); |
|
|
|
mainIL.append(ilLoop); |
|
|
|
peepHoleOptimization(methodGen); |
|
classGen.addMethod(methodGen); |
|
|
|
|
|
if (_importLevels != null) { |
|
for (Map.Entry<Integer, Integer> entry : _importLevels.entrySet()) { |
|
compileApplyImports(classGen, entry.getValue(), entry.getKey()); |
|
} |
|
} |
|
} |
|
|
|
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 { |
|
|
|
_templateIHs.put(template, next); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
@SuppressWarnings({"rawtypes", "unchecked"}) |
|
public void compileApplyImports(ClassGenerator classGen, int min, int max) { |
|
final XSLTC xsltc = classGen.getParser().getXSLTC(); |
|
final ConstantPoolGen cpg = classGen.getConstantPool(); |
|
final List<String> names = xsltc.getNamesIndex(); |
|
|
|
|
|
_namedTemplates = new HashMap<>(); |
|
_neededTemplates = new HashMap<>(); |
|
_templateIHs = new HashMap<>(); |
|
_templateILs = new HashMap<>(); |
|
_patternGroups = (List<LocationPathPattern>[])new ArrayList[32]; |
|
_rootPattern = null; |
|
|
|
|
|
List<Template> oldTemplates = _templates; |
|
|
|
|
|
_templates = new ArrayList<>(); |
|
for (Template template : oldTemplates) { |
|
final int prec = template.getImportPrecedence(); |
|
if ((prec >= min) && (prec < max)) addTemplate(template); |
|
} |
|
|
|
|
|
processPatterns(_keys); |
|
|
|
|
|
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"); |
|
|
|
|
|
final LocalVariableGen current; |
|
current = methodGen.addLocalVariable2("current", |
|
com.sun.org.apache.bcel.internal.generic.Type.INT, |
|
null); |
|
_currentIndex = current.getIndex(); |
|
|
|
mainIL.append(new ILOAD(methodGen.getLocalIndex(NODE_PNAME))); |
|
current.setStart(mainIL.append(new ISTORE(_currentIndex))); |
|
|
|
// Create the "body" instruction list that will eventually hold the |
|
|
|
final InstructionList body = new InstructionList(); |
|
body.append(NOP); |
|
|
|
// Create an instruction list that contains the default next-node |
|
|
|
final InstructionList ilLoop = new InstructionList(); |
|
ilLoop.append(RETURN); |
|
final InstructionHandle ihLoop = ilLoop.getStart(); |
|
|
|
|
|
InstructionList ilRecurse = |
|
compileDefaultRecursion(classGen, methodGen, ihLoop); |
|
InstructionHandle ihRecurse = ilRecurse.getStart(); |
|
|
|
|
|
InstructionList ilText = |
|
compileDefaultText(classGen, methodGen, ihLoop); |
|
InstructionHandle ihText = ilText.getStart(); |
|
|
|
|
|
final int[] types = new int[DTM.NTYPES + names.size()]; |
|
for (int i = 0; i < types.length; i++) { |
|
types[i] = i; |
|
} |
|
|
|
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 = names.get(i); |
|
isAttribute[i+DTM.NTYPES] = isAttributeName(name); |
|
isNamespace[i+DTM.NTYPES] = isNamespaceName(name); |
|
} |
|
|
|
|
|
compileTemplateCalls(classGen, methodGen, ihLoop, min, max); |
|
|
|
|
|
final TestSeq elemTest = _testSeq[DTM.ELEMENT_NODE]; |
|
InstructionHandle ihElem = ihRecurse; |
|
if (elemTest != null) { |
|
ihElem = elemTest.compile(classGen, methodGen, ihLoop); |
|
} |
|
|
|
|
|
final TestSeq attrTest = _testSeq[DTM.ATTRIBUTE_NODE]; |
|
InstructionHandle ihAttr = ihLoop; |
|
if (attrTest != null) { |
|
ihAttr = attrTest.compile(classGen, methodGen, ihAttr); |
|
} |
|
|
|
|
|
InstructionList ilKey = null; |
|
if (_idxTestSeq != null) { |
|
ilKey = _idxTestSeq.getInstructionList(); |
|
} |
|
|
|
// If there is a match on node() we need to replace ihElem |
|
|
|
if (_childNodeTestSeq != null) { |
|
|
|
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); |
|
} |
|
|
|
|
|
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; |
|
} |
|
} |
|
|
|
|
|
InstructionHandle elemNamespaceHandle = ihElem; |
|
InstructionList nsElem = compileNamespaces(classGen, methodGen, |
|
isNamespace, isAttribute, |
|
false, ihElem); |
|
if (nsElem != null) elemNamespaceHandle = nsElem.getStart(); |
|
|
|
|
|
InstructionList nsAttr = compileNamespaces(classGen, methodGen, |
|
isNamespace, isAttribute, |
|
true, ihAttr); |
|
InstructionHandle attrNamespaceHandle = ihAttr; |
|
if (nsAttr != null) attrNamespaceHandle = nsAttr.getStart(); |
|
|
|
|
|
final InstructionHandle[] targets = new InstructionHandle[types.length]; |
|
for (int i = DTM.NTYPES; i < targets.length; i++) { |
|
final TestSeq testSeq = _testSeq[i]; |
|
|
|
if (isNamespace[i]) { |
|
if (isAttribute[i]) |
|
targets[i] = attrNamespaceHandle; |
|
else |
|
targets[i] = elemNamespaceHandle; |
|
} |
|
|
|
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; |
|
} |
|
} |
|
|
|
|
|
targets[DTM.ROOT_NODE] = _rootPattern != null |
|
? getTemplateInstructionHandle(_rootPattern.getTemplate()) |
|
: ihRecurse; |
|
|
|
targets[DTM.DOCUMENT_NODE] = _rootPattern != null |
|
? getTemplateInstructionHandle(_rootPattern.getTemplate()) |
|
: ihRecurse; |
|
|
|
|
|
targets[DTM.TEXT_NODE] = _testSeq[DTM.TEXT_NODE] != null |
|
? _testSeq[DTM.TEXT_NODE].compile(classGen, methodGen, ihText) |
|
: ihText; |
|
|
|
|
|
targets[DTM.NAMESPACE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ELEMENT_NODE] = elemNamespaceHandle; |
|
|
|
|
|
targets[DTM.ATTRIBUTE_NODE] = attrNamespaceHandle; |
|
|
|
|
|
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; |
|
} |
|
|
|
|
|
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; |
|
|
|
|
|
targets[DTM.CDATA_SECTION_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.DOCUMENT_FRAGMENT_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.DOCUMENT_TYPE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ENTITY_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.ENTITY_REFERENCE_NODE] = ihLoop; |
|
|
|
|
|
targets[DTM.NOTATION_NODE] = ihLoop; |
|
|
|
|
|
|
|
|
|
for (int i = DTM.NTYPES; i < targets.length; i++) { |
|
final TestSeq testSeq = _testSeq[i]; |
|
|
|
if ((testSeq == null) || (isNamespace[i])) { |
|
if (isAttribute[i]) |
|
targets[i] = attrNamespaceHandle; |
|
else |
|
targets[i] = elemNamespaceHandle; |
|
} |
|
|
|
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); |
|
|
|
|
|
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)); |
|
|
|
|
|
InstructionHandle disp = body.append(new SWITCH(types,targets,ihLoop)); |
|
|
|
|
|
appendTestSequences(body); |
|
|
|
appendTemplateCode(body); |
|
|
|
|
|
if (nsElem != null) body.append(nsElem); |
|
|
|
if (nsAttr != null) body.append(nsAttr); |
|
|
|
|
|
body.append(ilRecurse); |
|
|
|
body.append(ilText); |
|
|
|
|
|
mainIL.append(body); |
|
|
|
|
|
current.setEnd(body.getEnd()); |
|
|
|
|
|
mainIL.append(ilLoop); |
|
|
|
peepHoleOptimization(methodGen); |
|
classGen.addMethod(methodGen); |
|
|
|
|
|
_templates = oldTemplates; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private void peepHoleOptimization(MethodGenerator methodGen) { |
|
InstructionList il = methodGen.getInstructionList(); |
|
InstructionFinder find = new InstructionFinder(il); |
|
InstructionHandle ih; |
|
String pattern; |
|
|
|
// LoadInstruction, POP => (removed) |
|
// pattern = "LoadInstruction POP"; |
|
// changed to lower case - changing to all lower case although only the instruction with capital I |
|
|
|
pattern = "loadinstruction pop"; |
|
|
|
for (Iterator<InstructionHandle[]> iter = find.search(pattern); iter.hasNext();) { |
|
InstructionHandle[] match = iter.next(); |
|
try { |
|
if (!match[0].hasTargeters() && !match[1].hasTargeters()) { |
|
il.delete(match[0], match[1]); |
|
} |
|
} |
|
catch (TargetLostException e) { |
|
// TODO: move target down into the list |
|
} |
|
} |
|
|
|
// ILOAD_N, ILOAD_N, SWAP, ISTORE_N => ILOAD_N |
|
// pattern = "ILOAD ILOAD SWAP ISTORE"; |
|
// changed to lower case - changing to all lower case although only the instruction with capital I |
|
|
|
pattern = "iload iload swap istore"; |
|
for (Iterator<InstructionHandle[]> iter = find.search(pattern); iter.hasNext();) { |
|
InstructionHandle[] match = iter.next(); |
|
try { |
|
com.sun.org.apache.bcel.internal.generic.ILOAD iload1 = |
|
(com.sun.org.apache.bcel.internal.generic.ILOAD) match[0].getInstruction(); |
|
com.sun.org.apache.bcel.internal.generic.ILOAD iload2 = |
|
(com.sun.org.apache.bcel.internal.generic.ILOAD) match[1].getInstruction(); |
|
com.sun.org.apache.bcel.internal.generic.ISTORE istore = |
|
(com.sun.org.apache.bcel.internal.generic.ISTORE) match[3].getInstruction(); |
|
|
|
if (!match[1].hasTargeters() && |
|
!match[2].hasTargeters() && |
|
!match[3].hasTargeters() && |
|
iload1.getIndex() == iload2.getIndex() && |
|
iload2.getIndex() == istore.getIndex()) |
|
{ |
|
il.delete(match[1], match[3]); |
|
} |
|
} |
|
catch (TargetLostException e) { |
|
// TODO: move target down into the list |
|
} |
|
} |
|
|
|
// LoadInstruction_N, LoadInstruction_M, SWAP => LoadInstruction_M, LoadInstruction_N |
|
// pattern = "LoadInstruction LoadInstruction SWAP"; |
|
// changed to lower case - changing to all lower case although only the instruction with capital I |
|
|
|
pattern = "loadinstruction loadinstruction swap"; |
|
for (Iterator<InstructionHandle[]> iter = find.search(pattern); iter.hasNext();) { |
|
InstructionHandle[] match = iter.next(); |
|
try { |
|
if (!match[0].hasTargeters() && |
|
!match[1].hasTargeters() && |
|
!match[2].hasTargeters()) |
|
{ |
|
Instruction load_m = match[1].getInstruction(); |
|
il.insert(match[0], load_m); |
|
il.delete(match[1], match[2]); |
|
} |
|
} |
|
catch (TargetLostException e) { |
|
// TODO: move target down into the list |
|
} |
|
} |
|
|
|
// ALOAD_N ALOAD_N => ALOAD_N DUP |
|
// pattern = "ALOAD ALOAD"; |
|
// changed to lower case - changing to all lower case although only the instruction with capital I |
|
|
|
pattern = "aload aload"; |
|
for (Iterator<InstructionHandle[]> iter = find.search(pattern); iter.hasNext();) { |
|
InstructionHandle[] match = iter.next(); |
|
try { |
|
if (!match[1].hasTargeters()) { |
|
com.sun.org.apache.bcel.internal.generic.ALOAD aload1 = |
|
(com.sun.org.apache.bcel.internal.generic.ALOAD) match[0].getInstruction(); |
|
com.sun.org.apache.bcel.internal.generic.ALOAD aload2 = |
|
(com.sun.org.apache.bcel.internal.generic.ALOAD) match[1].getInstruction(); |
|
|
|
if (aload1.getIndex() == aload2.getIndex()) { |
|
il.insert(match[1], new DUP()); |
|
il.delete(match[1]); |
|
} |
|
} |
|
} |
|
catch (TargetLostException e) { |
|
// TODO: move target down into the list |
|
} |
|
} |
|
} |
|
|
|
public InstructionHandle getTemplateInstructionHandle(Template template) { |
|
return _templateIHs.get(template); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private static boolean isAttributeName(String qname) { |
|
final int col = qname.lastIndexOf(':') + 1; |
|
return (qname.charAt(col) == '@'); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
private static boolean isNamespaceName(String qname) { |
|
final int col = qname.lastIndexOf(':'); |
|
return (col > -1 && qname.charAt(qname.length()-1) == '*'); |
|
} |
|
} |