implement long

This commit is contained in:
Zack Buhman 2024-12-25 00:06:54 -06:00
parent baa3db16b1
commit eef2c848e8
12 changed files with 337 additions and 105 deletions

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
*.out *.out
main main
print_class print_class
__pycache__

View File

@ -142,8 +142,14 @@ struct class_file * class_file_parse(const uint8_t * buf)
break; break;
case CONSTANT_Long: [[fallthrough]]; case CONSTANT_Long: [[fallthrough]];
case CONSTANT_Double: 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; break;
case CONSTANT_NameAndType: case CONSTANT_NameAndType:
constant->nameandtype.name_index = parse_u2(&buf); 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); constant->module.name_index = parse_u2(&buf);
break; break;
default: default:
#ifdef DEBUG
assert(false); assert(false);
#endif
break; break;
} }
} }

View File

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
typedef uint64_t u8;
typedef uint32_t u4; typedef uint32_t u4;
typedef uint16_t u2; typedef uint16_t u2;
typedef uint8_t u1; typedef uint8_t u1;
@ -58,13 +59,11 @@ struct constant_Float_info {
}; };
struct constant_Long_info { struct constant_Long_info {
u4 high_bytes; u8 bytes;
u4 low_bytes;
}; };
struct constant_Double_info { struct constant_Double_info {
u4 high_bytes; u8 bytes;
u4 low_bytes;
}; };
struct constant_NameAndType_info { struct constant_NameAndType_info {

View File

@ -181,7 +181,8 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent
method_name_length, method_name_length,
method_descriptor, method_descriptor,
method_descriptor_length); method_descriptor_length);
assert(e != nullptr); if (e == nullptr)
return nullptr;
return (struct method_info *)e->value; return (struct method_info *)e->value;
} }

View File

@ -2,6 +2,7 @@
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <inttypes.h>
#include "class_file.h" #include "class_file.h"
#include "bytes.h" #include "bytes.h"
@ -50,14 +51,12 @@ void print_constant(struct constant * constant)
*(float *)(&constant->_float.bytes)); *(float *)(&constant->_float.bytes));
break; break;
case CONSTANT_Long: case CONSTANT_Long:
printf("CONSTANT_Long high_bytes=%d low_bytes=%d\n", printf("CONSTANT_Long bytes=%" PRId64 "\n",
constant->_long.high_bytes, constant->_long.bytes);
constant->_long.low_bytes);
break; break;
case CONSTANT_Double: case CONSTANT_Double:
printf("CONSTANT_Double high_bytes=%d low_bytes=%d\n", printf("CONSTANT_Double bytes=%f\n",
constant->_long.high_bytes, *(double *)(&constant->_double.bytes));
constant->_long.low_bytes);
break; break;
case CONSTANT_NameAndType: case CONSTANT_NameAndType:
printf("CONSTANT_NameAndType %d %d\n", printf("CONSTANT_NameAndType %d %d\n",
@ -221,9 +220,11 @@ void print_class_file(struct class_file * class_file)
printf("constants:\n"); printf("constants:\n");
for (int i = 0; i < class_file->constant_pool_count - 1; i++) { for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
if (class_file->constant_pool[i].tag != 0) {
printf("% 3d: ", i + 1); printf("% 3d: ", i + 1);
print_constant(&class_file->constant_pool[i]); print_constant(&class_file->constant_pool[i]);
} }
}
printf("access_flags %04x\n", class_file->access_flags); printf("access_flags %04x\n", class_file->access_flags);
printf("this_class %d\n", class_file->this_class); printf("this_class %d\n", class_file->this_class);

View File

@ -321,7 +321,9 @@ void op_f2i(struct vm * vm)
void op_f2l(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) void op_fadd(struct vm * vm)
@ -599,7 +601,9 @@ void op_i2f(struct vm * vm)
void op_i2l(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) void op_i2s(struct vm * vm)
@ -629,9 +633,9 @@ void op_iaload(struct vm * vm)
void op_iand(struct vm * vm) void op_iand(struct vm * vm)
{ {
int32_t value2 = operand_stack_pop_u32(vm->current_frame); uint32_t value2 = operand_stack_pop_u32(vm->current_frame);
int32_t value1 = 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); 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 value2 = operand_stack_pop_u32(vm->current_frame);
uint32_t value1 = 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); 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 value2 = operand_stack_pop_u32(vm->current_frame);
uint32_t value1 = 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); operand_stack_push_u32(vm->current_frame, result);
} }
@ -1093,47 +1097,79 @@ void op_l2d(struct vm * vm)
void op_l2f(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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) void op_lookupswitch(struct vm * vm)
@ -1203,67 +1267,107 @@ void op_lookupswitch(struct vm * vm)
void op_lor(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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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 /* On successful resolution of the class, it is initialized if it has not
already been initialized (§5.5). already been initialized (§5.5).
(new) Upon execution of a new instruction, the class to be initialized is (new) Upon execution of a new instruction, the class to be initialized is
the class referenced by the instruction. */ the class referenced by the instruction. */
/*
if (!vm_initialize_class(vm, class_entry)) if (!vm_initialize_class(vm, class_entry))
return; 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"); assert(!"op_new");
} }
@ -1363,7 +1489,8 @@ void op_pop(struct vm * vm)
void op_pop2(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) void op_putfield(struct vm * vm, uint32_t index)

View File

@ -60,10 +60,20 @@ static int descriptor_nargs(struct constant * descriptor_constant)
int i = 1; int i = 1;
int nargs = 0; int nargs = 0;
while (i < descriptor_constant->utf8.length) { while (i < descriptor_constant->utf8.length) {
if (descriptor_constant->utf8.bytes[i] == ')') uint8_t byte = descriptor_constant->utf8.bytes[i];
if (byte == ')')
break; break;
if (descriptor_constant->utf8.bytes[i] != '[') switch (byte) {
case '[':
break;
case 'D': [[fallthrough]];
case 'J':
nargs += 2;
break;
default:
nargs += 1; nargs += 1;
break;
}
i += 1; i += 1;
} }
assert(i + 2 == descriptor_constant->utf8.length); assert(i + 2 == descriptor_constant->utf8.length);
@ -92,8 +102,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
struct class_file * class_file = class_entry->class_file; struct class_file * class_file = class_entry->class_file;
int constantvalue_name_index = find_constantvalue_name_index(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++) { for (int i = 0; i < class_file->fields_count; i++) {
struct field_info * field_info = &class_file->fields[i]; struct field_info * field_info = &class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC)) if (!(field_info->access_flags & FIELD_ACC_STATIC))
@ -117,6 +126,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
} }
} }
} }
}
/* Next, if C declares a class or interface initialization method, execute /* Next, if C declares a class or interface initialization method, execute
that method. */ that method. */
@ -232,8 +242,17 @@ void vm_method_return(struct vm * vm)
case 'S': [[fallthrough]]; case 'S': [[fallthrough]];
case 'I': [[fallthrough]]; case 'I': [[fallthrough]];
case 'F': case 'F':
{
uint32_t value = operand_stack_pop_u32(old_frame); uint32_t value = operand_stack_pop_u32(old_frame);
operand_stack_push_u32(vm->current_frame, value); 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; break;
case 'V': case 'V':
break; break;

View File

@ -109,6 +109,24 @@ static inline float operand_stack_pop_f32(struct frame * frame)
return f; 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); 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_static_method_call(struct vm * vm, struct class_file * class_file, struct method_info * method_info);
void vm_method_return(struct vm * vm); void vm_method_return(struct vm * vm);

View File

@ -18,6 +18,7 @@ int main(int argc, const char * argv[])
class_hash_table, class_hash_table,
(const uint8_t *)main_class, (const uint8_t *)main_class,
string_length(main_class)); string_length(main_class));
assert(class_entry != nullptr);
const char * method_name = "main"; const char * method_name = "main";
int method_name_length = string_length(method_name); int method_name_length = string_length(method_name);
@ -28,6 +29,7 @@ int main(int argc, const char * argv[])
method_name_length, method_name_length,
(const uint8_t *)method_descriptor, (const uint8_t *)method_descriptor,
method_descriptor_length); method_descriptor_length);
assert(method_info != nullptr);
struct vm vm; struct vm vm;
vm.class_hash_table.entry = class_hash_table; vm.class_hash_table.entry = class_hash_table;

