private Merge ( int locals, int localsTop, int stack, int stackTop, |
||
locals | int | |
localsTop | int | |
stack | int | |
stackTop | int | |
pool | ||
리턴 | bool |
/// <summary> /// Perform a merge of type state and add the super block to the work /// list if the merge changed anything. /// </summary> /// <remarks> /// Perform a merge of type state and add the super block to the work /// list if the merge changed anything. /// </remarks> private void FlowInto(SuperBlock sb) { if (sb.Merge(this.locals, this.localsTop, this.stack, this.stackTop, this._enclosing.itsConstantPool)) { this.AddToWorkList(sb); } }
/// <summary>Replace the contents of a super block with no-ops.</summary> /// <remarks> /// Replace the contents of a super block with no-ops. /// The above description is not strictly true; the last instruction is /// an athrow instruction. This technique is borrowed from ASM's /// developer guide: http://asm.ow2.org/doc/developer-guide.html#deadcode /// The proposed algorithm fills a block with nop, ending it with an /// athrow. The stack map generated would be empty locals with an /// exception on the stack. In theory, it shouldn't matter what the /// locals are, as long as the stack has an exception for the athrow bit. /// However, it turns out that if the code being modified falls into an /// exception handler, it causes problems. Therefore, if it does, then /// we steal the locals from the exception block. /// If the block itself is an exception handler, we remove it from the /// exception table to simplify block dependencies. /// </remarks> private void KillSuperBlock(SuperBlock sb) { int[] locals = new int[0]; int[] stack = new int[] { TypeInfo.OBJECT("java/lang/Throwable", this._enclosing.itsConstantPool) }; // If the super block is handled by any exception handler, use its // locals as the killed block's locals. Ignore uninitialized // handlers, because they will also be killed and removed from the // exception table. for (int i = 0; i < this._enclosing.itsExceptionTableTop; i++) { ExceptionTableEntry ete = this._enclosing.itsExceptionTable[i]; int eteStart = this._enclosing.GetLabelPC(ete.itsStartLabel); int eteEnd = this._enclosing.GetLabelPC(ete.itsEndLabel); int handlerPC = this._enclosing.GetLabelPC(ete.itsHandlerLabel); SuperBlock handlerSB = this.GetSuperBlockFromOffset(handlerPC); if ((sb.GetStart() > eteStart && sb.GetStart() < eteEnd) || (eteStart > sb.GetStart() && eteStart < sb.GetEnd()) && handlerSB.IsInitialized()) { locals = handlerSB.GetLocals(); break; } } // Remove any exception table entry whose handler is the killed // block. This removes block dependencies to make stack maps for // dead blocks easier to create. for (int i_1 = 0; i_1 < this._enclosing.itsExceptionTableTop; i_1++) { ExceptionTableEntry ete = this._enclosing.itsExceptionTable[i_1]; int eteStart = this._enclosing.GetLabelPC(ete.itsStartLabel); if (eteStart == sb.GetStart()) { for (int j = i_1 + 1; j < this._enclosing.itsExceptionTableTop; j++) { this._enclosing.itsExceptionTable[j - 1] = this._enclosing.itsExceptionTable[j]; } this._enclosing.itsExceptionTableTop--; i_1--; } } sb.Merge(locals, locals.Length, stack, stack.Length, this._enclosing.itsConstantPool); int end = sb.GetEnd() - 1; this._enclosing.itsCodeBuffer[end] = unchecked((byte)ByteCode.ATHROW); for (int bci = sb.GetStart(); bci < end; bci++) { this._enclosing.itsCodeBuffer[bci] = unchecked((byte)ByteCode.NOP); } }