All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.lib.profiler.instrumentation.DynamicConstantPoolExtension Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.lib.profiler.instrumentation;

import org.netbeans.lib.profiler.classfile.DynamicClassInfo;
import org.netbeans.lib.profiler.global.CommonConstants;


/**
 * Support for adding multiple different fragments to a class's constant pool, that also keeps track of whether
 * a particular fragment has already been added to this class or not.
 * The main API call for this class is getCPFragment, that returns a relocated (i.e. with indices adjusted for a concrete
 * given class) copy of added constant pool for particular injection type defined in JFluid. Once this operation is
 * performed, the information is registered in the corresponding ClassInfo (it is assumed that a real class in the JVM is
 * actually instrumented by adding this cpool fragment). Thus if subsequently for this class the constant pool fragment
 * for the same injection type is requested again, an empty result is returned.
 *
 * When performing actual method instrumentation (bytecode rewriting), use cpool indices of injected methods defined as
 * public static variables in CPExtensionsRepository. These variables need to be adjusted for the base cpool count value
 * for the given class/injection type.
 *
 * @author Misha Dmitriev
 */
public class DynamicConstantPoolExtension extends ConstantPoolExtension implements CommonConstants {
    //~ Static fields/initializers -----------------------------------------------------------------------------------------------

    //------------------------------------------ Private implementation -------------------------------------------------
    private static DynamicConstantPoolExtension emptyECP = new DynamicConstantPoolExtension();

    //~ Instance fields ----------------------------------------------------------------------------------------------------------

    protected DynamicClassInfo clazz;

    //~ Constructors -------------------------------------------------------------------------------------------------------------

    protected DynamicConstantPoolExtension(DynamicClassInfo clazz, int injectionType, int baseCPCount, int secondaryCPCount) {
        super(CPExtensionsRepository.getStandardCPFragment(injectionType), baseCPCount, secondaryCPCount);
        this.clazz = clazz;
    }

    protected DynamicConstantPoolExtension() {
    }

    //~ Methods ------------------------------------------------------------------------------------------------------------------

    /**
     * Re-create the whole appended constant pool chunk out of (possibly several) fragments added for different
     * kinds of instrumentation at possibly different times.
     */
    public static DynamicConstantPoolExtension getAllAddedCPFragments(DynamicClassInfo clazz) {
        DynamicConstantPoolExtension res = new DynamicConstantPoolExtension(); // Equivalent of emptyECP
        int lowerBaseCPCountBound = 0;
        int baseCPCLen = clazz.getBaseCPoolCountLen();

        for (int j = 0; j < baseCPCLen; j++) {
            int minBaseCPCount = 0xFFFFFFF;
            int cpFragmentIdx = -1;

            // Find the CP fragment with the minimum base index, that hasn't been used yet
            for (int i = 0; i < baseCPCLen; i++) {
                int curCPCount = clazz.getBaseCPoolCount(i);

                if (curCPCount != -1) {
                    if ((curCPCount > lowerBaseCPCountBound) && (curCPCount < minBaseCPCount)) {
                        minBaseCPCount = curCPCount;
                        cpFragmentIdx = i;
                    }
                }
            }

            // If such a fragment exists, append it to the result. Otherwise return the final result.
            if (cpFragmentIdx != -1) {
                DynamicConstantPoolExtension res1 = newDynamicCPExtension(clazz, cpFragmentIdx,
                                                                          clazz.getBaseCPoolCount(cpFragmentIdx));
                res.addedCPContents = res.getConcatenatedContents(res1); // Don't change res contents, because initially it's emptyECP
                res.nAddedEntries += res1.nAddedEntries;
                lowerBaseCPCountBound = minBaseCPCount;
            } else {
                return res;
            }
        }

        return res;
    }

    public static DynamicConstantPoolExtension getCPFragment(DynamicClassInfo clazz, int injType) {
        if (clazz.getBaseCPoolCount(injType) != -1) {
            return emptyECP; // clazz's cpool already extended for this instrumentation type
        } else {
            int currentCPCount = clazz.getCurrentCPoolCount();
            DynamicConstantPoolExtension ecp = newDynamicCPExtension(clazz, injType, currentCPCount);
            clazz.setBaseCPoolCount(injType, currentCPCount);
            clazz.setCurrentCPoolCount(currentCPCount + ecp.nAddedEntries);

            return ecp;
        }
    }

    public static DynamicConstantPoolExtension getEmptyCPFragment() {
        return emptyECP;
    }

    //-------------------------------------------- Protected methods ---------------------------------------------------
    protected static DynamicConstantPoolExtension newDynamicCPExtension(DynamicClassInfo clazz, int injectionType, int baseCPCount) {
        int secondaryCPCount = 0;

        switch (injectionType) {
            case INJ_RECURSIVE_ROOT_METHOD:
            case INJ_RECURSIVE_MARKER_METHOD:
                secondaryCPCount = clazz.getBaseCPoolCount(INJ_RECURSIVE_NORMAL_METHOD);

                break;
            case INJ_RECURSIVE_SAMPLED_ROOT_METHOD:
            case INJ_RECURSIVE_SAMPLED_MARKER_METHOD:
                secondaryCPCount = clazz.getBaseCPoolCount(INJ_RECURSIVE_SAMPLED_NORMAL_METHOD);

                break;
        }

        return new DynamicConstantPoolExtension(clazz, injectionType, baseCPCount, secondaryCPCount);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy