public static IRubyObject fixnumOperatorFail(ThreadContext context, IRubyObject caller, IRubyObject self, JRubyCallSite site, RubyFixnum value) throws Throwable { String operator = site.name(); RubyClass selfClass = InvokeDynamicSupport.pollAndGetClass(context, self); CacheEntry entry = site.entry; if (entry.typeOk(selfClass)) { return entry.method.call(context, self, selfClass, operator, value); } else { entry = selfClass.searchWithCache(operator); if (InvokeDynamicSupport.methodMissing(entry, site.callType(), operator, caller)) { return InvokeDynamicSupport.callMethodMissing(entry, site.callType(), context, self, operator, value); } site.entry = entry; return entry.method.call(context, self, selfClass, operator, value); } }
private static MethodHandle findParameterHelper(String name, Class nativeIntClass) { return findStatic(JITRuntime.class, name + (int.class == nativeIntClass ? 32 : 64), MethodType.methodType(nativeIntClass, IRubyObject.class)); }
/** * Cache a BigInteger using invokedynamic. Used for Bignum construction * * @param method the method compiler with which bytecode is emitted * @param bigint the BigInteger to cache */ @Override public void cacheBigInteger(BaseBodyCompiler method, BigInteger bigint) { if (!RubyInstanceConfig.INVOKEDYNAMIC_LITERALS) { super.cacheBigInteger(method, bigint); return; } String asString = bigint.toString(16); method.method.invokedynamic( "getBigInteger", sig(BigInteger.class), InvokeDynamicSupport.getBigIntegerHandle(), asString); }
public static IRubyObject invoke(InvokeSite site, ThreadContext context, IRubyObject self, IRubyObject arg0) throws Throwable { RubyClass selfClass = self.getMetaClass(); String methodName = site.name; SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData(); CacheEntry entry = selfClass.searchWithCache(methodName); DynamicMethod method = entry.method; if (methodMissing(entry, CallType.NORMAL, methodName, self)) { return callMethodMissing(entry, CallType.NORMAL, context, self, methodName, arg0); } MethodHandle mh = getHandle(selfClass, switchPoint, site, method, 1, false); site.setTarget(mh); return (IRubyObject)mh.invokeWithArguments(context, self, arg0); }
nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); findStatic(RubyFixnum.class, "newFixnum", methodType(RubyFixnum.class, Ruby.class, long.class)), 0, runtime); findStatic(InvocationLinker.class, "fixnumOrNil", methodType(IRubyObject.class, Ruby.class, nativeReturn)), 0, runtime); findStatic(RubyFloat.class, "newFloat", methodType(RubyFloat.class, Ruby.class, double.class)), 0, runtime); findStatic(InvocationLinker.class, "floatOrNil", methodType(IRubyObject.class, Ruby.class, nativeReturn)), 0, runtime); findStatic(RubyBoolean.class, "newBoolean", methodType(RubyBoolean.class, Ruby.class, boolean.class)), 0, runtime); findStatic(InvocationLinker.class, "booleanOrNil", methodType(IRubyObject.class, Ruby.class, Boolean.class)), 0, runtime); findStatic(InvocationLinker.class, "stringOrNil", methodType(IRubyObject.class, Ruby.class, CharSequence.class)),
int offset = ((FieldVariableAccessor)accessor).getOffset(); Class cls = REIFIED_OBJECT_CLASSES[offset]; setValue = findStatic(cls, "setVariableChecked", methodType(void.class, cls, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, IRubyObject.class)); } else { setValue = findStatic(accessor.getClass(), "setVariableChecked", methodType(void.class, RubyBasicObject.class, RubyClass.class, int.class, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, RubyClass.class, int.class, IRubyObject.class)); setValue = insertArguments(setValue, 1, realClass, accessor.getIndex()); if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset on type " + self.getMetaClass().id + " failed (polymorphic)" + extractSourceInfo(site)); fallback = findStatic(InvokeDynamicSupport.class, "setVariableFail", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class, IRubyObject.class)); fallback = fallback.bindTo(site); site.setTarget(fallback); if (RubyInstanceConfig.LOG_INDY_BINDINGS) { if (direct) { LOG.info(site.name + "\tset field on type " + self.getMetaClass().id + " added to PIC" + extractSourceInfo(site)); } else { LOG.info(site.name + "\tset on type " + self.getMetaClass().id + " added to PIC" + extractSourceInfo(site)); MethodHandle test = findStatic(InvocationLinker.class, "testRealClass", methodType(boolean.class, int.class, IRubyObject.class)); test = insertArguments(test, 0, accessor.getClassId()); test = dropArguments(test, 1, IRubyObject.class); if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset on class " + self.getMetaClass().id + " bound directly" + extractSourceInfo(site)); site.setTarget(setValue);
MethodHandle setValue = findVirtual(IRubyObject.class, "setVariable", methodType(void.class, int.class, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, int.class, IRubyObject.class)); setValue = insertArguments(setValue, 1, accessor.getIndex());
public void pollThreadEvents() { if (!RubyInstanceConfig.THREADLESS_COMPILE_ENABLED) { if (Options.COMPILE_INVOKEDYNAMIC.load()) { // switchpoint version loadThreadContext(); method.invokedynamic( "checkpoint", sig(void.class, ThreadContext.class), InvokeDynamicSupport.checkpointHandle()); } else { loadThreadContext(); invokeThreadContext("pollThreadEvents", sig(void.class)); } } }
/** * Cache a closure body (BlockBody) using invokedynamic. */ @Override public int cacheClosure(BaseBodyCompiler method, String closureMethod, int arity, StaticScope scope, String file, int line, boolean hasMultipleArgsHead, NodeType argsNodeId, ASTInspector inspector) { String descriptor = Helpers.buildBlockDescriptor( closureMethod, arity, file, line, hasMultipleArgsHead, argsNodeId, inspector); method.loadThis(); method.loadThreadContext(); int scopeIndex = cacheStaticScope(method, scope); method.method.invokedynamic( "getBlockBody", sig(BlockBody.class, Object.class, ThreadContext.class, StaticScope.class), InvokeDynamicSupport.getBlockBodyHandle(), descriptor); return scopeIndex; }
/** * Cache a closure body (BlockBody) for 1.9 mode using invokedynamic. */ @Override public int cacheClosure19(BaseBodyCompiler method, String closureMethod, int arity, StaticScope scope, String file, int line, boolean hasMultipleArgsHead, NodeType argsNodeId, String parameterList, ASTInspector inspector) { String descriptor = Helpers.buildBlockDescriptor19( closureMethod, arity, file, line, hasMultipleArgsHead, argsNodeId, parameterList, inspector); method.loadThis(); method.loadThreadContext(); int scopeIndex = cacheStaticScope(method, scope); method.method.invokedynamic( "getBlockBody19", sig(BlockBody.class, Object.class, ThreadContext.class, StaticScope.class), InvokeDynamicSupport.getBlockBody19Handle(), descriptor); return scopeIndex; }
public static IRubyObject invokeSelf(InvokeSite site, ThreadContext context, IRubyObject self, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) throws Throwable { RubyClass selfClass = self.getMetaClass(); String methodName = site.name; SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData(); CacheEntry entry = selfClass.searchWithCache(methodName); DynamicMethod method = entry.method; if (methodMissing(entry, CallType.FUNCTIONAL, methodName, self)) { return callMethodMissing(entry, CallType.FUNCTIONAL, context, self, methodName, arg0, arg1, arg2); } MethodHandle mh = getHandle(selfClass, switchPoint, site, method, 3, false); site.setTarget(mh); return (IRubyObject)mh.invokeWithArguments(context, self, arg0, arg1, arg2); }
nativeTarget = findStatic(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); } else { nativeTarget = findVirtual(nativeCall.getNativeTarget(), nativeCall.getNativeName(), apparentType); findStatic(RubyFixnum.class, "newFixnum", methodType(RubyFixnum.class, Ruby.class, long.class)), 0, runtime); findStatic(InvocationLinker.class, "fixnumOrNil", methodType(IRubyObject.class, Ruby.class, nativeReturn)), 0, runtime); findStatic(RubyFloat.class, "newFloat", methodType(RubyFloat.class, Ruby.class, double.class)), 0, runtime); findStatic(InvocationLinker.class, "floatOrNil", methodType(IRubyObject.class, Ruby.class, nativeReturn)), 0, runtime); findStatic(RubyBoolean.class, "newBoolean", methodType(RubyBoolean.class, Ruby.class, boolean.class)), 0, runtime); findStatic(InvocationLinker.class, "booleanOrNil", methodType(IRubyObject.class, Ruby.class, Boolean.class)), 0, runtime); findStatic(InvocationLinker.class, "stringOrNil", methodType(IRubyObject.class, Ruby.class, CharSequence.class)),
int offset = ((FieldVariableAccessor)accessor).getOffset(); Class cls = REIFIED_OBJECT_CLASSES[offset]; setValue = findStatic(cls, "setVariableChecked", methodType(void.class, cls, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, IRubyObject.class)); } else { setValue = findStatic(accessor.getClass(), "setVariableChecked", methodType(void.class, RubyBasicObject.class, RubyClass.class, int.class, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, RubyClass.class, int.class, IRubyObject.class)); setValue = insertArguments(setValue, 1, realClass, accessor.getIndex()); if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset on type " + self.getMetaClass().id + " failed (polymorphic)" + extractSourceInfo(site)); fallback = findStatic(InvokeDynamicSupport.class, "setVariableFail", methodType(IRubyObject.class, VariableSite.class, IRubyObject.class, IRubyObject.class)); fallback = fallback.bindTo(site); site.setTarget(fallback); if (RubyInstanceConfig.LOG_INDY_BINDINGS) { if (direct) { LOG.info(site.name + "\tset field on type " + self.getMetaClass().id + " added to PIC" + extractSourceInfo(site)); } else { LOG.info(site.name + "\tset on type " + self.getMetaClass().id + " added to PIC" + extractSourceInfo(site)); MethodHandle test = findStatic(InvocationLinker.class, "testRealClass", methodType(boolean.class, int.class, IRubyObject.class)); test = insertArguments(test, 0, accessor.getClassId()); test = dropArguments(test, 1, IRubyObject.class); if (RubyInstanceConfig.LOG_INDY_BINDINGS) LOG.info(site.name + "\tset on class " + self.getMetaClass().id + " bound directly" + extractSourceInfo(site)); site.setTarget(setValue);
MethodHandle setValue = findVirtual(IRubyObject.class, "setVariable", methodType(void.class, int.class, Object.class)); setValue = explicitCastArguments(setValue, methodType(void.class, IRubyObject.class, int.class, IRubyObject.class)); setValue = insertArguments(setValue, 1, accessor.getIndex());
public void pollThreadEvents() { if (!RubyInstanceConfig.THREADLESS_COMPILE_ENABLED) { if (Options.COMPILE_INVOKEDYNAMIC.load()) { // switchpoint version loadThreadContext(); method.invokedynamic( "checkpoint", sig(void.class, ThreadContext.class), InvokeDynamicSupport.checkpointHandle()); } else { loadThreadContext(); invokeThreadContext("pollThreadEvents", sig(void.class)); } } }
/** * Cache a closure body (BlockBody) using invokedynamic. */ @Override public int cacheClosure(BaseBodyCompiler method, String closureMethod, int arity, StaticScope scope, String file, int line, boolean hasMultipleArgsHead, NodeType argsNodeId, ASTInspector inspector) { String descriptor = Helpers.buildBlockDescriptor( closureMethod, arity, file, line, hasMultipleArgsHead, argsNodeId, inspector); method.loadThis(); method.loadThreadContext(); int scopeIndex = cacheStaticScope(method, scope); method.method.invokedynamic( "getBlockBody", sig(BlockBody.class, Object.class, ThreadContext.class, StaticScope.class), InvokeDynamicSupport.getBlockBodyHandle(), descriptor); return scopeIndex; }
/** * Cache a closure body (BlockBody) for 1.9 mode using invokedynamic. */ @Override public int cacheClosure19(BaseBodyCompiler method, String closureMethod, int arity, StaticScope scope, String file, int line, boolean hasMultipleArgsHead, NodeType argsNodeId, String parameterList, ASTInspector inspector) { String descriptor = Helpers.buildBlockDescriptor19( closureMethod, arity, file, line, hasMultipleArgsHead, argsNodeId, parameterList, inspector); method.loadThis(); method.loadThreadContext(); int scopeIndex = cacheStaticScope(method, scope); method.method.invokedynamic( "getBlockBody19", sig(BlockBody.class, Object.class, ThreadContext.class, StaticScope.class), InvokeDynamicSupport.getBlockBody19Handle(), descriptor); return scopeIndex; }
public static IRubyObject fail(JRubyCallSite site, ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0, IRubyObject arg1) throws Throwable { RubyClass selfClass = pollAndGetClass(context, self); String name = site.name(); CacheEntry entry = site.entry; if (entry.typeOk(selfClass)) { return entry.method.call(context, self, selfClass, name, arg0, arg1); } else { entry = selfClass.searchWithCache(name); if (methodMissing(entry, site.callType(), name, caller)) { return callMethodMissing(entry, site.callType(), context, self, name, arg0, arg1); } site.entry = entry; return entry.method.call(context, self, selfClass, name, arg0, arg1); } }
public static IRubyObject invokeSelf(InvokeSite site, ThreadContext context, IRubyObject self, IRubyObject arg0) throws Throwable { RubyClass selfClass = self.getMetaClass(); String methodName = site.name; SwitchPoint switchPoint = (SwitchPoint)selfClass.getInvalidator().getData(); CacheEntry entry = selfClass.searchWithCache(methodName); DynamicMethod method = entry.method; if (methodMissing(entry, CallType.FUNCTIONAL, methodName, self)) { return callMethodMissing(entry, CallType.FUNCTIONAL, context, self, methodName, arg0); } MethodHandle mh = getHandle(selfClass, switchPoint, site, method, 1, false); site.setTarget(mh); return (IRubyObject)mh.invokeWithArguments(context, self, arg0); }
private static MethodHandle findParameterHelper(String name, Class nativeIntClass) { return findStatic(JITRuntime.class, name + (int.class == nativeIntClass ? 32 : 64), MethodType.methodType(nativeIntClass, IRubyObject.class)); }