From: tromey Date: Fri, 1 Feb 2002 05:48:00 +0000 (+0000) Subject: * verify.cc (state::enter_subroutine): New method. X-Git-Tag: upstream/4.9.2~88997 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cc6ebd51e79ad82a2b2252e312c58fe5f6ab50f0;p=platform%2Fupstream%2Flinaro-gcc.git * verify.cc (state::enter_subroutine): New method. (handle_jsr_insn): Use it. (state::merge): When processing a `ret', correctly use subroutine's state to determine which local variables have changed. (push_exception_jump): Don't let stack overflow. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@49388 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/libjava/ChangeLog b/libjava/ChangeLog index ffdf432..45cab38 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,12 @@ +2002-01-31 Tom Tromey + + * verify.cc (state::enter_subroutine): New method. + (handle_jsr_insn): Use it. + (state::merge): When processing a `ret', correctly use + subroutine's state to determine which local variables have + changed. + (push_exception_jump): Don't let stack overflow. + 2002-01-31 Joseph S. Myers * gnu/gcj/convert/Convert.java: Only include one copyright year in diff --git a/libjava/verify.cc b/libjava/verify.cc index 1035cda..c9cfb88 100644 --- a/libjava/verify.cc +++ b/libjava/verify.cc @@ -891,6 +891,18 @@ private: // FIXME: subroutine handling? } + // Modify this state to reflect entry into a subroutine. + void enter_subroutine (int npc, int max_locals) + { + subroutine = npc; + // Mark all items as unchanged. Each subroutine needs to keep + // track of its `changed' state independently. In the case of + // nested subroutines, this information will be merged back into + // parent by the `ret'. + for (int i = 0; i < max_locals; ++i) + local_changed[i] = false; + } + // Merge STATE_OLD into this state. Destructively modifies this // state. Returns true if the new state was in fact changed. // Will throw an exception if the states are not mergeable. @@ -936,7 +948,12 @@ private: // Merge local variables. for (int i = 0; i < max_locals; ++i) { - if (! ret_semantics || local_changed[i]) + // If we're not processing a `ret', then we merge every + // local variable. If we are processing a `ret', then we + // only merge locals which changed in the subroutine. When + // processing a `ret', STATE_OLD is the state at the point + // of the `ret', and THIS is the state just after the `jsr'. + if (! ret_semantics || state_old->local_changed[i]) { if (locals[i].merge (state_old->locals[i], true, verifier)) { @@ -1264,6 +1281,8 @@ private: this, true); state s (current_state, current_method->max_stack, current_method->max_locals); + if (current_method->max_stack < 1) + verify_fail ("stack overflow at exception handler"); s.set_exception (t, current_method->max_stack); push_jump_merge (pc, &s); } @@ -1401,18 +1420,19 @@ private: current_state->check_no_uninitialized_objects (current_method->max_locals, this); check_nonrecursive_call (current_state->subroutine, npc); - // Temporarily modify the current state so that it looks like we are - // in the subroutine. + // Create a new state and modify it as appropriate for entry into + // a subroutine. We're writing this in a weird way because, + // unfortunately, push_type only works on the current state. push_type (return_address_type); - int save = current_state->subroutine; - current_state->subroutine = npc; - - // Merge into the subroutine. push_jump_merge (npc, current_state); - - // Undo our modifications. - current_state->subroutine = save; + // Clean up the weirdness. pop_type (return_address_type); + + // On entry to the subroutine, the subroutine number must be set + // and the locals must be marked as cleared. We do this after + // merging state so that we don't erroneously "notice" a variable + // change merely on entry. + states[npc]->enter_subroutine (npc, current_method->max_locals); } jclass construct_primitive_array_type (type_val prim)