JRubyCallSite.java

  1. /*
  2.  ***** BEGIN LICENSE BLOCK *****
  3.  * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Eclipse Public
  6.  * License Version 1.0 (the "License"); you may not use this file
  7.  * except in compliance with the License. You may obtain a copy of
  8.  * the License at http://www.eclipse.org/legal/epl-v10.html
  9.  *
  10.  * Software distributed under the License is distributed on an "AS
  11.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  12.  * implied. See the License for the specific language governing
  13.  * rights and limitations under the License.
  14.  *
  15.  * Alternatively, the contents of this file may be used under the terms of
  16.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  17.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  18.  * in which case the provisions of the GPL or the LGPL are applicable instead
  19.  * of those above. If you wish to allow use of your version of this file only
  20.  * under the terms of either the GPL or the LGPL, and not to allow others to
  21.  * use your version of this file under the terms of the EPL, indicate your
  22.  * decision by deleting the provisions above and replace them with the notice
  23.  * and other provisions required by the GPL or the LGPL. If you do not delete
  24.  * the provisions above, a recipient may use your version of this file under
  25.  * the terms of any one of the EPL, the GPL or the LGPL.
  26.  ***** END LICENSE BLOCK *****/

  27. package org.jruby.runtime.invokedynamic;

  28. import com.headius.invokebinder.Signature;
  29. import java.lang.invoke.MethodHandle;
  30. import java.lang.invoke.MethodHandles.Lookup;
  31. import java.lang.invoke.MethodType;
  32. import java.lang.invoke.MutableCallSite;
  33. import java.util.Collections;
  34. import java.util.HashSet;
  35. import java.util.Set;
  36. import java.util.concurrent.atomic.AtomicLong;

  37. import org.jruby.RubyClass;
  38. import org.jruby.runtime.Block;

  39. import org.jruby.runtime.CallType;
  40. import org.jruby.runtime.ThreadContext;
  41. import org.jruby.runtime.builtin.IRubyObject;
  42. import org.jruby.runtime.callsite.CacheEntry;

  43. public class JRubyCallSite extends MutableCallSite {
  44.     private final Lookup lookup;
  45.     private final CallType callType;
  46.     public CacheEntry entry = CacheEntry.NULL_CACHE;
  47.     private final Set<Integer> seenTypes = new HashSet<Integer>();
  48.     private final boolean expression;
  49.     private final String name;
  50.     private int clearCount;
  51.     private static final AtomicLong SITE_ID = new AtomicLong(1);
  52.     private final long siteID = SITE_ID.getAndIncrement();
  53.     private final String file;
  54.     private final int line;
  55.     private boolean boundOnce = false;
  56.     private final Signature signature;
  57.     private final Signature fullSignature;
  58.     private final int arity;

  59.     public JRubyCallSite(Lookup lookup, MethodType type, CallType callType, String file, int line, String name, boolean expression) {
  60.         super(type);

  61.         this.name = name;
  62.         this.callType = callType;

  63.         Signature startSig;
  64.         int argOffset;

  65.         if (callType == CallType.SUPER) {
  66.             // super calls receive current class argument, so offsets and signature are different
  67.             startSig = JRubyCallSite.STANDARD_SUPER_SIG;
  68.             argOffset = 4;
  69.         } else {
  70.             startSig = JRubyCallSite.STANDARD_SITE_SIG;
  71.             argOffset = 3;
  72.         }

  73.         int arity;
  74.         if (type.parameterType(type.parameterCount() - 1) == Block.class) {
  75.             arity = type.parameterCount() - (argOffset + 1);

  76.             if (arity == 1 && type.parameterType(argOffset) == IRubyObject[].class) {
  77.                 arity = -1;
  78.                 startSig = startSig.appendArg("args", IRubyObject[].class);
  79.             } else {
  80.                 for (int i = 0; i < arity; i++) {
  81.                     startSig = startSig.appendArg("arg" + i, IRubyObject.class);
  82.                 }
  83.             }
  84.             startSig = startSig.appendArg("block", Block.class);
  85.             fullSignature = signature = startSig;
  86.         } else {
  87.             arity = type.parameterCount() - argOffset;

  88.             if (arity == 1 && type.parameterType(argOffset) == IRubyObject[].class) {
  89.                 arity = -1;
  90.                 startSig = startSig.appendArg("args", IRubyObject[].class);
  91.             } else {
  92.                 for (int i = 0; i < arity; i++) {
  93.                     startSig = startSig.appendArg("arg" + i, IRubyObject.class);
  94.                 }
  95.             }
  96.             signature = startSig;
  97.             fullSignature = startSig.appendArg("block", Block.class);
  98.         }

  99.         this.arity = arity;

  100.         this.lookup = lookup;
  101.         this.expression = expression;
  102.         this.file = file;
  103.         this.line = line;
  104.     }
  105.    
  106.     public int arity() {
  107.         return arity;
  108.     }
  109.    
  110.     public Lookup lookup() {
  111.         return lookup;
  112.     }

  113.     public CallType callType() {
  114.         return callType;
  115.     }

  116.     public boolean isAttrAssign() {
  117.         return false;
  118.     }

  119.     public boolean isIterator() {
  120.         return false;
  121.     }
  122.    
  123.     public boolean isExpression() {
  124.         return expression;
  125.     }
  126.    
  127.     public String name() {
  128.         return name;
  129.     }
  130.    
  131.     public synchronized boolean hasSeenType(int typeCode) {
  132.         return seenTypes.contains(typeCode);
  133.     }
  134.    
  135.     public synchronized void addType(int typeCode) {
  136.         seenTypes.add(typeCode);
  137.     }
  138.    
  139.     public synchronized int seenTypesCount() {
  140.         return seenTypes.size();
  141.     }
  142.    
  143.     public synchronized void clearTypes() {
  144.         seenTypes.clear();
  145.         clearCount++;
  146.     }
  147.    
  148.     public int clearCount() {
  149.         return clearCount;
  150.     }

  151.     public long siteID() {
  152.         return siteID;
  153.     }

  154.     public String file() {
  155.         return file;
  156.     }

  157.     public int line() {
  158.         return line;
  159.     }

  160.     public boolean boundOnce() {
  161.         return boundOnce;
  162.     }

  163.     public void boundOnce(boolean boundOnce) {
  164.         this.boundOnce = boundOnce;
  165.     }

  166.     @Override
  167.     public void setTarget(MethodHandle target) {
  168.         super.setTarget(target);
  169.         boundOnce = true;
  170.     }

  171.     public void setInitialTarget(MethodHandle target) {
  172.         super.setTarget(target);
  173.     }
  174.    
  175.     /**
  176.      * Get the actual incoming Signature for this call site.
  177.      *
  178.      * This represents the actual argument list.
  179.      *
  180.      * @return the actual Signature at the call site
  181.      */
  182.     public Signature signature() {
  183.         return signature;
  184.     }
  185.    
  186.     /**
  187.      * Get the "full" signature equivalent to this call site.
  188.      *
  189.      * The "full" signature always guarantees context, caller, and block args
  190.      * are provided. It could also be considered the standard intermediate
  191.      * signature all calls eventually pass through.
  192.      *
  193.      * @return the "full" intermediate signature
  194.      */
  195.     public Signature fullSignature() {
  196.         return fullSignature;
  197.     }
  198.    
  199.     public static final Signature STANDARD_SITE_SIG = Signature
  200.             .returning(IRubyObject.class)
  201.             .appendArg("context", ThreadContext.class)
  202.             .appendArg("caller", IRubyObject.class)
  203.             .appendArg("self", IRubyObject.class);
  204.     public static final Signature STANDARD_SITE_SIG_1ARG = STANDARD_SITE_SIG.appendArg("arg0", IRubyObject.class);
  205.     public static final Signature STANDARD_SITE_SIG_2ARG = STANDARD_SITE_SIG_1ARG.appendArg("arg1", IRubyObject.class);
  206.     public static final Signature STANDARD_SITE_SIG_3ARG = STANDARD_SITE_SIG_2ARG.appendArg("arg2", IRubyObject.class);
  207.     public static final Signature STANDARD_SITE_SIG_NARG = STANDARD_SITE_SIG.appendArg("args", IRubyObject[].class);
  208.    
  209.     public static final Signature[] STANDARD_SITE_SIGS = {
  210.         STANDARD_SITE_SIG,
  211.         STANDARD_SITE_SIG_1ARG,
  212.         STANDARD_SITE_SIG_2ARG,
  213.         STANDARD_SITE_SIG_3ARG,
  214.         STANDARD_SITE_SIG_NARG,
  215.     };
  216.    
  217.     public static final Signature STANDARD_SITE_SIG_BLOCK = STANDARD_SITE_SIG.appendArg("block", Block.class);
  218.     public static final Signature STANDARD_SITE_SIG_1ARG_BLOCK = STANDARD_SITE_SIG_1ARG.appendArg("block", Block.class);
  219.     public static final Signature STANDARD_SITE_SIG_2ARG_BLOCK = STANDARD_SITE_SIG_2ARG.appendArg("block", Block.class);
  220.     public static final Signature STANDARD_SITE_SIG_3ARG_BLOCK = STANDARD_SITE_SIG_3ARG.appendArg("block", Block.class);
  221.     public static final Signature STANDARD_SITE_SIG_NARG_BLOCK = STANDARD_SITE_SIG_NARG.appendArg("block", Block.class);
  222.     public static final Signature[] STANDARD_SITE_SIGS_BLOCK = {
  223.         STANDARD_SITE_SIG_BLOCK,
  224.         STANDARD_SITE_SIG_1ARG_BLOCK,
  225.         STANDARD_SITE_SIG_2ARG_BLOCK,
  226.         STANDARD_SITE_SIG_3ARG_BLOCK,
  227.         STANDARD_SITE_SIG_NARG_BLOCK,
  228.     };

  229.     public static final Signature STANDARD_SUPER_SIG = Signature
  230.             .returning(IRubyObject.class)
  231.             .appendArg("context", ThreadContext.class)
  232.             .appendArg("caller", IRubyObject.class)
  233.             .appendArg("self", IRubyObject.class)
  234.             .appendArg("class", RubyClass.class);
  235. }