/* * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.vm.profile; import com.sun.max.annotate.*; import com.sun.max.unsafe.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.actor.member.*; import com.sun.max.vm.code.*; import com.sun.max.vm.compiler.*; /** * This class contains several utility methods for dealing with method instrumentation. */ public class MethodInstrumentation { public static int initialEntryCount = 5000; public static final int DEFAULT_RECEIVER_METHOD_PROFILE_ENTRIES = 3; /** * Methods whose invocation count (entry count) is within 90 % of the recompilation threshold * (see {@link #initialEntryCount}), are protected from {@linkplain CodeEviction code eviction}. */ public static final double PROTECTION_PERCENTAGE = 0.9; public static int protectionThreshold = (int) (1 - PROTECTION_PERCENTAGE) * initialEntryCount; private static boolean enabled; public static void enable(int initialEntryCount) { enabled = true; MethodInstrumentation.initialEntryCount = initialEntryCount; MethodInstrumentation.protectionThreshold = (int) (1 - PROTECTION_PERCENTAGE) * initialEntryCount; } public static MethodProfile.Builder createMethodProfile(ClassMethodActor classMethodActor) { if (enabled) { return new MethodProfile.Builder(); } return null; } @NEVER_INLINE public static void recordType(MethodProfile mpo, Hub hub, int mpoIndex, int entries) { findAndIncrement(mpo, mpoIndex, entries, hub.classActor.id); } @NEVER_INLINE public static void recordReceiver(MethodProfile mpo, Word entrypoint, int mpoIndex, int entries) { findAndIncrement(mpo, mpoIndex, entries, entrypoint.asOffset().toInt()); } @INLINE public static void recordEntrypoint(MethodProfile mpo, Object receiver) { if (--mpo.entryCount <= 0) { CompilationBroker.instrumentationCounterOverflow(mpo, receiver); } } @INLINE public static void recordBackwardBranch(MethodProfile mpo) { mpo.entryCount--; } @INLINE private static void findAndIncrement(MethodProfile mpo, int index, int entries, int id) { int[] data = mpo.rawData(); int max = index + entries * 2; for (int i = index; i < max; i += 2) { if (data[i] == id) { // this entry matches data[i + 1]++; return; } else if (data[i] == 0) { // this entry is empty data[i] = id; data[i + 1] = 1; return; } } // failed to find matching entry, increment default data[index + entries * 2 + 1]++; } public static Hub computeMostFrequentHub(MethodProfile mpo, int bci, int threshold, float ratio) { if (mpo != null) { Integer[] hubProfile = mpo.getTypeProfile(bci); if (hubProfile != null) { int total = 0; for (int i = 0; i < hubProfile.length; i++) { // count up the total of all entries Integer hubId = hubProfile[i]; Integer count = hubProfile[i + 1]; if (hubId != null && count != null) { total += count; } } if (total >= threshold) { // if there are enough recorded entries int thresh = (int) (ratio * total); for (int i = 0; i < hubProfile.length; i++) { Integer hubId = hubProfile[i]; Integer count = hubProfile[i + 1]; if (hubId != null && count != null && count >= thresh) { return idToHub(hubId); } } } } } return null; } private static Hub idToHub(Integer hubId) { if (hubId != null && hubId > 0) { // TODO: convert hub id to hub } return null; } }