From eef2c848e86f7370d7cda57e837fdab7e9a5cd6a Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Wed, 25 Dec 2024 00:06:54 -0600 Subject: [PATCH] implement long --- .gitignore | 3 +- c/class_file.c | 12 ++- c/class_file.h | 7 +- c/class_resolver.c | 3 +- c/debug_class_file.c | 17 ++-- c/execute.c | 209 ++++++++++++++++++++++++++++++++++--------- c/frame.c | 67 +++++++++----- c/frame.h | 18 ++++ c/main.c | 2 + class_file.py | 38 ++++---- gen_decoder.py | 9 +- p/Long.java | 57 ++++++++++++ 12 files changed, 337 insertions(+), 105 deletions(-) create mode 100644 p/Long.java diff --git a/.gitignore b/.gitignore index 17c1e98..fdeb6ca 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ *.class *.out main -print_class \ No newline at end of file +print_class +__pycache__ \ No newline at end of file diff --git a/c/class_file.c b/c/class_file.c index 332aa81..540e9c8 100644 --- a/c/class_file.c +++ b/c/class_file.c @@ -142,8 +142,14 @@ struct class_file * class_file_parse(const uint8_t * buf) break; case CONSTANT_Long: [[fallthrough]]; case CONSTANT_Double: - constant->_long.high_bytes = parse_u4(&buf); - constant->_long.low_bytes = parse_u4(&buf); + { + uint64_t high_bytes = parse_u4(&buf); + uint64_t low_bytes = parse_u4(&buf); + constant->_long.bytes = high_bytes << 32 | low_bytes; + // long and double use two constant pool entries + class_file->constant_pool[i + 1].tag = 0; + i += 1; + } break; case CONSTANT_NameAndType: constant->nameandtype.name_index = parse_u2(&buf); @@ -170,9 +176,7 @@ struct class_file * class_file_parse(const uint8_t * buf) constant->module.name_index = parse_u2(&buf); break; default: - #ifdef DEBUG assert(false); - #endif break; } } diff --git a/c/class_file.h b/c/class_file.h index b621f41..5f53b0b 100644 --- a/c/class_file.h +++ b/c/class_file.h @@ -2,6 +2,7 @@ #include +typedef uint64_t u8; typedef uint32_t u4; typedef uint16_t u2; typedef uint8_t u1; @@ -58,13 +59,11 @@ struct constant_Float_info { }; struct constant_Long_info { - u4 high_bytes; - u4 low_bytes; + u8 bytes; }; struct constant_Double_info { - u4 high_bytes; - u4 low_bytes; + u8 bytes; }; struct constant_NameAndType_info { diff --git a/c/class_resolver.c b/c/class_resolver.c index d8fa8d4..0c96f5c 100644 --- a/c/class_resolver.c +++ b/c/class_resolver.c @@ -181,7 +181,8 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent method_name_length, method_descriptor, method_descriptor_length); - assert(e != nullptr); + if (e == nullptr) + return nullptr; return (struct method_info *)e->value; } diff --git a/c/debug_class_file.c b/c/debug_class_file.c index 2f4eb2d..4f10a56 100644 --- a/c/debug_class_file.c +++ b/c/debug_class_file.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "class_file.h" #include "bytes.h" @@ -50,14 +51,12 @@ void print_constant(struct constant * constant) *(float *)(&constant->_float.bytes)); break; case CONSTANT_Long: - printf("CONSTANT_Long high_bytes=%d low_bytes=%d\n", - constant->_long.high_bytes, - constant->_long.low_bytes); + printf("CONSTANT_Long bytes=%" PRId64 "\n", + constant->_long.bytes); break; case CONSTANT_Double: - printf("CONSTANT_Double high_bytes=%d low_bytes=%d\n", - constant->_long.high_bytes, - constant->_long.low_bytes); + printf("CONSTANT_Double bytes=%f\n", + *(double *)(&constant->_double.bytes)); break; case CONSTANT_NameAndType: printf("CONSTANT_NameAndType %d %d\n", @@ -221,8 +220,10 @@ void print_class_file(struct class_file * class_file) printf("constants:\n"); for (int i = 0; i < class_file->constant_pool_count - 1; i++) { - printf("% 3d: ", i + 1); - print_constant(&class_file->constant_pool[i]); + if (class_file->constant_pool[i].tag != 0) { + printf("% 3d: ", i + 1); + print_constant(&class_file->constant_pool[i]); + } } printf("access_flags %04x\n", class_file->access_flags); diff --git a/c/execute.c b/c/execute.c index 708e2d2..2b8e65b 100644 --- a/c/execute.c +++ b/c/execute.c @@ -321,7 +321,9 @@ void op_f2i(struct vm * vm) void op_f2l(struct vm * vm) { - assert(!"op_f2l"); + float value = operand_stack_pop_f32(vm->current_frame); + int64_t result = (int64_t)value; + operand_stack_push_u64(vm->current_frame, result); } void op_fadd(struct vm * vm) @@ -599,7 +601,9 @@ void op_i2f(struct vm * vm) void op_i2l(struct vm * vm) { - assert(!"op_i2l"); + int32_t value = operand_stack_pop_u32(vm->current_frame); + int64_t result = (int64_t)value; + operand_stack_push_u64(vm->current_frame, result); } void op_i2s(struct vm * vm) @@ -629,9 +633,9 @@ void op_iaload(struct vm * vm) void op_iand(struct vm * vm) { - int32_t value2 = operand_stack_pop_u32(vm->current_frame); - int32_t value1 = operand_stack_pop_u32(vm->current_frame); - int32_t result = value1 & value2; + uint32_t value2 = operand_stack_pop_u32(vm->current_frame); + uint32_t value1 = operand_stack_pop_u32(vm->current_frame); + uint32_t result = value1 & value2; operand_stack_push_u32(vm->current_frame, result); } @@ -954,7 +958,7 @@ void op_ior(struct vm * vm) { uint32_t value2 = operand_stack_pop_u32(vm->current_frame); uint32_t value1 = operand_stack_pop_u32(vm->current_frame); - int32_t result = value1 | value2; + uint32_t result = value1 | value2; operand_stack_push_u32(vm->current_frame, result); } @@ -1072,7 +1076,7 @@ void op_ixor(struct vm * vm) { uint32_t value2 = operand_stack_pop_u32(vm->current_frame); uint32_t value1 = operand_stack_pop_u32(vm->current_frame); - int32_t result = value1 ^ value2; + uint32_t result = value1 ^ value2; operand_stack_push_u32(vm->current_frame, result); } @@ -1093,47 +1097,79 @@ void op_l2d(struct vm * vm) void op_l2f(struct vm * vm) { - assert(!"op_l2f"); + int64_t value = operand_stack_pop_u64(vm->current_frame); + float result = (float)value; + operand_stack_push_f32(vm->current_frame, result); } void op_l2i(struct vm * vm) { - assert(!"op_l2i"); + int64_t value = operand_stack_pop_u64(vm->current_frame); + int32_t result = (int32_t)value; + operand_stack_push_u32(vm->current_frame, result); } void op_ladd(struct vm * vm) { - assert(!"op_ladd"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int64_t result = value1 + value2; + operand_stack_push_u64(vm->current_frame, result); } void op_laload(struct vm * vm) { - assert(!"op_laload"); + int32_t index = operand_stack_pop_u32(vm->current_frame); + int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + assert(arrayref[0] > 0 && index < arrayref[0]); + int64_t * longarray = (int64_t *)&arrayref[1]; + int64_t value = longarray[index]; + operand_stack_push_u64(vm->current_frame, value); } void op_land(struct vm * vm) { - assert(!"op_land"); + uint64_t value2 = operand_stack_pop_u64(vm->current_frame); + uint64_t value1 = operand_stack_pop_u64(vm->current_frame); + uint64_t result = value1 & value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lastore(struct vm * vm) { - assert(!"op_lastore"); + int64_t value = operand_stack_pop_u64(vm->current_frame); + int32_t index = operand_stack_pop_u32(vm->current_frame); + int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + assert(arrayref[0] > 0 && index < arrayref[0]); + int64_t * longarray = (int64_t *)&arrayref[1]; + longarray[index] = value; } void op_lcmp(struct vm * vm) { - assert(!"op_lcmp"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + bool greater = value1 > value2; + bool equal = value1 == value2; + int32_t value; + if (equal) { + value = 0; + } else if (greater) { + value = 1; + } else { // less than + value = -1; + } + operand_stack_push_u32(vm->current_frame, value); } void op_lconst_0(struct vm * vm) { - assert(!"op_lconst_0"); + operand_stack_push_u64(vm->current_frame, 0); } void op_lconst_1(struct vm * vm) { - assert(!"op_lconst_1"); + operand_stack_push_u64(vm->current_frame, 1); } void op_ldc(struct vm * vm, uint32_t index) @@ -1148,7 +1184,12 @@ void op_ldc(struct vm * vm, uint32_t index) void op_ldc2_w(struct vm * vm, uint32_t index) { - assert(!"op_ldc2_w"); + struct constant * constant = &vm->current_thread.current_class->constant_pool[index - 1]; + #ifdef DEBUG + assert(constant->tag == CONSTANT_Long || constant->tag == CONSTANT_Double); + #endif + int64_t value = constant->_long.bytes; + operand_stack_push_u64(vm->current_frame, value); } void op_ldc_w(struct vm * vm, uint32_t index) @@ -1158,42 +1199,65 @@ void op_ldc_w(struct vm * vm, uint32_t index) void op_ldiv(struct vm * vm) { - assert(!"op_ldiv"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int64_t result = value1 / value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lload(struct vm * vm, uint32_t index) { - assert(!"op_lload"); + uint32_t low = vm->current_frame->local_variable[index]; + uint32_t high = vm->current_frame->local_variable[index + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } void op_lload_0(struct vm * vm) { - assert(!"op_lload_0"); + uint32_t low = vm->current_frame->local_variable[0]; + uint32_t high = vm->current_frame->local_variable[0 + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } void op_lload_1(struct vm * vm) { - assert(!"op_lload_1"); + uint32_t low = vm->current_frame->local_variable[1]; + uint32_t high = vm->current_frame->local_variable[1 + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } void op_lload_2(struct vm * vm) { - assert(!"op_lload_2"); + uint32_t low = vm->current_frame->local_variable[2]; + uint32_t high = vm->current_frame->local_variable[2 + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } void op_lload_3(struct vm * vm) { - assert(!"op_lload_3"); + uint32_t low = vm->current_frame->local_variable[3]; + uint32_t high = vm->current_frame->local_variable[3 + 1]; + operand_stack_push_u32(vm->current_frame, low); + operand_stack_push_u32(vm->current_frame, high); } void op_lmul(struct vm * vm) { - assert(!"op_lmul"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int64_t result = value1 * value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lneg(struct vm * vm) { - assert(!"op_lneg"); + int64_t value = operand_stack_pop_u64(vm->current_frame); + int64_t result = -value; + operand_stack_push_u64(vm->current_frame, result); } void op_lookupswitch(struct vm * vm) @@ -1203,67 +1267,107 @@ void op_lookupswitch(struct vm * vm) void op_lor(struct vm * vm) { - assert(!"op_lor"); + uint64_t value2 = operand_stack_pop_u64(vm->current_frame); + uint64_t value1 = operand_stack_pop_u64(vm->current_frame); + uint64_t result = value1 | value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lrem(struct vm * vm) { - assert(!"op_lrem"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int64_t result = value1 % value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lreturn(struct vm * vm) { - assert(!"op_lreturn"); + assert(vm->current_frame->return_type == 'J'); + vm_method_return(vm); } void op_lshl(struct vm * vm) { - assert(!"op_lshl"); + int32_t value2 = operand_stack_pop_u32(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int s = value2 & 0b111111; + int64_t result = value1 << s; + operand_stack_push_u64(vm->current_frame, result); } void op_lshr(struct vm * vm) { - assert(!"op_lshr"); + int32_t value2 = operand_stack_pop_u32(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int s = value2 & 0b111111; + int64_t result = value1 >> s; + operand_stack_push_u64(vm->current_frame, result); } void op_lstore(struct vm * vm, uint32_t index) { - assert(!"op_lstore"); + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[index + 1] = high; + vm->current_frame->local_variable[index] = low; } void op_lstore_0(struct vm * vm) { - assert(!"op_lstore_0"); + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[0 + 1] = high; + vm->current_frame->local_variable[0] = low; } void op_lstore_1(struct vm * vm) { - assert(!"op_lstore_1"); + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[1 + 1] = high; + vm->current_frame->local_variable[1] = low; } void op_lstore_2(struct vm * vm) { - assert(!"op_lstore_2"); + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[2 + 1] = high; + vm->current_frame->local_variable[2] = low; } void op_lstore_3(struct vm * vm) { - assert(!"op_lstore_3"); + uint32_t high = operand_stack_pop_u32(vm->current_frame); + uint32_t low = operand_stack_pop_u32(vm->current_frame); + vm->current_frame->local_variable[3 + 1] = high; + vm->current_frame->local_variable[3] = low; } void op_lsub(struct vm * vm) { - assert(!"op_lsub"); + int64_t value2 = operand_stack_pop_u64(vm->current_frame); + int64_t value1 = operand_stack_pop_u64(vm->current_frame); + int64_t result = value1 - value2; + operand_stack_push_u64(vm->current_frame, result); } void op_lushr(struct vm * vm) { - assert(!"op_lushr"); + int32_t value2 = operand_stack_pop_u32(vm->current_frame); + uint64_t value1 = operand_stack_pop_u64(vm->current_frame); + int s = value2 & 0b111111; + uint64_t result = value1 >> s; + operand_stack_push_u64(vm->current_frame, result); } void op_lxor(struct vm * vm) { - assert(!"op_lxor"); + uint64_t value2 = operand_stack_pop_u64(vm->current_frame); + uint64_t value1 = operand_stack_pop_u64(vm->current_frame); + uint64_t result = value1 ^ value2; + operand_stack_push_u64(vm->current_frame, result); } void op_monitorenter(struct vm * vm) @@ -1283,16 +1387,38 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions) void op_new(struct vm * vm, uint32_t index) { + struct constant * class_constant = &vm->current_thread.current_class->constant_pool[index - 1]; + #ifdef DEBUG + assert(class_constant->tag == CONSTANT_Class); + #endif + struct constant * class_name_constant = &vm->current_thread.current_class->constant_pool[class_constant->class.name_index - 1]; + #ifdef DEBUG + assert(class_name_constant->tag == CONSTANT_Utf8); + #endif + + struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length, + vm->class_hash_table.entry, + class_name_constant->utf8.bytes, + class_name_constant->utf8.length); + assert(class_entry != nullptr); + /* On successful resolution of the class, it is initialized if it has not already been initialized (§5.5). (new) Upon execution of a new instruction, the class to be initialized is the class referenced by the instruction. */ - /* if (!vm_initialize_class(vm, class_entry)) return; - */ + + /* Memory for a new instance of that class is allocated from the + garbage-collected heap, and the instance variables of the new object are + initialized to their default initial values (§2.3, §2.4). The objectref, a + reference to the instance, is pushed onto the operand stack. */ + + int fields_count = class_entry->class_file->fields_count; + (void)fields_count; + //int32_t * arrayref = memory_allocate(); assert(!"op_new"); } @@ -1363,7 +1489,8 @@ void op_pop(struct vm * vm) void op_pop2(struct vm * vm) { - assert(!"op_pop2"); + operand_stack_pop_u32(vm->current_frame); + operand_stack_pop_u32(vm->current_frame); } void op_putfield(struct vm * vm, uint32_t index) diff --git a/c/frame.c b/c/frame.c index 235494d..2533041 100644 --- a/c/frame.c +++ b/c/frame.c @@ -60,10 +60,20 @@ static int descriptor_nargs(struct constant * descriptor_constant) int i = 1; int nargs = 0; while (i < descriptor_constant->utf8.length) { - if (descriptor_constant->utf8.bytes[i] == ')') + uint8_t byte = descriptor_constant->utf8.bytes[i]; + if (byte == ')') break; - if (descriptor_constant->utf8.bytes[i] != '[') + switch (byte) { + case '[': + break; + case 'D': [[fallthrough]]; + case 'J': + nargs += 2; + break; + default: nargs += 1; + break; + } i += 1; } assert(i + 2 == descriptor_constant->utf8.length); @@ -92,28 +102,28 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry) struct class_file * class_file = class_entry->class_file; int constantvalue_name_index = find_constantvalue_name_index(class_file); - assert(constantvalue_name_index != 0); + if (constantvalue_name_index != 0) { + for (int i = 0; i < class_file->fields_count; i++) { + struct field_info * field_info = &class_file->fields[i]; + if (!(field_info->access_flags & FIELD_ACC_STATIC)) + continue; - for (int i = 0; i < class_file->fields_count; i++) { - struct field_info * field_info = &class_file->fields[i]; - if (!(field_info->access_flags & FIELD_ACC_STATIC)) - continue; + for (int j = 0; j < field_info->attributes_count; j++) { + if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) { + struct attribute_info * attribute = &field_info->attributes[j]; + struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1]; + assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String - for (int j = 0; j < field_info->attributes_count; j++) { - if (field_info->attributes[j].attribute_name_index == constantvalue_name_index) { - struct attribute_info * attribute = &field_info->attributes[j]; - struct constant * constantvalue = &class_file->constant_pool[attribute->constantvalue->constantvalue_index - 1]; - assert(constantvalue->tag == CONSTANT_Integer); // also need to support CONSTANT_String - - struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1]; - assert(name_constant->tag == CONSTANT_Utf8); - struct field_entry * field_entry = class_resolver_lookup_field(class_entry, - name_constant->utf8.bytes, - name_constant->utf8.length); - assert(field_entry != nullptr); - field_entry->value = constantvalue->integer.bytes; - printf(" constantvalue: %d\n", field_entry->value); - break; + struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1]; + assert(name_constant->tag == CONSTANT_Utf8); + struct field_entry * field_entry = class_resolver_lookup_field(class_entry, + name_constant->utf8.bytes, + name_constant->utf8.length); + assert(field_entry != nullptr); + field_entry->value = constantvalue->integer.bytes; + printf(" constantvalue: %d\n", field_entry->value); + break; + } } } } @@ -232,8 +242,17 @@ void vm_method_return(struct vm * vm) case 'S': [[fallthrough]]; case 'I': [[fallthrough]]; case 'F': - uint32_t value = operand_stack_pop_u32(old_frame); - operand_stack_push_u32(vm->current_frame, value); + { + uint32_t value = operand_stack_pop_u32(old_frame); + operand_stack_push_u32(vm->current_frame, value); + } + break; + case 'D': [[fallthrough]]; + case 'J': + { + uint64_t value = operand_stack_pop_u64(old_frame); + operand_stack_push_u64(vm->current_frame, value); + } break; case 'V': break; diff --git a/c/frame.h b/c/frame.h index 8a2b35c..24040ea 100644 --- a/c/frame.h +++ b/c/frame.h @@ -109,6 +109,24 @@ static inline float operand_stack_pop_f32(struct frame * frame) return f; } +static inline void operand_stack_push_u64(struct frame * frame, uint64_t value) +{ + frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 0); + frame->operand_stack_ix++; + frame->operand_stack[frame->operand_stack_ix] = (uint32_t)(value >> 32); + frame->operand_stack_ix++; +} + +static inline uint64_t operand_stack_pop_u64(struct frame * frame) +{ + frame->operand_stack_ix--; + uint64_t high = frame->operand_stack[frame->operand_stack_ix]; + frame->operand_stack_ix--; + uint64_t low = frame->operand_stack[frame->operand_stack_ix]; + uint64_t value = (high << 32) | (low << 0); + return value; +} + bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry); void vm_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info); void vm_method_return(struct vm * vm); diff --git a/c/main.c b/c/main.c index 4447875..2891208 100644 --- a/c/main.c +++ b/c/main.c @@ -18,6 +18,7 @@ int main(int argc, const char * argv[]) class_hash_table, (const uint8_t *)main_class, string_length(main_class)); + assert(class_entry != nullptr); const char * method_name = "main"; int method_name_length = string_length(method_name); @@ -28,6 +29,7 @@ int main(int argc, const char * argv[]) method_name_length, (const uint8_t *)method_descriptor, method_descriptor_length); + assert(method_info != nullptr); struct vm vm; vm.class_hash_table.entry = class_hash_table; diff --git a/class_file.py b/class_file.py index fbe8452..5d3ff2c 100644 --- a/class_file.py +++ b/class_file.py @@ -1,17 +1,11 @@ import struct import sys from binascii import hexlify +import csv -def parse_row(s): - a, b, c, d = s.strip().split(',') - return int(a), c, int(d) +from gen_decoder import parse_opcode_table -def parse_opcode_table(buf): - rows = [parse_row(i) for i in buf.strip().split('\n')] - return {opcode: (name, args) for opcode, name, args in rows} - -with open('opcodes.csv', 'r') as f: - opcode_table = parse_opcode_table(f.read()) +opcode_table = parse_opcode_table() def size_to_format(size): if size == 4: @@ -60,7 +54,11 @@ def parse_cp_info(buf): buf, value = field(buf, field_size) last_value = value d[field_name] = value - return buf, (name, d) + if tag in {5, 6}: + entries = 2 + else: + entries = 1 + return buf, (name, d), entries def parse_attribute_info(buf): buf, attribute_name_index = field(buf, 2) @@ -96,12 +94,12 @@ def dump_opcodes(buf, indent): ix = 0 while len(buf) > 0: op = buf[0] - name, arg_length = opcode_table[op] + instruction = opcode_table[op] buf = buf[1:] - args = list(buf[0:arg_length]) - print(indent, f"{ix:> 3}", name, args) - ix += 1 + arg_length - buf = buf[arg_length:] + args = list(buf[0:instruction.arguments_size]) + print(indent, f"{ix:> 3}", instruction.mnemonic, args) + ix += 1 + instruction.arguments_size + buf = buf[instruction.arguments_size:] def print_code_info(buf, indent, constant_pool): code_attribute = [ @@ -158,10 +156,14 @@ def parse_class(buf): print("constant_pool:") constant_pool = [] - for i in range(constant_pool_count - 1): - buf, cp_info = parse_cp_info(buf) + i = 1 + while i < constant_pool_count: + buf, cp_info, entries = parse_cp_info(buf) constant_pool.append(cp_info) - print(i + 1, cp_info) + if entries == 2: + constant_pool.append(None) + print(i, cp_info) + i += entries buf, access_flags = field(buf, 2) buf, this_class = field(buf, 2) diff --git a/gen_decoder.py b/gen_decoder.py index 7264f06..0d08bb9 100644 --- a/gen_decoder.py +++ b/gen_decoder.py @@ -240,7 +240,8 @@ def renderer(): return _render(out, lines) return render, out -render, out = renderer() -render(generate_print_decoder()) -render(generate_execute_decoder()) -sys.stdout.write(out.getvalue()) +if __name__ == "__main__": + render, out = renderer() + render(generate_print_decoder()) + render(generate_execute_decoder()) + sys.stdout.write(out.getvalue()) diff --git a/p/Long.java b/p/Long.java new file mode 100644 index 0000000..ea63248 --- /dev/null +++ b/p/Long.java @@ -0,0 +1,57 @@ +package p; + +class Long { + static long test(long n, long m) { + long y = n + m; // 21 + long z = y % 9999; // 21 + long a = z * 5; // 105 + long b = a + 1; // 106 + long c = b / 3; + long d = c & 0x0ffffffff0L; // 32 + long e = d | 0x1000000000L; // 68719476768 (16, 32) + long f = e - 2; // 68719476766 (16, 30) + long g = -f; // -68719476766 (-17, -30) + long h = g >> 1; + long i = h << 2; + long j = i >>> 1; + long k = j ^ 0xffffffffffffffffL; // -9223371968135299043 + return k; + } + + static void test2(long a) { + int b = (int)a; + float c = (float)a; + long d = (long)b; + long e = (long)c; + } + + static boolean test3(long a, long b) { + boolean c = a > b; + if (c) { + return -a == b; + } else { + return -b <= a; + } + } + + static long test4() { + long[] arr = {1, 2, 3, 4}; + long sum = 0; + for (int i = 0; i < arr.length; i++) { + sum += arr[i]; + } + boolean b = sum > 1; + return sum * 4; // 40 + } + + // -9223371968135299059 + // -2147483632 + // 13 + public static void main() { + long a = test(10, 11); + int b = (int)a; + test2(10); + test3(88, 123); + test4(); + } +}