Example usage for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_astore

List of usage examples for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_astore

Introduction

In this page you can find the example usage for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_astore.

Prototype

byte OPC_astore

To view the source code for org.eclipse.jdt.internal.compiler.codegen Opcodes OPC_astore.

Click Source Link

Usage

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/*from w  w w  .  jav a  2 s.  com*/
 *  - 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);
    }

}