void BCEscapeAnalyzer::merge_block_states(StateInfo *blockstates, ciBlock *dest, StateInfo *s_state) { StateInfo *d_state = blockstates+dest->index(); int nlocals = _method->max_locals(); // exceptions may cause transfer of control to handlers in the middle of a // block, so we don't merge the incoming state of exception handlers if (dest->is_handler()) return; if (!d_state->_initialized ) { // destination not initialized, just copy for (int i = 0; i < nlocals; i++) { d_state->_vars[i] = s_state->_vars[i]; } for (int i = 0; i < s_state->_stack_height; i++) { d_state->_stack[i] = s_state->_stack[i]; } d_state->_stack_height = s_state->_stack_height; d_state->_max_stack = s_state->_max_stack; d_state->_initialized = true; } else if (!dest->processed()) { // we have not yet walked the bytecodes of dest, we can merge // the states assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); for (int i = 0; i < nlocals; i++) { d_state->_vars[i].set_union(s_state->_vars[i]); } for (int i = 0; i < s_state->_stack_height; i++) { d_state->_stack[i].set_union(s_state->_stack[i]); } } else { // the bytecodes of dest have already been processed, mark any // arguments in the source state which are not in the dest state // as global escape. // Future refinement: we only need to mark these variable to the // maximum escape of any variables in dest state assert(d_state->_stack_height == s_state->_stack_height, "computed stack heights must match"); ArgumentMap extra_vars; for (int i = 0; i < nlocals; i++) { ArgumentMap t; t = s_state->_vars[i]; t.set_difference(d_state->_vars[i]); extra_vars.set_union(t); } for (int i = 0; i < s_state->_stack_height; i++) { ArgumentMap t; t.clear(); t = s_state->_stack[i]; t.set_difference(d_state->_stack[i]); extra_vars.set_union(t); } set_global_escape(extra_vars); } }
StateInfo() { empty_map.clear(); }