/* * 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.object; import java.lang.reflect.*; import com.sun.max.lang.*; import com.sun.max.tele.*; import com.sun.max.tele.reference.*; import com.sun.max.tele.util.*; import com.sun.max.tele.value.*; import com.sun.max.unsafe.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.actor.member.*; import com.sun.max.vm.layout.*; import com.sun.max.vm.layout.Layout.HeaderField; import com.sun.max.vm.object.*; import com.sun.max.vm.value.*; /** * Inspector's canonical surrogate for an object implemented as a {@link Hybrid} in the VM, * one of the three kinds of low level Maxine heap implementation objects. * A {@link Hybrid} object has both fields, as in a tuple, and array elements; it cannot be expressed * as an ordinary Java type. * It is allocated as if it were an array of words, with length specified in the header as with Java arrays. * The detailed breakdown of the object's structure is expressed in the subclass {@link TeleHub}. */ public abstract class TeleHybridObject extends TeleObject { protected TeleHybridObject(TeleVM vm, RemoteReference reference) { super(vm, reference, vm.layoutScheme().hybridLayout); } @Override public ObjectKind kind() { return ObjectKind.HYBRID; } @Override public int objectSize() { // A hybrid object is sized as if it were all one big array, even though the memory will // be used differently in different parts. return Layout.hybridLayout().getArraySize(readArrayLength()).toInt(); } @Override public HeaderField[] headerFields() { return Layout.hybridLayout().headerFields(); } @Override public Address fieldAddress(FieldActor fieldActor) { return origin().plus(fieldActor.offset()); } @Override public int fieldSize(FieldActor fieldActor) { return fieldActor.kind.width.numberOfBytes; } /** * {@inheritDoc} * <p> * When the field is a reference, this does <em>not</em> follow forwarding pointers. */ @Override public Value readFieldValue(FieldActor fieldActor) { if (fieldActor.kind.isReference) { // Does not follow forwarding pointers return TeleReferenceValue.from(vm(), reference().readReference(fieldActor.offset())); } return fieldActor.readValue(reference()); } /** * @return length of the word array part of this hybrid in the VM */ private int readWordArrayLength() { return Layout.wordArrayLayout().readLength(reference()); } /** * @return an element of the word array part of this hybrid in the VM */ public Word readWord(int wordIndex) { return Layout.getWord(reference(), wordIndex); } /** * @return length of the int array part of this hybrid in the VM */ public int readArrayLength() { return objects().unsafeReadArrayLength(reference()); } /** * @return an element of the int array part of this hybrid in the VM */ public int readArrayInt(int intIndex) { return Layout.getInt(reference(), intIndex); } @Override public Object shallowCopy() { final ClassActor classActor = classActorForObjectType(); final Class<?> javaClass = classActor.toJava(); try { final Object protoHybridObject = ObjectUtils.allocateInstance(javaClass); ClassActor holderClassActor = classActor; // The tuple part do { for (FieldActor fieldActor : holderClassActor.localInstanceFieldActors()) { if (!(fieldActor.kind.isReference || fieldActor.isInjected())) { final Field field = fieldActor.toJava(); field.setAccessible(true); try { field.set(protoHybridObject, readFieldValue(fieldActor).asBoxedJavaValue()); } catch (IllegalAccessException illegalAccessException) { TeleError.unexpected("could not access field: " + field, illegalAccessException); } } } holderClassActor = holderClassActor.superClassActor; } while (holderClassActor != null); // Expand to include the array part final int wordArrayLength = readWordArrayLength(); Hybrid newHybridObject = (Hybrid) protoHybridObject; newHybridObject = newHybridObject.expand(wordArrayLength); for (int wordIndex = newHybridObject.firstWordIndex(); wordIndex <= newHybridObject.lastWordIndex(); wordIndex++) { newHybridObject.setWord(wordIndex, readWord(wordIndex)); } for (int intIndex = newHybridObject.firstIntIndex(); intIndex <= newHybridObject.lastIntIndex(); intIndex++) { newHybridObject.setInt(intIndex, readArrayInt(intIndex)); } return newHybridObject; } catch (InstantiationException instantiationException) { TeleError.unexpected("could not allocate instance: " + javaClass, instantiationException); } return null; } }