1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: MethodGenerator.java,v 1.15 2004/02/16 22:26:44 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
  20. import com.sun.org.apache.bcel.internal.generic.ALOAD;
  21. import com.sun.org.apache.bcel.internal.generic.ASTORE;
  22. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  23. import com.sun.org.apache.bcel.internal.generic.ICONST;
  24. import com.sun.org.apache.bcel.internal.generic.ILOAD;
  25. import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  26. import com.sun.org.apache.bcel.internal.generic.ISTORE;
  27. import com.sun.org.apache.bcel.internal.generic.Instruction;
  28. import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  29. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  30. import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
  31. import com.sun.org.apache.bcel.internal.generic.MethodGen;
  32. import com.sun.org.apache.bcel.internal.generic.Type;
  33. /**
  34. * @author Jacek Ambroziak
  35. * @author Santiago Pericas-Geertsen
  36. */
  37. public class MethodGenerator extends MethodGen
  38. implements com.sun.org.apache.xalan.internal.xsltc.compiler.Constants {
  39. protected static final int INVALID_INDEX = -1;
  40. private static final String START_ELEMENT_SIG
  41. = "(" + STRING_SIG + ")V";
  42. private static final String END_ELEMENT_SIG
  43. = START_ELEMENT_SIG;
  44. private InstructionList _mapTypeSub;
  45. private static final int DOM_INDEX = 1;
  46. private static final int ITERATOR_INDEX = 2;
  47. private static final int HANDLER_INDEX = 3;
  48. private Instruction _iloadCurrent;
  49. private Instruction _istoreCurrent;
  50. private final Instruction _astoreHandler;
  51. private final Instruction _aloadHandler;
  52. private final Instruction _astoreIterator;
  53. private final Instruction _aloadIterator;
  54. private final Instruction _aloadDom;
  55. private final Instruction _astoreDom;
  56. private final Instruction _startElement;
  57. private final Instruction _endElement;
  58. private final Instruction _startDocument;
  59. private final Instruction _endDocument;
  60. private final Instruction _attribute;
  61. private final Instruction _uniqueAttribute;
  62. private final Instruction _namespace;
  63. private final Instruction _setStartNode;
  64. private final Instruction _reset;
  65. private final Instruction _nextNode;
  66. private SlotAllocator _slotAllocator;
  67. private boolean _allocatorInit = false;
  68. public MethodGenerator(int access_flags, Type return_type,
  69. Type[] arg_types, String[] arg_names,
  70. String method_name, String class_name,
  71. InstructionList il, ConstantPoolGen cpg) {
  72. super(access_flags, return_type, arg_types, arg_names, method_name,
  73. class_name, il, cpg);
  74. _astoreHandler = new ASTORE(HANDLER_INDEX);
  75. _aloadHandler = new ALOAD(HANDLER_INDEX);
  76. _astoreIterator = new ASTORE(ITERATOR_INDEX);
  77. _aloadIterator = new ALOAD(ITERATOR_INDEX);
  78. _aloadDom = new ALOAD(DOM_INDEX);
  79. _astoreDom = new ASTORE(DOM_INDEX);
  80. final int startElement =
  81. cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  82. "startElement",
  83. START_ELEMENT_SIG);
  84. _startElement = new INVOKEINTERFACE(startElement, 2);
  85. final int endElement =
  86. cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  87. "endElement",
  88. END_ELEMENT_SIG);
  89. _endElement = new INVOKEINTERFACE(endElement, 2);
  90. final int attribute =
  91. cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  92. "addAttribute",
  93. "("
  94. + STRING_SIG
  95. + STRING_SIG
  96. + ")V");
  97. _attribute = new INVOKEINTERFACE(attribute, 3);
  98. final int uniqueAttribute =
  99. cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  100. "addUniqueAttribute",
  101. "("
  102. + STRING_SIG
  103. + STRING_SIG
  104. + "I)V");
  105. _uniqueAttribute = new INVOKEINTERFACE(uniqueAttribute, 4);
  106. final int namespace =
  107. cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  108. "namespaceAfterStartElement",
  109. "("
  110. + STRING_SIG
  111. + STRING_SIG
  112. + ")V");
  113. _namespace = new INVOKEINTERFACE(namespace, 3);
  114. int index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  115. "startDocument",
  116. "()V");
  117. _startDocument = new INVOKEINTERFACE(index, 1);
  118. index = cpg.addInterfaceMethodref(TRANSLET_OUTPUT_INTERFACE,
  119. "endDocument",
  120. "()V");
  121. _endDocument = new INVOKEINTERFACE(index, 1);
  122. index = cpg.addInterfaceMethodref(NODE_ITERATOR,
  123. SET_START_NODE,
  124. SET_START_NODE_SIG);
  125. _setStartNode = new INVOKEINTERFACE(index, 2);
  126. index = cpg.addInterfaceMethodref(NODE_ITERATOR,
  127. "reset", "()"+NODE_ITERATOR_SIG);
  128. _reset = new INVOKEINTERFACE(index, 1);
  129. index = cpg.addInterfaceMethodref(NODE_ITERATOR, NEXT, NEXT_SIG);
  130. _nextNode = new INVOKEINTERFACE(index, 1);
  131. _slotAllocator = new SlotAllocator();
  132. _slotAllocator.initialize(getLocalVariables());
  133. _allocatorInit = true;
  134. }
  135. /**
  136. * Allocates a local variable. If the slot allocator has already been
  137. * initialized, then call addLocalVariable2() so that the new variable
  138. * is known to the allocator. Failing to do this may cause the allocator
  139. * to return a slot that is already in use.
  140. */
  141. public LocalVariableGen addLocalVariable(String name, Type type,
  142. InstructionHandle start,
  143. InstructionHandle end)
  144. {
  145. return (_allocatorInit) ? addLocalVariable2(name, type, start)
  146. : super.addLocalVariable(name, type, start, end);
  147. }
  148. public LocalVariableGen addLocalVariable2(String name, Type type,
  149. InstructionHandle start)
  150. {
  151. return super.addLocalVariable(name, type,
  152. _slotAllocator.allocateSlot(type),
  153. start, null);
  154. }
  155. public void removeLocalVariable(LocalVariableGen lvg) {
  156. _slotAllocator.releaseSlot(lvg);
  157. super.removeLocalVariable(lvg);
  158. }
  159. public Instruction loadDOM() {
  160. return _aloadDom;
  161. }
  162. public Instruction storeDOM() {
  163. return _astoreDom;
  164. }
  165. public Instruction storeHandler() {
  166. return _astoreHandler;
  167. }
  168. public Instruction loadHandler() {
  169. return _aloadHandler;
  170. }
  171. public Instruction storeIterator() {
  172. return _astoreIterator;
  173. }
  174. public Instruction loadIterator() {
  175. return _aloadIterator;
  176. }
  177. public final Instruction setStartNode() {
  178. return _setStartNode;
  179. }
  180. public final Instruction reset() {
  181. return _reset;
  182. }
  183. public final Instruction nextNode() {
  184. return _nextNode;
  185. }
  186. public final Instruction startElement() {
  187. return _startElement;
  188. }
  189. public final Instruction endElement() {
  190. return _endElement;
  191. }
  192. public final Instruction startDocument() {
  193. return _startDocument;
  194. }
  195. public final Instruction endDocument() {
  196. return _endDocument;
  197. }
  198. public final Instruction attribute() {
  199. return _attribute;
  200. }
  201. public final Instruction uniqueAttribute() {
  202. return _uniqueAttribute;
  203. }
  204. public final Instruction namespace() {
  205. return _namespace;
  206. }
  207. public Instruction loadCurrentNode() {
  208. if (_iloadCurrent == null) {
  209. int idx = getLocalIndex("current");
  210. if (idx > 0)
  211. _iloadCurrent = new ILOAD(idx);
  212. else
  213. _iloadCurrent = new ICONST(0);
  214. }
  215. return _iloadCurrent;
  216. }
  217. public Instruction storeCurrentNode() {
  218. return _istoreCurrent != null
  219. ? _istoreCurrent
  220. : (_istoreCurrent = new ISTORE(getLocalIndex("current")));
  221. }
  222. /** by default context node is the same as current node. MK437 */
  223. public Instruction loadContextNode() {
  224. return loadCurrentNode();
  225. }
  226. public Instruction storeContextNode() {
  227. return storeCurrentNode();
  228. }
  229. public int getLocalIndex(String name) {
  230. return getLocalVariable(name).getIndex();
  231. }
  232. public LocalVariableGen getLocalVariable(String name) {
  233. final LocalVariableGen[] vars = getLocalVariables();
  234. for (int i = 0; i < vars.length; i++)
  235. if (vars[i].getName().equals(name))
  236. return vars[i];
  237. return null;
  238. }
  239. public void setMaxLocals() {
  240. // Get the current number of local variable slots
  241. int maxLocals = super.getMaxLocals();
  242. int prevLocals = maxLocals;
  243. // Get numer of actual variables
  244. final LocalVariableGen[] localVars = super.getLocalVariables();
  245. if (localVars != null) {
  246. if (localVars.length > maxLocals)
  247. maxLocals = localVars.length;
  248. }
  249. // We want at least 5 local variable slots (for parameters)
  250. if (maxLocals < 5) maxLocals = 5;
  251. super.setMaxLocals(maxLocals);
  252. }
  253. }