/*
* 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.util.*;
import com.sun.max.tele.*;
import com.sun.max.tele.reference.*;
import com.sun.max.vm.actor.*;
import com.sun.max.vm.classfile.constant.*;
/**
* Canonical surrogate for an object of type {@link Actor} in the VM.
*/
public abstract class TeleActor extends TeleTupleObject {
/**
* Field is final once non-null so cache it.
*/
private Utf8Constant actorName;
/**
* This constructor follows no {@linkplain RemoteReference references}. This avoids the infinite regress that can occur when the VM
* object and another are mutually referential.
*/
protected TeleActor(TeleVM vm, RemoteReference actorReference) {
super(vm, actorReference);
}
/**
* @return contents of the {@code flags} field, read from this
* {@link Actor} in the VM.
*/
public final int getFlags() {
return fields().Actor_flags.readInt(reference());
}
/**
* Lists the textual names of flags that are set in this actor[
*
* Note that the the flag bit definitions for different subclasses of
* {@link Actor} may vary, and different flags are specified as appropriate
* for different entities. The approach here is to make no assumptions about
* the correctness of the flags, but simply report what flags are set. If a
* particular bit position is defined in more than one way, then all
* definitions will be shown as a concatenation of the names, separated
* by "/" to show that they define the
* same bit position. In other words, this method does not verify the
* <strong>correctness</strong> in any way.
*
* @return strings containing the names of the constants associated with each
* flag that is set.
*/
public final String[] getFlagNames() {
final int flagsValue = getFlags();
int nextFlagIndex = 0;
final String[] flags = new String[vm().platform().nBytesInWord()];
if ((flagsValue & Actor.ACC_PUBLIC) != 0) {
// 0x00000001
flags[nextFlagIndex++] = "ACC_PUBLIC";
}
if ((flagsValue & Actor.ACC_PRIVATE) != 0) {
// 0x00000002
flags[nextFlagIndex++] = "ACC_PRIVATE";
}
if ((flagsValue & Actor.ACC_PROTECTED) != 0) {
// 0x00000004
flags[nextFlagIndex++] = "ACC_PROTECTED";
}
if ((flagsValue & Actor.ACC_STATIC) != 0) {
// 0x00000008
flags[nextFlagIndex++] = "ACC_STATIC";
}
if ((flagsValue & Actor.ACC_FINAL) != 0) {
// 0x00000010
flags[nextFlagIndex++] = "ACC_FINAL";
}
if ((flagsValue & Actor.ACC_SUPER) != 0) {
// 0x00000020, doubly defined
flags[nextFlagIndex++] = "ACC_SUPER/ACC_SYNCHRONIZED";
}
if ((flagsValue & Actor.ACC_BRIDGE) != 0) {
// 0x00000040, doubly defined
flags[nextFlagIndex++] = "ACC_BRIDGE/ACC_VOLATILE";
}
if ((flagsValue & Actor.ACC_TRANSIENT) != 0) {
// 0x00000080, doubly defined
flags[nextFlagIndex++] = "ACC_TRANSIENT/ACC_VARARGS";
}
if ((flagsValue & Actor.ACC_NATIVE) != 0) {
// 0x00000100
flags[nextFlagIndex++] = "ACC_NATIVE";
}
if ((flagsValue & Actor.ACC_INTERFACE) != 0) {
// 0x00000200
flags[nextFlagIndex++] = "ACC_INTERFACE";
}
if ((flagsValue & Actor.ACC_ABSTRACT) != 0) {
// 0x00000400
flags[nextFlagIndex++] = "ACC_ABSTRACT";
}
if ((flagsValue & Actor.ACC_STRICT) != 0) {
// 0x00000800
flags[nextFlagIndex++] = "ACC_STRICT";
}
if ((flagsValue & Actor.ACC_SYNTHETIC) != 0) {
// 0x00001000
flags[nextFlagIndex++] = "ACC_SYNTHETIC";
}
if ((flagsValue & Actor.ACC_ANNOTATION) != 0) {
// 0x00002000, doubly defined
flags[nextFlagIndex++] = "ACC_ANNOTATION";
}
if ((flagsValue & Actor.ACC_ENUM) != 0) {
// 0x00004000, doubly defined
flags[nextFlagIndex++] = "ACC_ENUM/NO_SAFEPOINTS";
}
if ((flagsValue & Actor.DEPRECATED) != 0) {
// 0x00008000, doubly defined
flags[nextFlagIndex++] = "DEPRECATED";
}
if ((flagsValue & Actor.INJECTED) != 0) {
// 0x00010000, doubly defined
flags[nextFlagIndex++] = "INJECTED/VERIFIED";
}
if ((flagsValue & Actor.CONSTANT) != 0) {
// 0x00020000
flags[nextFlagIndex++] = "CONSTANT";
}
if ((flagsValue & Actor.CONSTANT_WHEN_NOT_ZERO) != 0) {
// 0x00040000
flags[nextFlagIndex++] = "CONSTANT_WHEN_NOT_ZERO";
}
if ((flagsValue & Actor.INNER_CLASS) != 0) {
// 0x00100000, doubly defined
flags[nextFlagIndex++] = "INNER_CLASS";
}
if ((flagsValue & Actor.TEMPLATE) != 0) {
// 0x00200000
flags[nextFlagIndex++] = "TEMPLATE";
}
if ((flagsValue & Actor.INITIALIZER) != 0) {
// 0x00400000, doubly defined
flags[nextFlagIndex++] = "INITIALIZER";
}
if ((flagsValue & Actor.C_FUNCTION) != 0) {
// 0x01000000
flags[nextFlagIndex++] = "C_FUNCTION";
}
if ((flagsValue & Actor.VM_ENTRY_POINT) != 0) {
// 0x02000000
flags[nextFlagIndex++] = "VM_ENTRY_POINT";
}
if ((flagsValue & Actor.FOLD) != 0) {
// 0x04000000
flags[nextFlagIndex++] = "FOLD";
}
if ((flagsValue & Actor.LOCAL_SUBSTITUTE) != 0) {
// 0x10000000
flags[nextFlagIndex++] = "LOCAL_SUBSTITUTE";
}
if ((flagsValue & Actor.UNSAFE) != 0) {
// 0x20000000
flags[nextFlagIndex++] = "UNSAFE";
}
if ((flagsValue & Actor.INLINE) != 0) {
// 0x40000000
flags[nextFlagIndex++] = "INLINE";
}
if ((flagsValue & Actor.NEVER_INLINE) != 0) {
// 0x80000000
flags[nextFlagIndex++] = "NEVER_INLINE";
}
return Arrays.copyOf(flags, nextFlagIndex);
}
public boolean isNative() {
return Actor.isNative(getFlags());
}
/**
* Gets the local {@link Actor} instance corresponding to this tele actor.
*/
protected abstract Actor actor();
/**
* @return the generic name of this {@link Actor}
*/
protected final Utf8Constant actorName() {
if (actorName == null) {
// Have to read the name using low level operations, because the name needed
// to create the local instance of the Actor.
RemoteReference utf8ConstantReference = fields().Actor_name.readRemoteReference(reference());
TeleUtf8Constant teleUtf8Constant = (TeleUtf8Constant) objects().makeTeleObject(utf8ConstantReference);
actorName = teleUtf8Constant.utf8Constant();
}
return actorName;
}
/** {@inheritDoc}
* <br>
* For the purposes of inspection, use a locally loaded copy of each actor.
*/
@Override
protected Object createDeepCopy(DeepCopier context) {
return actor();
}
}