/** 12.6.4 end of loop of 'for-in' statement. */ @Override public void visit(EndForInNode n, State state) { if (!Options.get().isForInSpecializationDisabled()) { if (!c.isScanning()) { // 1. Find successor block, context and base-state BasicBlock successor = state.getBasicBlock().getSingleSuccessor(); for (Pair<NodeAndContext<Context>, Context> ncc : c.getAnalysisLatticeElement() .getCallGraph() .getSources(BlockAndContext.makeEntry(n.getBlock(), state.getContext()))) { State nonSpecializedMergeState = state.clone(); Context nonSpecializedContext = ncc.getFirst().getContext(); // 2. Use State.mergeFunctionReturn to do the merge State forInBeginState = c.getAnalysisLatticeElement() .getState( n.getBlock().getEntryBlock().getEntryPredecessorBlock(), nonSpecializedContext); State forInEntryState = c.getAnalysisLatticeElement() .getState(n.getBlock().getEntryBlock(), state.getContext()); Value returnValue = nonSpecializedMergeState.mergeFunctionReturn( forInBeginState, forInBeginState, forInEntryState, nonSpecializedMergeState.getSummarized(), nonSpecializedMergeState.readRegister(AbstractNode.RETURN_REG)); nonSpecializedMergeState.setContext(nonSpecializedContext); nonSpecializedMergeState.writeRegister(AbstractNode.RETURN_REG, returnValue); if (state.hasExceptionRegisterValue()) { nonSpecializedMergeState.writeRegister( AbstractNode.EXCEPTION_REG, state.readRegister(AbstractNode.EXCEPTION_REG)); } // 3. Propagate only to the non-specialized successor nonSpecializedMergeState.setBasicBlock(n.getBlock().getSingleSuccessor()); c.propagateToBasicBlock(nonSpecializedMergeState, successor, nonSpecializedContext); } state.setToNone(); } } }
/** Transfer ordinary and exceptional return for the given call node and callee entry. */ public void transferReturn( AbstractNode call_node, BasicBlock callee_entry, Context caller_context, Context callee_context, Context edge_context) { if (call_node instanceof BeginForInNode) { for (EndForInNode endNode : ((BeginForInNode) call_node).getEndNodes()) { BasicBlock end_block = endNode.getBlock(); if (c.getAnalysisLatticeElement().getState(end_block, callee_context) != null) // (EndForInNode uses same context as corresponding BeginForInNode) c.addToWorklist(end_block, callee_context); } } else { // call_node is an ordinary call node Function callee = callee_entry.getFunction(); BasicBlock ordinary_exit = callee.getOrdinaryExit(); BasicBlock exceptional_exit = callee.getExceptionalExit(); State ordinary_exit_state = c.getAnalysisLatticeElement() .getState( ordinary_exit, callee_context); // (ReturnNode uses same context as corresponding function entry // node) State exceptional_exit_state = c.getAnalysisLatticeElement().getState(exceptional_exit, callee_context); NodeAndContext<Context> caller = new NodeAndContext<>(call_node, caller_context); if (ordinary_exit_state != null) { if (ordinary_exit.getFirstNode() instanceof ReturnNode) { ReturnNode returnNode = (ReturnNode) ordinary_exit.getFirstNode(); transferReturn( returnNode.getReturnValueRegister(), ordinary_exit, ordinary_exit_state.clone(), caller, edge_context); } else throw new AnalysisException("ReturnNode expected"); } if (exceptional_exit_state != null) { transferExceptionalReturn( exceptional_exit, exceptional_exit_state.clone(), caller, edge_context); } } }