/*
* Copyright (c) 2009, 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.vm.compiler.target;
import static com.sun.max.vm.compiler.CallEntryPoint.*;
import static com.sun.max.vm.compiler.target.Safepoints.*;
import java.util.*;
import com.sun.max.annotate.*;
import com.sun.max.unsafe.*;
import com.sun.max.vm.actor.member.*;
import com.sun.max.vm.code.*;
import com.sun.max.vm.code.CodeManager.Lifespan;
import com.sun.max.vm.compiler.*;
import com.sun.max.vm.runtime.*;
import com.sun.max.vm.stack.*;
/**
* An adapter is a code stub interposing a call between two methods that have different calling conventions. The adapter
* is called upon entry to the callee in the prologue specific to the {@linkplain CallEntryPoint entry point} used by
* the caller. This allows a call between two methods that share the same calling convention to avoid an adapter
* altogether.
*
* The adapter framework assumes there are exactly two calling conventions in use by the compilers in the VM. While the
* details are platform specific, the {@linkplain CallEntryPoint#OPTIMIZED_ENTRY_POINT "OPT"} calling convention mostly
* conforms to the C ABI of the underlying platform. The {@linkplain CallEntryPoint#BASELINE_ENTRY_POINT "baseline"} convention is
* used by code that maintains an expression stack (much like an interpreter) and it uses two separate registers for a
* frame pointer and a stack pointer. The frame pointer is used to access incoming arguments and local variables, and
* the stack pointer is used to maintain the Java expression stack. All arguments to Java calls under the "baseline"
* convention are passed via the Java expression stack.
*
* Return values are placed in a register under both conventions.
*/
public abstract class Adapter extends TargetMethod {
/**
* The type of adaptation performed by an adapter. Each enum value denotes an ordered pair of two
* different calling conventions. The platform specific details of each calling convention
* are documented by the platform-specific subclasses of {@link AdapterGenerator}.
*
*/
public enum Type {
/**
* Type of an adapter that interposes a call from code compiled with the baseline calling convention to
* code compiled with the "OPT" calling convention.
*/
BASELINE2OPT(BASELINE_ENTRY_POINT, OPTIMIZED_ENTRY_POINT),
/**
* Type of an adapter that interposes a call from code compiled with the "OPT" calling convention to
* code compiled with the "baseline" calling convention.
*/
OPT2BASELINE(OPTIMIZED_ENTRY_POINT, BASELINE_ENTRY_POINT);
Type(CallEntryPoint caller, CallEntryPoint callee) {
this.caller = caller;
this.callee = callee;
}
/**
* Denotes the calling convention of an adapter's caller.
*/
public final CallEntryPoint caller;
/**
* Denotes the calling convention of an adapter's callee.
*/
public final CallEntryPoint callee;
}
/**
* The generator that produced this adapter.
*/
@INSPECTED(deepCopied = false)
public final AdapterGenerator generator;
/**
* Creates an adapter and installs it in the code manager.
*
* @param generator the generator that produced the adapter
* @param description a textual description of the adapter
* @param frameSize the size of the adapter frame
* @param code the adapter code
* @param callPos
* @param callSize
*/
public Adapter(AdapterGenerator generator, String description, int frameSize, byte[] code, int callPos, int callSize) {
super(description, CallEntryPoint.OPTIMIZED_ENTRY_POINT);
this.setFrameSize(frameSize);
this.generator = generator;
final TargetBundleLayout targetBundleLayout = new TargetBundleLayout(0, 0, code.length);
Code.allocate(targetBundleLayout, this);
setData(null, null, code);
setSafepoints(new Safepoints(Safepoints.make(Safepoints.safepointPosForCall(callPos, callSize), callPos, INDIRECT_CALL)), TargetMethod.NO_DIRECT_CALLEES);
}
/**
* Gets the offset of the call to this adapter in a method's prologue.
*/
public abstract int callOffsetInPrologue();
/**
* Gets the size of the call to this adapter in a method's prologue.
*/
public abstract int callSizeInPrologue();
@Override
public Lifespan lifespan() {
return Lifespan.LONG;
}
@Override
public void gatherCalls(Set<MethodActor> directCalls, Set<MethodActor> virtualCalls, Set<MethodActor> interfaceCalls, Set<MethodActor> inlinedMethods) {
}
@Override
public boolean isPatchableCallSite(CodePointer callSite) {
FatalError.unexpected("Adapter should never be patched");
return false;
}
@Override
public CodePointer fixupCallSite(int callOffset, CodePointer callEntryPoint) {
throw FatalError.unexpected("Adapter should never be patched");
}
@Override
public CodePointer patchCallSite(int callOffset, CodePointer callEntryPoint) {
throw FatalError.unexpected("Adapter should never be patched");
}
@Override
public CodePointer throwAddressToCatchAddress(CodePointer throwAddress, Throwable exception) {
return CodePointer.zero();
}
@Override
public void prepareReferenceMap(StackFrameCursor current, StackFrameCursor callee, FrameReferenceMapVisitor preparer) {
}
@Override
public void catchException(StackFrameCursor current, StackFrameCursor callee, Throwable throwable) {
// Exceptions do not occur in adapters
}
}