/*
* Copyright (c) 2011, 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.ins.object;
import java.util.*;
import javax.swing.event.*;
import com.sun.max.ins.*;
import com.sun.max.ins.gui.*;
import com.sun.max.ins.view.*;
import com.sun.max.ins.view.InspectionViews.ViewKind;
import com.sun.max.tele.*;
import com.sun.max.tele.heap.region.*;
import com.sun.max.tele.object.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.heap.gcx.*;
/**
* An object view specialized for {@link HeapRegionInfo} object. This adds a pane to the ObjectView for information derived from {@link HeapRegionInfo} fields to
* ease debugging regionalized heap management. In particular, the pane display the region's id, the start and end addresses for the region, and the address to its first
* free chunk, if there is one.
*/
public final class HeapRegionInfoView extends ObjectView<HeapRegionInfoView> {
private InspectorTabbedPane tabbedPane;
private ObjectScrollPane fieldsPane;
private InspectorScrollPane regionInfoPane;
private boolean alternateDisplay;
private static final ViewKind VIEW_KIND = ViewKind.HEAP_REGION_INFO;
private static final String SHORT_NAME = "Heap Region Info";
private static final String LONG_NAME = "Heap Region Info View";
public static final class HeapRegionInfoViewManager extends AbstractMultiViewManager<HeapRegionInfoView> {
private final InspectorAction interactiveViewRegionInfoByAddressAction;
private final InspectorAction interactiveViewRegionInfoByRegionIDAction;
private final List<InspectorAction> makeViewActions;
protected HeapRegionInfoViewManager(Inspection inspection) {
super(inspection, VIEW_KIND, SHORT_NAME, LONG_NAME);
makeViewActions = new ArrayList<InspectorAction>(1);
interactiveViewRegionInfoByAddressAction = new InspectorAction(inspection(), "View RegionInfo for address...") {
@Override
protected void procedure() {
new AddressInputDialog(inspection(), Address.zero(), "View RegionInfo for address...", "View") {
@Override
public void entered(Address address) {
MaxMemoryManagementInfo info = vm().heap().getMemoryManagementInfo(address);
// TODO: revisit this.
if (info.status().equals(MaxMemoryManagementStatus.LIVE)) {
final MaxObject object = info.tele();
focus().setHeapObject(object);
} else {
gui().errorMessage("Heap Region Info not found for address " + address.to0xHexString());
}
}
};
}
};
interactiveViewRegionInfoByRegionIDAction = new InspectorAction(inspection(), "View RegionInfo for region ID ...") {
@Override
protected void procedure() {
final String input = gui().inputDialog("View RegionInfo for region ID...", "0");
if (input == null) {
// User clicked cancel
return;
}
try {
final int regionID = Integer.parseInt(input);
if (TeleRegionTable.theTeleRegionTable().isValidRegionID(regionID)) {
Address regionInfoAddress = TeleRegionTable.theTeleRegionTable().regionInfo(regionID);
final MaxObject object = vm().objects().findObjectAt(regionInfoAddress);
if (object != null && object instanceof TeleHeapRegionInfo) {
focus().setHeapObject(object);
}
} else {
gui().errorMessage("Not a valid region ID" + input);
}
} catch (NumberFormatException numberFormatException) {
gui().errorMessage("Not a region ID: " + input);
} catch (MaxVMBusyException e) {
gui().errorMessage("VM Busy");
}
}
};
makeViewActions.add(interactiveViewRegionInfoByAddressAction);
makeViewActions.add(interactiveViewRegionInfoByRegionIDAction);
}
public InspectorAction makeViewAction(final MaxObject object, String actionTitle) {
return new InspectorAction(inspection(), actionTitle == null ? "View Heap Region Info" : actionTitle) {
@Override
protected void procedure() {
TeleHeapRegionInfo teleHeapRegionInfo = (TeleHeapRegionInfo) vm().heap().getMemoryManagementInfo(object.origin()).tele();
if (teleHeapRegionInfo != null) {
focus().setHeapObject(teleHeapRegionInfo);
}
}
};
}
@Override
protected List<InspectorAction> makeViewActions() {
return makeViewActions;
}
}
private static HeapRegionInfoViewManager viewManager;
public static HeapRegionInfoViewManager viewManager(Inspection inspection) {
if (viewManager == null) {
viewManager = new HeapRegionInfoViewManager(inspection);
}
return viewManager;
}
HeapRegionInfoView(Inspection inspection, MaxObject object) {
super(inspection, object);
alternateDisplay = true;
createFrame(true);
}
@Override
protected void createViewContent() {
super.createViewContent();
final TeleHeapRegionInfo teleHeapRegionInfo = (TeleHeapRegionInfo) object();
final String name = teleHeapRegionInfo.classActorForObjectType().javaSignature(false);
tabbedPane = new InspectorTabbedPane(inspection());
tabbedPane.setBackground(viewBackgroundColor());
fieldsPane = ObjectScrollPane.createTupleFieldsPane(inspection(), this);
tabbedPane.add(name, fieldsPane);
regionInfoPane = new HeapRegionInfoTable(inspection(), this, teleHeapRegionInfo).makeHeapRegionInfoPane();
tabbedPane.add("Region #" + teleHeapRegionInfo.regionID() + " info", regionInfoPane);
tabbedPane.setSelectedComponent(alternateDisplay ? regionInfoPane : fieldsPane);
tabbedPane.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent event) {
final Prober prober = (Prober) tabbedPane.getSelectedComponent();
// Remember which display is now selected
alternateDisplay = prober == regionInfoPane;
// Refresh the display that is now visible.
prober.refresh(true);
}
});
getContentPane().add(tabbedPane);
// Opportunity for view-specific Object menu
makeMenu(MenuKind.OBJECT_MENU).add(defaultMenuItems(MenuKind.OBJECT_MENU));
}
@Override
protected void refreshState(boolean force) {
super.refreshState(force);
tabbedPane.setBackground(viewBackgroundColor());
// Only refresh the visible pane.
final Prober prober = (Prober) tabbedPane.getSelectedComponent();
prober.refresh(force);
}
}