1 /*
   2  * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.jtt.optimize;
  24 
  25 import java.lang.reflect.Field;
  26 import java.nio.ByteBuffer;
  27 
  28 import org.junit.Test;
  29 import org.junit.internal.AssumptionViolatedException;
  30 
  31 import org.graalvm.compiler.api.directives.GraalDirectives;
  32 import org.graalvm.compiler.jtt.JTTTest;
  33 
  34 import jdk.vm.ci.meta.ResolvedJavaMethod;
  35 import sun.misc.Unsafe;
  36 
  37 public class UnsafeDeopt extends JTTTest {
  38     private static final Unsafe unsafe;
  39 
  40     static {
  41         try {
  42             final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
  43             unsafeField.setAccessible(true);
  44             unsafe = (Unsafe) unsafeField.get(null);
  45         } catch (Exception e) {
  46             throw new Error(e);
  47         }
  48     }
  49 
  50     public static int readWriteReadUnsafe(long addr, int m) {
  51         int original = unsafe.getInt(addr);
  52         if (original != 0) {
  53             return -m;
  54         }
  55         unsafe.putInt(addr, m);
  56         if (m > 10) {
  57             if (m > 20) {
  58                 GraalDirectives.deoptimize();
  59             }
  60             unsafe.putInt(addr + 4, m);
  61         }
  62         return unsafe.getInt(addr);
  63     }
  64 
  65     public static int readWriteReadByteBuffer(ByteBuffer buffer, int m) {
  66         int original = buffer.getInt(0);
  67         if (original != 0) {
  68             return -m;
  69         }
  70         buffer.putInt(0, m);
  71         if (m > 10) {
  72             if (m > 20) {
  73                 GraalDirectives.deoptimize();
  74                 buffer.putInt(4, m);
  75             }
  76         }
  77         return buffer.getInt(0);
  78     }
  79 
  80     public long createBuffer() {
  81         long addr = unsafe.allocateMemory(32);
  82         unsafe.setMemory(addr, 32, (byte) 0);
  83         return addr;
  84     }
  85 
  86     public void disposeBuffer(long addr) {
  87         unsafe.freeMemory(addr);
  88     }
  89 
  90     @Test
  91     public void testUnsafe() {
  92         int m = 42;
  93         long addr1 = createBuffer();
  94         long addr2 = createBuffer();
  95         try {
  96             ResolvedJavaMethod method = getResolvedJavaMethod("readWriteReadUnsafe");
  97             Object receiver = method.isStatic() ? null : this;
  98             Result expect = executeExpected(method, receiver, addr1, m);
  99             if (getCodeCache() == null) {
 100                 return;
 101             }
 102             testAgainstExpected(method, expect, receiver, addr2, m);
 103         } catch (AssumptionViolatedException e) {
 104             // Suppress so that subsequent calls to this method within the
 105             // same Junit @Test annotated method can proceed.
 106         } finally {
 107             disposeBuffer(addr1);
 108             disposeBuffer(addr2);
 109         }
 110     }
 111 
 112     @Test
 113     public void testByteBuffer() {
 114         int m = 42;
 115         try {
 116             ResolvedJavaMethod method = getResolvedJavaMethod("readWriteReadByteBuffer");
 117             Object receiver = method.isStatic() ? null : this;
 118             Result expect = executeExpected(method, receiver, ByteBuffer.allocateDirect(32), m);
 119             if (getCodeCache() == null) {
 120                 return;
 121             }
 122             ByteBuffer warmupBuffer = ByteBuffer.allocateDirect(32);
 123             for (int i = 0; i < 10000; ++i) {
 124                 readWriteReadByteBuffer(warmupBuffer, (i % 50) + 1);
 125                 warmupBuffer.putInt(0, 0);
 126             }
 127             testAgainstExpected(method, expect, receiver, ByteBuffer.allocateDirect(32), m);
 128         } catch (AssumptionViolatedException e) {
 129             // Suppress so that subsequent calls to this method within the
 130             // same Junit @Test annotated method can proceed.
 131         }
 132     }
 133 }