diff options
author | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-03-10 04:50:21 +0000 |
---|---|---|
committer | tromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-03-10 04:50:21 +0000 |
commit | 5922d6f0430e391b4c62f399b45ffbd641819af0 (patch) | |
tree | 3d84de36381d8c5b7296763dfb90dfd90f8e1a5f /libjava/verify.cc | |
parent | 7b3ac3407fcce2e911d526e1f022cdbe2f33da60 (diff) | |
download | gcc-5922d6f0430e391b4c62f399b45ffbd641819af0.tar.gz |
* verify.cc (state::NO_STACK): New constant.
(state::is_unmerged_ret_state): Handle case where stacktop is
NO_STACK.
(state::merge): Handle NO_STACK merges.
(handle_jsr_insn): Invalidate PC, and use special NO_STACK state
for instruction following jsr.
(stacktop, stackdepth): Removed unused variables.
(pop_jump): Ignore case where all remaining states are skipped.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@50526 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libjava/verify.cc')
-rw-r--r-- | libjava/verify.cc | 75 |
1 files changed, 53 insertions, 22 deletions
diff --git a/libjava/verify.cc b/libjava/verify.cc index 36dbcccb8d4..2fcfb607cc9 100644 --- a/libjava/verify.cc +++ b/libjava/verify.cc @@ -90,12 +90,6 @@ private: // be many `ret' instructions, so a linked list is ok. subr_entry_info *entry_points; - // The current top of the stack, in terms of slots. - int stacktop; - // The current depth of the stack. This will be larger than - // STACKTOP when wide types are on the stack. - int stackdepth; - // The bytecode itself. unsigned char *bytecode; // The exceptions. @@ -773,10 +767,10 @@ private: // location. struct state { - // Current top of stack. + // The current top of the stack, in terms of slots. int stacktop; - // Current stack depth. This is like the top of stack but it - // includes wide variable information. + // The current depth of the stack. This will be larger than + // STACKTOP when wide types are on the stack. int stackdepth; // The stack. type *stack; @@ -806,6 +800,11 @@ private: // NO_NEXT marks the state at the end of the reverification list. static const int NO_NEXT = -2; + // This is used to mark the stack depth at the instruction just + // after a `jsr' when we haven't yet processed the corresponding + // `ret'. See handle_jsr_insn for more information. + static const int NO_STACK = -1; + state () : this_type () { @@ -951,13 +950,29 @@ private: changed = true; } - // Merge stacks. - if (state_old->stacktop != stacktop) + // Merge stacks. Special handling for NO_STACK case. + if (state_old->stacktop == NO_STACK) + { + // Nothing to do in this case; we don't care about modifying + // the old state. + } + else if (stacktop == NO_STACK) + { + stacktop = state_old->stacktop; + stackdepth = state_old->stackdepth; + for (int i = 0; i < stacktop; ++i) + stack[i] = state_old->stack[i]; + changed = true; + } + else if (state_old->stacktop != stacktop) verifier->verify_fail ("stack sizes differ"); - for (int i = 0; i < state_old->stacktop; ++i) + else { - if (stack[i].merge (state_old->stack[i], false, verifier)) - changed = true; + for (int i = 0; i < state_old->stacktop; ++i) + { + if (stack[i].merge (state_old->stack[i], false, verifier)) + changed = true; + } } // Merge local variables. @@ -1048,6 +1063,8 @@ private: // Return true if this state is the unmerged result of a `ret'. bool is_unmerged_ret_state (int max_locals) const { + if (stacktop == NO_STACK) + return true; for (int i = 0; i < max_locals; ++i) { if (locals[i].key == unused_by_subroutine_type) @@ -1343,10 +1360,9 @@ private: npc = states[npc]->next; } - // If we've skipped states and there is nothing else, that's a - // bug. - if (skipped) - verify_fail ("pop_jump: can't happen"); + // Note that we might have gotten here even when there are + // remaining states to process. That can happen if we find a + // `jsr' without a `ret'. return state::NO_NEXT; } @@ -1450,12 +1466,10 @@ private: current_state->check_no_uninitialized_objects (current_method->max_locals, this); check_nonrecursive_call (current_state->subroutine, npc); - // 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. + // Modify our state as appropriate for entry into a subroutine. push_type (return_address_type); push_jump_merge (npc, current_state); - // Clean up the weirdness. + // Clean up. pop_type (return_address_type); // On entry to the subroutine, the subroutine number must be set @@ -1463,6 +1477,23 @@ private: // merging state so that we don't erroneously "notice" a variable // change merely on entry. states[npc]->enter_subroutine (npc, current_method->max_locals); + + // Indicate that we don't know the stack depth of the instruction + // following the `jsr'. The idea here is that we need to merge + // 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); + invalidate_pc (); } jclass construct_primitive_array_type (type_val prim) |