001/* 002 * Copyright (c) 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.truffle.test; 024 025import org.junit.*; 026 027import com.oracle.graal.truffle.test.nodes.*; 028import com.oracle.truffle.api.*; 029import com.oracle.truffle.api.frame.*; 030import com.oracle.truffle.api.instrument.*; 031import com.oracle.truffle.api.instrument.impl.*; 032import com.oracle.truffle.api.nodes.*; 033 034/** 035 * Tests for a single simple PE test with various combinations of instrumentation attached. None of 036 * the instrumentation ultimate does anything, so should compile away. 037 */ 038public class InstrumentationPartialEvaluationTest extends PartialEvaluationTest { 039 040 public static Object constant42() { 041 return 42; 042 } 043 044 @Test 045 public void constantValueUninstrumented() { 046 FrameDescriptor fd = new FrameDescriptor(); 047 AbstractTestNode result = new ConstantTestNode(42); 048 RootTestNode root = new RootTestNode(fd, "constantValue", result); 049 root.adoptChildren(); 050 assertPartialEvalEquals("constant42", root); 051 } 052 053 @Test 054 public void constantValueProbedNoInstruments() { 055 FrameDescriptor fd = new FrameDescriptor(); 056 AbstractTestNode result = new ConstantTestNode(42); 057 RootTestNode root = new RootTestNode(fd, "constantValue", result); 058 root.adoptChildren(); 059 result.probe(); 060 assertPartialEvalEquals("constant42", root); 061 } 062 063 @Test 064 public void constantValueProbedNullInstrument1() { 065 FrameDescriptor fd = new FrameDescriptor(); 066 AbstractTestNode result = new ConstantTestNode(42); 067 RootTestNode root = new RootTestNode(fd, "constantValue", result); 068 root.adoptChildren(); 069 Probe probe = result.probe(); 070 Instrument instrument = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument"); 071 probe.attach(instrument); 072 assertPartialEvalEquals("constant42", root); 073 } 074 075 @Test 076 public void constantValueProbedNullInstrument2() { 077 FrameDescriptor fd = new FrameDescriptor(); 078 AbstractTestNode result = new ConstantTestNode(42); 079 RootTestNode root = new RootTestNode(fd, "constantValue", result); 080 root.adoptChildren(); 081 Probe probe = result.probe(); 082 Instrument instrument = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument"); 083 probe.attach(instrument); 084 assertPartialEvalEquals("constant42", root); 085 } 086 087 @Test 088 public void constantValueProbedNullInstrumentDisposed1() { 089 FrameDescriptor fd = new FrameDescriptor(); 090 AbstractTestNode result = new ConstantTestNode(42); 091 RootTestNode root = new RootTestNode(fd, "constantValue", result); 092 root.adoptChildren(); 093 Probe probe = result.probe(); 094 Instrument instrument = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument"); 095 probe.attach(instrument); 096 instrument.dispose(); 097 assertPartialEvalEquals("constant42", root); 098 } 099 100 @Test 101 public void constantValueProbedNullInstrumentDisposed2() { 102 FrameDescriptor fd = new FrameDescriptor(); 103 AbstractTestNode result = new ConstantTestNode(42); 104 RootTestNode root = new RootTestNode(fd, "constantValue", result); 105 root.adoptChildren(); 106 Probe probe = result.probe(); 107 Instrument instrument = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument"); 108 probe.attach(instrument); 109 instrument.dispose(); 110 assertPartialEvalEquals("constant42", root); 111 } 112 113 @Test 114 public void constantValueProbedTwoNullInstruments1() { 115 FrameDescriptor fd = new FrameDescriptor(); 116 AbstractTestNode result = new ConstantTestNode(42); 117 RootTestNode root = new RootTestNode(fd, "constantValue", result); 118 root.adoptChildren(); 119 Probe probe = result.probe(); 120 Instrument instrument1 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 1"); 121 probe.attach(instrument1); 122 Instrument instrument2 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 2"); 123 probe.attach(instrument2); 124 assertPartialEvalEquals("constant42", root); 125 } 126 127 @Test 128 public void constantValueProbedTwoNullInstruments2() { 129 FrameDescriptor fd = new FrameDescriptor(); 130 AbstractTestNode result = new ConstantTestNode(42); 131 RootTestNode root = new RootTestNode(fd, "constantValue", result); 132 root.adoptChildren(); 133 Probe probe = result.probe(); 134 Instrument instrument1 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 1"); 135 probe.attach(instrument1); 136 Instrument instrument2 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 2"); 137 probe.attach(instrument2); 138 assertPartialEvalEquals("constant42", root); 139 } 140 141 @Test 142 public void constantValueProbedThreeNullInstruments1() { 143 FrameDescriptor fd = new FrameDescriptor(); 144 AbstractTestNode result = new ConstantTestNode(42); 145 RootTestNode root = new RootTestNode(fd, "constantValue", result); 146 root.adoptChildren(); 147 Probe probe = result.probe(); 148 Instrument instrument1 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 1"); 149 probe.attach(instrument1); 150 Instrument instrument2 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 2"); 151 probe.attach(instrument2); 152 Instrument instrument3 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 3"); 153 probe.attach(instrument3); 154 assertPartialEvalEquals("constant42", root); 155 } 156 157 @Test 158 public void constantValueProbedThreeNullInstruments2() { 159 FrameDescriptor fd = new FrameDescriptor(); 160 AbstractTestNode result = new ConstantTestNode(42); 161 RootTestNode root = new RootTestNode(fd, "constantValue", result); 162 root.adoptChildren(); 163 Probe probe = result.probe(); 164 Instrument instrument1 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 1"); 165 probe.attach(instrument1); 166 Instrument instrument2 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 2"); 167 probe.attach(instrument2); 168 Instrument instrument3 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 3"); 169 probe.attach(instrument3); 170 assertPartialEvalEquals("constant42", root); 171 } 172 173 @Test 174 public void constantValueProbedThreeNullInstrumentsOneDisposed1() { 175 FrameDescriptor fd = new FrameDescriptor(); 176 AbstractTestNode result = new ConstantTestNode(42); 177 RootTestNode root = new RootTestNode(fd, "constantValue", result); 178 root.adoptChildren(); 179 Probe probe = result.probe(); 180 Instrument instrument1 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 1"); 181 probe.attach(instrument1); 182 Instrument instrument2 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 2"); 183 probe.attach(instrument2); 184 Instrument instrument3 = Instrument.create(new DefaultSimpleInstrumentListener(), "Null test Instrument 3"); 185 probe.attach(instrument3); 186 instrument2.dispose(); 187 assertPartialEvalEquals("constant42", root); 188 } 189 190 @Test 191 public void constantValueProbedThreeNullInstrumentsOneDisposed2() { 192 FrameDescriptor fd = new FrameDescriptor(); 193 AbstractTestNode result = new ConstantTestNode(42); 194 RootTestNode root = new RootTestNode(fd, "constantValue", result); 195 root.adoptChildren(); 196 Probe probe = result.probe(); 197 Instrument instrument1 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 1"); 198 probe.attach(instrument1); 199 Instrument instrument2 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 2"); 200 probe.attach(instrument2); 201 Instrument instrument3 = Instrument.create(new DefaultStandardInstrumentListener(), "Null test Instrument 3"); 202 probe.attach(instrument3); 203 instrument2.dispose(); 204 assertPartialEvalEquals("constant42", root); 205 } 206 207 @Test 208 public void constantValueInertAdvancedInstrumentRootFactory() { 209 FrameDescriptor fd = new FrameDescriptor(); 210 AbstractTestNode result = new ConstantTestNode(42); 211 RootTestNode root = new RootTestNode(fd, "constantValue", result); 212 root.adoptChildren(); 213 Probe testProbe = result.probe(); 214 // A factory that could insert a AdvancedInstrumentRoot into the AST, but which never does. 215 Instrument instrument = Instrument.create(null, new AdvancedInstrumentRootFactory() { 216 217 public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) { 218 return null; 219 } 220 }, null, "test AdvancedInstrument"); 221 testProbe.attach(instrument); 222 223 // It all gets compiled away 224 assertPartialEvalEquals("constant42", root); 225 } 226 227 @Test 228 public void constantValueInertAdvancedInstrumentRoot() { 229 FrameDescriptor fd = new FrameDescriptor(); 230 AbstractTestNode resultTestNode = new ConstantTestNode(42); 231 RootTestNode rootTestNode = new RootTestNode(fd, "constantValue", resultTestNode); 232 rootTestNode.adoptChildren(); 233 Probe testProbe = resultTestNode.probe(); 234 // Factory inserts a AdvancedInstrumentRoot with empty methods into instrumentation . 235 Instrument instrument = Instrument.create(null, new AdvancedInstrumentRootFactory() { 236 237 @Override 238 public AdvancedInstrumentRoot createInstrumentRoot(Probe probe, Node node) { 239 return new AdvancedInstrumentRoot() { 240 241 public String instrumentationInfo() { 242 return null; 243 } 244 245 @Override 246 public Object executeRoot(Node n, VirtualFrame frame) { 247 return null; 248 } 249 }; 250 } 251 }, null, "test AdvancedInstrument"); 252 testProbe.attach(instrument); 253 254 // It all gets compiled away. 255 assertPartialEvalEquals("constant42", rootTestNode); 256 } 257 258 @Test 259 public void instrumentDeopt() { 260 final FrameDescriptor fd = new FrameDescriptor(); 261 final AbstractTestNode result = new ConstantTestNode(42); 262 final RootTestNode root = new RootTestNode(fd, "constantValue", result); 263 final Probe[] probe = new Probe[1]; 264 final int[] count = {1}; 265 count[0] = 0; 266 // Register a "prober" that will get applied when CallTarget gets created. 267 final ASTProber prober = new ASTProber() { 268 269 @Override 270 public void probeAST(Node node) { 271 node.accept(new NodeVisitor() { 272 273 @Override 274 public boolean visit(Node visitedNode) { 275 if (visitedNode instanceof ConstantTestNode) { 276 probe[0] = visitedNode.probe(); 277 } 278 return true; 279 } 280 281 }); 282 } 283 }; 284 Probe.registerASTProber(prober); 285 try { 286 final RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(root); 287 288 // The CallTarget has one Probe, attached to the ConstantTestNode, ready to run 289 Assert.assertEquals(42, callTarget.call()); // Correct result 290 Assert.assertEquals(0, count[0]); // Didn't count anything 291 292 // Add a counting instrument; this changes the "Probe state" and should cause a deopt 293 final Instrument countingInstrument = Instrument.create(new DefaultSimpleInstrumentListener() { 294 295 @Override 296 public void enter(Probe p) { 297 count[0] = count[0] + 1; 298 } 299 }, null); 300 probe[0].attach(countingInstrument); 301 302 Assert.assertEquals(42, callTarget.call()); // Correct result 303 Assert.assertEquals(1, count[0]); // Counted the first call 304 305 // Remove the counting instrument; this changes the "Probe state" and should cause a 306 // deopt 307 countingInstrument.dispose(); 308 309 Assert.assertEquals(42, callTarget.call()); // Correct result 310 Assert.assertEquals(1, count[0]); // Didn't count this time 311 } finally { 312 Probe.unregisterASTProber(prober); 313 } 314 315 } 316 317 /** 318 * Experimental feature; not yet validated. 319 */ 320 @Test 321 public void specialOptInstrument() { 322 final FrameDescriptor fd = new FrameDescriptor(); 323 final AbstractTestNode result = new ConstantTestNode(42); 324 final RootTestNode root = new RootTestNode(fd, "constantValue", result); 325 final Probe[] probe = new Probe[1]; 326 final int[] count = {1}; 327 count[0] = 0; 328 // Register a "prober" that will get applied when CallTarget gets created. 329 final ASTProber prober = new ASTProber() { 330 331 @Override 332 public void probeAST(Node node) { 333 node.accept(new NodeVisitor() { 334 335 @Override 336 public boolean visit(Node visitedNode) { 337 if (visitedNode instanceof ConstantTestNode) { 338 probe[0] = visitedNode.probe(); 339 } 340 return true; 341 } 342 }); 343 } 344 }; 345 Probe.registerASTProber(prober); 346 try { 347 final RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(root); 348 349 // The CallTarget has one Probe, attached to the ConstantTestNode, ready to run 350 Assert.assertEquals(42, callTarget.call()); // Correct result 351 352 final boolean[] isCurrentlyCompiled = {false}; 353 final Instrument optInstrument = Instrument.create(new Instrument.TruffleOptListener() { 354 355 @Override 356 public void notifyIsCompiled(boolean isCompiled) { 357 isCurrentlyCompiled[0] = isCompiled; 358 } 359 }); 360 probe[0].attach(optInstrument); 361 362 Assert.assertEquals(42, callTarget.call()); // Correct result 363 Assert.assertFalse(isCurrentlyCompiled[0]); 364 365 // TODO (mlvdv) compile, call again, and assert that isCurrentlyCompiled == true 366 367 } finally { 368 Probe.unregisterASTProber(prober); 369 } 370 371 } 372}