1 /*
   2  * Copyright (c) 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 package jdk.internal.foreign.abi;
  24 
  25 import static sun.security.action.GetBooleanAction.privilegedGetProperty;
  26 
  27 public class ShuffleRecipe {
  28     private static final boolean DEBUG = privilegedGetProperty("jdk.internal.foreign.abi.ShuffleRecipe.DEBUG");
  29 
  30     private final long[] recipe;
  31 
  32     private final int nArgumentPulls;
  33     private final int nReturnPulls;
  34 
  35     ShuffleRecipe(long[] recipe, int nArgumentPulls, int nReturnPulls) {
  36         this.recipe = recipe;
  37         this.nArgumentPulls = nArgumentPulls;
  38         this.nReturnPulls = nReturnPulls;
  39     }
  40 
  41     public static ShuffleRecipe make(CallingSequence callingSequence) {
  42         ShuffleRecipeBuilder builder = new ShuffleRecipeBuilder();
  43 
  44         // Arguments
  45         callingSequence.getBindings(StorageClass.STACK_ARGUMENT_SLOT).stream().forEach(binding -> {
  46             if (binding == null) {
  47                 builder.getArgumentsCollector().add(ShuffleRecipeClass.STACK, ShuffleRecipeOperation.SKIP);
  48             } else {
  49                 builder.getArgumentsCollector().addPull(ShuffleRecipeClass.STACK);
  50             }
  51         });
  52 
  53         int indexInClass = 0;
  54         for(ArgumentBinding binding : callingSequence.getBindings(StorageClass.VECTOR_ARGUMENT_REGISTER)) {
  55             while(indexInClass < binding.getStorage().getStorageIndex()) {
  56                 builder.getArgumentsCollector().add(ShuffleRecipeClass.VECTOR, ShuffleRecipeOperation.SKIP);
  57                 indexInClass++;
  58             }
  59             builder.getArgumentsCollector().addPulls(ShuffleRecipeClass.VECTOR, binding.getStorage().getSize() / 8);
  60             indexInClass++;
  61         }
  62 
  63         indexInClass = 0;
  64         for(ArgumentBinding binding : callingSequence.getBindings(StorageClass.INTEGER_ARGUMENT_REGISTER)) {
  65             while(indexInClass < binding.getStorage().getStorageIndex()) {
  66                 builder.getArgumentsCollector().add(ShuffleRecipeClass.INTEGER, ShuffleRecipeOperation.SKIP);
  67                 indexInClass++;
  68             }
  69             builder.getArgumentsCollector().addPull(ShuffleRecipeClass.INTEGER);
  70             indexInClass++;
  71         }
  72 
  73         // Returns
  74         builder.getReturnsCollector().addPulls(ShuffleRecipeClass.INTEGER, callingSequence.getBindings(StorageClass.INTEGER_RETURN_REGISTER).size());
  75 
  76         callingSequence.getBindings(StorageClass.VECTOR_RETURN_REGISTER).stream().forEach(binding -> {
  77             builder.getReturnsCollector().addPulls(ShuffleRecipeClass.VECTOR, binding.getStorage().getSize() / 8);
  78         });
  79 
  80         callingSequence.getBindings(StorageClass.X87_RETURN_REGISTER).stream().forEach(binding -> {
  81             builder.getReturnsCollector().addPulls(ShuffleRecipeClass.X87, binding.getStorage().getSize() / 8);
  82         });
  83 
  84         if(DEBUG) {
  85             System.out.println("Translating CallingSequence:");
  86             System.out.println(callingSequence.asString().indent(2));
  87             System.out.println("into:");
  88             System.out.println(builder.asString().indent(2));
  89         }
  90 
  91         return builder.build();
  92     }
  93 
  94     public long[] getRecipe() {
  95         return recipe;
  96     }
  97 
  98     public int getNoofArgumentPulls() {
  99         return nArgumentPulls;
 100     }
 101 
 102     public int getNoofReturnPulls() {
 103         return nReturnPulls;
 104     }
 105 
 106     @Override
 107     public String toString() {
 108         StringBuilder sb = new StringBuilder();
 109 
 110         sb.append("ShuffleRecipe { nArgumentPulls: ").append(nArgumentPulls).append(" nReturnPulls: ").append(nReturnPulls).append("}\n");
 111 
 112         return sb.toString();
 113     }
 114 }