📄 kaffe.def
字号:
}#endif adjustpc((4 - (pc % 4)) + 12 + (high - low + 1) * 4);}define_insn(LOOKUPSWITCH){ /* * ..., key -> ... */ check_stack_int(0); npc = (pc + 1 + 3) & -4; idx = (int32)((getcode(npc+4) << 24) | (getcode(npc+5) << 16) | (getcode(npc+6) << 8) | getcode(npc+7)); trace_jcode (("lookupswitch %d\n", idx)); slot_alloctmp(mtable); slot_alloctmp(tmp); move_label_const(tmp, reference_table_label(7)); if (idx != 0) { slot_alloctmp(tmp2); move_ref(tmp2, tmp); add_ref_const(tmp, tmp, idx * switchpair_size); end_sub_block(); set_label(LOOKUPSWITCH, 5); start_sub_block(); load_key(mtable, tmp); end_sub_block(); cbranch_int_eq(mtable, stack(0), reference_label(LOOKUPSWITCH, 6)); start_sub_block(); add_ref_const(tmp, tmp, -switchpair_size); end_sub_block(); cbranch_ref_ne(tmp, tmp2, reference_label(LOOKUPSWITCH, 5)); slot_freetmp(tmp2); start_sub_block(); add_ref_const(tmp, tmp, -switchpair_addr); end_sub_block(); set_label(LOOKUPSWITCH, 6); start_sub_block(); add_ref_const(tmp, tmp, switchpair_addr); } load_code_ref(tmp, tmp); end_sub_block(); branch_indirect(table_code_label(tmp)); pop(1); slot_freetmp(mtable); slot_freetmp(tmp);#if defined(TRANSLATOR) { set_label(LOOKUPSWITCH, 7); build_code_ref(&getcode(npc), pc); build_key(&getcode(npc)); /* Dummy key */ for (low = 1; low <= idx; low++) { build_key(&getcode(npc + (low * switchpair_size))); build_code_ref(&getcode(npc + (low * switchpair_size) + switchpair_addr), pc); } }#endif adjustpc((4 - (pc % 4)) + (idx + 1) * 8);}define_insn(IRETURN){ trace_jcode (("ireturn\n")); check_stack_int(0); monitor_exit(); returnarg_int(rstack(0)); ret();}define_insn(LRETURN){ trace_jcode (("lreturn\n")); check_stack_long(0); monitor_exit(); returnarg_long(rstack_long(0)); ret();}define_insn(FRETURN){ trace_jcode (("freturn\n")); check_stack_float(0); monitor_exit(); returnarg_float(rstack_float(0)); ret();}define_insn(DRETURN){ trace_jcode (("dreturn\n")); check_stack_double(0); monitor_exit(); returnarg_double(rstack_double(0)); ret();}define_insn(ARETURN){ trace_jcode (("areturn\n")); check_stack_ref(0); monitor_exit(); returnarg_ref(rstack_ref(0)); ret();}define_insn(RETURN){ trace_jcode (("return\n")); monitor_exit();#if defined(ENABLE_JVMPI) softcall_exit_method(globalMethod);#endif ret();}/* * This macro initialises the static data associated with a class. */#define INIT_STATIC_CLASS(c) \ if (c != 0 && c->state != CSTATE_COMPLETE) { \ softcall_initialise_class(c); \ }define_insn(GETSTATIC){ /* * ... -> ..., value */ check_pcidx (0); idx = (uint16)((getpc(0) << 8) | getpc(1)); trace_jcode (("getstatic %d\n", idx)); get_static_field_info_noerror(idx); if (field_class() == 0) { softcall_nosuchclass(field_classname()); switch (field_sig()->data[0]) { case 'J': case 'D': push(2); break; default: push(1); break; } break; } INIT_STATIC_CLASS(field_class()); if (field_field() == 0) { softcall_nosuchfield(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': push(2); break; default: push(1); break; } } else if (!(field_field()->accflags & ACC_STATIC)) { softcall_incompatibleclasschange(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': push(2); break; default: push(1); break; } } else if (!checkFieldAccess(current_class(), field_class(), field_field())) { softcall_illegalaccess(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': push(2); break; default: push(1); break; } } /* Use the proper load to increase the chances of the translator getting data in the right type of register. */ else if (!FIELD_ISPRIM(field_field())) { push(1); load_addr_ref(stack(0), FIELD_ADDRESS(field_field())); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) { case 'I': push(1); load_addr_int(stack(0), FIELD_ADDRESS(field_field())); break; case 'S': push(1); load_addr_short(stack(0), FIELD_ADDRESS(field_field())); break; case 'B': case 'Z': push(1); load_addr_byte(stack(0), FIELD_ADDRESS(field_field())); break; case 'C': push(1); load_addr_char(stack(0), FIELD_ADDRESS(field_field())); break; case 'F': push(1); load_addr_float(stack(0), FIELD_ADDRESS(field_field())); break; case 'J': push(2); load_addr_long(stack_long(0), FIELD_ADDRESS(field_field())); break; case 'D': push(2); load_addr_double(stack_double(0), FIELD_ADDRESS(field_field())); break; default: ABORT(); }}define_insn(PUTSTATIC){ /* * ..., value -> ... */ check_pcidx (0); idx = (uint16)((getpc(0) << 8) | getpc(1)); trace_jcode (("putstatic %d\n", idx)); get_static_field_info_noerror(idx); if (field_class() == 0) { softcall_nosuchclass(field_classname()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(2); break; default: pop(1); break; } break; } INIT_STATIC_CLASS(field_class()); if (field_field() == 0) { softcall_nosuchfield(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(2); break; default: pop(1); break; } } else if (!(field_field()->accflags & ACC_STATIC)) { softcall_incompatibleclasschange(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(2); break; default: pop(1); break; } } else if (((field_field()->accflags & ACC_FINAL) && ((field_class() != current_class()))) || !checkFieldAccess(current_class(), field_class(), field_field())) { softcall_illegalaccess(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(2); break; default: pop(1); break; } } else if (!FIELD_ISPRIM(field_field())) { SOFT_ADDREFERENCE_STATIC(field_statics(), stack(0)); store_addr_ref(FIELD_ADDRESS(field_field()), stack(0)); pop(1); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) { case 'I': store_addr_int(FIELD_ADDRESS(field_field()), stack(0)); pop(1); break; case 'S': store_addr_short(FIELD_ADDRESS(field_field()), stack(0)); pop(1); break; case 'B': case 'Z': store_addr_byte(FIELD_ADDRESS(field_field()), stack(0)); pop(1); break; case 'C': store_addr_char(FIELD_ADDRESS(field_field()), stack(0)); pop(1); break; case 'F': store_addr_float(FIELD_ADDRESS(field_field()), stack(0)); pop(1); break; case 'J': store_addr_long(FIELD_ADDRESS(field_field()), stack_long(0)); pop(2); break; case 'D': store_addr_double(FIELD_ADDRESS(field_field()), stack_double(0)); pop(2); break; default: ABORT(); }}define_insn(GETFIELD){ /* * ..., obj-ref -> ..., value */ check_pcidx (0); check_stack_ref(0); check_null(GETFIELD, stack(0), 34); idx = (uint16)((getpc(0) << 8) | getpc(1)); trace_jcode (("getfield %d\n", idx)); get_field_info(idx); /* If field not found we put an exception down */ if (field_field() == 0) { softcall_nosuchfield(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(1); break; default: break; } } else if (field_field()->accflags & ACC_STATIC) { softcall_incompatibleclasschange(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(1); break; default: break; } } else if (!checkFieldAccess(current_class(), field_class(), field_field())) { softcall_illegalaccess(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(1); break; default: break; } } /* Use the proper load to increase the chances of the translator getting data in the right type of register. */ else if (!FIELD_ISPRIM(field_field())) { load_offset_ref(stack(0), rstack(0), FIELD_BOFFSET(field_field())); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) { case 'I': load_offset_int(stack(0), rstack(0), FIELD_BOFFSET(field_field())); break; case 'S': load_offset_short(stack(0), rstack(0), FIELD_BOFFSET(field_field())); break; case 'B': case 'Z': load_offset_byte(stack(0), rstack(0), FIELD_BOFFSET(field_field())); break; case 'C': load_offset_char(stack(0), rstack(0), FIELD_BOFFSET(field_field())); break; case 'F': load_offset_float(stack(0), stack(0), FIELD_BOFFSET(field_field())); break; case 'J': load_offset_long(stack_long(-1), stack(0), FIELD_BOFFSET(field_field())); push(1); break; case 'D': load_offset_double(stack_double(-1), stack(0), FIELD_BOFFSET(field_field())); push(1); break; default: ABORT(); }}define_insn(PUTFIELD){ /* * ..., obj-ref, value -> ... */ check_pcidx (0); idx = (uint16)((getpc(0) << 8) | getpc(1)); trace_jcode (("putfield %d\n", idx)); get_field_info(idx); if (field_field() == 0) { softcall_nosuchfield(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(3); break; default: pop(2); break; } } else if (field_field()->accflags & ACC_STATIC) { softcall_incompatibleclasschange(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(3); break; default: pop(2); break; } } else if (((field_field()->accflags & ACC_FINAL) && ((field_class() != current_class()))) || !checkFieldAccess(current_class(), field_class(), field_field())) { softcall_illegalaccess(field_classname(), field_name()); switch (field_sig()->data[0]) { case 'J': case 'D': pop(3); break; default: pop(2); break; } } /* Use the proper store to increase the chances of the translator having the data in the right type of register already. */ else if (!FIELD_ISPRIM(field_field())) { check_stack_ref(1); check_null(PUTFIELD, rstack(1), 35); SOFT_ADDREFERENCE(rstack(1), rstack(0)); store_offset_ref(rstack(1), FIELD_BOFFSET(field_field()), rstack(0)); pop(2); } else switch (CLASS_PRIM_SIG(FIELD_TYPE(field_field()))) { case 'I': check_stack_ref(1); check_null(PUTFIELD, stack(1), 36); store_offset_int(stack(1), FIELD_BOFFSET(field_field()), stack(0)); pop(2); break; case 'S': check_stack_ref(1); check_null(PUTFIELD, stack(1), 37); store_offset_short(stack(1), FIELD_BOFFSET(field_field()), stack(0)); pop(2); break; case 'B': case 'Z': check_stack_ref(1); check_null(PUTFIELD, stack(1), 38); store_offset_byte(stack(1), FIELD_BOFFSET(field_field()), stack(0)); pop(2); break; case 'C': check_stack_ref(1); check_null(PUTFIELD, stack(1), 39); store_offset_char(stack(1), FIELD_BOFFSET(field_field()), stack(0)); pop(2); break; case 'F': check_stack_ref(1); check_null(PUTFIELD, stack(1), 40); store_offset_float(stack(1), FIELD_BOFFSET(field_field()), stack(0)); pop(2); break; case 'J': check_stack_ref(2); check_null(PUTFIELD, stack(2), 41); store_offset_long(stack(2), FIELD_BOFFSET(field_field()), stack_long(0)); pop(3); break; case 'D': check_stack_ref(2); check_null(PUTFIELD, stack(2), 42); store_offset_double(stack(2), FIELD_BOFFSET(field_field()), stack_double(0)); pop(3); break; default: ABORT(); }}#define METHOD_RETURN_VALUE() \do { \ /* Store the return type (if necessary) */ \ switch (low) { \ case 'V': \ break; \ case 'L': \ case '[': \ push(1); \ return_ref(stack(0)); \ break; \ case 'I': \ case 'Z': \ case 'S': \ case 'B': \ case 'C': \ push(1); \ return_int(stack(0)); \ break; \ case 'F': \ push(1); \ return_float(stack(0)); \ break; \ case 'J': \ push(2); \ return_long(stack_long(0)); \ break; \ case 'D': \ push(2); \ return_double(stack_double(0)); \ break; \ default: \ ABORT(); \ } \} while (0)define_insn(INVOKEVIRTUAL){ /* * ..., obj, ..args.., -> ... */ check_pcidx (0); idx = (uint16)((getpc(0) << 8) | getpc(1)); trace_jcode (("invokevirtual %d\n", idx)); get_method_info_noerror(idx); /* If class doesn't exist, call 'NoSuchClassError' */ if (method_class() == 0) { softcall_nosuchclass(method_classname()); low = method_returntype(); pop(method_nargs() + 1); METHOD_RETURN_VALUE(); } /* If method doesn't exist, call 'NoSuchMethodError' */ else if (method_method() == 0) { softcall_nosuchmethod(method_class(), method_name(), method_sig()); low = method_returntype(); pop(method_nargs() + 1); METHOD_RETURN_VALUE(); } else if (method_method()->accflags & ACC_STATIC) { softcall_incompatibleclasschange(method_classname(), method_name()); low = method_returntype(); pop(method_nargs() + 1); METHOD_RETURN_VALUE(); } else if (method_class()->accflags & ACC_INTERFACE) { softcall_incompatibleclasschange(method_classname(), method_name()); low = method_returntype(); pop(method_nargs() + 1); METHOD_RETURN_VALUE(); } else if (!checkMethodAccess(current_class(), method_class(), method_method())) { softcall_illegalaccess(method_classname(), method_name()); low = method_returntype(); pop(method_nargs() + 1); METHOD_RETURN_VALUE(); } else { int is_virtual = method_method()->idx >= 0; if (is_virtual) { slot_alloctmp(tmp); }#ifdef TRANSLATOR else { tmp = 0; /* for compiler warning */ }#endif idx = method_nargs(); check_null(INVOKEVIRTUAL, stack(idx), 34); check_stack_ref(idx); if( !is_virtual && METHOD_TRANSLATED(method_method()) && ( (void (*) (void)) (METHOD_NATIVECODE(method_method())) == soft_null_call) ) { idx += 1; pop(idx); } else { if (is_virtual) { /* Find dispatch table in object */ load_offset_ref(tmp, stack(idx), method_dtable_offset); /* Check method table for cached entry */ load_offset_ref(tmp, tmp, DTABLE_METHODOFFSET + method_idx() * DTABLE_METHODSIZE); } else { /* Explicitly check that object is non-null. * Implicitly done in the dispatch table * lookup. */ explicit_check_null(INVOKEVIRTUAL, stack(idx),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -