src/share/vm/prims/jvmtiClassFileReconstituter.cpp

Print this page

        

@@ -41,11 +41,11 @@
 # include "bytes_arm.hpp"
 #endif
 #ifdef TARGET_ARCH_ppc
 # include "bytes_ppc.hpp"
 #endif
-// FIXME: add Deprecated, LVTT attributes
+// FIXME: add Deprecated attribute
 // FIXME: fix Synthetic attribute
 // FIXME: per Serguei, add error return handling for constantPoolOopDesc::copy_cpool_bytes()
 
 
 // Write the field information portion of ClassFile structure

@@ -135,10 +135,11 @@
 void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) {
   constMethodHandle const_method(thread(), method->constMethod());
   u2 line_num_cnt = 0;
   int stackmap_len = 0;
   int local_variable_table_length = 0;
+  int local_variable_type_table_length = 0;
 
   // compute number and length of attributes
   int attr_count = 0;
   int attr_size = 0;
   if (const_method->has_linenumber_table()) {

@@ -171,12 +172,12 @@
       attr_size += 2 + 4 + stackmap_len;
     }
   }
   if (method->has_localvariable_table()) {
     local_variable_table_length = method->localvariable_table_length();
-    ++attr_count;
     if (local_variable_table_length != 0) {
+      ++attr_count;
       // Compute the size of the local variable table attribute (VM stores raw):
       // LocalVariableTable_attribute {
       //   u2 attribute_name_index;
       //   u4 attribute_length;
       //   u2 local_variable_table_length;

@@ -186,13 +187,38 @@
       //     u2 name_index;
       //     u2 descriptor_index;
       //     u2 index;
       //   }
       attr_size += 2 + 4 + 2 + local_variable_table_length * (2 + 2 + 2 + 2 + 2);
+
+      // Local variables with generic signatures must have LVTT entries
+      LocalVariableTableElement *elem = method->localvariable_table_start();
+      for (int idx = 0; idx < local_variable_table_length; idx++) {
+        if (elem[idx].signature_cp_index > 0) {
+          local_variable_type_table_length++;
     }
   }
+    }
 
+    if (local_variable_type_table_length != 0) {
+      ++attr_count;
+      // Compute the size of the local variable type table attribute (VM stores raw):
+      // LocalVariableTypeTable_attribute {
+      //   u2 attribute_name_index;
+      //   u4 attribute_length;
+      //   u2 local_variable_type_table_length;
+      //   {
+      //     u2 start_pc;
+      //     u2 length;
+      //     u2 name_index;
+      //     u2 signature_index;
+      //     u2 index;
+      //   }
+      attr_size += 2 + 4 + 2 + local_variable_type_table_length * (2 + 2 + 2 + 2 + 2);
+    }
+  }
+
   ExceptionTable exception_table(method());
   int exception_table_length = exception_table.length();
   int code_size = const_method->code_size();
   int size =
     2+2+4 +                                // max_stack, max_locals, code_length

@@ -223,10 +249,13 @@
     write_stackmap_table_attribute(method, stackmap_len);
   }
   if (local_variable_table_length != 0) {
     write_local_variable_table_attribute(method, local_variable_table_length);
   }
+  if (local_variable_type_table_length != 0) {
+    write_local_variable_type_table_attribute(method, local_variable_type_table_length);
+  }
 }
 
 // Write Exceptions attribute
 // JVMSpec|   Exceptions_attribute {
 // JVMSpec|     u2 attribute_name_index;

@@ -387,11 +416,11 @@
     write_u2(stream.bci());
     write_u2(stream.line());
   }
 }
 
-// Write LineNumberTable attribute
+// Write LocalVariableTable attribute
 // JVMSpec|   LocalVariableTable_attribute {
 // JVMSpec|     u2 attribute_name_index;
 // JVMSpec|     u4 attribute_length;
 // JVMSpec|     u2 local_variable_table_length;
 // JVMSpec|     {  u2 start_pc;

@@ -417,10 +446,43 @@
       write_u2(elem->slot);
       elem++;
     }
 }
 
+// Write LocalVariableTypeTable attribute
+// JVMSpec|   LocalVariableTypeTable_attribute {
+// JVMSpec|     u2 attribute_name_index;
+// JVMSpec|     u4 attribute_length;
+// JVMSpec|     u2 local_variable_type_table_length;
+// JVMSpec|     { u2 start_pc;
+// JVMSpec|       u2 length;
+// JVMSpec|       u2 name_index;
+// JVMSpec|       u2 signature_index;
+// JVMSpec|       u2 index;
+// JVMSpec|     } local_variable_type_table[local_variable_type_table_length];
+// JVMSpec|   }
+void JvmtiClassFileReconstituter::write_local_variable_type_table_attribute(methodHandle method, u2 num_entries) {
+    write_attribute_name_index("LocalVariableTypeTable");
+    write_u4(2 + num_entries * (2 + 2 + 2 + 2 + 2));
+    write_u2(num_entries);
+
+    LocalVariableTableElement *elem = method->localvariable_table_start();
+    for (int j=0; j<method->localvariable_table_length(); j++) {
+      if (elem->signature_cp_index > 0) {
+        // Local variable has a generic signature - write LVTT attribute entry
+        write_u2(elem->start_bci);
+        write_u2(elem->length);
+        write_u2(elem->name_cp_index);
+        write_u2(elem->signature_cp_index);
+        write_u2(elem->slot);
+        num_entries--;
+      }
+      elem++;
+    }
+    assert(num_entries == 0, "just checking");
+}
+
 // Write stack map table attribute
 // JSR-202|   StackMapTable_attribute {
 // JSR-202|     u2 attribute_name_index;
 // JSR-202|     u4 attribute_length;
 // JSR-202|     u2 number_of_entries;