LocalVarsAttr.java 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (c) 1997, 2004 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. /* Represents the contents of a standard "LocalVariableTable" attribute.
  6. * @author Per Bothner
  7. */
  8. public class LocalVarsAttr extends Attribute
  9. {
  10. private Method method;
  11. /* Map local slot index to the local variable that is there. */
  12. Variable[] used;
  13. public Scope current_scope;
  14. Scope parameter_scope;
  15. /** Add a new LocalVarsAttr to a CodeAttr. */
  16. public LocalVarsAttr(CodeAttr code)
  17. {
  18. super("LocalVariableTable");
  19. addToFrontOf(code);
  20. method = (Method) code.getContainer();
  21. code.locals = this;
  22. }
  23. /** Create, but don't link into method.code's attributes list (yet). */
  24. public LocalVarsAttr(Method method)
  25. {
  26. super("LocalVariableTable");
  27. CodeAttr code = method.code;
  28. this.method = method;
  29. code.locals = this;
  30. }
  31. public final Method getMethod() { return method; }
  32. public VarEnumerator allVars ()
  33. {
  34. return new VarEnumerator (parameter_scope);
  35. }
  36. public void enterScope (Scope scope) {
  37. scope.linkChild (current_scope);
  38. current_scope = scope;
  39. CodeAttr code = method.getCode();
  40. for (Variable var = scope.firstVar (); var != null; var = var.nextVar ())
  41. {
  42. if (var.isSimple ())
  43. {
  44. if (! var.isAssigned ())
  45. var.allocateLocal(code);
  46. else if (used[var.offset] == null)
  47. used[var.offset] = var;
  48. else if (used[var.offset] != var)
  49. throw new Error ("inconsistent local variable assignments for "
  50. +var+" != "+used[var.offset]);
  51. }
  52. }
  53. }
  54. /** Mark scopes upto specified scope as 'preserved'.
  55. * This means that the local variable slots are not available for reuse
  56. * when the scope exits. The effected scopes are all ancestor scopes from
  57. * the current scope (inclusive) upto the specified scope (exclusive). */
  58. public void preserveVariablesUpto(Scope scope)
  59. {
  60. for (Scope cur = current_scope; cur != scope; cur = cur.parent)
  61. cur.preserved = true;
  62. }
  63. public final boolean isEmpty ()
  64. {
  65. VarEnumerator vars = allVars();
  66. Variable var;
  67. while ((var = vars.nextVar ()) != null)
  68. {
  69. if (var.isSimple () && var.name != null)
  70. return false;
  71. }
  72. return true;
  73. }
  74. public final int getCount ()
  75. {
  76. int local_variable_count = 0;
  77. VarEnumerator vars = allVars();
  78. Variable var;
  79. while ((var = vars.nextVar ()) != null)
  80. {
  81. if (var.shouldEmit())
  82. local_variable_count++;
  83. }
  84. return local_variable_count;
  85. }
  86. public final int getLength()
  87. {
  88. return 2 + 10 * getCount();
  89. }
  90. public void assignConstants (ClassType cl)
  91. {
  92. super.assignConstants(cl);
  93. VarEnumerator vars = allVars ();
  94. Variable var;
  95. while ((var = vars.nextVar ()) != null)
  96. {
  97. if (var.isSimple () && var.name != null)
  98. {
  99. if (var.name_index == 0)
  100. var.name_index = cl.getConstants().addUtf8(var.getName()).index;
  101. if (var.signature_index == 0)
  102. var.signature_index
  103. = cl.getConstants().addUtf8(var.getType().getSignature()).index;
  104. }
  105. }
  106. }
  107. public void write (DataOutputStream dstr) throws java.io.IOException
  108. {
  109. VarEnumerator vars = allVars ();
  110. Variable var;
  111. dstr.writeShort (getCount());
  112. for (vars.reset (); (var = vars.nextVar ()) != null; )
  113. {
  114. if (var.shouldEmit())
  115. {
  116. Scope scope = var.getScope();
  117. int start_pc = scope.start.position;
  118. int end_pc = scope.end.position;
  119. dstr.writeShort(start_pc);
  120. dstr.writeShort(end_pc - start_pc);
  121. dstr.writeShort(var.name_index);
  122. dstr.writeShort(var.signature_index);
  123. dstr.writeShort(var.offset);
  124. }
  125. }
  126. }
  127. public void print (ClassTypeWriter dst)
  128. {
  129. VarEnumerator vars = allVars ();
  130. dst.print("Attribute \"");
  131. dst.print(getName());
  132. dst.print("\", length:");
  133. dst.print(getLength());
  134. dst.print(", count: ");
  135. dst.println(getCount());
  136. Variable var;
  137. for (vars.reset (); (var = vars.nextVar ()) != null; )
  138. {
  139. if (var.isSimple () && var.name != null)
  140. {
  141. dst.print(" slot#");
  142. dst.print(var.offset);
  143. dst.print(": name: ");
  144. dst.printOptionalIndex(var.name_index);
  145. dst.print(var.getName());
  146. dst.print(", type: ");
  147. dst.printOptionalIndex(var.signature_index);
  148. dst.printSignature(var.getType());
  149. dst.print(" (pc: ");
  150. Scope scope = var.getScope();
  151. int start_pc, end_pc;
  152. if (scope == null || scope.start == null || scope.end == null
  153. || (start_pc = scope.start.position) < 0
  154. || (end_pc = scope.end.position) < 0)
  155. dst.print("unknown");
  156. else
  157. {
  158. dst.print(start_pc);
  159. dst.print(" length: ");
  160. dst.print(end_pc - start_pc);
  161. }
  162. dst.println(')');
  163. }
  164. }
  165. }
  166. }