// 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; // JSR-202| stack_map_frame_entries[number_of_entries]; // JSR-202| } void JvmtiClassFileReconstituter::write_stackmap_table_attribute(methodHandle method, int stackmap_len) { write_attribute_name_index("StackMapTable"); write_u4(stackmap_len); memcpy( writeable_address(stackmap_len), (void*)(method->stackmap_data()->adr_at(0)), stackmap_len); }
// Write Code attribute // JVMSpec| Code_attribute { // JVMSpec| u2 attribute_name_index; // JVMSpec| u4 attribute_length; // JVMSpec| u2 max_stack; // JVMSpec| u2 max_locals; // JVMSpec| u4 code_length; // JVMSpec| u1 code[code_length]; // JVMSpec| u2 exception_table_length; // JVMSpec| { u2 start_pc; // JVMSpec| u2 end_pc; // JVMSpec| u2 handler_pc; // JVMSpec| u2 catch_type; // JVMSpec| } exception_table[exception_table_length]; // JVMSpec| u2 attributes_count; // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) { ConstMethod* const_method = 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()) { line_num_cnt = line_number_table_entries(method); if (line_num_cnt != 0) { ++attr_count; // Compute the complete size of the line number table attribute: // LineNumberTable_attribute { // u2 attribute_name_index; // u4 attribute_length; // u2 line_number_table_length; // { u2 start_pc; // u2 line_number; // } line_number_table[line_number_table_length]; // } attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2); } } if (method->has_stackmap_table()) { stackmap_len = method->stackmap_data()->length(); if (stackmap_len != 0) { ++attr_count; // Compute the size of the stack map table attribute (VM stores raw): // StackMapTable_attribute { // u2 attribute_name_index; // u4 attribute_length; // u2 number_of_entries; // stack_map_frame_entries[number_of_entries]; // } attr_size += 2 + 4 + stackmap_len; } } if (method->has_localvariable_table()) { local_variable_table_length = method->localvariable_table_length(); 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; // { // u2 start_pc; // u2 length; // 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 code_size + // code 2 + // exception_table_length (2+2+2+2) * exception_table_length + // exception_table 2 + // attributes_count attr_size; // attributes write_attribute_name_index("Code"); write_u4(size); write_u2(method->verifier_max_stack()); write_u2(method->max_locals()); write_u4(code_size); copy_bytecodes(method, (unsigned char*)writeable_address(code_size)); write_u2(exception_table_length); for (int index = 0; index < exception_table_length; index++) { write_u2(exception_table.start_pc(index)); write_u2(exception_table.end_pc(index)); write_u2(exception_table.handler_pc(index)); write_u2(exception_table.catch_type_index(index)); } write_u2(attr_count); if (line_num_cnt != 0) { write_line_number_table_attribute(method, line_num_cnt); } if (stackmap_len != 0) { 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 Code attribute // JVMSpec| Code_attribute { // JVMSpec| u2 attribute_name_index; // JVMSpec| u4 attribute_length; // JVMSpec| u2 max_stack; // JVMSpec| u2 max_locals; // JVMSpec| u4 code_length; // JVMSpec| u1 code[code_length]; // JVMSpec| u2 exception_table_length; // JVMSpec| { u2 start_pc; // JVMSpec| u2 end_pc; // JVMSpec| u2 handler_pc; // JVMSpec| u2 catch_type; // JVMSpec| } exception_table[exception_table_length]; // JVMSpec| u2 attributes_count; // JVMSpec| attribute_info attributes[attributes_count]; // JVMSpec| } void JvmtiClassFileReconstituter::write_code_attribute(methodHandle method) { constMethodHandle const_method(thread(), method->constMethod()); u2 line_num_cnt = 0; int stackmap_len = 0; // compute number and length of attributes -- FIXME: for now no LVT int attr_count = 0; int attr_size = 0; if (const_method->has_linenumber_table()) { line_num_cnt = line_number_table_entries(method); if (line_num_cnt != 0) { ++attr_count; // Compute the complete size of the line number table attribute: // LineNumberTable_attribute { // u2 attribute_name_index; // u4 attribute_length; // u2 line_number_table_length; // { u2 start_pc; // u2 line_number; // } line_number_table[line_number_table_length]; // } attr_size += 2 + 4 + 2 + line_num_cnt * (2 + 2); } } if (method->has_stackmap_table()) { stackmap_len = method->stackmap_data()->length(); if (stackmap_len != 0) { ++attr_count; // Compute the size of the stack map table attribute (VM stores raw): // StackMapTable_attribute { // u2 attribute_name_index; // u4 attribute_length; // u2 number_of_entries; // stack_map_frame_entries[number_of_entries]; // } attr_size += 2 + 4 + stackmap_len; } } typeArrayHandle exception_table(thread(), const_method->exception_table()); int exception_table_length = exception_table->length(); int exception_table_entries = exception_table_length / 4; int code_size = const_method->code_size(); int size = 2+2+4 + // max_stack, max_locals, code_length code_size + // code 2 + // exception_table_length (2+2+2+2) * exception_table_entries + // exception_table 2 + // attributes_count attr_size; // attributes write_attribute_name_index("Code"); write_u4(size); write_u2(method->max_stack()); write_u2(method->max_locals()); write_u4(code_size); copy_bytecodes(method, (unsigned char*)writeable_address(code_size)); write_u2(exception_table_entries); for (int index = 0; index < exception_table_length; ) { write_u2(exception_table->int_at(index++)); write_u2(exception_table->int_at(index++)); write_u2(exception_table->int_at(index++)); write_u2(exception_table->int_at(index++)); } write_u2(attr_count); if (line_num_cnt != 0) { write_line_number_table_attribute(method, line_num_cnt); } if (stackmap_len != 0) { write_stackmap_table_attribute(method, stackmap_len); } // FIXME: write LVT attribute }