Mercurial > hg > Members > kono > jpf-core
diff src/tests/gov/nasa/jpf/test/basic/JPF_gov_nasa_jpf_test_basic_MJITest.java @ 0:61d41facf527
initial v8 import (history reset)
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 23 Jan 2015 10:14:01 -0800 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/tests/gov/nasa/jpf/test/basic/JPF_gov_nasa_jpf_test_basic_MJITest.java Fri Jan 23 10:14:01 2015 -0800 @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2014, United States Government, as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All rights reserved. + * + * The Java Pathfinder core (jpf-core) platform is licensed under the + * Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package gov.nasa.jpf.test.basic; + +import gov.nasa.jpf.annotation.MJI; +import gov.nasa.jpf.vm.DirectCallStackFrame; +import gov.nasa.jpf.vm.MJIEnv; +import gov.nasa.jpf.vm.MethodInfo; +import gov.nasa.jpf.vm.NativePeer; +import gov.nasa.jpf.vm.ThreadInfo; +import gov.nasa.jpf.vm.UncaughtException; + +/** + * native peer class for unit testing MJI + */ +public class JPF_gov_nasa_jpf_test_basic_MJITest extends NativePeer { + + // intercept <clinit> + @MJI + public void $clinit (MJIEnv env, int rcls) { + System.out.println("# entering native <clinit>"); + env.setStaticIntField(rcls, "sdata", 42); + } + + // intercept MJITest(int i) ctor + @MJI + public void $init__I__V (MJIEnv env, int robj, int i) { + // NOTE : if we directly intercept the ctor, then we also have + // to take care of calling the proper superclass ctors + // better approach is to refactor this into a separate native method + // (say init0(..)) + System.out.println("# entering native <init>(I)"); + env.setIntField(robj, "idata", i); + } + + @MJI + public int nativeCreate2DimIntArray__II___3_3I (MJIEnv env, int robj, int size1, + int size2) { + System.out.println("# entering nativeCreate2DimIntArray()"); + int ar = env.newObjectArray("[I", size1); + + for (int i = 0; i < size1; i++) { + int ea = env.newIntArray(size2); + + if (i == 1) { + env.setIntArrayElement(ea, 1, 42); + } + + env.setReferenceArrayElement(ar, i, ea); + } + + return ar; + } + + // check if the non-mangled name lookup works + @MJI + public int nativeCreateIntArray (MJIEnv env, int robj, int size) { + System.out.println("# entering nativeCreateIntArray()"); + + int ar = env.newIntArray(size); + + env.setIntArrayElement(ar, 1, 1); + + return ar; + } + + @MJI + public int nativeCreateStringArray (MJIEnv env, int robj, int size) { + System.out.println("# entering nativeCreateStringArray()"); + + int ar = env.newObjectArray("Ljava/lang/String;", size); + env.setReferenceArrayElement(ar, 1, env.newString("one")); + + return ar; + } + + @MJI + public void nativeException____V (MJIEnv env, int robj) { + System.out.println("# entering nativeException()"); + env.throwException("java.lang.UnsupportedOperationException", "caught me"); + } + + @SuppressWarnings("null") + @MJI + public int nativeCrash (MJIEnv env, int robj) { + System.out.println("# entering nativeCrash()"); + String s = null; + return s.length(); + } + + @MJI + public int nativeInstanceMethod (MJIEnv env, int robj, double d, + char c, boolean b, int i) { + System.out.println("# entering nativeInstanceMethod() d=" + d + + ", c=" + c + ", b=" + b + ", i=" + i); + + if ((d == 2.0) && (c == '?') && b) { + return i + 2; + } + + return 0; + } + + @MJI + public long nativeStaticMethod__JLjava_lang_String_2__J (MJIEnv env, int rcls, long l, + int stringRef) { + System.out.println("# entering nativeStaticMethod()"); + + String s = env.getStringObject(stringRef); + + if ("Blah".equals(s)) { + return l + 2; + } + + return 0; + } + + + /* + * nativeRoundtripLoop shows how to + * + * (1) round trip into JPF executed code from within native methods + * + * (2) loop inside of native methods that do round trips (using the + * DirectCallStackFrame's local slots) + * + * the call chain is: + * + * JPF: testRoundtripLoop + * VM: nativeRoundTripLoop x 3 + * JPF: roundtrip + * VM: nativeInnerRoundtrip + */ + + @MJI + public int nativeInnerRoundtrip__I__I (MJIEnv env, int robj, int a){ + System.out.println("# entering nativeInnerRoundtrip()"); + + return a+2; + } + + @MJI + public int nativeRoundtripLoop__I__I (MJIEnv env, int robj, int a) { + System.out.println("# entering nativeRoundtripLoop(): " + a); + + MethodInfo mi = env.getClassInfo(robj).getMethod("roundtrip(I)I",false); + ThreadInfo ti = env.getThreadInfo(); + DirectCallStackFrame frame = ti.getReturnedDirectCall(); + + if (frame == null){ // first time + frame = mi.createDirectCallStackFrame(ti, 1); + frame.setLocalVariable( 0, 0); + + int argOffset = frame.setReferenceArgument(0, robj, null); + frame.setArgument( argOffset, a+1, null); + + ti.pushFrame(frame); + + return 42; // whatever, we come back + + } else { // direct call returned + + // this method can't be executed unless the class is already initialized, + // i.e. we don't have to check for overlayed clinit calls and the frame + // has to be the one we pushed + assert frame.getCallee() == mi; + + // this shows how to get information back from the JPF roundtrip into + // the native method + int r = frame.getResult(); // the return value of the direct call above + int i = frame.getLocalVariable(0); + + if (i < 3) { // repeat the round trip + // we have to reset so that the PC is re-initialized + frame.reset(); + frame.setLocalVariable(0, i + 1); + + int argOffset = frame.setReferenceArgument( 0, robj, null); + frame.setArgument( argOffset, r+1, null); + + ti.pushFrame(frame); + return 42; + + } else { // done, return the final value + return r; + } + } + } + + /** + * this shows how to synchronously JPF-enter a method from native peer or + * listener code + */ + @MJI + public int nativeHiddenRoundtrip__I__I (MJIEnv env, int robj, int a){ + ThreadInfo ti = env.getThreadInfo(); + + System.out.println("# entering nativeHiddenRoundtrip: " + a); + MethodInfo mi = env.getClassInfo(robj).getMethod("atomicStuff(I)I",false); + + DirectCallStackFrame frame = mi.createDirectCallStackFrame(ti, 0); + + int argOffset = frame.setReferenceArgument( 0, robj, null); + frame.setArgument( argOffset, a, null); + frame.setFireWall(); + + try { + ti.executeMethodHidden(frame); + //ti.advancePC(); + + } catch (UncaughtException ux) { // frame's method is firewalled + System.out.println("# hidden method execution failed, leaving nativeHiddenRoundtrip: " + ux); + ti.clearPendingException(); + ti.popFrame(); // this is still the DirectCallStackFrame, and we want to continue execution + return -1; + } + + // get the return value from the (already popped) frame + int res = frame.getResult(); + + System.out.println("# exit nativeHiddenRoundtrip: " + res); + return res; + } + +}