1 /* 2 * Copyright (c) 2015, 2018, 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 24 25 package org.graalvm.compiler.core.test; 26 27 import static java.nio.file.StandardOpenOption.READ; 28 import static java.nio.file.StandardOpenOption.WRITE; 29 30 import java.io.File; 31 import java.io.IOException; 32 import java.nio.ByteBuffer; 33 import java.nio.MappedByteBuffer; 34 import java.nio.channels.FileChannel; 35 import java.nio.channels.FileChannel.MapMode; 36 import java.nio.file.Files; 37 import java.nio.file.Path; 38 39 import org.graalvm.compiler.nodes.StructuredGraph; 40 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 41 import org.graalvm.compiler.phases.common.inlining.InliningPhase; 42 import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; 43 import org.graalvm.compiler.phases.tiers.HighTierContext; 44 import org.junit.Assert; 45 import org.junit.Assume; 46 import org.junit.Test; 47 48 import jdk.vm.ci.code.InstalledCode; 49 import jdk.vm.ci.code.InvalidInstalledCodeException; 50 import jdk.vm.ci.meta.ResolvedJavaMethod; 51 import jdk.vm.ci.meta.ResolvedJavaType; 52 import sun.misc.Unsafe; 53 54 public class MarkUnsafeAccessTest extends GraalCompilerTest { 55 56 public static Unsafe unsafe; 57 getRaw()58 public void getRaw() { 59 unsafe.getInt(0L); 60 } 61 get()62 public void get() { 63 unsafe.getInt(null, 0L); 64 } 65 putRaw()66 public void putRaw() { 67 unsafe.putInt(0L, 0); 68 } 69 put()70 public void put() { 71 unsafe.putInt(null, 0L, 0); 72 } 73 cas()74 public void cas() { 75 unsafe.compareAndSwapInt(null, 0, 0, 0); 76 } 77 noAccess()78 public void noAccess() { 79 unsafe.addressSize(); 80 unsafe.pageSize(); 81 } 82 assertHasUnsafe(String name, boolean hasUnsafe)83 private void assertHasUnsafe(String name, boolean hasUnsafe) { 84 Assert.assertEquals(hasUnsafe, compile(getResolvedJavaMethod(name), null).hasUnsafeAccess()); 85 } 86 87 @Test testGet()88 public void testGet() { 89 assertHasUnsafe("get", true); 90 assertHasUnsafe("getRaw", true); 91 } 92 93 @Test testPut()94 public void testPut() { 95 assertHasUnsafe("put", true); 96 assertHasUnsafe("putRaw", true); 97 } 98 99 @Test testCas()100 public void testCas() { 101 assertHasUnsafe("cas", true); 102 } 103 104 @Test testNoAcces()105 public void testNoAcces() { 106 assertHasUnsafe("noAccess", false); 107 } 108 109 @FunctionalInterface 110 private interface MappedByteBufferGetter { get(MappedByteBuffer mbb)111 byte get(MappedByteBuffer mbb); 112 } 113 114 @Test testStandard()115 public void testStandard() throws IOException { 116 testMappedByteBuffer(MappedByteBuffer::get); 117 } 118 119 @Test testCompiled()120 public void testCompiled() throws IOException { 121 Assume.assumeFalse("Crashes on AArch64 (GR-8351)", System.getProperty("os.arch").equalsIgnoreCase("aarch64")); 122 ResolvedJavaMethod getMethod = asResolvedJavaMethod(getMethod(ByteBuffer.class, "get", new Class<?>[]{})); 123 ResolvedJavaType mbbClass = getMetaAccess().lookupJavaType(MappedByteBuffer.class); 124 ResolvedJavaMethod getMethodImpl = mbbClass.findUniqueConcreteMethod(getMethod).getResult(); 125 Assert.assertNotNull(getMethodImpl); 126 StructuredGraph graph = parseForCompile(getMethodImpl); 127 HighTierContext highContext = getDefaultHighTierContext(); 128 new CanonicalizerPhase().apply(graph, highContext); 129 new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); 130 InstalledCode compiledCode = getCode(getMethodImpl, graph); 131 testMappedByteBuffer(mbb -> { 132 try { 133 return (byte) compiledCode.executeVarargs(mbb); 134 } catch (InvalidInstalledCodeException e) { 135 Assert.fail(); 136 return 0; 137 } 138 }); 139 } 140 141 private static final int BLOCK_SIZE = 512; 142 private static final int BLOCK_COUNT = 16; 143 testMappedByteBuffer(MappedByteBufferGetter getter)144 public void testMappedByteBuffer(MappedByteBufferGetter getter) throws IOException { 145 Path tmp = Files.createTempFile(null, null); 146 tmp.toFile().deleteOnExit(); 147 FileChannel tmpFileChannel = FileChannel.open(tmp, READ, WRITE); 148 ByteBuffer bb = ByteBuffer.allocate(BLOCK_SIZE); 149 while (bb.remaining() >= 4) { 150 bb.putInt(0xA8A8A8A8); 151 } 152 for (int i = 0; i < BLOCK_COUNT; ++i) { 153 bb.flip(); 154 while (bb.hasRemaining()) { 155 tmpFileChannel.write(bb); 156 } 157 } 158 tmpFileChannel.force(true); 159 MappedByteBuffer mbb = tmpFileChannel.map(MapMode.READ_WRITE, 0, BLOCK_SIZE * BLOCK_COUNT); 160 Assert.assertEquals((byte) 0xA8, mbb.get()); 161 mbb.position(mbb.position() + BLOCK_SIZE); 162 Assert.assertEquals((byte) 0xA8, mbb.get()); 163 boolean truncated = false; 164 try { 165 tmpFileChannel.truncate(0); 166 tmpFileChannel.force(true); 167 truncated = true; 168 } catch (IOException e) { 169 // not all platforms support truncating memory-mapped files 170 } 171 Assume.assumeTrue(truncated); 172 try { 173 mbb.position(BLOCK_SIZE); 174 getter.get(mbb); 175 176 // Make a call that goes into native code to materialize async exception 177 new File("").exists(); 178 } catch (InternalError e) { 179 return; 180 } 181 Assert.fail("Expected exception"); 182 } 183 } 184