private ClassWriter createJavaMethodCtor(String namePath, String sup, String parameterDesc) throws Exception { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); String sourceFile = namePath.substring(namePath.lastIndexOf('/') + 1) + ".gen"; cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, namePath, null, sup, null); cw.visitSource(sourceFile, null); SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", JAVA_SUPER_SIG, null, null); mv.start(); mv.aloadMany(0, 1, 2); mv.visitMethodInsn(INVOKESPECIAL, sup, "<init>", JAVA_SUPER_SIG); mv.aload(0); mv.ldc(parameterDesc); mv.invokevirtual(p(JavaMethod.class), "setParameterDesc", sig(void.class, String.class)); mv.voidreturn(); mv.end(); return cw; }
public void loadSelfBlock() { int selfBlockOffset = signature.argOffset(JVMVisitor.SELF_BLOCK_NAME); if (selfBlockOffset == -1) { adapter.aconst_null(); } else { adapter.aload(selfBlockOffset); } }
private SkinnyMethodAdapter startBlockCall(ClassWriter cw) { SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC | ACC_SYNTHETIC | ACC_FINAL, "call", BLOCK_CALL_SIG, null, null); mv.visitCode(); return mv; }
private void invokeTraceCompiledPre(SkinnyMethodAdapter mv, String superClass, int traceBoolIndex, String filename, int line) { mv.aloadMany(0, 1); // method, threadContext mv.iload(traceBoolIndex); // traceEnable mv.aload(4); // invokedName mv.ldc(filename); mv.ldc(line); mv.invokevirtual(superClass, "callTraceCompiled", sig(void.class, ThreadContext.class, boolean.class, String.class, String.class, int.class)); }
m = new SkinnyMethodAdapter(cv, ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC, "invoke", signature, null, null); m.start(); m.aload(1); // receiver if (method.getDeclaringClass() != Object.class) { m.checkcast(p(method.getDeclaringClass())); default: for (int i = 0; i < paramTypes.length; i++) { m.aload(2); // Object[] args m.pushInt(i); m.aaload(); Class paramClass = paramTypes[i]; if (paramClass.isPrimitive()) { Class boxType = getBoxType(paramClass); m.checkcast(p(boxType)); m.invokevirtual(p(boxType), paramClass.toString() + "Value", sig(paramClass)); } else if (paramClass != Object.class) { m.checkcast(p(paramClass)); m.invokestatic(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes)); } else if (Modifier.isInterface(method.getDeclaringClass().getModifiers())) { m.invokeinterface(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes)); } else { m.invokevirtual(p(method.getDeclaringClass()), method.getName(), sig(returnType, paramTypes)); m.aconst_null(); } else if (returnType.isPrimitive()) {
mv.pushInt(paramTypes.length); mv.anewarray(p(IRubyObject.class)); mv.dup(); mv.pushInt(i); mv.aload(rubyIndex); if (paramType == byte.class || paramType == short.class || paramType == char.class || paramType == int.class) { mv.iload(argIndex++); mv.invokestatic(p(JavaUtil.class), "convertJavaToRuby", sig(IRubyObject.class, Ruby.class, int.class)); } else if (paramType == long.class) { mv.lload(argIndex); argIndex += 2; // up two slots, for long's two halves mv.invokestatic(p(JavaUtil.class), "convertJavaToRuby", sig(IRubyObject.class, Ruby.class, long.class)); } else if (paramType == float.class) { mv.fload(argIndex++); mv.invokestatic(p(JavaUtil.class), "convertJavaToRuby", sig(IRubyObject.class, Ruby.class, float.class)); } else if (paramType == double.class) { mv.dload(argIndex); argIndex += 2; // up two slots, for long's two halves mv.invokestatic(p(JavaUtil.class), "convertJavaToRuby", sig(IRubyObject.class, Ruby.class, double.class)); } else if (paramType == boolean.class) { mv.iload(argIndex++); mv.invokestatic(p(JavaUtil.class), "convertJavaToRuby", sig(IRubyObject.class, Ruby.class, boolean.class)); mv.aload(rubyIndex); mv.aload(argIndex++); mv.invokestatic(p(JavaUtil.class), "convertJavaToUsableRubyObject", sig(IRubyObject.class, Ruby.class, Object.class)); } else {
method.aload(ARGS_INDEX); method.arraylength(); method.ldc(jrubyMethod.required()); method.if_icmplt(arityError); checkArity = true; method.aload(ARGS_INDEX); method.arraylength(); method.ldc(jrubyMethod.required()); method.if_icmplt(arityError); method.aload(ARGS_INDEX); method.arraylength(); method.ldc(jrubyMethod.required() + jrubyMethod.optional()); method.if_icmpgt(arityError); checkArity = true; } else { method.aload(ARGS_INDEX); method.arraylength(); method.ldc(jrubyMethod.required()); method.if_icmpne(arityError); checkArity = true; method.go_to(noArityError); method.label(arityError); method.aload(THREADCONTEXT_INDEX); method.invokevirtual(p(ThreadContext.class), "getRuntime", sig(Ruby.class));
case 0: signature = sig(IRubyObject.class); // return IRubyObject foo() m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, javaMethodName, signature, null, null); generateMethodAnnotations(methodAnnos, m, parameterAnnos); m.aload(0); m.ldc(id); m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class)); break; case 1: signature = sig(IRubyObject.class, IRubyObject.class); // return IRubyObject foo(IRubyObject arg1) m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, javaMethodName, signature, null, null); generateMethodAnnotations(methodAnnos, m, parameterAnnos); m.aload(0); m.ldc(id); m.aload(1); // IRubyObject arg1 m.invokevirtual(javaPath, "callMethod", sig(IRubyObject.class, String.class, IRubyObject.class)); break; Class[] params = new Class[paramCount]; Arrays.fill(params, IRubyObject.class); signature = sig(IRubyObject.class, params); m = new SkinnyMethodAdapter(cw, ACC_PUBLIC, javaMethodName, signature, null, null); generateMethodAnnotations(methodAnnos, m, parameterAnnos); m.aload(0); m.ldc(id); m.pushInt(paramCount);
method = new SkinnyMethodAdapter( script.getClassVisitor(), ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC, null, null); method.start(); method.aloadMany(0, 1, 2); method.invokestatic(script.getClassname(), nextName, sig(IRubyObject[].class, "L" + script.getClassname() + ";", ThreadContext.class, IRubyObject[].class)); method.areturn(); method.end(); method = new SkinnyMethodAdapter( script.getClassVisitor(), ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC, null, null); method.start(); method.aload(2); method.pushInt(i); method.arraystore(); method.aload(2); method.areturn();
private void beginInit() { ClassVisitor cv = getClassVisitor(); initMethod = new SkinnyMethodAdapter(cv, ACC_PUBLIC, "<init>", sig(Void.TYPE), null, null); initMethod.start(); initMethod.aload(THIS); initMethod.invokespecial(p(AbstractScript.class), "<init>", sig(Void.TYPE)); // JRUBY-3014: make __FILE__ dynamically determined at load time, but // we provide a reasonable default here initMethod.aload(THIS); initMethod.ldc(getSourcename()); initMethod.putfield(getClassname(), "filename", ci(String.class)); }
private ClassWriter createCompiledCtor(String namePath, String shortPath, String sup) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES); cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, namePath, null, sup, null); cw.visitSource(shortPath, null); SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", "()V", null, null); mv.visitCode(); mv.aload(0); mv.visitMethodInsn(INVOKESPECIAL, sup, "<init>", "()V"); mv.voidreturn(); mv.end(); return cw; }
public void beginChainedMethod() { method.start(); method.aload(StandardASMCompiler.THREADCONTEXT_INDEX); method.invokevirtual(p(ThreadContext.class), "getCurrentScope", sig(DynamicScope.class)); method.astore(getDynamicScopeIndex()); // if more than 4 locals, get the locals array too if (scope.getNumberOfVariables() > 4) { method.aload(getDynamicScopeIndex()); method.invokevirtual(p(DynamicScope.class), "getValues", sig(IRubyObject[].class)); method.astore(getVarsArrayIndex()); } // visit a label to start scoping for local vars in this method method.label(scopeStart); }
private void buildObjectArray(String type, Object[] sourceArray, ArrayCallback callback) { if (sourceArray.length == 0) { method.getstatic(p(IRubyObject.class), "NULL_ARRAY", ci(IRubyObject[].class)); } else if (sourceArray.length <= Helpers.MAX_SPECIFIC_ARITY_OBJECT_ARRAY) { // if we have a specific-arity helper to construct an array for us, use that for (int i = 0; i < sourceArray.length; i++) { callback.nextValue(this, sourceArray, i); } invokeUtilityMethod("constructObjectArray", sig(IRubyObject[].class, params(IRubyObject.class, sourceArray.length))); } else { // brute force construction inline method.pushInt(sourceArray.length); method.anewarray(type); for (int i = 0; i < sourceArray.length; i++) { method.dup(); method.pushInt(i); callback.nextValue(this, sourceArray, i); method.arraystore(); } } }
private static void objectToString(final int line, SkinnyMethodAdapter mv) { if ( line > 0 ) mv.line(line); mv.aload(0); mv.invokespecial(p(Object.class), "toString", sig(String.class)); mv.areturn(); }
private static void objectHashCode(final int line, SkinnyMethodAdapter mv) { if ( line > 0 ) mv.line(line); mv.aload(0); mv.invokespecial(p(Object.class), "hashCode", sig(Integer.TYPE)); mv.ireturn(); }
public void preMultiAssign(int head, boolean args) { // arrayish object is on stack, call utility and unpack if (head == 1 && args) { invokeUtilityMethod("arraySlice1N", sig(IRubyObject[].class, IRubyObject.class)); method.dup(); method.pushInt(1); method.aaload(); method.swap(); method.pushInt(0); method.aaload(); } else if (head == 1 && !args) { invokeUtilityMethod("arraySlice1", sig(IRubyObject.class, IRubyObject.class)); } else { throw new RuntimeException("invalid preMultiAssign args: " + head + ", " + args); } }
protected void emitVarargsMethodWrapper(IRScope scope, String variableName, String specificName, Signature variableSignature, Signature specificSignature) { jvm.pushmethod(variableName, scope, variableSignature, false); IRBytecodeAdapter m = jvmMethod(); // check arity org.jruby.runtime.Signature scopeSig = scope.getStaticScope().getSignature(); checkArity(scopeSig.required(), scopeSig.opt(), scopeSig.hasRest(), scopeSig.hasKwargs(), scopeSig.keyRest()); // push leading args m.loadContext(); m.loadStaticScope(); m.loadSelf(); // unwrap specific args if (scopeSig.required() > 0) { for (int i = 0; i < scopeSig.required(); i++) { m.loadArgs(); jvmAdapter().pushInt(i); jvmAdapter().aaload(); } } // push trailing args m.loadBlock(); m.loadFrameClass(); m.loadFrameName(); // invoke specific-arity version and return Method specificMethod = new Method(specificName, Type.getType(specificSignature.type().returnType()), IRRuntimeHelpers.typesFromSignature(specificSignature)); jvmAdapter().invokestatic(m.getClassData().clsName, specificName, specificMethod.getDescriptor()); jvmAdapter().areturn(); jvm.popmethod(); }
@Override public void TraceInstr(TraceInstr traceInstr) { jvmMethod().loadContext(); jvmAdapter().getstatic(p(RubyEvent.class), traceInstr.getEvent().name(), ci(RubyEvent.class)); String name = traceInstr.getName(); if (name == null) { jvmAdapter().aconst_null(); } else { jvmAdapter().ldc(name); } jvmAdapter().ldc(traceInstr.getFilename()); jvmAdapter().ldc(traceInstr.getLinenumber()); jvmMethod().invokeIRHelper("callTrace", sig(void.class, ThreadContext.class, RubyEvent.class, String.class, String.class, int.class)); }