001/* 002 * Copyright (c) 2014, 2014, 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 */ 023 024package com.oracle.graal.hotspot.amd64.test; 025 026import jdk.internal.jvmci.amd64.*; 027import jdk.internal.jvmci.hotspot.*; 028import jdk.internal.jvmci.meta.*; 029import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; 030import static jdk.internal.jvmci.code.ValueUtil.*; 031 032import org.junit.*; 033 034import com.oracle.graal.api.replacements.*; 035import com.oracle.graal.asm.amd64.*; 036import com.oracle.graal.graph.*; 037import com.oracle.graal.hotspot.*; 038import com.oracle.graal.hotspot.nodes.*; 039import com.oracle.graal.hotspot.nodes.CompressionNode.CompressionOp; 040import com.oracle.graal.hotspot.nodes.type.*; 041import com.oracle.graal.hotspot.test.*; 042import com.oracle.graal.lir.*; 043import com.oracle.graal.lir.asm.*; 044import com.oracle.graal.lir.gen.*; 045import com.oracle.graal.nodeinfo.*; 046import com.oracle.graal.nodes.*; 047import com.oracle.graal.nodes.spi.*; 048 049public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { 050 051 @Before 052 public void checkAMD64() { 053 Assume.assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64); 054 } 055 056 private static final Object object = new Object() { 057 058 @Override 059 public String toString() { 060 return "testObject"; 061 } 062 }; 063 064 private static Object loadThroughPatch(Object obj) { 065 return obj; 066 } 067 068 public static Object oopSnippet() { 069 Object patch = loadThroughPatch(object); 070 if (object != patch) { 071 return "invalid patch"; 072 } 073 System.gc(); 074 patch = loadThroughPatch(object); 075 if (object != patch) { 076 return "failed after gc"; 077 } 078 return patch; 079 } 080 081 @Test 082 public void oopTest() { 083 test("oopSnippet"); 084 } 085 086 private static Object loadThroughCompressedPatch(Object obj) { 087 return obj; 088 } 089 090 public static Object narrowOopSnippet() { 091 Object patch = loadThroughCompressedPatch(object); 092 if (object != patch) { 093 return "invalid patch"; 094 } 095 System.gc(); 096 patch = loadThroughCompressedPatch(object); 097 if (object != patch) { 098 return "failed after gc"; 099 } 100 return patch; 101 } 102 103 @Test 104 public void narrowOopTest() { 105 Assume.assumeTrue("skipping narrow oop data patch test", config.useCompressedOops); 106 test("narrowOopSnippet"); 107 } 108 109 public static Object compareSnippet() { 110 Object uncompressed = loadThroughPatch(object); 111 Object compressed = loadThroughCompressedPatch(object); 112 if (object != uncompressed) { 113 return "uncompressed failed"; 114 } 115 if (object != compressed) { 116 return "compressed failed"; 117 } 118 if (uncompressed != compressed) { 119 return "uncompressed != compressed"; 120 } 121 return object; 122 } 123 124 @Test 125 public void compareTest() { 126 Assume.assumeTrue("skipping narrow oop data patch test", config.useCompressedOops); 127 test("compareSnippet"); 128 } 129 130 private static final HotSpotVMConfig config = HotSpotGraalRuntime.runtime().getConfig(); 131 private static boolean initReplacements = false; 132 133 @Before 134 public void initReplacements() { 135 if (!initReplacements) { 136 getReplacements().registerSubstitutions(DataPatchInConstantsTest.class, DataPatchInConstantsTestSubstitutions.class); 137 initReplacements = true; 138 } 139 } 140 141 @ClassSubstitution(DataPatchInConstantsTest.class) 142 private static class DataPatchInConstantsTestSubstitutions { 143 144 @MethodSubstitution 145 public static Object loadThroughPatch(Object obj) { 146 return LoadThroughPatchNode.load(obj); 147 } 148 149 @MethodSubstitution 150 public static Object loadThroughCompressedPatch(Object obj) { 151 Object compressed = CompressionNode.compression(CompressionOp.Compress, obj, config.getOopEncoding()); 152 Object patch = LoadThroughPatchNode.load(compressed); 153 return CompressionNode.compression(CompressionOp.Uncompress, patch, config.getOopEncoding()); 154 } 155 } 156 157 @NodeInfo 158 private static final class LoadThroughPatchNode extends FixedWithNextNode implements LIRLowerable { 159 public static final NodeClass<LoadThroughPatchNode> TYPE = NodeClass.create(LoadThroughPatchNode.class); 160 161 @Input protected ValueNode input; 162 163 public LoadThroughPatchNode(ValueNode input) { 164 super(TYPE, input.stamp()); 165 this.input = input; 166 } 167 168 public void generate(NodeLIRBuilderTool generator) { 169 assert input.isConstant(); 170 171 LIRGeneratorTool gen = generator.getLIRGeneratorTool(); 172 Variable ret = gen.newVariable(gen.getLIRKind(stamp())); 173 174 gen.append(new LoadThroughPatchOp(input.asConstant(), stamp() instanceof NarrowOopStamp, ret)); 175 generator.setResult(this, ret); 176 } 177 178 @NodeIntrinsic 179 public static native Object load(Object obj); 180 } 181 182 private static final class LoadThroughPatchOp extends LIRInstruction { 183 public static final LIRInstructionClass<LoadThroughPatchOp> TYPE = LIRInstructionClass.create(LoadThroughPatchOp.class); 184 185 final Constant c; 186 final boolean compressed; 187 @Def({REG}) AllocatableValue result; 188 189 LoadThroughPatchOp(Constant c, boolean compressed, AllocatableValue result) { 190 super(TYPE); 191 this.c = c; 192 this.compressed = compressed; 193 this.result = result; 194 } 195 196 @Override 197 public void emitCode(CompilationResultBuilder crb) { 198 AMD64Address address = (AMD64Address) crb.recordDataReferenceInCode(c, compressed ? 4 : 8); 199 AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm; 200 if (compressed) { 201 asm.movl(asRegister(result), address); 202 } else { 203 asm.movq(asRegister(result), address); 204 } 205 } 206 } 207}