1 /*
   2  * Copyright (c) 2019, 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 import java.util.concurrent.atomic.AtomicInteger;
  26 import java.util.List;
  27 import java.util.HashMap;
  28 import java.util.ArrayList;
  29 
  30 public class ParallelLambdaLoad {
  31     public static int NUM_THREADS = 10;
  32     public static int MAX_CLASSES = 10;
  33     public static AtomicInteger num_ready[];
  34     public static boolean isRuntime;
  35 
  36     public static void main(String args[]) throws Throwable {
  37         isRuntime = (args.length == 1 && args[0].equals("run")) ? true : false;
  38         num_ready = new AtomicInteger[MAX_CLASSES];
  39         for (int i = 0; i < MAX_CLASSES; i++) {
  40             num_ready[i] = new AtomicInteger();
  41         }
  42 
  43         ArrayList<Thread> list = new ArrayList<>();
  44 
  45         list.add(new Thread(() -> {
  46                DoSomething ds = new DoSomething(0);
  47                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
  48                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
  49                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
  50                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
  51                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
  52                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
  53                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
  54                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
  55                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
  56                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
  57           }));
  58         list.add(new Thread(() -> {
  59                DoSomething ds = new DoSomething(1);
  60                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
  61                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
  62                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
  63                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
  64                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
  65                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
  66                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
  67                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
  68                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
  69                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
  70            }));
  71         list.add(new Thread(() -> {
  72                DoSomething ds = new DoSomething(2);
  73                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
  74                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
  75                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
  76                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
  77                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
  78                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
  79                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
  80                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
  81                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
  82                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
  83            }));
  84         list.add(new Thread(() -> {
  85                DoSomething ds = new DoSomething(3);
  86                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
  87                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
  88                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
  89                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
  90                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
  91                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
  92                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
  93                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
  94                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
  95                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
  96            }));
  97         list.add(new Thread(() -> {
  98                DoSomething ds = new DoSomething(4);
  99                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 100                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 101                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 102                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 103                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 104                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 105                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 106                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 107                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 108                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 109            }));
 110         list.add(new Thread(() -> {
 111                DoSomething ds = new DoSomething(5);
 112                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 113                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 114                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 115                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 116                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 117                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 118                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 119                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 120                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 121                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 122            }));
 123         list.add(new Thread(() -> {
 124                DoSomething ds = new DoSomething(6);
 125                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 126                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 127                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 128                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 129                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 130                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 131                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 132                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 133                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 134                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 135            }));
 136         list.add(new Thread(() -> {
 137                DoSomething ds = new DoSomething(7);
 138                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 139                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 140                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 141                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 142                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 143                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 144                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 145                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 146                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 147                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 148            }));
 149         list.add(new Thread(() -> {
 150                DoSomething ds = new DoSomething(8);
 151                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 152                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 153                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 154                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 155                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 156                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 157                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 158                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 159                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 160                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 161            }));
 162         list.add(new Thread(() -> {
 163                DoSomething ds = new DoSomething(9);
 164                {ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
 165                {ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
 166                {ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
 167                {ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
 168                {ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
 169                {ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
 170                {ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
 171                {ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
 172                {ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
 173                {ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
 174            }));
 175 
 176 
 177         for (Thread t : list) {
 178             t.start();
 179         }
 180 
 181         for (Thread t : list) {
 182             t.join();
 183         }
 184 
 185         synchronized(map) {
 186             System.out.println("map size " + map.size());
 187             int expectedSize = NUM_THREADS * MAX_CLASSES;
 188             if (map.size() != expectedSize) {
 189                 throw new RuntimeException("Expected number of lamdba classes is " +
 190                     expectedSize + " but got only " + map.size());
 191             }
 192         }
 193     }
 194 
 195     static HashMap<Class<?>, Class<?>> map = new HashMap<>();
 196 }
 197 
 198 class DoSomething {
 199     DoSomething(int dummy) {}
 200 
 201     public void run() {
 202         Class<?> c = LambdaVerification.getCallerClass(1);
 203         synchronized(ParallelLambdaLoad.map) {
 204             ParallelLambdaLoad.map.put(c, c);
 205         }
 206         LambdaVerification.verifyCallerIsArchivedLambda(ParallelLambdaLoad.isRuntime);
 207     }
 208 }
 209 
 210 class ThreadUtil {
 211     static void WaitForLock(int i) {
 212         // Spin until every thread is ready to proceed
 213         ParallelLambdaLoad.num_ready[i].incrementAndGet();
 214         while (ParallelLambdaLoad.num_ready[i].intValue() < ParallelLambdaLoad.NUM_THREADS) {
 215             ;
 216         }
 217     }
 218 }