/*
* Copyright (c) 2007, 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.tele.method;
import java.lang.reflect.*;
import java.util.*;
import com.sun.max.annotate.*;
import com.sun.max.io.*;
import com.sun.max.program.*;
import com.sun.max.tele.*;
import com.sun.max.tele.field.*;
import com.sun.max.tele.field.VmFieldAccess.InspectedMemberReifier;
import com.sun.max.tele.method.CodeLocation.VmCodeLocationManager;
import com.sun.max.tele.object.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.actor.member.*;
import com.sun.max.vm.code.*;
import com.sun.max.vm.compiler.target.*;
import com.sun.max.vm.heap.*;
import com.sun.max.vm.runtime.*;
import com.sun.max.vm.tele.*;
import com.sun.max.vm.thread.*;
import com.sun.max.vm.type.*;
/**
* Singleton collection of access to specific methods in the VM.
* <p>
* The {@link INSPECTED} annotation is employed to denote methods that will be accessed remotely.
* A field of the appropriate {@link TeleMethodAccess} subtype is generated into this file
* by executing the {@link #main(String[])} method in this class (ensuring that the VM
* class path contains all the {@code com.sun.max} classes).
*/
public final class VmMethodAccess extends AbstractVmHolder implements MaxMethods {
private static final int TRACE_VALUE = 1;
private static VmMethodAccess vmMethodsAccess;
public static VmMethodAccess make(TeleVM vm, VmCodeLocationManager codeManager) {
if (vmMethodsAccess == null) {
vmMethodsAccess = new VmMethodAccess(vm, codeManager);
}
return vmMethodsAccess;
}
// Checkstyle: stop field name check
// START GENERATED CONTENT
public final TeleStaticMethodAccess Code_codePointerToTargetMethod = new TeleStaticMethodAccess(vm(), Code.class, "codePointerToTargetMethod", SignatureDescriptor.fromJava(TargetMethod.class, Pointer.class));
public final TeleStaticMethodAccess FatalError_breakpoint = new TeleStaticMethodAccess(vm(), FatalError.class, "breakpoint", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess FatalError_unexpected = new TeleStaticMethodAccess(vm(), FatalError.class, "unexpected", SignatureDescriptor.fromJava(FatalError.class, String.class, boolean.class, Throwable.class, Pointer.class));
public final TeleStaticMethodAccess CodeManager$Inspect_inspectableCodeEvictionCompleted = new TeleStaticMethodAccess(vm(), CodeManager.Inspect.class, "inspectableCodeEvictionCompleted", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess CodeManager$Inspect_inspectableCodeEvictionStarted = new TeleStaticMethodAccess(vm(), CodeManager.Inspect.class, "inspectableCodeEvictionStarted", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableDecreaseMemoryRequested = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableDecreaseMemoryRequested", SignatureDescriptor.fromJava(void.class, Size.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableGCCompleted = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableGCCompleted", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableGCReclaiming = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableGCReclaiming", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableGCStarting = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableGCStarting", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableIncreaseMemoryRequested = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableIncreaseMemoryRequested", SignatureDescriptor.fromJava(void.class, Size.class));
public final TeleStaticMethodAccess HeapScheme$Inspect_inspectableObjectRelocated = new TeleStaticMethodAccess(vm(), HeapScheme.Inspect.class, "inspectableObjectRelocated", SignatureDescriptor.fromJava(void.class, Address.class, Address.class));
public final TeleStaticMethodAccess InspectableCodeInfo_inspectableCodeEvictionCompleted = new TeleStaticMethodAccess(vm(), InspectableCodeInfo.class, "inspectableCodeEvictionCompleted", SignatureDescriptor.fromJava(void.class, CodeRegion.class));
public final TeleStaticMethodAccess InspectableCodeInfo_inspectableCodeEvictionStarted = new TeleStaticMethodAccess(vm(), InspectableCodeInfo.class, "inspectableCodeEvictionStarted", SignatureDescriptor.fromJava(void.class, CodeRegion.class));
public final TeleStaticMethodAccess InspectableCompilationInfo_inspectableCompilationCompleted = new TeleStaticMethodAccess(vm(), InspectableCompilationInfo.class, "inspectableCompilationCompleted", SignatureDescriptor.fromJava(void.class, String.class, String.class, String.class, TargetMethod.class));
public final TeleStaticMethodAccess InspectableCompilationInfo_inspectableCompilationStarted = new TeleStaticMethodAccess(vm(), InspectableCompilationInfo.class, "inspectableCompilationStarted", SignatureDescriptor.fromJava(void.class, String.class, String.class, String.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableDecreaseMemoryRequested = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableDecreaseMemoryRequested", SignatureDescriptor.fromJava(void.class, Size.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableGCAnalyzing = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableGCAnalyzing", SignatureDescriptor.fromJava(void.class, long.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableGCMutating = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableGCMutating", SignatureDescriptor.fromJava(void.class, long.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableGCReclaiming = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableGCReclaiming", SignatureDescriptor.fromJava(void.class, long.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableIncreaseMemoryRequested = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableIncreaseMemoryRequested", SignatureDescriptor.fromJava(void.class, Size.class));
public final TeleStaticMethodAccess InspectableHeapInfo_inspectableObjectRelocated = new TeleStaticMethodAccess(vm(), InspectableHeapInfo.class, "inspectableObjectRelocated", SignatureDescriptor.fromJava(void.class, Address.class, Address.class));
public final TeleStaticMethodAccess TargetBreakpoint_findOriginalCode = new TeleStaticMethodAccess(vm(), TargetBreakpoint.class, "findOriginalCode", SignatureDescriptor.fromJava(byte[].class, long.class));
public final TeleStaticMethodAccess VmThread_detached = new TeleStaticMethodAccess(vm(), VmThread.class, "detached", SignatureDescriptor.fromJava(void.class));
public final TeleStaticMethodAccess VmThread_run = new TeleStaticMethodAccess(vm(), VmThread.class, "run", SignatureDescriptor.fromJava(void.class, Pointer.class, Pointer.class, Pointer.class));
// END GENERATED CONTENT
// Checkstyle: resume field name check
private final CodeLocation compilationStarted;
private final CodeLocation compilationCompleted;
private final CodeLocation gcMutating;
private final CodeLocation gcAnalyzing;
private final CodeLocation gcReclaiming;
private final CodeLocation vmThreadRunning;
private final CodeLocation vmThreadDetached;
private final List<CodeLocation> clientInspectableMethods;
private VmMethodAccess(TeleVM vm, VmCodeLocationManager codeManager) {
super(vm);
// Uncomment to enable verifying that the generated content in this class is up to date when running the inspector
// updateSource(true);
// Note that for this to work correctly, the named methods must be compiled into the boot heap.
compilationStarted = codeManager.createMachineCodeLocation(InspectableCompilationInfo_inspectableCompilationStarted, "Compilation start (internal)");
compilationCompleted = codeManager.createMachineCodeLocation(InspectableCompilationInfo_inspectableCompilationCompleted, "Compilation complete (internal)");
gcMutating = codeManager.createMachineCodeLocation(InspectableHeapInfo_inspectableGCMutating, "GC completed (internal)");
gcAnalyzing = codeManager.createMachineCodeLocation(InspectableHeapInfo_inspectableGCAnalyzing, "GC starting (internal)");
gcReclaiming = codeManager.createMachineCodeLocation(InspectableHeapInfo_inspectableGCReclaiming, "GC reclaiming (internal)");
vmThreadRunning = codeManager.createMachineCodeLocation(VmThread_run, "VmThread running (internal) ");
vmThreadDetached = codeManager.createMachineCodeLocation(VmThread_detached, "VmThread detached (internal) ");
final List<CodeLocation> methods = new ArrayList<CodeLocation>();
methods.add(codeManager.createMachineCodeLocation(FatalError_breakpoint, "FatalError:breakpoint()"));
methods.add(codeManager.createMachineCodeLocation(FatalError_unexpected, "FatalError:unexpected()"));
methods.add(codeManager.createMachineCodeLocation(HeapScheme$Inspect_inspectableGCStarting, "Start of GC analyzing"));
methods.add(codeManager.createMachineCodeLocation(HeapScheme$Inspect_inspectableGCReclaiming, "Start of GC reclaiming"));
methods.add(codeManager.createMachineCodeLocation(HeapScheme$Inspect_inspectableGCCompleted, "End of GC"));
methods.add(codeManager.createMachineCodeLocation(HeapScheme$Inspect_inspectableObjectRelocated, "Object relocated"));
methods.add(codeManager.createMachineCodeLocation(CodeManager$Inspect_inspectableCodeEvictionStarted, "Start of Code Eviction"));
methods.add(codeManager.createMachineCodeLocation(CodeManager$Inspect_inspectableCodeEvictionCompleted, "End of Code Eviction"));
clientInspectableMethods = Collections.unmodifiableList(methods);
}
/**
* Identifies methods in the VM that can be offered to clients as convenient
* stopping places.
* <br>
* <strong>Note</strong>: a clear separation is made between methods that are only
* to be used by clients and those used by internal mechanisms.
*
* @return methods suitable for setting client-requested breakpoints.
*/
public List<CodeLocation> clientInspectableMethods() {
return clientInspectableMethods;
}
/**
* @return a VM method for internal (non-client) use that is called when a method compilation starts
*/
public CodeLocation compilationStartedMethodLocation() {
return compilationStarted;
}
/**
* @return a VM method for internal (non-client) use that is called when a method compilation finishes.
*/
public CodeLocation compilationCompletedMethodLocation() {
return compilationCompleted;
}
/**
* @return a VM method for internal (non-client) use that is called whenever a thread enter its run method (equivalent to whenever a new thread is running) .
*/
public CodeLocation vmThreadRunMethodLocation() {
return vmThreadRunning;
}
/**
* @return a VM method for internal (non-client) use that is called whenever a VmThread has detached itself from the active list.
*/
public CodeLocation vmThreadDetachedMethodLocation() {
return vmThreadDetached;
}
/**
* @return a VM method for internal (non-client) use that is called just after each GC starts,
* i.e. when it enters the {@link HeapPhase#ANALYZING} phase.
*/
public CodeLocation gcAnalyzingMethodLocation() {
return gcAnalyzing;
}
/**
* @return a VM method for internal (non-client) use that is called just after each GC starts
* reclaiming, i.e. when it enters the {@link HeapPhase#RECLAIMING} phase.
*/
public CodeLocation gcReclaimingMethodLocation() {
return gcReclaiming;
}
/**
* @return a VM method for internal (non-client) use that is called just after each GC end,
* i.e. when it enters the {@link HeapPhase#MUTATING}.
*/
public CodeLocation gcMutatingMethodLocation() {
return gcMutating;
}
public TeleClassMethodActor findClassMethodActor(MethodKey methodKey) {
if (vm().tryLock()) {
try {
final TeleClassActor teleClassActor = classes().findTeleClassActor(methodKey.holder());
if (teleClassActor != null) {
// the class has been loaded; find a matching method
for (TeleClassMethodActor teleClassMethodActor : teleClassActor.getTeleClassMethodActors()) {
MethodKey testMethodKey = new MethodKey.MethodActorKey(teleClassMethodActor.methodActor());
if (testMethodKey.equals(methodKey)) {
return teleClassMethodActor;
}
}
}
} finally {
vm().unlock();
}
}
return null;
}
public TeleMethodActor findMethodActor(MethodKey methodKey) {
if (vm().tryLock()) {
try {
final TeleClassActor teleClassActor = classes().findTeleClassActor(methodKey.holder());
if (teleClassActor != null) {
// the class has been loaded; find a matching method
for (TeleMethodActor teleMethodActor : teleClassActor.getTeleMethodActors()) {
MethodKey testMethodKey = new MethodKey.MethodActorKey(teleMethodActor.methodActor());
if (testMethodKey.equals(methodKey)) {
return teleMethodActor;
}
}
}
} finally {
vm().unlock();
}
}
return null;
}
public static void main(String[] args) {
Trace.begin(1, "VmMethods updating GENERATED CONTENT");
Trace.on(1);
Trace.end(1, "VmMethods updating GENERATED CONTENT");
updateSource(false);
}
private static String javaName(Class c) {
if (c.isArray()) {
return javaName(c.getComponentType()) + "[]";
}
return c.getSimpleName();
}
private static void updateSource(boolean inInspector) {
final InspectedMemberReifier<Method> methodReifier = new InspectedMemberReifier<Method>() {
public void reify(Method method, IndentWriter writer) {
final Class c = method.getDeclaringClass();
final boolean isStatic = Modifier.isStatic(method.getModifiers());
final String holder = c.getName().substring(c.getPackage().getName().length() + 1);
final String name = method.getName();
String sig = "SignatureDescriptor.fromJava(" + javaName(method.getReturnType()) + ".class";
for (Class p : method.getParameterTypes()) {
sig += ", " + javaName(p) + ".class";
}
sig += ")";
final String inspectorFieldName = holder + (name.charAt(0) == '_' ? name : '_' + name);
final String inspectorFieldType = "Tele" + (isStatic ? "Static" : "Virtual") + "MethodAccess";
writer.println("public final " + inspectorFieldType + " " + inspectorFieldName + " = new " + inspectorFieldType + "(vm(), " +
holder.replace('$', '.') + ".class, \"" + name + "\", " + sig + ");");
}
};
VmFieldAccess.updateSource(VmMethodAccess.class, Method.class, methodReifier, inInspector);
}
}