/*
* 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.vm.code;
import java.lang.management.*;
import com.sun.max.annotate.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.*;
import com.sun.max.vm.compiler.target.*;
import com.sun.max.vm.heap.*;
import com.sun.max.vm.management.*;
import com.sun.max.vm.runtime.*;
/**
* Utilities for managing target code. This class offers a number of services
* for allocating and managing the target code regions. It also offers a static
* facade that hides the details of operations such as finding a target method
* by a code address, allocating space for a new target method, etc.
*/
public final class Code {
private Code() {
}
static boolean TraceCodeAllocation;
static {
VMOptions.addFieldOption("-XX:", "TraceCodeAllocation", "Trace allocation from the code cache.");
}
/**
* Used by the Inspector to uniquely identify the special boot code region.
*/
@INSPECTED
private static final String CODE_BOOT_NAME = "Code-Boot";
/**
* The code region that contains the boot code.
*/
@INSPECTED
@CONSTANT_WHEN_NOT_ZERO
private static CodeRegion bootCodeRegion = new CodeRegion(Address.fromInt(Integer.MAX_VALUE / 2).wordAligned(), Size.fromInt(Integer.MAX_VALUE / 4), CODE_BOOT_NAME);
/**
* The code manager singleton instance.
*/
@INSPECTED
private static final CodeManager codeManager = VMConfiguration.vmConfig().heapScheme().createCodeManager();
public static CodeManager getCodeManager() {
return codeManager;
}
/**
* Initializes the code manager and {@link CodePointer} base address.
*/
public static void initialize() {
codeManager.initialize();
CodePointer.initialize(bootCodeRegion.start());
}
/**
* Allocates space in a code region for the code-related arrays of a given target method
* and {@linkplain TargetMethod#setCodeArrays(byte[], Pointer, byte[], Object[]) initializes} them.
*
* @param targetBundleLayout describes the layout of the arrays in the allocate space
* @param targetMethod the target method for which the code-related arrays are allocated
*/
public static void allocate(TargetBundleLayout targetBundleLayout, TargetMethod targetMethod) {
codeManager.allocate(targetBundleLayout, targetMethod, false, targetMethod.lifespan());
}
/**
* Allocates space in the heap for the code-related arrays of a given target method
* and {@linkplain TargetMethod#setCodeArrays(byte[], Pointer, byte[], Object[]) initializes} them.
* The target method cannot be executed. This option exists for the purpose of testing
* or benchmarking a compiler at runtime without polluting the code cache.
*
* @param targetBundleLayout describes the layout of the arrays in the allocate space
* @param targetMethod the target method for which the code-related arrays are allocated
*/
public static void allocateInHeap(TargetBundleLayout targetBundleLayout, TargetMethod targetMethod) {
codeManager.allocate(targetBundleLayout, targetMethod, true, targetMethod.lifespan());
}
/**
* Determines whether any code region contains the specified address.
*
* @param address the address to check
* @return {@code true} if the specified address is contained in some code region
* managed by the code manager; {@code false} otherwise
*/
public static boolean contains(Address address) {
return codeManager.codePointerToCodeRegion(address) != null;
}
/**
* Looks up the target method that contains the specified code pointer.
*
* @param codePointer a pointer to code
* @return a reference to the target method that contains the specified code pointer, if
* one exists; {@code null} otherwise
*/
@INSPECTED
public static TargetMethod codePointerToTargetMethod(Pointer codePointer) {
boolean wasDisabled = SafepointPoll.disable();
TargetMethod result = codeManager.codePointerToTargetMethod(codePointer);
if (!wasDisabled) {
SafepointPoll.enable();
}
return result;
}
/**
* Removes a target method from this code manager, freeing its space when it is safe to do so.
*
* @param targetMethod the target method to discard
*/
public static void discardTargetMethod(TargetMethod targetMethod) {
// do nothing.
}
/**
* Visits each cell that is managed by the code manager.
*
* @param cellVisitor the cell visitor to call back for each cell
* @param includeBootCode specifies if the cells in the {@linkplain Code#bootCodeRegion() boot code region} should
* also be visited
*/
public static void visitCells(CellVisitor cellVisitor, boolean includeBootCode) {
codeManager.visitCells(cellVisitor, includeBootCode);
}
public static Size getRuntimeCodeRegionSize() {
return codeManager.getRuntimeBaselineCodeRegionSize().plus(codeManager.getRuntimeOptCodeRegionSize());
}
public static MemoryManagerMXBean getMemoryManagerMXBean() {
return new CodeMemoryManagerMXBean("Code");
}
public static CodeRegion bootCodeRegion() {
return bootCodeRegion;
}
@HOSTED_ONLY
public static void resetBootCodeRegion() {
bootCodeRegion = new CodeRegion(bootCodeRegion.start(), bootCodeRegion.size(), bootCodeRegion.regionName());
}
private static class CodeMemoryManagerMXBean extends MemoryManagerMXBeanAdaptor {
CodeMemoryManagerMXBean(String name) {
super(name);
add(new CodeMemoryPoolMXBean(bootCodeRegion(), this));
add(new CodeMemoryPoolMXBean(codeManager.getRuntimeBaselineCodeRegion(), this));
add(new CodeMemoryPoolMXBean(codeManager.getRuntimeOptCodeRegion(), this));
}
}
private static class CodeMemoryPoolMXBean extends MemoryPoolMXBeanAdaptor {
CodeMemoryPoolMXBean(CodeRegion codeRegion, MemoryManagerMXBean manager) {
super(MemoryType.NON_HEAP, codeRegion, manager);
}
}
}