Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    ***** BEGIN LICENSE BLOCK *****
    * Version: EPL 1.0/GPL 2.0/LGPL 2.1
    *
    * The contents of this file are subject to the Eclipse Public
    * License Version 1.0 (the "License"); you may not use this file
    * except in compliance with the License. You may obtain a copy of
    * the License at http://www.eclipse.org/legal/epl-v10.html
    *
   * Software distributed under the License is distributed on an "AS
   * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
   * implied. See the License for the specific language governing
   * rights and limitations under the License.
   * 
   * Alternatively, the contents of this file may be used under the terms of
   * either of the GNU General Public License Version 2 or later (the "GPL"),
   * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   * in which case the provisions of the GPL or the LGPL are applicable instead
   * of those above. If you wish to allow use of your version of this file only
   * under the terms of either the GPL or the LGPL, and not to allow others to
   * use your version of this file under the terms of the EPL, indicate your
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the EPL, the GPL or the LGPL.
   ***** END LICENSE BLOCK *****/
  
  package org.jruby.runtime.invokedynamic;
  
  import org.jruby.*;
  import static org.jruby.util.CodegenUtils.*;
  
  import  org.objectweb.asm.Handle;
  import  org.objectweb.asm.Opcodes;
  
  import static java.lang.invoke.MethodHandles.*;
  import static java.lang.invoke.MethodType.*;
  
  @SuppressWarnings("deprecation")
  public class InvokeDynamicSupport {
      private static final Logger LOG = LoggerFactory.getLogger("InvokeDynamicSupport");
      
      ////////////////////////////////////////////////////////////////////////////
      // BOOTSTRAP HANDLES
      ////////////////////////////////////////////////////////////////////////////
      
      public final static String BOOTSTRAP_BARE_SIG = sig(CallSite.classLookup.classString.classMethodType.class);
      public final static String BOOTSTRAP_INT_SIG = sig(CallSite.classLookup.classString.classMethodType.classint.class);
      public final static String BOOTSTRAP_STRING_STRING_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classString.class);
      public final static String BOOTSTRAP_STRING_STRING_INT_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classString.classint.class);
      public final static String BOOTSTRAP_STRING_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.class);
      public final static String BOOTSTRAP_STRING_CALLTYPE_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classCallType.class);
      public final static String BOOTSTRAP_LONG_SIG = sig(CallSite.classLookup.classString.classMethodType.classlong.class);
      public final static String BOOTSTRAP_DOUBLE_SIG = sig(CallSite.classLookup.classString.classMethodType.classdouble.class);
      public final static String BOOTSTRAP_LONG_STRING_INT_SIG = sig(CallSite.classLookup.classString.classMethodType.classlong.classString.classint.class);
      public final static String BOOTSTRAP_DOUBLE_STRING_INT_SIG = sig(CallSite.classLookup.classString.classMethodType.classdouble.classString.classint.class);
      public final static String BOOTSTRAP_STRING_INT_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classint.class);
      public final static String BOOTSTRAP_STRING_LONG_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classlong.class);
      public final static String BOOTSTRAP_STRING_DOUBLE_SIG = sig(CallSite.classLookup.classString.classMethodType.classString.classdouble.class);
      
      public static Handle getBootstrapHandle(String nameClass typeString sig) {
          return new Handle(Opcodes.H_INVOKESTATIC, p(type), namesig);
      }
      
      public static Handle getBootstrapHandle(String nameString sig) {
          return getBootstrapHandle(nameInvokeDynamicSupport.classsig);
      }
     
     public static Handle getInvocationHandle() {
         return getBootstrapHandle("invocationBootstrap"InvocationLinker.class);
     }
     
     public static Handle getConstantHandle() {
         return getBootstrapHandle("getConstantBootstrap");
     }
     
     public static Handle getConstantBooleanHandle() {
         return getBootstrapHandle("getConstantBooleanBootstrap");
     }
     
     public static Handle getByteListHandle() {
         return getBootstrapHandle("getByteListBootstrap");
     }
     
     public static Handle getRegexpHandle() {
         return getBootstrapHandle("getRegexpBootstrap");
     }
     
     public static Handle getSymbolHandle() {
         return getBootstrapHandle("getSymbolBootstrap");
     }
     
     public static Handle getFixnumHandle() {
         return getBootstrapHandle("getFixnumBootstrap");
     }
     
     public static Handle getFloatHandle() {
         return getBootstrapHandle("getFloatBootstrap");
     }
     
     public static Handle getStaticScopeHandle() {
         return getBootstrapHandle("getStaticScopeBootstrap");
     }
     
     public static Handle getLoadStaticScopeHandle() {
         return getBootstrapHandle("getLoadStaticScopeBootstrap");
     }
     
     public static Handle getCallSiteHandle() {
         return getBootstrapHandle("getCallSiteBootstrap");
     }
     
     public static Handle getStringHandle() {
         return getBootstrapHandle("getStringBootstrap");
     }
     
     public static Handle getBigIntegerHandle() {
         return getBootstrapHandle("getBigIntegerBootstrap");
     }
     
     public static Handle getEncodingHandle() {
         return getBootstrapHandle("getEncodingBootstrap");
     }
     
     public static Handle getBlockBodyHandle() {
         return getBootstrapHandle("getBlockBodyBootstrap");
     }
     
     public static Handle getBlockBody19Handle() {
         return getBootstrapHandle("getBlockBody19Bootstrap");
     }
     
     public static Handle getFixnumOperatorHandle() {
         return getBootstrapHandle("fixnumOperatorBootstrap"MathLinker.class);
     }
     
     public static Handle getFixnumBooleanHandle() {
         return getBootstrapHandle("fixnumBooleanBootstrap"MathLinker.class);
     }
     
     public static Handle getFloatOperatorHandle() {
         return getBootstrapHandle("floatOperatorBootstrap"MathLinker.class);
     }
     
     public static Handle getVariableHandle() {
         return getBootstrapHandle("variableBootstrap");
     }
     
     public static Handle getContextFieldHandle() {
         return getBootstrapHandle("contextFieldBootstrap");
     }
     
     public static Handle getGlobalHandle() {
         return getBootstrapHandle("globalBootstrap");
     }
     
     public static Handle getGlobalBooleanHandle() {
         return getBootstrapHandle("globalBooleanBootstrap");
     }
     
     public static Handle getLoadBooleanHandle() {
         return getBootstrapHandle("loadBooleanBootstrap");
     }
     
     public static Handle checkpointHandle() {
         return getBootstrapHandle("checkpointBootstrap");
     }
     
     ////////////////////////////////////////////////////////////////////////////
     // BOOTSTRAP METHODS
     ////////////////////////////////////////////////////////////////////////////
     
     // <editor-fold desc="bootstraps">
     
     public static CallSite contextFieldBootstrap(Lookup lookupString nameMethodType typethrows NoSuchMethodExceptionIllegalAccessException {
         MutableCallSite site = new MutableCallSite(type);
         
         if (name.equals("nil")) {
             site.setTarget(Binder.from(type).insert(0, site).invokeStatic(lookupInvokeDynamicSupport.class"loadNil"));
         } else if (name.equals("runtime")) {
             site.setTarget(Binder.from(type).insert(0, site).invokeStatic(lookupInvokeDynamicSupport.class"loadRuntime"));
         }
         
         return site;
     }
     
     public static IRubyObject loadNil(MutableCallSite siteThreadContext contextthrows Throwable {
         site.setTarget(Binder.from(IRubyObject.classThreadContext.class).drop(0).constant(context.nil));
         
         return context.nil;
     }
     
     public static Ruby loadRuntime(MutableCallSite siteThreadContext contextthrows Throwable {
         site.setTarget(Binder.from(Ruby.classThreadContext.class).drop(0).constant(context.runtime));
         
         return context.runtime;
     }
 
     public static CallSite getConstantBootstrap(Lookup lookupString nameMethodType typeint scopeIndexthrows NoSuchMethodExceptionIllegalAccessException {
         RubyConstantCallSite site;
 
         site = new RubyConstantCallSite(typename);
         
         MethodType fallbackType = methodType(IRubyObject.classRubyConstantCallSite.classAbstractScript.classThreadContext.classint.class);
         MethodHandle myFallback = insertArguments(
                 lookup.findStatic(InvokeDynamicSupport.class"constantFallback",
                 fallbackType),
                 0,
                 site);
         myFallback = insertArguments(myFallback, 2, scopeIndex);
         site.setTarget(myFallback);
         return site;
     }
 
     public static CallSite getConstantBooleanBootstrap(Lookup lookupString nameMethodType typeint scopeIndexthrows NoSuchMethodExceptionIllegalAccessException {
         RubyConstantCallSite site;
 
         site = new RubyConstantCallSite(typename);
         
         MethodType fallbackType = methodType(boolean.classRubyConstantCallSite.classAbstractScript.classThreadContext.classint.class);
         MethodHandle myFallback = insertArguments(
                 lookup.findStatic(InvokeDynamicSupport.class"constantBooleanFallback",
                 fallbackType),
                 0,
                 site);
         myFallback = insertArguments(myFallback, 2, scopeIndex);
         site.setTarget(myFallback);
         return site;
     }
 
     public static CallSite getByteListBootstrap(Lookup lookupString nameMethodType typeString asStringString encodingName) {
         byte[] bytes = Helpers.stringToRawBytes(asString);
         Encoding encoding = EncodingDB.getEncodings().get(encodingName.getBytes()).getEncoding();
         ByteList byteList = new ByteList(bytesencoding);
         
         return new ConstantCallSite(constant(ByteList.classbyteList));
     }
     
     public static CallSite getRegexpBootstrap(Lookup lookupString nameMethodType typeString asStringString encodingNameint options) {
         byte[] bytes = Helpers.stringToRawBytes(asString);
         Encoding encoding = EncodingDB.getEncodings().get(encodingName.getBytes()).getEncoding();
         ByteList byteList = new ByteList(bytesencoding);
         
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initRegexp",
                 methodType(RubyRegexp.classMutableCallSite.classThreadContext.classByteList.classint.class));
         init = insertArguments(init, 2, byteListoptions);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getSymbolBootstrap(Lookup lookupString nameMethodType typeString symbol) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initSymbol",
                 methodType(RubySymbol.classMutableCallSite.classThreadContext.classString.class));
         init = insertArguments(init, 2, symbol);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getFixnumBootstrap(Lookup lookupString nameMethodType typelong value) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initFixnum",
                 methodType(RubyFixnum.classMutableCallSite.classThreadContext.classlong.class));
         init = insertArguments(init, 2, value);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getFloatBootstrap(Lookup lookupString nameMethodType typedouble value) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initFloat",
                 methodType(RubyFloat.classMutableCallSite.classThreadContext.classdouble.class));
         init = insertArguments(init, 2, value);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getStaticScopeBootstrap(Lookup lookupString nameMethodType typeString scopeStringint index) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initStaticScope",
                 methodType(StaticScope.classMutableCallSite.classAbstractScript.classThreadContext.classStaticScope.classString.classint.class));
         init = insertArguments(init, 4, scopeStringindex);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getLoadStaticScopeBootstrap(Lookup lookupString nameMethodType typeint index) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "loadStaticScope",
                 methodType(StaticScope.classMutableCallSite.classAbstractScript.classint.class));
         init = insertArguments(init, 2, index);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
 
     public static CallSite getCallSiteBootstrap(Lookup lookupString nameMethodType typeString callNameint callTypeChar) {
         org.jruby.runtime.CallSite callSite = null;
         switch (callTypeChar) {
             case 'N':
                 callSite = MethodIndex.getCallSite(callName);
                 break;
             case 'F':
                 callSite = MethodIndex.getFunctionalCallSite(callName);
                 break;
             case 'V':
                 callSite = MethodIndex.getVariableCallSite(callName);
                 break;
             case 'S':
                 callSite = MethodIndex.getSuperCallSite();
                 break;
         }
         
         return new ConstantCallSite(constant(org.jruby.runtime.CallSite.classcallSite));
     }
     
     public static CallSite getStringBootstrap(Lookup lookupString nameMethodType typeString asStringString encodingNameint codeRange) {
         byte[] bytes = Helpers.stringToRawBytes(asString);
         Encoding encoding = EncodingDB.getEncodings().get(encodingName.getBytes()).getEncoding();
         ByteList byteList = new ByteList(bytesencoding);
         
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "newString",
                 methodType(RubyString.classThreadContext.classByteList.classint.class));
         init = insertArguments(init, 1, byteListcodeRange);
         site.setTarget(init);
         return site;
     }
 
     public static CallSite getBigIntegerBootstrap(Lookup lookupString nameMethodType typeString asString) {
         BigInteger byteList = new BigInteger(asString, 16);
         
         return new ConstantCallSite(constant(BigInteger.classbyteList));
     }
     
     public static CallSite getEncodingBootstrap(Lookup lookupString nameMethodType typeString encodingName) {
         Encoding encoding = EncodingDB.getEncodings().get(encodingName.getBytes()).getEncoding();
         
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initEncoding",
                 methodType(RubyEncoding.classMutableCallSite.classThreadContext.classEncoding.class));
         init = insertArguments(init, 2, encoding);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getBlockBodyBootstrap(Lookup lookupString nameMethodType typeString descriptor) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initBlockBody",
                 methodType(BlockBody.classMutableCallSite.classObject.classThreadContext.classStaticScope.classString.class));
         init = insertArguments(init, 4, descriptor);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
     
     public static CallSite getBlockBody19Bootstrap(Lookup lookupString nameMethodType typeString descriptor) {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle init = findStatic(
                 InvokeDynamicSupport.class,
                 "initBlockBody19",
                 methodType(BlockBody.classMutableCallSite.classObject.classThreadContext.classStaticScope.classString.class));
         init = insertArguments(init, 4, descriptor);
         init = insertArguments(
                 init,
                 0,
                 site);
         site.setTarget(init);
         return site;
     }
 
     public static CallSite variableBootstrap(Lookup lookupString nameMethodType typeString fileint linethrows Throwable {
         String[] names = name.split(":");
         String operation = names[0];
         String varName = names[1];
         VariableSite site = new VariableSite(typevarNamefileline);
         MethodHandle handle;
         
         if (operation.equals("get")) {
             handle = lookup.findStatic(InvokeDynamicSupport.class"getVariableFallback"methodType(IRubyObject.classVariableSite.classIRubyObject.class));
         } else if (operation.equals("set")) {
             handle = lookup.findStatic(InvokeDynamicSupport.class"setVariableFallback"methodType(IRubyObject.classVariableSite.classIRubyObject.classIRubyObject.class));
         } else {
             throw new RuntimeException("invalid variable access type");
         }
         
         handle = handle.bindTo(site);
         site.setTarget(handle);
         
         return site;
     }
     
     public static IRubyObject getVariableFallback(VariableSite siteIRubyObject selfthrows Throwable {
         RubyClass realClass = self.getMetaClass().getRealClass();
         VariableAccessor accessor = realClass.getVariableAccessorForRead(site.name);
         
         // produce nil if the variable has not been initialize
         MethodHandle nullToNil = findStatic(Helpers.class"nullToNil"methodType(IRubyObject.classIRubyObject.classIRubyObject.class));
         nullToNil = insertArguments(nullToNil, 1, self.getRuntime().getNil());
         nullToNil = explicitCastArguments(nullToNilmethodType(IRubyObject.classObject.class));
         
         // get variable value and filter with nullToNil
         MethodHandle getValue;
         boolean direct = false;
         
         if (accessor instanceof FieldVariableAccessor) {
             direct = true;
             int offset = ((FieldVariableAccessor)accessor).getOffset();
             Class cls = [offset];
             getValue = lookup().findGetter(cls"var" + offsetObject.class);
             getValue = explicitCastArguments(getValuemethodType(Object.classIRubyObject.class));
         } else {
             getValue = findStatic(VariableAccessor.class"getVariable"methodType(Object.classRubyBasicObject.classint.class));
             getValue = explicitCastArguments(getValuemethodType(Object.classIRubyObject.classint.class));
             getValue = insertArguments(getValue, 1, accessor.getIndex());
         }
         
         getValue = filterReturnValue(getValuenullToNil);
         
         // prepare fallback
         MethodHandle fallback = null;
         if (site.chainCount() + 1 > ..load()) {
             if (..load()) .info(site.name + "\tqet on type " + self.getMetaClass(). + " failed (polymorphic)" + extractSourceInfo(site));
             fallback = findStatic(InvokeDynamicSupport.class"getVariableFail"methodType(IRubyObject.classVariableSite.classIRubyObject.class));
             fallback = fallback.bindTo(site);
             site.setTarget(fallback);
             return (IRubyObject)fallback.invokeWithArguments(self);
         } else {
             if (..load()) {
                 if (direct) {
                     .info(site.name + "\tget field on type " + self.getMetaClass(). + " added to PIC" + extractSourceInfo(site));
                 } else {
                     .info(site.name + "\tget on type " + self.getMetaClass(). + " added to PIC" + extractSourceInfo(site));
                 }
             }
             fallback = site.getTarget();
             site.incrementChainCount();
         }
         
         // prepare test
         MethodHandle test = findStatic(InvocationLinker.class"testRealClass"methodType(boolean.classint.classIRubyObject.class));
         test = insertArguments(test, 0, accessor.getClassId());
         
         getValue = guardWithTest(testgetValuefallback);
         
         if (..load()) .info(site.name + "\tget on class " + self.getMetaClass(). + " bound directly" + extractSourceInfo(site));
         site.setTarget(getValue);
         
         return (IRubyObject)getValue.invokeWithArguments(self);
     }
 
     public static IRubyObject getVariableFail(VariableSite siteIRubyObject selfthrows Throwable {
         return site.getVariable(self);
     }
     
     public static final Class[] REIFIED_OBJECT_CLASSES = {
         RubyObjectVar0.class,
         RubyObjectVar1.class,
         RubyObjectVar2.class,
         RubyObjectVar3.class,
         RubyObjectVar4.class,
         RubyObjectVar5.class,
         RubyObjectVar6.class,
         RubyObjectVar7.class,
         RubyObjectVar8.class,
         RubyObjectVar9.class,
     };
     
     public static IRubyObject setVariableFallback(VariableSite siteIRubyObject selfIRubyObject valuethrows Throwable {
         RubyClass realClass = self.getMetaClass().getRealClass();
         VariableAccessor accessor = realClass.getVariableAccessorForWrite(site.name);
 
         // return provided value
         MethodHandle returnValue = identity(IRubyObject.class);
         returnValue = dropArguments(returnValue, 0, IRubyObject.class);
 
         // set variable value and fold by returning value
         MethodHandle setValue;
         boolean direct = false;
         
         if (accessor instanceof FieldVariableAccessor) {
             direct = true;
             int offset = ((FieldVariableAccessor)accessor).getOffset();
             Class cls = [offset];
             setValue = findStatic(cls"setVariableChecked"methodType(void.classclsObject.class));
             setValue = explicitCastArguments(setValuemethodType(void.classIRubyObject.classIRubyObject.class));
         } else {
             setValue = findStatic(accessor.getClass(), "setVariableChecked"methodType(void.classRubyBasicObject.classRubyClass.classint.classObject.class));
             setValue = explicitCastArguments(setValuemethodType(void.classIRubyObject.classRubyClass.classint.classIRubyObject.class));
             setValue = insertArguments(setValue, 1, realClassaccessor.getIndex());
         }
         
         setValue = foldArguments(returnValuesetValue);
 
         // prepare fallback
         MethodHandle fallback = null;
         if (site.chainCount() + 1 > ..load()) {
             if (..load()) .info(site.name + "\tset on type " + self.getMetaClass(). + " failed (polymorphic)" + extractSourceInfo(site));
             fallback = findStatic(InvokeDynamicSupport.class"setVariableFail"methodType(IRubyObject.classVariableSite.classIRubyObject.classIRubyObject.class));
             fallback = fallback.bindTo(site);
             site.setTarget(fallback);
             return (IRubyObject)fallback.invokeWithArguments(selfvalue);
         } else {
             if (..load()) {
                 if (direct) {
                     .info(site.name + "\tset field on type " + self.getMetaClass(). + " added to PIC" + extractSourceInfo(site));
                 } else {
                     .info(site.name + "\tset on type " + self.getMetaClass(). + " added to PIC" + extractSourceInfo(site));
                 }
             }
             fallback = site.getTarget();
             site.incrementChainCount();
         }
 
         // prepare test
         MethodHandle test = findStatic(InvocationLinker.class"testRealClass"methodType(boolean.classint.classIRubyObject.class));
         test = insertArguments(test, 0, accessor.getClassId());
         test = dropArguments(test, 1, IRubyObject.class);
 
         setValue = guardWithTest(testsetValuefallback);
 
         if (..load()) .info(site.name + "\tset on class " + self.getMetaClass(). + " bound directly" + extractSourceInfo(site));
         site.setTarget(setValue);
 
         return (IRubyObject)setValue.invokeWithArguments(selfvalue);
     }
 
     public static IRubyObject setVariableFail(VariableSite siteIRubyObject selfIRubyObject valuethrows Throwable {
         return site.setVariable(selfvalue);
     }
 
     public static CallSite globalBootstrap(Lookup lookupString nameMethodType typeString fileint linethrows Throwable {
         String[] names = name.split(":");
         String operation = names[0];
         String varName = JavaNameMangler.demangleMethodName(names[1]);
         GlobalSite site = new GlobalSite(typevarNamefileline);
         MethodHandle handle;
         
         if (operation.equals("get")) {
             handle = lookup.findStatic(InvokeDynamicSupport.class"getGlobalFallback"methodType(IRubyObject.classGlobalSite.classThreadContext.class));
         } else {
             throw new RuntimeException("invalid variable access type");
         }
         
         handle = handle.bindTo(site);
         site.setTarget(handle);
         
         return site;
     }
 
     public static CallSite globalBooleanBootstrap(Lookup lookupString nameMethodType typeString fileint linethrows Throwable {
         String[] names = name.split(":");
         String operation = names[0];
         String varName = JavaNameMangler.demangleMethodName(names[1]);
         GlobalSite site = new GlobalSite(typevarNamefileline);
         MethodHandle handle;
         
         if (operation.equals("getBoolean")) {
             handle = lookup.findStatic(InvokeDynamicSupport.class"getGlobalBooleanFallback"methodType(boolean.classGlobalSite.classThreadContext.class));
         } else {
             throw new RuntimeException("invalid variable access type");
         }
         
         handle = handle.bindTo(site);
         site.setTarget(handle);
         
         return site;
     }
 
     public static CallSite loadBooleanBootstrap(Lookup lookupString nameMethodType typethrows Throwable {
         String[] names = name.split(":");
         String operation = names[0];
         boolean value = Boolean.parseBoolean(names[1]);
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle handle;
         
         if (operation.equals("loadBoolean")) {
             handle = lookup.findStatic(InvokeDynamicSupport.class"loadBoolean"methodType(RubyBoolean.classMutableCallSite.classboolean.classThreadContext.class));
         } else {
             throw new RuntimeException("invalid variable access type");
         }
         
         handle = insertArguments(handle, 0, sitevalue);
         site.setTarget(handle);
         
         return site;
     }
     
     public static IRubyObject getGlobalFallback(GlobalSite siteThreadContext contextthrows Throwable {
         Ruby runtime = context.runtime;
         GlobalVariable variable = runtime.getGlobalVariables().getVariable(site.name);
         
         if (site.failures() > ..load() ||
                 variable.getScope() != ..) {
             
             // use uncached logic forever
             if (..load()) .info("global " + site.name + " (" + site.file() + ":" + site.line() + ") rebound > " + ..load() + " times, reverting to simple lookup");
             
             MethodHandle uncached = lookup().findStatic(InvokeDynamicSupport.class"getGlobalUncached"methodType(IRubyObject.classGlobalVariable.class));
             uncached = uncached.bindTo(variable);
             uncached = dropArguments(uncached, 0, ThreadContext.class);
             site.setTarget(uncached);
             return (IRubyObject)uncached.invokeWithArguments(context);
         }
         
         Invalidator invalidator = variable.getInvalidator();
         IRubyObject value = variable.getAccessor().getValue();
         
         MethodHandle target = constant(IRubyObject.classvalue);
         target = dropArguments(target, 0, ThreadContext.class);
         MethodHandle fallback = lookup().findStatic(InvokeDynamicSupport.class"getGlobalFallback"methodType(IRubyObject.classGlobalSite.classThreadContext.class));
         fallback = fallback.bindTo(site);
         
         target = ((SwitchPoint)invalidator.getData()).guardWithTest(targetfallback);
         
         site.setTarget(target);
         
         if (..load()) .info("global " + site.name + " (" + site.file() + ":" + site.line() + ") cached");
         
         return value;
     }
     
     public static IRubyObject getGlobalUncached(GlobalVariable variablethrows Throwable {
         return variable.getAccessor().getValue();
     }
     
     public static boolean getGlobalBooleanFallback(GlobalSite siteThreadContext contextthrows Throwable {
         Ruby runtime = context.runtime;
         GlobalVariable variable = runtime.getGlobalVariables().getVariable(site.name);
         
         if (site.failures() > ..load() ||
                 variable.getScope() != ..) {
             
             // use uncached logic forever
             if (..load()) .info("global " + site.name + " (" + site.file() + ":" + site.line() + ") rebound > " + ..load() + " times, reverting to simple lookup");
 
             MethodHandle uncached = lookup().findStatic(InvokeDynamicSupport.class"getGlobalBooleanUncached"methodType(boolean.classGlobalVariable.class));
             uncached = uncached.bindTo(variable);
             uncached = dropArguments(uncached, 0, ThreadContext.class);
             site.setTarget(uncached);
             return (Boolean)uncached.invokeWithArguments(context);
         }
         
         Invalidator invalidator = variable.getInvalidator();
         boolean value = variable.getAccessor().getValue().isTrue();
         
         MethodHandle target = constant(boolean.classvalue);
         target = dropArguments(target, 0, ThreadContext.class);
         MethodHandle fallback = lookup().findStatic(InvokeDynamicSupport.class"getGlobalBooleanFallback"methodType(boolean.classGlobalSite.classThreadContext.class));
         fallback = fallback.bindTo(site);
         
         target = ((SwitchPoint)invalidator.getData()).guardWithTest(targetfallback);
         
         site.setTarget(target);
         
         if (..load()) .info("global " + site.name + " (" + site.file() + ":" + site.line() + ") cached as boolean");
         
         return value;
     }
     
     public static boolean getGlobalBooleanUncached(GlobalVariable variablethrows Throwable {
         return variable.getAccessor().getValue().isTrue();
     }
 
     public static CallSite checkpointBootstrap(Lookup lookupString nameMethodType typethrows Throwable {
         MutableCallSite site = new MutableCallSite(type);
         MethodHandle handle = lookup.findStatic(InvokeDynamicSupport.class"checkpointFallback"methodType(void.classMutableCallSite.classThreadContext.class));
         
         handle = handle.bindTo(site);
         site.setTarget(handle);
         
         return site;
     }
     
     public static void checkpointFallback(MutableCallSite siteThreadContext contextthrows Throwable {
         Ruby runtime = context.runtime;
         Invalidator invalidator = runtime.getCheckpointInvalidator();
         
         MethodHandle target = Binder
                 .from(void.classThreadContext.class)
                 .nop();
         MethodHandle fallback = lookup().findStatic(InvokeDynamicSupport.class"checkpointFallback"methodType(void.classMutableCallSite.classThreadContext.class));
         fallback = fallback.bindTo(site);
         
         target = ((SwitchPoint)invalidator.getData()).guardWithTest(targetfallback);
         
         site.setTarget(target);
     }
     
     // </editor-fold>
     
     ////////////////////////////////////////////////////////////////////////////
     // INITIAL AND FALLBACK METHODS FOR POST BOOTSTRAP
     ////////////////////////////////////////////////////////////////////////////
     
     public static IRubyObject constantFallback(RubyConstantCallSite site
             AbstractScript scriptThreadContext contextint scopeIndex) {
         SwitchPoint switchPoint = (SwitchPoint)context.runtime.getConstantInvalidator(site.name()).getData();
         StaticScope scope = script.getScope(scopeIndex);
         IRubyObject value = scope.getConstant(site.name());
         
         if (value != null) {
             if (..load()) .info("constant " + site.name() + " bound directly");
             
             MethodHandle valueHandle = constant(IRubyObject.classvalue);
             valueHandle = dropArguments(valueHandle, 0, AbstractScript.classThreadContext.class);
 
             MethodHandle fallback = insertArguments(
                     findStatic(InvokeDynamicSupport.class"constantFallback",
                     methodType(IRubyObject.classRubyConstantCallSite.classAbstractScript.classThreadContext.classint.class)),
                     0,
                     site);
             fallback = insertArguments(fallback, 2, scopeIndex);
 
             MethodHandle gwt = switchPoint.guardWithTest(valueHandlefallback);
             site.setTarget(gwt);
         } else {
             value = scope.getModule()
                     .callMethod(context"const_missing"context.runtime.newSymbol(site.name()));
         }
         
         return value;
     }
 
     public static boolean constantBooleanFallback(RubyConstantCallSite site
             AbstractScript scriptThreadContext contextint scopeIndex) {
         SwitchPoint switchPoint = (SwitchPoint)context.runtime.getConstantInvalidator(site.name()).getData();
         StaticScope scope = script.getScope(scopeIndex);
         IRubyObject value = scope.getConstant(site.name());
         
         if (value != null) {
             if (..load()) .info("constant " + site.name() + " bound directly");
             
             MethodHandle valueHandle = constant(boolean.classvalue.isTrue());
             valueHandle = dropArguments(valueHandle, 0, AbstractScript.classThreadContext.class);
 
             MethodHandle fallback = insertArguments(
                     findStatic(InvokeDynamicSupport.class"constantBooleanFallback",
                     methodType(boolean.classRubyConstantCallSite.classAbstractScript.classThreadContext.classint.class)),
                     0,
                     site);
             fallback = insertArguments(fallback, 2, scopeIndex);
 
             MethodHandle gwt = switchPoint.guardWithTest(valueHandlefallback);
             site.setTarget(gwt);
         } else {
             value = scope.getModule()
                     .callMethod(context"const_missing"context.runtime.newSymbol(site.name()));
         }
         
         boolean booleanValue = value.isTrue();
         
         return booleanValue;
     }
     
     public static RubyRegexp initRegexp(MutableCallSite siteThreadContext contextByteList patternint options) {
         RubyRegexp regexp = RubyRegexp.newRegexp(context.runtimepattern, RegexpOptions.fromEmbeddedOptions(options));
         regexp.setLiteral();
         site.setTarget(dropArguments(constant(RubyRegexp.classregexp), 0, ThreadContext.class));
         return regexp;
     }
     
     public static RubySymbol initSymbol(MutableCallSite siteThreadContext contextString symbol) {
         RubySymbol rubySymbol = context.runtime.newSymbol(symbol);
         site.setTarget(dropArguments(constant(RubySymbol.classrubySymbol), 0, ThreadContext.class));
         return rubySymbol;
     }
     
     public static RubyFixnum initFixnum(MutableCallSite siteThreadContext contextlong value) {
         RubyFixnum rubyFixnum = context.runtime.newFixnum(value);
         site.setTarget(dropArguments(constant(RubyFixnum.classrubyFixnum), 0, ThreadContext.class));
         return rubyFixnum;
     }
     
     public static RubyFloat initFloat(MutableCallSite siteThreadContext contextdouble value) {
         RubyFloat rubyFloat = context.runtime.newFloat(value);
         site.setTarget(dropArguments(constant(RubyFloat.classrubyFloat), 0, ThreadContext.class));
         return rubyFloat;
     }
     
     public static StaticScope initStaticScope(MutableCallSite siteAbstractScript scriptThreadContext contextStaticScope parentString staticScopeint index) {
         StaticScope scope = script.getScope(contextparentstaticScopeindex);
         site.setTarget(dropArguments(constant(StaticScope.class