1 /*
   2  * Copyright (c) 2015, 2015, 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.deopt;
  26 
  27 import java.util.concurrent.CountDownLatch;
  28 
  29 import org.junit.Assert;
  30 import org.junit.Assume;
  31 import org.junit.Test;
  32 
  33 import org.graalvm.compiler.core.common.GraalOptions;
  34 import org.graalvm.compiler.core.test.GraalCompilerTest;
  35 
  36 import jdk.vm.ci.code.InstalledCode;
  37 
  38 public final class SafepointRethrowDeoptTest extends GraalCompilerTest {
  39 
  40     private static final Object RETURN_VALUE = "1 2 3";
  41     private static final RuntimeException BREAK_EX = new RuntimeException();
  42     private static final RuntimeException CONTINUE_EX = new RuntimeException();
  43     private static volatile int terminate;
  44     private static volatile int entered;
  45 
  46     public static Object execute() {
  47         entered = 1;
  48         for (;;) {
  49             try {
  50                 if (terminate != 0) {
  51                     throw BREAK_EX;
  52                 } else {
  53                     throw CONTINUE_EX;
  54                 }
  55             } catch (RuntimeException e) {
  56                 if (e == BREAK_EX) {
  57                     break;
  58                 } else if (e == CONTINUE_EX) {
  59                     continue;
  60                 }
  61                 throw e;
  62             }
  63         }
  64         return RETURN_VALUE;
  65     }
  66 
  67     @Test
  68     public void test() {
  69         Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue());
  70         synchronized (SafepointRethrowDeoptTest.class) {
  71             // needs static fields
  72             terminate = 1;
  73 
  74             InstalledCode installed = getCode(getResolvedJavaMethod("execute"));
  75 
  76             terminate = 0;
  77             entered = 0;
  78             CountDownLatch cdl = new CountDownLatch(1);
  79             Thread t1 = new Thread(() -> {
  80                 try {
  81                     cdl.await();
  82                     while (entered == 0) {
  83                         /* spin */
  84                     }
  85                     installed.invalidate();
  86                 } catch (InterruptedException e) {
  87                     Assert.fail("interrupted");
  88                 } finally {
  89                     terminate = 1;
  90                 }
  91             });
  92             Thread t2 = new Thread(() -> {
  93                 cdl.countDown();
  94                 Object result;
  95                 try {
  96                     result = installed.executeVarargs();
  97                 } catch (Exception e) {
  98                     e.printStackTrace();
  99                     Assert.fail("exception");
 100                     return;
 101                 }
 102                 Assert.assertEquals(RETURN_VALUE, result);
 103             });
 104 
 105             t1.start();
 106             t2.start();
 107             try {
 108                 t1.join();
 109                 t2.join();
 110             } catch (InterruptedException e) {
 111                 Assert.fail("interrupted");
 112             }
 113         }
 114     }
 115 }