/*
* Copyright (c) 2009, 2011, 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.oracle.max.vm.ext.maxri;
import static com.sun.max.vm.MaxineVM.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import com.sun.cri.ci.*;
import com.sun.max.annotate.*;
import com.sun.max.vm.*;
import com.sun.max.vm.actor.member.*;
import com.sun.max.vm.compiler.*;
import com.sun.max.vm.compiler.target.*;
import com.sun.max.vm.heap.*;
import com.sun.max.vm.object.*;
import com.sun.max.vm.runtime.*;
import com.sun.max.vm.stack.*;
/**
* This class contains the implementation of runtime calls that are called by
* code emitted by the CRI compilers.
*/
public class MaxRuntimeCalls {
// a local flag to enable calls to verify the reference map for each runtime call
private static final boolean ENABLE_REFMAP_VERIFICATION = true;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MAX_RUNTIME_ENTRYPOINT {
CiRuntimeCall runtimeCall();
}
public static ClassMethodActor getClassMethodActor(CiRuntimeCall call) {
final ClassMethodActor result = runtimeCallMethods[call.ordinal()];
assert result != null : "no runtime method defined for " + call;
return result;
}
private static ClassMethodActor[] runtimeCallMethods = new ClassMethodActor[CiRuntimeCall.values().length];
static {
for (Method method : MaxRuntimeCalls.class.getMethods()) {
MAX_RUNTIME_ENTRYPOINT entry = method.getAnnotation(MAX_RUNTIME_ENTRYPOINT.class);
if (entry != null) {
registerMethod(method, entry.runtimeCall());
}
}
for (CiRuntimeCall call : CiRuntimeCall.values()) {
assert checkCompatible(call, getClassMethodActor(call));
}
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.UnwindException)
public static void runtimeUnwindException(Throwable throwable) throws Throwable {
Throw.raise(throwable);
}
@HOSTED_ONLY
private static boolean checkCompatible(CiRuntimeCall call, ClassMethodActor classMethodActor) {
assert classMethodActor.descriptor().returnKind(true) == call.resultKind;
CiKind[] kinds = CiUtil.signatureToKinds(classMethodActor);
for (int i = 0; i < call.arguments.length; i++) {
assert kinds[i] == call.arguments[i] : call + " incompatible with " + classMethodActor;
}
return true;
}
private static void verifyRefMaps() {
if (ENABLE_REFMAP_VERIFICATION && StackReferenceMapPreparer.VerifyRefMaps) {
StackReferenceMapPreparer.verifyReferenceMapsForThisThread();
}
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.RegisterFinalizer)
public static void runtimeRegisterFinalizer(Object object) {
verifyRefMaps();
if (ObjectAccess.readClassActor(object).hasFinalizer()) {
SpecialReferenceManager.registerFinalizee(object);
}
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.HandleException)
public static void runtimeHandleException(Throwable throwable) throws Throwable {
verifyRefMaps();
Throw.raise(throwable);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.OSRMigrationEnd)
public static void runtimeOSRMigrationEnd() {
verifyRefMaps();
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.JavaTimeMillis)
public static long runtimeJavaTimeMillis() {
verifyRefMaps();
return MaxineVM.native_currentTimeMillis();
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.JavaTimeNanos)
public static long runtimeJavaTimeNanos() {
verifyRefMaps();
return MaxineVM.native_nanoTime();
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.Debug)
public static void runtimeDebug() {
verifyRefMaps();
throw FatalError.unexpected("Debug");
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmethicLrem)
public static long runtimeArithmethicLrem(long a, long b) {
verifyRefMaps();
throw FatalError.unexpected("Compiler should directly translate LREM");
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticLdiv)
public static long runtimeArithmeticLdiv(long a, long b) {
verifyRefMaps();
throw FatalError.unexpected("Compiler should directly translate LDIV");
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticFrem)
public static float runtimeArithmeticFrem(float v1, float v2) {
verifyRefMaps();
return Snippets.floatRemainder(v1, v2);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticDrem)
public static double runtimeArithmeticDrem(double v1, double v2) {
verifyRefMaps();
return Snippets.doubleRemainder(v1, v2);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticCos)
public static double runtimeArithmeticCos(double v) {
verifyRefMaps();
return Math.cos(v);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticTan)
public static double runtimeArithmeticTan(double v) {
verifyRefMaps();
return Math.tan(v);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticLog)
public static double runtimeArithmeticLog(double v) {
verifyRefMaps();
return Math.log(v);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticLog10)
public static double runtimeArithmeticLog10(double v) {
verifyRefMaps();
return Math.log10(v);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.ArithmeticSin)
public static double runtimeArithmeticSin(double v) {
verifyRefMaps();
return Math.sin(v);
}
/**
* The body of this method is provided by {@link Stubs#genUncommonTrapStub()}.
*/
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.Deoptimize)
public static void uncommonTrap() {
throw FatalError.unexpected("stub should be overwritten");
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.SetDeoptInfo)
public static void setDeoptInfo(Object info) {
// TODO
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.CreateNullPointerException)
public static Object createNullPointerException() {
return new NullPointerException();
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.CreateOutOfBoundsException)
public static Object createOutOfBoundsException(int index) {
return new ArrayIndexOutOfBoundsException(index);
}
@MAX_RUNTIME_ENTRYPOINT(runtimeCall = CiRuntimeCall.GenericCallback)
public static Object genericCallback(CiGenericCallback cb, Object arg) {
throw FatalError.unimplemented();
}
@HOSTED_ONLY
private static void registerMethod(Method selectedMethod, CiRuntimeCall call) {
ClassMethodActor classMethodActor = null;
assert runtimeCallMethods[call.ordinal()] == null : "method already defined";
classMethodActor = ClassMethodActor.fromJava(selectedMethod);
runtimeCallMethods[call.ordinal()] = classMethodActor;
if (MaxineVM.isHosted()) {
new CriticalMethod(classMethodActor, CallEntryPoint.OPTIMIZED_ENTRY_POINT);
} else {
vm().compilationBroker.compile(classMethodActor, null);
}
}
}