001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.test; 024 025import static java.nio.file.StandardOpenOption.*; 026 027import java.io.*; 028import java.nio.*; 029import java.nio.channels.*; 030import java.nio.channels.FileChannel.*; 031import java.nio.file.*; 032 033import org.junit.*; 034 035import com.oracle.graal.nodes.*; 036import com.oracle.graal.phases.common.*; 037import com.oracle.graal.phases.common.inlining.*; 038import com.oracle.graal.phases.common.inlining.policy.*; 039import com.oracle.graal.phases.tiers.*; 040 041import jdk.internal.jvmci.code.*; 042import jdk.internal.jvmci.meta.*; 043import sun.misc.*; 044 045public class MarkUnsafeAccessTest extends GraalCompilerTest { 046 047 public static Unsafe unsafe; 048 049 public void getRaw() { 050 unsafe.getInt(0L); 051 } 052 053 public void get() { 054 unsafe.getInt(null, 0L); 055 } 056 057 public void putRaw() { 058 unsafe.putInt(0L, 0); 059 } 060 061 public void put() { 062 unsafe.putInt(null, 0L, 0); 063 } 064 065 public void cas() { 066 unsafe.compareAndSwapInt(null, 0, 0, 0); 067 } 068 069 public void noAccess() { 070 unsafe.addressSize(); 071 unsafe.pageSize(); 072 } 073 074 private void assertHasUnsafe(String name, boolean hasUnsafe) { 075 Assert.assertEquals(hasUnsafe, compile(getResolvedJavaMethod(name), null).hasUnsafeAccess()); 076 } 077 078 @Test 079 public void testGet() { 080 assertHasUnsafe("get", true); 081 assertHasUnsafe("getRaw", true); 082 } 083 084 @Test 085 public void testPut() { 086 assertHasUnsafe("put", true); 087 assertHasUnsafe("putRaw", true); 088 } 089 090 @Test 091 public void testCas() { 092 assertHasUnsafe("cas", true); 093 } 094 095 @Test 096 public void testNoAcces() { 097 assertHasUnsafe("noAccess", false); 098 } 099 100 @FunctionalInterface 101 private interface MappedByteBufferGetter { 102 byte get(MappedByteBuffer mbb); 103 } 104 105 @Test 106 public void testStandard() throws IOException { 107 testMappedByteBuffer(MappedByteBuffer::get); 108 } 109 110 @Test 111 public void testCompiled() throws IOException { 112 ResolvedJavaMethod getMethod = asResolvedJavaMethod(getMethod(ByteBuffer.class, "get", new Class<?>[]{})); 113 ResolvedJavaType mbbClass = getMetaAccess().lookupJavaType(MappedByteBuffer.class); 114 ResolvedJavaMethod getMethodImpl = mbbClass.findUniqueConcreteMethod(getMethod).getResult(); 115 Assert.assertNotNull(getMethodImpl); 116 StructuredGraph graph = parseForCompile(getMethodImpl); 117 HighTierContext highContext = getDefaultHighTierContext(); 118 new CanonicalizerPhase().apply(graph, highContext); 119 new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); 120 InstalledCode compiledCode = getCode(getMethodImpl, graph); 121 testMappedByteBuffer(mbb -> { 122 try { 123 return (byte) compiledCode.executeVarargs(mbb); 124 } catch (InvalidInstalledCodeException e) { 125 Assert.fail(); 126 return 0; 127 } 128 }); 129 } 130 131 private static final int BLOCK_SIZE = 512; 132 private static final int BLOCK_COUNT = 16; 133 134 public void testMappedByteBuffer(MappedByteBufferGetter getter) throws IOException { 135 Path tmp = Files.createTempFile(null, null); 136 tmp.toFile().deleteOnExit(); 137 FileChannel tmpFileChannel = FileChannel.open(tmp, READ, WRITE); 138 ByteBuffer bb = ByteBuffer.allocate(BLOCK_SIZE); 139 while (bb.remaining() >= 4) { 140 bb.putInt(0xA8A8A8A8); 141 } 142 for (int i = 0; i < BLOCK_COUNT; ++i) { 143 bb.flip(); 144 while (bb.hasRemaining()) { 145 tmpFileChannel.write(bb); 146 } 147 } 148 tmpFileChannel.force(true); 149 MappedByteBuffer mbb = tmpFileChannel.map(MapMode.READ_WRITE, 0, BLOCK_SIZE * BLOCK_COUNT); 150 Assert.assertEquals((byte) 0xA8, mbb.get()); 151 mbb.position(mbb.position() + BLOCK_SIZE); 152 Assert.assertEquals((byte) 0xA8, mbb.get()); 153 boolean truncated = false; 154 try { 155 tmpFileChannel.truncate(0); 156 tmpFileChannel.force(true); 157 truncated = true; 158 } catch (IOException e) { 159 // not all platforms support truncating memory-mapped files 160 } 161 Assume.assumeTrue(truncated); 162 try { 163 mbb.position(BLOCK_SIZE); 164 getter.get(mbb); 165 System.currentTimeMillis(); // materialize async exception 166 } catch (InternalError e) { 167 return; 168 } 169 Assert.fail("Expected exception"); 170 } 171}