View File

@ -1,17 +1,11 @@
import struct import struct
import sys import sys
from binascii import hexlify from binascii import hexlify
import csv
def parse_row(s): from gen_decoder import parse_opcode_table
a, b, c, d = s.strip().split(',')
return int(a), c, int(d)
def parse_opcode_table(buf): opcode_table = parse_opcode_table()
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())
def size_to_format(size): def size_to_format(size):
if size == 4: if size == 4:
@ -60,7 +54,11 @@ def parse_cp_info(buf):
buf, value = field(buf, field_size) buf, value = field(buf, field_size)
last_value = value last_value = value
d[field_name] = 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): def parse_attribute_info(buf):
buf, attribute_name_index = field(buf, 2) buf, attribute_name_index = field(buf, 2)
@ -96,12 +94,12 @@ def dump_opcodes(buf, indent):
ix = 0 ix = 0
while len(buf) > 0: while len(buf) > 0:
op = buf[0] op = buf[0]
name, arg_length = opcode_table[op] instruction = opcode_table[op]
buf = buf[1:] buf = buf[1:]
args = list(buf[0:arg_length]) args = list(buf[0:instruction.arguments_size])
print(indent, f"{ix:> 3}", name, args) print(indent, f"{ix:> 3}", instruction.mnemonic, args)
ix += 1 + arg_length ix += 1 + instruction.arguments_size
buf = buf[arg_length:] buf = buf[instruction.arguments_size:]
def print_code_info(buf, indent, constant_pool): def print_code_info(buf, indent, constant_pool):
code_attribute = [ code_attribute = [
@ -158,10 +156,14 @@ def parse_class(buf):
print("constant_pool:") print("constant_pool:")
constant_pool = [] constant_pool = []
for i in range(constant_pool_count - 1): i = 1
buf, cp_info = parse_cp_info(buf) while i < constant_pool_count:
buf, cp_info, entries = parse_cp_info(buf)
constant_pool.append(cp_info) 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, access_flags = field(buf, 2)
buf, this_class = field(buf, 2) buf, this_class = field(buf, 2)

View File

@ -240,7 +240,8 @@ def renderer():
return _render(out, lines) return _render(out, lines)
return render, out return render, out
render, out = renderer() if __name__ == "__main__":
render(generate_print_decoder()) render, out = renderer()
render(generate_execute_decoder()) render(generate_print_decoder())
sys.stdout.write(out.getvalue()) render(generate_execute_decoder())
sys.stdout.write(out.getvalue())

57
p/Long.java Normal file
View File

@ -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();
}
}