PageRenderTime 30ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/gnu/bytecode/Method.java

https://gitlab.com/kashell/Kawa
Java | 369 lines | 271 code | 55 blank | 43 comment | 52 complexity | 1b4f388b8ee530529ff672333b59b7d5 MD5 | raw file
  1. // Copyright (c) 1997, 2007 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.bytecode;
  4. import java.io.*;
  5. /**
  6. * Represents a method in a <code>ClassType</code>.
  7. * <p>
  8. * A <code>Method</code> contain a <code>CodeAttr</code> object;
  9. * the interface for generating bytecode instructions is primarily
  10. * in <code>CodeAttr</code>.
  11. * <p>
  12. * All the methods whose name start with <code>compile_</code> are
  13. * deprecated, and should not be used; use the methods
  14. * in <code>CodeAttr</code>instead.
  15. */
  16. public class Method implements AttrContainer, Member {
  17. private String name;
  18. Type[] arg_types;
  19. Type return_type;
  20. int access_flags;
  21. int name_index; /* Index in constant table, or 0 if un-assigned */
  22. int signature_index; /* Index in constant table, or 0 if un-assigned */
  23. Method next;
  24. ClassType classfile;
  25. CodeAttr code;
  26. /* #ifdef JAVA8 */
  27. java.lang.reflect.Executable rmethod;
  28. /* #else */
  29. // java.lang.reflect.AccessibleObject rmethod;
  30. /* #endif */
  31. Attribute attributes;
  32. public final Attribute getAttributes() { return attributes; }
  33. public final void setAttributes (Attribute attributes)
  34. { this.attributes = attributes; }
  35. ExceptionsAttr exceptions;
  36. public final ExceptionsAttr getExceptionAttr() { return exceptions; }
  37. public void setExceptions(short[] exn_indices) {
  38. if (exceptions == null)
  39. exceptions = new ExceptionsAttr(this);
  40. exceptions.setExceptions(exn_indices, classfile);
  41. }
  42. public void setExceptions(ClassType[] exn_types) {
  43. if (exceptions == null)
  44. exceptions = new ExceptionsAttr(this);
  45. exceptions.setExceptions(exn_types);
  46. }
  47. public final CodeAttr getCode () { return code; }
  48. private Method() {
  49. }
  50. /** Make a generic "clone" method.
  51. * This is used for array types.
  52. */
  53. static Method makeCloneMethod(Type returnType) {
  54. Method method = new Method();
  55. method.name = "clone";
  56. method.access_flags = Access.PUBLIC;
  57. method.arg_types = Type.typeArray0;
  58. method.return_type = returnType;
  59. method.classfile = Type.objectType;
  60. return method;
  61. }
  62. /** A copy constructor, except you can override the declaring class.
  63. * This can be used to improve binary compatibility by emitting method
  64. * references where the declared class is the type of the receiver.
  65. */
  66. public Method(Method base, ClassType clas) {
  67. arg_types = base.arg_types;
  68. return_type = base.return_type;
  69. name = base.name;
  70. access_flags = base.access_flags;
  71. classfile = clas;
  72. }
  73. Method(ClassType clfile, int flags) {
  74. if (clfile.last_method == null)
  75. clfile.methods = this;
  76. else
  77. clfile.last_method.next = this;
  78. clfile.last_method = this;
  79. clfile.methods_count++;
  80. access_flags = flags;
  81. classfile = clfile;
  82. }
  83. public final void setStaticFlag(boolean is_static) {
  84. if (is_static)
  85. access_flags |= Access.STATIC;
  86. else
  87. access_flags ^= ~Access.STATIC;
  88. }
  89. public final boolean getStaticFlag() {
  90. return (access_flags & Access.STATIC) != 0;
  91. }
  92. public final boolean isAbstract() {
  93. return (access_flags & Access.ABSTRACT) != 0;
  94. }
  95. public final boolean isNative() {
  96. return (access_flags & Access.NATIVE) != 0;
  97. }
  98. public int getModifiers() {
  99. return access_flags;
  100. }
  101. public void setModifiers(int modifiers) {
  102. access_flags = modifiers;
  103. }
  104. public final ConstantPool getConstants() {
  105. return classfile.constants;
  106. }
  107. public Scope pushScope() {
  108. prepareCode(0);
  109. return code.pushScope();
  110. }
  111. /** True if control could reach here. */
  112. public final boolean reachableHere () { return code.reachableHere(); }
  113. public Scope popScope() { return code.popScope(); }
  114. /**
  115. * Allocate slots for a local variable (or parameter).
  116. * @param local the variable we need to allocate
  117. */
  118. @Deprecated public void allocate_local(Variable local) {
  119. local.allocateLocal(code);
  120. }
  121. /** Allocate a Code attribute, and prepare to generate code.
  122. * Most code generators should use the startCode convenience method. */
  123. public void initCode() {
  124. if (classfile.constants == null)
  125. classfile.constants = new ConstantPool();
  126. prepareCode(0);
  127. code.sourceDbgExt = classfile.sourceDbgExt;
  128. code.noteParamTypes();
  129. code.pushScope();
  130. }
  131. /** Recommended method to create a new CodeAttr for this Method. */
  132. public CodeAttr startCode() {
  133. initCode();
  134. code.addParamLocals();
  135. return code;
  136. }
  137. void kill_local(Variable var) { var.freeLocal(code); }
  138. /** Method that must be called before we generate any instructions.
  139. * Set so there is room for at least max_size bytes of code.
  140. */
  141. void prepareCode(int max_size) {
  142. if (code == null)
  143. code = new CodeAttr(this);
  144. code.reserve(max_size);
  145. }
  146. // This method should be called before we generate code for
  147. // an instruction (or sequence).
  148. // An upper bound of the intruction length is max_size.
  149. // deprecated!
  150. void instruction_start_hook(int max_size) {
  151. prepareCode(max_size);
  152. }
  153. final Type pop_stack_type () { return code.popType(); }
  154. final void push_stack_type (Type type) { code.pushType(type); }
  155. public void compile_checkcast(Type type) {
  156. code.emitCheckcast(type);
  157. }
  158. public void maybe_compile_checkcast(Type type) {
  159. Type stack_type = code.topType();
  160. if (type != stack_type) // FIXME rather simple-minded, but safe.
  161. code.emitCheckcast(type);
  162. }
  163. @Deprecated
  164. public void compile_push_value(Variable var) { code.emitLoad(var); }
  165. @Deprecated public void compile_store_value(Variable var) {
  166. code.emitStore(var);
  167. }
  168. public void compile_push_this() {
  169. code.emitPushThis();
  170. }
  171. void write (DataOutputStream dstr, ClassType classfile)
  172. throws java.io.IOException {
  173. dstr.writeShort (access_flags);
  174. dstr.writeShort (name_index);
  175. dstr.writeShort (signature_index);
  176. Attribute.writeAll(this, dstr);
  177. }
  178. public static String makeSignature(Type arg_types[], Type return_type) {
  179. /* #ifdef JAVA5 */
  180. StringBuilder buf = new StringBuilder(100);
  181. /* #else */
  182. // StringBuffer buf = new StringBuffer(100);
  183. /* #endif */
  184. int args_count = arg_types.length;
  185. buf.append('(');
  186. for (int i = 0; i < args_count; i++)
  187. buf.append (arg_types[i].getSignature());
  188. buf.append(')');
  189. buf.append(return_type.getSignature());
  190. return buf.toString();
  191. }
  192. public static String makeGenericSignature(Type arg_types[],
  193. Type return_type) {
  194. StringBuilder buf = new StringBuilder(100);
  195. int args_count = arg_types.length;
  196. buf.append('(');
  197. for (int i = 0; i < args_count; i++)
  198. buf.append (arg_types[i].getMaybeGenericSignature());
  199. buf.append(')');
  200. buf.append(return_type.getMaybeGenericSignature());
  201. return buf.toString();
  202. }
  203. String signature;
  204. public String getSignature() {
  205. if (signature == null)
  206. signature = makeSignature(arg_types, return_type);
  207. return signature;
  208. }
  209. public void setSignature(String signature) {
  210. int len = signature.length();
  211. if (len < 3 || signature.charAt(0) != '(')
  212. throw new ClassFormatError("bad method signature");
  213. int pos = 1;
  214. java.util.Stack<Type> types = new java.util.Stack<Type>();
  215. for (;;) {
  216. int arg_sig_len = Type.signatureLength(signature, pos);
  217. if (arg_sig_len < 0) {
  218. if (pos < len && signature.charAt(pos) == ')')
  219. break;
  220. throw new ClassFormatError("bad method signature");
  221. }
  222. Type arg_type = Type.signatureToType(signature, pos, arg_sig_len);
  223. types.push(arg_type);
  224. pos += arg_sig_len;
  225. }
  226. arg_types = new Type[types.size()];
  227. for (int i = types.size(); --i >= 0; )
  228. arg_types[i] = (Type) types.pop();
  229. return_type = Type.signatureToType(signature, pos+1, len-pos-1);
  230. }
  231. public void setSignature(int signature_index) {
  232. CpoolUtf8 sigConstant = (CpoolUtf8)
  233. getConstants().getForced(signature_index, ConstantPool.UTF8);
  234. this.signature_index = signature_index;
  235. setSignature(sigConstant.string);
  236. }
  237. public <T extends java.lang.annotation.Annotation>
  238. T getAnnotation(Class<T> clas) {
  239. T ann = RuntimeAnnotationsAttr.getAnnotation(this, clas);
  240. if (ann != null)
  241. return ann;
  242. return rmethod == null ? null : rmethod.getAnnotation(clas);
  243. }
  244. void assignConstants() {
  245. ConstantPool constants = getConstants();
  246. if (name_index == 0 && name != null)
  247. name_index = constants.addUtf8(name).index;
  248. String signature = getSignature();
  249. String genericSignature = makeGenericSignature(arg_types, return_type);
  250. if (signature_index == 0)
  251. signature_index = constants.addUtf8(signature).index;
  252. if (genericSignature != null && ! genericSignature.equals(signature)) {
  253. SignatureAttr attr = new SignatureAttr(genericSignature);
  254. attr.addToFrontOf(this);
  255. }
  256. Attribute.assignConstants(this, classfile);
  257. }
  258. public ClassType getDeclaringClass() { return classfile; }
  259. public final Type getReturnType() { return return_type; }
  260. public final void setReturnType(Type type) { return_type = type; }
  261. public final Type[] getParameterTypes() { return arg_types; }
  262. public final ClassType[] getExceptions()
  263. {
  264. if (exceptions == null) return null;
  265. return exceptions.getExceptions();
  266. }
  267. public final String getName() {
  268. return name;
  269. }
  270. public final void setName(String name) {
  271. this.name = name;
  272. }
  273. public final void setName(int name_index) {
  274. if (name_index <= 0)
  275. name = null;
  276. else {
  277. CpoolUtf8 nameConstant = (CpoolUtf8)
  278. getConstants().getForced(name_index, ConstantPool.UTF8);
  279. name = nameConstant.string;
  280. }
  281. this.name_index = name_index;
  282. }
  283. public final Method getNext() {
  284. return next;
  285. }
  286. public void listParameters(StringBuffer sbuf) {
  287. int args_count = arg_types.length;
  288. sbuf.append('(');
  289. for (int i = 0; i < args_count; i++) {
  290. if (i > 0)
  291. sbuf.append(',');
  292. sbuf.append (arg_types[i].getName());
  293. }
  294. sbuf.append(')');
  295. }
  296. public String toString() {
  297. StringBuffer sbuf = new StringBuffer(100);
  298. ClassType declaring = getDeclaringClass();
  299. sbuf.append(declaring != null ? declaring.getName() : "???");
  300. sbuf.append('.');
  301. sbuf.append(name);
  302. if (arg_types != null) {
  303. listParameters(sbuf);
  304. if (return_type != null)
  305. sbuf.append(return_type.getName());
  306. }
  307. return sbuf.toString();
  308. }
  309. public void cleanupAfterCompilation() {
  310. attributes = null;
  311. exceptions = null;
  312. code = null;
  313. }
  314. };