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.replacements.test; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import org.junit.*; 030 031import com.oracle.graal.api.directives.*; 032import com.oracle.graal.compiler.test.*; 033import com.oracle.graal.graphbuilderconf.GraphBuilderConfiguration.Plugins; 034import com.oracle.graal.graphbuilderconf.*; 035import com.oracle.graal.graphbuilderconf.InvocationPlugins.Registration; 036import com.oracle.graal.nodes.*; 037import com.oracle.graal.replacements.*; 038import com.oracle.graal.word.*; 039import com.oracle.graal.word.nodes.*; 040 041/** 042 * Tests for derived oops in reference maps. 043 */ 044public class DerivedOopTest extends GraalCompilerTest implements Snippets { 045 046 private static class Pointers { 047 public long basePointer; 048 public long internalPointer; 049 050 public long delta() { 051 return internalPointer - basePointer; 052 } 053 054 @Override 055 public boolean equals(Object obj) { 056 if (!(obj instanceof Pointers)) { 057 return false; 058 } 059 060 Pointers other = (Pointers) obj; 061 return this.delta() == other.delta(); 062 } 063 064 @Override 065 public int hashCode() { 066 return (int) delta(); 067 } 068 } 069 070 private static class Result { 071 public Pointers beforeGC; 072 public Pointers afterGC; 073 074 public Result() { 075 beforeGC = new Pointers(); 076 afterGC = new Pointers(); 077 } 078 079 @Override 080 public int hashCode() { 081 final int prime = 31; 082 int result = 1; 083 result = prime * result + ((afterGC == null) ? 0 : afterGC.hashCode()); 084 result = prime * result + ((beforeGC == null) ? 0 : beforeGC.hashCode()); 085 return result; 086 } 087 088 @Override 089 public boolean equals(Object obj) { 090 if (!(obj instanceof Result)) { 091 return false; 092 } 093 Result other = (Result) obj; 094 return Objects.equals(this.beforeGC, other.beforeGC) && Objects.equals(this.afterGC, other.afterGC); 095 } 096 } 097 098 @Test 099 public void testFieldOffset() { 100 // Run a couple times to encourage objects to move 101 for (int i = 0; i < 4; i++) { 102 Result r = new Result(); 103 test("fieldOffsetSnippet", r, 16L); 104 105 Assert.assertEquals(r.beforeGC.delta(), r.afterGC.delta()); 106 } 107 } 108 109 static long getRawPointer(Object obj) { 110 // fake implementation for interpreter 111 return obj.hashCode(); 112 } 113 114 static long getRawPointerIntrinsic(Object obj) { 115 return Word.fromObject(obj).rawValue(); 116 } 117 118 public static Result fieldOffsetSnippet(Result obj, long offset) { 119 long internalPointer = getRawPointer(obj) + offset; 120 121 // make sure the internal pointer is computed before the safepoint 122 GraalDirectives.blackhole(internalPointer); 123 124 obj.beforeGC.basePointer = getRawPointer(obj); 125 obj.beforeGC.internalPointer = internalPointer; 126 127 System.gc(); 128 129 obj.afterGC.basePointer = getRawPointer(obj); 130 obj.afterGC.internalPointer = internalPointer; 131 132 return obj; 133 } 134 135 @Override 136 protected Plugins getDefaultGraphBuilderPlugins() { 137 Plugins plugins = super.getDefaultGraphBuilderPlugins(); 138 Registration r = new Registration(plugins.getInvocationPlugins(), DerivedOopTest.class); 139 140 ResolvedJavaMethod intrinsic = getResolvedJavaMethod("getRawPointerIntrinsic"); 141 r.register1("getRawPointer", Object.class, new InvocationPlugin() { 142 public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { 143 b.intrinsify(targetMethod, intrinsic, new ValueNode[]{arg}); 144 return true; 145 } 146 }); 147 148 return plugins; 149 } 150 151 @Override 152 protected boolean checkHighTierGraph(StructuredGraph graph) { 153 assert graph.getNodes().filter(WordCastNode.class).count() > 0 : "DerivedOopTest.toLong should be intrinsified"; 154 return super.checkHighTierGraph(graph); 155 } 156}