/* * 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 com.sun.max.jdwp.vm.data.*; import com.sun.max.jdwp.vm.proxy.*; import com.sun.max.tele.*; import com.sun.max.tele.interpreter.*; import com.sun.max.tele.reference.*; import com.sun.max.tele.util.*; 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.classfile.*; import com.sun.max.vm.classfile.constant.*; import com.sun.max.vm.type.*; /** * Canonical surrogate for an object of type {@link MethodActor} in the VM. */ public abstract class TeleMethodActor extends TeleMemberActor implements MethodProvider { private MethodActor methodActor; /** * 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 TeleMethodActor(TeleVM vm, RemoteReference methodActorReference) { super(vm, methodActorReference); } /** * @return local {@link MethodActor} corresponding the the VM's {@link MethodActor} for this method. */ public MethodActor methodActor() { if (methodActor == null) { Utf8Constant actorName = actorName(); if (actorName != null) { // Cannot use member index as it may be different in local ClassActor SignatureDescriptor signature = (SignatureDescriptor) getTeleDescriptor().descriptor(); ClassActor classActor = getTeleHolder().classActor(); methodActor = classActor.findLocalMethodActor(actorName, signature); assert methodActor != null : "Could not find " + actorName.string + signature + " in " + classActor; assert actorName.string.equals(methodActor.name.string); } } return methodActor; } @Override public Actor actor() { return methodActor(); } /** * @return Whether this method has bytecodes in the VM. */ public boolean hasCodeAttribute() { return getTeleCodeAttribute() != null; } /** * @return The bytecodes associated with this method in the VM. * The {@link CodeAttribute} will not be the expected one from the classfile of the * method's {@link ClassActor holder}, in the event that the method was substituted. */ public abstract TeleCodeAttribute getTeleCodeAttribute(); /** * @return whether the method in the VM had its {@link CodeAttribute} substituted from another class. */ public boolean isSubstituted() { return teleClassActorSubstitutedFrom() != null; } /** * Local surrogate for the {@link ClassActor} in the VM from which a code substitution for this * method originated, null if the method has not been substituted. */ public TeleClassActor teleClassActorSubstitutedFrom() { final TeleCodeAttribute teleCodeAttribute = getTeleCodeAttribute(); if (teleCodeAttribute != null) { final TeleClassActor codeAttributeHolder = teleCodeAttribute.getTeleConstantPool().getTeleHolder(); return codeAttributeHolder == getTeleHolder() ? null : codeAttributeHolder; } return null; } @Override public String maxineTerseRole() { return "MethodActor"; } public VMValue invoke(ObjectProvider object, VMValue[] args, ThreadProvider threadProvider, boolean singleThreaded, boolean nonVirtual) { final VMValue[] newArgs = new VMValue[args.length + 1]; newArgs[0] = vm().vmAccess().createObjectProviderValue(object); System.arraycopy(args, 0, newArgs, 1, args.length); // TODO: Currently the nonVirtual parameter is ignored. return invokeStatic(newArgs, threadProvider, singleThreaded); } public VMValue invokeStatic(VMValue[] args, ThreadProvider threadProvider, boolean singleThreaded) { // TODO: Check ClassMethodActor / MethodActor relationship final com.sun.max.vm.value.Value[] realArgs = new com.sun.max.vm.value.Value[args.length]; for (int i = 0; i < args.length; i++) { realArgs[i] = vm().jdwpValueToMaxineValue(args[i]); } try { final com.sun.max.vm.value.Value result = TeleInterpreter.execute(vm(), (ClassMethodActor) methodActor(), realArgs); return vm().maxineValueToJDWPValue(result); } catch (TeleInterpreterException teleInterpreterException) { TeleError.unexpected("method interpretation failed", teleInterpreterException); return null; } } public ReferenceTypeProvider getReferenceTypeHolder() { return super.getTeleHolder(); } public String getSignature() { return methodActor().descriptor().toString(); } public String getSignatureWithGeneric() { return methodActor().genericSignatureString(); } public LineTableEntry[] getLineTable() { return new LineTableEntry[0]; } public VariableTableEntry[] getVariableTable() { return new VariableTableEntry[0]; } public int getNumberOfArguments() { return (methodActor().isStatic() ? 0 : 1) + methodActor().descriptor().computeNumberOfSlots(); } }