List of usage examples for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_nop
byte OPC_nop
To view the source code for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_nop.
Click Source Link
From source file:org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer.java
License:Open Source License
/** * This method replaces all references to constantpool of the superclass with references * to current subclass constantpool/* w w w.jav a 2 s . co m*/ * - all References in codeToAdjust will be exchanged * - unknown references must be added to the ConstantPool of classFile * * @param dstClassFile This is the destination Classfile wich contains the later flushed ConstantPool * @param mModel the destination method * @param codeToAdjust this is the duplicated code-part of the code_attribute (see getCodeByteCode) * @param codeAttributeOffset attribute offset within codeToAdjust * @param codeLength length of codeToAdjust * @param isCtorAddingMarkArg are we copying into a tsuper ctor with additional marger arg? */ private void adjustCode(ClassFile dstClassFile, MethodModel mModel, byte[] codeToAdjust, int codeAttributeOffset, int codeLength, boolean isCtorAddingMarkArg) { /* * States concerning marker-arg chaining sequences: * (See class comment of class ExlicitConstructorCall for background information). * * 0 : do nothing * 1 : this is a ctor * 2 : saw aconst_null * 3 : saw astore_<n> : volatile state: immediately leave this state. * When in state 3 we immediately see a self call invokespecial * replace the chaining sequence and replace the method to call; * This heuristic is safe, since the sequence * "aconst_null; astore<n>; invokespecial" * could not be created from source-code. */ int state = 1; boolean initCachesAdded = false; int actualBytecodeStart = codeAttributeOffset + CODE_ATTR_PREFIX_LEN; for (int i = actualBytecodeStart; i < actualBytecodeStart + codeLength; i++) { //get byte from bytecode array byte b_int = codeToAdjust[i]; //get number of operands from Table int length = OTByteCodes.cpReferenceLength(b_int); // if byte code is followed by a reference into the cp if (length != 0) { //get reference from current code position -> a reference consist of one or more bytes int ref = OTByteCodes.getRef(length, codeToAdjust, i + 1); ConstantPoolObject src_cpo = this._reader.readConstantPoolObject(ref, length); ConstantPoolObject dst_cpo = this._mapper.mapConstantPoolObject(src_cpo, state == 3/*addMarkerArgAllowed*/); if (dst_cpo.isMethod()) { if (dst_cpo.isIllegallyCopiedCtor()) { // illegal ctor is actually used: report as error! AbstractMethodDeclaration methodDecl = mModel.getDecl(); methodDecl.scope.problemReporter().illegallyCopiedDefaultCtor(methodDecl, methodDecl.scope.referenceType()); return; } MethodBinding method = dst_cpo.getMethodRef(); if (state == 3) { if (isCtorAddingMarkArg && method.overriddenTSupers != null && method.isConstructor()) { // statemachine recognized full pattern for chaining marker arg. Patch now: MethodBinding tsuperVersion = findTSuperVersion(method); if (tsuperVersion != null) { replaceChainArg(codeToAdjust, i - 3); dst_cpo.setMethod(tsuperVersion); } } else if (method.parameters.length > src_cpo.getMethodRef().parameters.length) { if (method.copyInheritanceSrc != null) { // overwrite 2-byte astore_n: // as to leave preceding aconst_null on stack to match the tsuper-marker codeToAdjust[i - 2] = Opcodes.OPC_nop; codeToAdjust[i - 1] = Opcodes.OPC_nop; } } } } this._writer.writeConstantPoolObject(codeToAdjust, i + 1, length, dst_cpo); } else if (b_int == Opcodes.OPC_nop && mModel != null && mModel.liftedParams != null && mModel.liftedParams.length > 0) { int arg = checkPatchLiftingNops(codeToAdjust, i); if (arg >= 0) { // found a nop sequence to be patched (constant parts are already patched) ConstantPoolObject dst_cpo = null; int loadPos = arg & 0x1FFF; // bit 0x2000 flags (storePos > 3) if (!initCachesAdded) { // only insert once // find the _OT$initCaches method: dst_cpo = getInitCachesMethod(dstClassFile); if (dst_cpo != null) { // write the method reference into the nop space: this._writer.writeConstantPoolObject(codeToAdjust, i + 2, 2, dst_cpo); } initCachesAdded = true; } if (dst_cpo == null) { codeToAdjust[i + 1] = Opcodes.OPC_nop; // delete invokevirtual // Note: aload_0 and pop are already balanced } int offset = (loadPos > 3) ? 1 : 0; // longer byte code used for aload? // find the lift method: dst_cpo = getLiftMethod(dstClassFile, mModel, loadPos); if (dst_cpo == null) return; // cannot perform required lifting // write the method reference into the nop space: this._writer.writeConstantPoolObject(codeToAdjust, i + offset + 8, 2, dst_cpo); // call sequence had two additional loads, reserve space on the stack: incrementWord(codeToAdjust, codeAttributeOffset, 6, 2); // max_stack++ length = 10 + offset; if ((arg & 0x2000) != 0) // longer byte code used for astore? length++; } } // state machine: if (state == 1 && b_int == Opcodes.OPC_aconst_null) state = 2; else if (state == 2 && b_int == Opcodes.OPC_astore) state = 3; else if (state == 3) state = 0; // patch sequence not followed by self call: quit state machine. i += length; // also skip parameters, which are not CP-index i += OTByteCodes.getParamLength(b_int, codeToAdjust, i, actualBytecodeStart); } }
From source file:org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer.java
License:Open Source License
/** Look for the nop pattern of a local var that is used to * prepare for lifting. If the pattern is found, patch all those * opcodes, that are constant (see class comment in Lifting). *//*ww w . j a v a 2s .com*/ private int checkPatchLiftingNops(byte[] code, int idx) { int i; // Expecting 6 nops: for (i = idx + 1; i < idx + 6; i++) if (code[i] != Opcodes.OPC_nop) return -1; // Expecting aload_<loadPos>: int loadPos = OTByteCodes.getAloadPos(code[idx + 6], code[idx + 7]); if (loadPos == -1) return -1; int storeStart = (loadPos > 3) ? 8 : 7; // depends on space for pos operand // Expecting 3 nops: for (i = idx + storeStart; i < idx + storeStart + 3; i++) if (code[i] != Opcodes.OPC_nop) return -1; // Expecting astore_<storePos>: int storePos = OTByteCodes.getAstorePos(code[idx + 10], code[idx + 11]); if (storePos == -1) return -1; // Full match, start patching: // patching 6 nops: code[idx + 0] = Opcodes.OPC_aload_0; code[idx + 1] = Opcodes.OPC_invokevirtual; // [idx+2/3]: space for "_OT$initCaches" code[idx + 4] = Opcodes.OPC_pop; code[idx + 5] = Opcodes.OPC_aload_0; // leave aload<loadPos> if (loadPos > 3) idx++; // patching 3 nops: code[idx + 7] = Opcodes.OPC_invokevirtual; // [idx+8/9]: space for _OT$liftTo<Role> // leave astore<storePos> if (storePos > 3) loadPos += 0x2000; // flag to client that longer byte code is used return loadPos; }
From source file:org.eclipse.objectteams.otdt.internal.core.compiler.bytecode.BytecodeTransformer.java
License:Open Source License
/** Perform changes to code sequence produced by addChainingPlaceholder(). */ private void replaceChainArg(byte[] codeToAdjust, int idx) { codeToAdjust[idx] = Opcodes.OPC_nop; codeToAdjust[idx + 1] = Opcodes.OPC_aload; // argument to aload remains unchanged from astore }