return r;
}
- type pop64 ()
- {
- type r = pop_raw ();
- if (! r.iswide ())
- verify_fail ("wide pop of narrow type");
- return r;
- }
-
type pop_type (type match)
{
match.promote ();
for (subr_info *subr = jsr_ptrs[csub]; subr != NULL; subr = subr->next)
{
+ // We might be returning to a `jsr' that is at the end of the
+ // bytecode. This is ok if we never return from the called
+ // subroutine, but if we see this here it is an error.
+ if (subr->pc >= current_method->code_length)
+ verify_fail ("fell off end");
+
// Temporarily modify the current state so it looks like we're
// in the enclosing context.
current_state->subroutine = get_subroutine (subr->pc);
// the local variable state across the jsr, but the subroutine
// might change the stack depth, so we can't make any assumptions
// about it. So we have yet another special case. We know that
- // at this point PC points to the instruction after the jsr.
-
- // FIXME: what if we have a jsr at the end of the code, but that
- // jsr has no corresponding ret? Is this verifiable, or is it
- // not? If it is then we need a special case here.
- if (PC >= current_method->code_length)
- verify_fail ("fell off end");
-
- current_state->stacktop = state::NO_STACK;
- push_jump_merge (PC, current_state);
+ // at this point PC points to the instruction after the jsr. Note
+ // that it is ok to have a `jsr' at the end of the bytecode,
+ // provided that the called subroutine never returns. So, we have
+ // a special case here and another one when we handle the ret.
+ if (PC < current_method->code_length)
+ {
+ current_state->stacktop = state::NO_STACK;
+ push_jump_merge (PC, current_state);
+ }
invalidate_pc ();
}
bool initialize_stack ()
{
int var = 0;
- bool is_init = false;
+ bool is_init = _Jv_equalUtf8Consts (current_method->self->name,
+ gcj::init_name);
+ bool is_clinit = _Jv_equalUtf8Consts (current_method->self->name,
+ gcj::clinit_name);
using namespace java::lang::reflect;
if (! Modifier::isStatic (current_method->self->accflags))
{
type kurr (current_class);
- if (_Jv_equalUtf8Consts (current_method->self->name, gcj::init_name))
+ if (is_init)
{
kurr.set_uninitialized (type::SELF, this);
is_init = true;
}
+ else if (is_clinit)
+ verify_fail ("<clinit> method must be static");
set_variable (0, kurr);
current_state->set_this_type (kurr);
++var;
}
+ else
+ {
+ if (is_init)
+ verify_fail ("<init> method must be non-static");
+ }
// We have to handle wide arguments specially here.
int arg_count = _Jv_count_arguments (current_method->self->signature);
pop32 ();
break;
case op_pop2:
- pop64 ();
+ {
+ type t = pop_raw ();
+ if (! t.iswide ())
+ pop32 ();
+ }
break;
case op_dup:
{