defineclass.cc (_Jv_ClassReader::read_one_code_attribute): Added LocalVariableTable attribute handling.

2007-02-15  Kyle Galloway  <kgallowa@redhat.com>

	* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
    Added LocalVariableTable attribute handling.
    (_Jv_ClassReader::pool_Utf8_to_char_arr): New method.
    * jvmti.cc (_Jv_JVMTI_GetLocalVariableTable): New method.
    * include/java-interp.h: Added local_var_table and
    local_var_table_len fields to _Jv_InterpMethod.
    (_Jv_InterpMethod::get_local_var_table): New method.
    * testsuite/libjava.jvmti/interp/getlocalvartable.java: New
    test.
    * testsuite/libjava.jvmti/interp/getlocalvartable.jar: New test.
    * testsuite/libjava.jvmti/interp/getlocalvartable.out: Output
    for new test.
    * testsuite/libjava.jvmti/interp/getlocalvartable.h: New test.
    * testsuite/libjava.jvmti/interp/natgetlocalvartable.cc: New
    test.

From-SVN: r121999
This commit is contained in:
Kyle Galloway 2007-02-15 15:08:27 +00:00 committed by Kyle Galloway
parent ed765125f2
commit fe60528edc
5 changed files with 202 additions and 3 deletions

View File

@ -1,3 +1,21 @@
2007-02-15 Kyle Galloway <kgallowa@redhat.com>
* defineclass.cc (_Jv_ClassReader::read_one_code_attribute):
Added LocalVariableTable attribute handling.
(_Jv_ClassReader::pool_Utf8_to_char_arr): New method.
* jvmti.cc (_Jv_JVMTI_GetLocalVariableTable): New method.
* include/java-interp.h: Added local_var_table and
local_var_table_len fields to _Jv_InterpMethod.
(_Jv_InterpMethod::get_local_var_table): New method.
* testsuite/libjava.jvmti/interp/getlocalvartable.java: New
test.
* testsuite/libjava.jvmti/interp/getlocalvartable.jar: New test.
* testsuite/libjava.jvmti/interp/getlocalvartable.out: Output
for new test.
* testsuite/libjava.jvmti/interp/getlocalvartable.h: New test.
* testsuite/libjava.jvmti/interp/natgetlocalvartable.cc: New
test.
2007-02-15 Kyle Galloway <kgallowa@redhat.com>
* gnu/classpath/jdwp/natVMVirtualMachine (getFrames): Implement.

View File

@ -299,6 +299,9 @@ struct _Jv_ClassReader
/** check an utf8 entry, without creating a Utf8Const object */
bool is_attribute_name (int index, const char *name);
/** return the value of a utf8 entry in the passed array */
int pool_Utf8_to_char_arr (int index, char **entry);
/** here goes the class-loader members defined out-of-line */
void handleConstantPool ();
@ -784,6 +787,18 @@ _Jv_ClassReader::is_attribute_name (int index, const char *name)
return !memcmp (bytes+offsets[index]+2, name, len);
}
// Get a UTF8 value from the constant pool and turn it into a garbage
// collected char array.
int _Jv_ClassReader::pool_Utf8_to_char_arr (int index, char** entry)
{
check_tag (index, JV_CONSTANT_Utf8);
int len = get2u (bytes + offsets[index]);
*entry = reinterpret_cast<char *> (_Jv_AllocBytes (len + 1));
(*entry)[len] = '\0';
memcpy (*entry, bytes + offsets[index] + 2, len);
return len + 1;
}
void _Jv_ClassReader::read_one_field_attribute (int field_index,
bool *found_value)
{
@ -979,6 +994,34 @@ void _Jv_ClassReader::read_one_code_attribute (int method_index)
method->line_table_len = table_len;
method->line_table = table;
}
else if (is_attribute_name (name, "LocalVariableTable"))
{
_Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
(def_interp->interpreted_methods[method_index]);
if (method->local_var_table != NULL)
throw_class_format_error ("Method already has LocalVariableTable");
int table_len = read2u ();
_Jv_LocalVarTableEntry *table
= reinterpret_cast<_Jv_LocalVarTableEntry *>
(_Jv_AllocRawObj (table_len * sizeof (_Jv_LocalVarTableEntry)));
for (int i = 0; i < table_len; i++)
{
table[i].bytecode_start_pc = read2u ();
table[i].length = read2u ();
int len;
len = pool_Utf8_to_char_arr (read2u (), &table[i].name);
len = pool_Utf8_to_char_arr (read2u (), &table[i].descriptor);
table[i].slot = read2u ();
if (table[i].slot > method->max_locals || table[i].slot < 0)
throw_class_format_error ("Malformed Local Variable Table: Invalid Slot");
}
method->local_var_table_len = table_len;
method->local_var_table = table;
}
else
{
/* ignore unknown code attributes */

View File

@ -137,6 +137,21 @@ struct _Jv_LineTableEntry
int line;
};
// This structure holds local variable information.
// The pc value is the first pc where the variable must have a value and it
// must continue to have a value until (start_pc + length).
// The name is the variable name, and the descriptor contains type information.
// The slot is the index in the local variable array of this method, long and
// double occupy slot and slot+1.
struct _Jv_LocalVarTableEntry
{
int bytecode_start_pc;
int length;
char *name;
char *descriptor;
int slot;
};
class _Jv_InterpMethod : public _Jv_MethodBase
{
// Breakpoint instruction
@ -157,6 +172,10 @@ class _Jv_InterpMethod : public _Jv_MethodBase
// Length of the line_table - when this is zero then line_table is NULL.
int line_table_len;
_Jv_LineTableEntry *line_table;
// The local variable table length and the table itself
int local_var_table_len;
_Jv_LocalVarTableEntry *local_var_table;
pc_t prepared;
int number_insn_slots;
@ -224,6 +243,20 @@ class _Jv_InterpMethod : public _Jv_MethodBase
{
return static_cast<int> (max_locals);
}
/* Get info for a local variable of this method.
* If there is no loca_var_table for this method it will return -1.
* table_slot indicates which slot in the local_var_table to get, if there is
* no variable at this location it will return 0.
* Otherwise, it will return the number of table slots after the selected
* slot, indexed from 0.
*
* Example: there are 5 slots in the table, you request slot 0 so it will
* return 4.
*/
int get_local_var_table (char **name, char **sig, char **generic_sig,
jlong *startloc, jint *length, jint *slot,
int table_slot);
/* Installs a break instruction at the given code index. Returns
the pc_t of the breakpoint or NULL if index is invalid. */

View File

@ -1414,6 +1414,30 @@ _Jv_InterpMethod::get_line_table (jlong& start, jlong& end,
#endif // !DIRECT_THREADED
}
int
_Jv_InterpMethod::get_local_var_table (char **name, char **sig,
char **generic_sig, jlong *startloc,
jint *length, jint *slot,
int table_slot)
{
if (local_var_table == NULL)
return -2;
if (table_slot >= local_var_table_len)
return -1;
else
{
*name = local_var_table[table_slot].name;
*sig = local_var_table[table_slot].descriptor;
*generic_sig = local_var_table[table_slot].descriptor;
*startloc = static_cast<jlong>
(local_var_table[table_slot].bytecode_start_pc);
*length = static_cast<jint> (local_var_table[table_slot].length);
*slot = static_cast<jint> (local_var_table[table_slot].slot);
}
return local_var_table_len - table_slot -1;
}
pc_t
_Jv_InterpMethod::install_break (jlong index)
{

View File

@ -703,6 +703,88 @@ _Jv_JVMTI_GetLineNumberTable (jvmtiEnv *env, jmethodID method,
return JVMTI_ERROR_NONE;
}
static jvmtiError JNICALL
_Jv_JVMTI_GetLocalVariableTable (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
jint *num_locals,
jvmtiLocalVariableEntry **locals)
{
REQUIRE_PHASE (env, JVMTI_PHASE_LIVE);
NULL_CHECK (num_locals);
NULL_CHECK (locals);
CHECK_FOR_NATIVE_METHOD(method);
jclass klass;
jvmtiError jerr = env->GetMethodDeclaringClass (method, &klass);
if (jerr != JVMTI_ERROR_NONE)
return jerr;
_Jv_InterpMethod *imeth = reinterpret_cast<_Jv_InterpMethod *>
(_Jv_FindInterpreterMethod (klass, method));
if (imeth == NULL)
return JVMTI_ERROR_INVALID_METHODID;
jerr = env->GetMaxLocals (method, num_locals);
if (jerr != JVMTI_ERROR_NONE)
return jerr;
jerr = env->Allocate (static_cast<jlong>
((*num_locals) * sizeof (jvmtiLocalVariableEntry)),
reinterpret_cast<unsigned char **> (locals));
if (jerr != JVMTI_ERROR_NONE)
return jerr;
//the slot in the methods local_var_table to get
int table_slot = 0;
char *name;
char *sig;
char *generic_sig;
while (table_slot < *num_locals
&& imeth->get_local_var_table (&name, &sig, &generic_sig,
&((((*locals)[table_slot].start_location))),
&((*locals)[table_slot].length),
&((*locals)[table_slot].slot),
table_slot)
>= 0)
{
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
reinterpret_cast<unsigned char **>
(&(*locals)[table_slot].name));
if (jerr != JVMTI_ERROR_NONE)
return jerr;
strcpy ((*locals)[table_slot].name, name);
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
reinterpret_cast<unsigned char **>
(&(*locals)[table_slot].signature));
if (jerr != JVMTI_ERROR_NONE)
return jerr;
strcpy ((*locals)[table_slot].signature, sig);
jerr = env->Allocate (static_cast<jlong> (strlen (name) + 1),
reinterpret_cast<unsigned char **>
(&(*locals)[table_slot].generic_signature));
if (jerr != JVMTI_ERROR_NONE)
return jerr;
strcpy ((*locals)[table_slot].generic_signature, generic_sig);
table_slot++;
}
if (table_slot == 0)
return JVMTI_ERROR_ABSENT_INFORMATION;
// If there are double or long variables in the table, the the table will be
// smaller than the max number of slots, so correct for this here.
if ((table_slot) < *num_locals)
*num_locals = table_slot;
return JVMTI_ERROR_NONE;
}
static jvmtiError JNICALL
_Jv_JVMTI_IsMethodNative (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
jboolean *result)
@ -733,8 +815,7 @@ _Jv_JVMTI_IsMethodSynthetic (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
}
static jvmtiError JNICALL
_Jv_JVMTI_GetMaxLocals (MAYBE_UNUSED jvmtiEnv *env, jmethodID method,
jint *max_locals)
_Jv_JVMTI_GetMaxLocals (jvmtiEnv *env, jmethodID method, jint *max_locals)
{
REQUIRE_PHASE (env, JVMTI_PHASE_START | JVMTI_PHASE_LIVE);
NULL_CHECK (max_locals);
@ -1686,7 +1767,7 @@ struct _Jv_jvmtiEnv _Jv_JVMTI_Interface =
UNIMPLEMENTED, // GetArgumentsSize
_Jv_JVMTI_GetLineNumberTable, // GetLineNumberTable
UNIMPLEMENTED, // GetMethodLocation
UNIMPLEMENTED, // GetLocalVariableTable
_Jv_JVMTI_GetLocalVariableTable, // GetLocalVariableTable
RESERVED, // reserved73
RESERVED, // reserved74
UNIMPLEMENTED, // GetBytecodes