/* * 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.jdwp.vm.proxy.*; import com.sun.max.jdwp.vm.proxy.VMValue.Type; 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.vm.actor.*; import com.sun.max.vm.actor.holder.*; import com.sun.max.vm.actor.member.*; import com.sun.max.vm.type.*; /** * Canonical surrogate for a {@link ClassActor} in the VM. */ public abstract class TeleClassActor extends TeleActor implements ReferenceTypeProvider { private ClassActor classActor; private boolean initialized = false; // Fields are final; cache them. private TeleClassLoader teleClassLoader; private int id; private TeleTypeDescriptor teleTypeDescriptor; protected TeleClassActor(TeleVM vm, RemoteReference classActorReference) { super(vm, classActorReference); } @Override public final Actor actor() { if (classActor == null) { classActor = classes().makeClassActor(reference()); } return classActor; } /** * @return Local {@link ClassActor} corresponding the {@link ClassActor} in the VM. */ public final ClassActor classActor() { return (ClassActor) actor(); } private void initialize() { if (!initialized) { final RemoteReference classLoaderReference = fields().ClassActor_classLoader.readRemoteReference(reference()); teleClassLoader = (TeleClassLoader) objects().makeTeleObject(classLoaderReference); id = fields().ClassActor_id.readInt(reference()); final RemoteReference typeDescriptorReference = fields().ClassActor_typeDescriptor.readRemoteReference(reference()); teleTypeDescriptor = (TeleTypeDescriptor) objects().makeTeleObject(typeDescriptorReference); initialized = true; } } /** * @return surrogate for the {@link ClassLoader} in the VM for this class in the VM. * There is no local counterpart for these; all local surrogate objects are created by one * ClassLoader. */ public TeleClassLoader getTeleClassLoader() { initialize(); return teleClassLoader; } /** * @return the serial ID of the {@link ClassActor} in the VM. */ public int getId() { initialize(); return id; } /** * @return surrogate for the {@link TypeDescriptor} in theVM for this class in the VM. */ public TeleTypeDescriptor getTeleTypeDescriptor() { initialize(); return teleTypeDescriptor; } // @Override // protected Object createDeepCopy(DeepCopier context) { // // Translate into local equivalent // return classActor(); // } public TeleClass getTeleClass() { final RemoteReference reference = fields().ClassActor_javaClass.readRemoteReference(reference()); if (reference.isZero()) { // TODO: assert that this class is the object class! return null; } return (TeleClass) objects().makeTeleObject(reference); } /** * @return surrogate for the {@link StaticTuple} of the {@link ClassActor} in the VM. */ public TeleStaticTuple getTeleStaticTuple() { final RemoteReference staticTupleReference = fields().ClassActor_staticTuple.readRemoteReference(reference()); return (TeleStaticTuple) objects().makeTeleObject(staticTupleReference); } /** * @return surrogate for the {@link DynamicHub} of the {@link ClassActor} in the VM. */ public TeleDynamicHub getTeleDynamicHub() { final RemoteReference dynamicHubReference = fields().ClassActor_dynamicHub.readRemoteReference(reference()); return (TeleDynamicHub) objects().makeTeleObject(dynamicHubReference); } /** * @return surrogate for the {@link StaticHub} of the {@link ClassActor} in the VM. */ public TeleStaticHub getTeleStaticHub() { final RemoteReference staticHubReference = fields().ClassActor_staticHub.readRemoteReference(reference()); return (TeleStaticHub) objects().makeTeleObject(staticHubReference); } /** * @return surrogate for the {@link ClassActor} in the VM for the type of the components of * this array type, null if not an array type */ public TeleClassActor getTeleComponentClassActor() { final RemoteReference componentClassActorReference = fields().ClassActor_componentClassActor.readRemoteReference(reference()); return (TeleClassActor) objects().makeTeleObject(componentClassActorReference); } /** * @return Reference to the constants in the VM's constant pool for the class, null if an array type */ public TeleConstantPool getTeleConstantPool() { if (classActor().isTupleClass()) { return (TeleConstantPool) objects().makeTeleObject(fields().TupleClassActor_constantPool.readRemoteReference(reference())); } else if (classActor().isHybridClass()) { return (TeleConstantPool) objects().makeTeleObject(fields().HybridClassActor_constantPool.readRemoteReference(reference())); } return null; } private List<TeleFieldActor> readTeleStaticFieldActors() { final List<TeleFieldActor> teleStaticFieldActors = new LinkedList<TeleFieldActor>(); final RemoteReference staticFieldActorsArrayRef = fields().ClassActor_localStaticFieldActors.readRemoteReference(reference()); final TeleArrayObject teleStaticFieldActorsArray = (TeleArrayObject) objects().makeTeleObject(staticFieldActorsArrayRef); for (int index = 0; index < teleStaticFieldActorsArray.length(); index++) { final TeleFieldActor teleStaticFieldActor = (TeleFieldActor) objects().makeTeleObject(teleStaticFieldActorsArray.readRemoteReference(index)); teleStaticFieldActors.add(teleStaticFieldActor); } return teleStaticFieldActors; } /** * @return surrogates for the local (not inherited) static {@link FieldActor}s associated with the class in the VM. */ public List<TeleFieldActor> getTeleStaticFieldActors() { return readTeleStaticFieldActors(); } private List<TeleFieldActor> readTeleInstanceFieldActors() { final List<TeleFieldActor> teleInstanceFieldActors = new LinkedList<TeleFieldActor>(); final RemoteReference instanceFieldActorsArrayRef = fields().ClassActor_localInstanceFieldActors.readRemoteReference(reference()); final TeleArrayObject teleInstanceFieldActorsArray = (TeleArrayObject) objects().makeTeleObject(instanceFieldActorsArrayRef); for (int index = 0; index < teleInstanceFieldActorsArray.length(); index++) { final TeleFieldActor teleInstanceFieldActor = (TeleFieldActor) objects().makeTeleObject(teleInstanceFieldActorsArray.readRemoteReference(index)); teleInstanceFieldActors.add(teleInstanceFieldActor); } return teleInstanceFieldActors; } /** * @return surrogates for the local (not inherited) instance {@link FieldActor}s associated with the class in the VM. */ public List<TeleFieldActor> getTeleInstanceFieldActors() { return readTeleInstanceFieldActors(); } /** * @return surrogates for the local (not inherited) {@link FieldActor}s associated with the class in the VM: both static and instance fields. */ public List<TeleFieldActor> getTeleFieldActors() { final List<TeleFieldActor> teleFieldActors = new LinkedList<TeleFieldActor>(); teleFieldActors.addAll(readTeleStaticFieldActors()); teleFieldActors.addAll(readTeleInstanceFieldActors()); return teleFieldActors; } private List<TeleInterfaceMethodActor> readTeleInterfaceMethodActors() { final List<TeleInterfaceMethodActor> teleInterfaceMethodActors = new LinkedList<TeleInterfaceMethodActor>(); final RemoteReference interfaceMethodActorsArrayRef = fields().ClassActor_localInterfaceMethodActors.readRemoteReference(reference()); final TeleArrayObject teleInterfaceMethodActorsArray = (TeleArrayObject) objects().makeTeleObject(interfaceMethodActorsArrayRef); for (int index = 0; index < teleInterfaceMethodActorsArray.length(); index++) { final TeleInterfaceMethodActor teleInterfaceMethodActor = (TeleInterfaceMethodActor) objects().makeTeleObject(teleInterfaceMethodActorsArray.readRemoteReference(index)); teleInterfaceMethodActors.add(teleInterfaceMethodActor); } return teleInterfaceMethodActors; } /** * @return surrogates for the local (not inherited) {@link InterfaceMethodActor}s associated with the class in the VM. */ public List<TeleInterfaceMethodActor> getTeleInterfaceMethodActors() { return readTeleInterfaceMethodActors(); } private List<TeleStaticMethodActor> readTeleStaticMethodActors() { final List<TeleStaticMethodActor> teleStaticMethodActors = new LinkedList<TeleStaticMethodActor>(); final RemoteReference staticMethodActorsArrayRef = fields().ClassActor_localStaticMethodActors.readRemoteReference(reference()); final TeleArrayObject teleStaticMethodActorsArray = (TeleArrayObject) objects().makeTeleObject(staticMethodActorsArrayRef); TeleError.check(teleStaticMethodActorsArray != null, "Can't find static methd actors array for " + classActor()); for (int index = 0; index < teleStaticMethodActorsArray.length(); index++) { final TeleStaticMethodActor teleStaticMethodActor = (TeleStaticMethodActor) objects().makeTeleObject(teleStaticMethodActorsArray.readRemoteReference(index)); teleStaticMethodActors.add(teleStaticMethodActor); } return teleStaticMethodActors; } /** * @return surrogates for the local (not inherited) {@link StaticMethodActor}s associated with the class in the VM. */ public List<TeleStaticMethodActor> getTeleStaticMethodActors() { return readTeleStaticMethodActors(); } private List<TeleVirtualMethodActor> readTeleVirtualMethodActors() { final List<TeleVirtualMethodActor> tleVirtualMethodActors = new LinkedList<TeleVirtualMethodActor>(); final RemoteReference virtualMethodActorsArrayRef = fields().ClassActor_localVirtualMethodActors.readRemoteReference(reference()); final TeleArrayObject teleVirtualMethodActorsArray = (TeleArrayObject) objects().makeTeleObject(virtualMethodActorsArrayRef); for (int index = 0; index < teleVirtualMethodActorsArray.length(); index++) { final TeleVirtualMethodActor teleVirtualMethodActor = (TeleVirtualMethodActor) objects().makeTeleObject(teleVirtualMethodActorsArray.readRemoteReference(index)); tleVirtualMethodActors.add(teleVirtualMethodActor); } return tleVirtualMethodActors; } /** * @return surrogates for the local (not inherited) {@link VirtualMethodActor}s associated with the class in the VM. */ public List<TeleVirtualMethodActor> getTeleVirtualMethodActors() { return readTeleVirtualMethodActors(); } /** * @return surrogates for the local (not inherited) {@link ClassMethodActor}s associated with the class in the VM: both static and virtual methods. */ public List<TeleClassMethodActor> getTeleClassMethodActors() { ArrayList<TeleClassMethodActor> result = new ArrayList<TeleClassMethodActor>(); result.addAll(readTeleStaticMethodActors()); result.addAll(readTeleVirtualMethodActors()); return result; } /** * @return surrogates for all of the the local (not inherited) {@link MethodActor}s associated with the class in the VM: static, virtual, and interface methods. */ public List<TeleMethodActor> getTeleMethodActors() { ArrayList<TeleMethodActor> result = new ArrayList<TeleMethodActor>(); result.addAll(readTeleStaticMethodActors()); result.addAll(readTeleVirtualMethodActors()); result.addAll(readTeleInterfaceMethodActors()); return result; } @Override public String maxineTerseRole() { return "ClassActor"; } public final String getName() { return actorName().string; } public ClassLoaderProvider classLoader() { return getTeleClassLoader(); } public ClassObjectProvider classObject() { return getTeleClass(); } private abstract class FakeFieldProvider implements FieldProvider { private static final String PREFIX = "X_"; private final String name; private final VMValue.Type type; private final String signature; public FakeFieldProvider(String name, VMValue.Type type, String signature) { this.name = PREFIX + name; this.type = type; this.signature = signature; } public ReferenceTypeProvider getReferenceTypeHolder() { return TeleClassActor.this; } public VMValue getStaticValue() { assert false : "This field is not a static field!"; return null; } public void setStaticValue(VMValue value) { assert false : "This field is not a static field!"; } public void setValue(ObjectProvider object, VMValue value) { assert false : "This field is readonly!"; } public int getFlags() { return FieldActor.ACC_FINAL; } public String getGenericSignature() { return getSignature(); } public String getName() { return actorName().string; } public String getSignature() { return signature; } public Type getType() { return type; } } private final FieldProvider fakeAddressField = new FakeFieldProvider("address", VMValue.Type.LONG, JavaTypeDescriptor.LONG.toString()) { public VMValue getValue(ObjectProvider object) { return vm().vmAccess().createLongValue(((TeleObject) object).reference().toOrigin().asAddress().toLong()); } }; private final FieldProvider fakeHubField = new FakeFieldProvider("hub", VMValue.Type.PROVIDER, "Lcom/sun/max/vm/actor/holder/Hub;") { public VMValue getValue(ObjectProvider object) { return vm().maxineValueToJDWPValue(TeleReferenceValue.from(vm(), ((TeleObject) object).getTeleHub().reference())); } }; private final FieldProvider fakeMiscField = new FakeFieldProvider("misc", VMValue.Type.LONG, JavaTypeDescriptor.LONG.toString()) { public VMValue getValue(ObjectProvider object) { return vm().vmAccess().createLongValue(((TeleObject) object).readMiscWord().asAddress().toLong()); } }; public FieldProvider[] getFields() { final List<TeleFieldActor> list = getTeleFieldActors(); final List<FieldProvider> result = new ArrayList<FieldProvider>(); result.addAll(list); if (this.classActor().superClassActor == null) { result.add(0, fakeAddressField); result.add(0, fakeMiscField); result.add(0, fakeHubField); } final FieldProvider[] resultArray = new FieldProvider[list.size()]; return result.toArray(resultArray); } public InterfaceProvider[] getImplementedInterfaces() { final HashSet<InterfaceActor> interfaces = classActor().getAllInterfaceActors(); final List<InterfaceProvider> result = new LinkedList<InterfaceProvider>(); for (InterfaceActor interfaceActor : interfaces) { final InterfaceProvider interfaceProvider = (TeleInterfaceActor) classes().findTeleClassActor(interfaceActor.typeDescriptor); if (interfaceProvider != this) { result.add(interfaceProvider); } } return result.toArray(new InterfaceProvider[result.size()]); } public MethodProvider[] getMethods() { List<TeleMethodActor> teleMethodActors = getTeleMethodActors(); return teleMethodActors.toArray(new MethodProvider[teleMethodActors.size()]); } public ReferenceTypeProvider[] getNestedTypes() { final ClassActor[] actors = classActor().innerClassActors(); final ReferenceTypeProvider[] result = new ReferenceTypeProvider[actors.length]; for (int i = 0; i < actors.length; i++) { result[i] = classes().findTeleClassActor(actors[i].typeDescriptor); } return result; } public ObjectProvider[] getInstances() { // TODO: Implement this correctly. return null; } public String getSignature() { return classActor().typeDescriptor.toString(); } public String getSignatureWithGeneric() { return classActor().genericSignatureString(); } public int getStatus() { // TODO: Correct implementation. int status = 0; if (classActor().isInitialized()) { status |= ClassStatus.INITIALIZED; } if (classActor().isInitialized()) { status |= ClassStatus.PREPARED; } if (classActor().isInitialized()) { status |= ClassStatus.VERIFIED; } return status; } public String getSourceFileName() { return classActor().sourceFileName; } public Type getType() { return TeleVM.maxineKindToJDWPType(classActor().kind); } public int majorVersion() { return classActor().majorVersion; } public int minorVersion() { return classActor().minorVersion; } }