Package org.jruby.compiler.impl

Examples of org.jruby.compiler.impl.SkinnyMethodAdapter


        String ciClassname = "L" + classname + ";";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
        cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, namePath, null, COMPILED_BLOCK_SUPER_CLASS_NAME, null);
        cw.visitSource(namePath, null);
        cw.visitField(ACC_PRIVATE | ACC_FINAL, "$scriptObject", ciClassname, null, null);
        SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", sig(Void.TYPE, params(Object.class)), null, null);
        mv.start();
        mv.aload(0);
        mv.invokespecial(p(CompiledBlockCallback.class), "<init>", sig(void.class));
        mv.aloadMany(0, 1);
        mv.checkcast(classname);
        mv.putfield(namePath, "$scriptObject", ciClassname);
        mv.voidreturn();
        mv.end();

        return cw;
    }
View Full Code Here


        String ciClassname = "L" + classname + ";";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
        cw.visit(RubyInstanceConfig.JAVA_VERSION, ACC_PUBLIC + ACC_SUPER, namePath, null, p(Object.class), new String[] {COMPILED_BLOCK_19_INTERFACE_NAME});
        cw.visitSource(namePath, null);
        cw.visitField(ACC_PRIVATE | ACC_FINAL, "$scriptObject", ciClassname, null, null);
        SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "<init>", sig(Void.TYPE, params(Object.class)), null, null);
        mv.start();
        mv.aload(0);
        mv.invokespecial(p(Object.class), "<init>", sig(void.class));
        mv.aloadMany(0, 1);
        mv.checkcast(classname);
        mv.putfield(namePath, "$scriptObject", ciClassname);
        mv.voidreturn();
        mv.end();

        return cw;
    }
View Full Code Here

    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;
    }
View Full Code Here

    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;
    }
View Full Code Here

    private SkinnyMethodAdapter beginMethod(ClassWriter cw, String methodName, int specificArity, boolean block) {
        switch (specificArity) {
        default:
        case -1:
            if (block) {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_BLOCK, null, null);
            } else {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG, null, null);
            }
        case 0:
            if (block) {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_ZERO_BLOCK, null, null);
            } else {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_ZERO, null, null);
            }
        case 1:
            if (block) {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_ONE_BLOCK, null, null);
            } else {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_ONE, null, null);
            }
        case 2:
            if (block) {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_TWO_BLOCK, null, null);
            } else {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_TWO, null, null);
            }
        case 3:
            if (block) {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_THREE_BLOCK, null, null);
            } else {
                return new SkinnyMethodAdapter(cw, ACC_PUBLIC, methodName, COMPILED_CALL_SIG_THREE, null, null);
            }
        }
    }
View Full Code Here

                    specificArity = desc.required;
                }
            }

            boolean hasBlock = desc.hasBlock;
            SkinnyMethodAdapter mv = null;

            mv = beginMethod(cw, callName, specificArity, hasBlock);
            mv.visitCode();

            createAnnotatedMethodInvocation(desc, mv, superClass, specificArity, hasBlock);

            mv.end();
        }
    }
View Full Code Here

            StaticScope scope, CallConfiguration callConfig, String filename, int line,
            MethodNodes methodNodes) {
        String sup = COMPILED_SUPER_CLASS_NAME;
        ClassWriter cw;
        cw = createCompiledCtor(invokerPath, invokerPath, sup);
        SkinnyMethodAdapter mv = null;
        String signature = null;
        boolean specificArity = false;

        // if trace, need to at least populate a backtrace frame
        if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
            switch (callConfig) {
            case FrameNoneScopeDummy:
                callConfig = CallConfiguration.FrameBacktraceScopeDummy;
                break;
            case FrameNoneScopeFull:
                callConfig = CallConfiguration.FrameBacktraceScopeFull;
                break;
            case FrameNoneScopeNone:
                callConfig = CallConfiguration.FrameBacktraceScopeNone;
                break;
            }
        }

        if (scope.getRestArg() >= 0 || scope.getOptionalArgs() > 0 || scope.getRequiredArgs() > 3) {
            signature = COMPILED_CALL_SIG_BLOCK;
            mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "call", signature, null, null);
        } else {
            specificArity = true;

            mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "call", COMPILED_CALL_SIG_BLOCK, null, null);
            mv.start();

            // check arity
            mv.aloadMany(0, 1, 4, 5); // method, context, name, args, required
            mv.pushInt(scope.getRequiredArgs());
            mv.invokestatic(p(JavaMethod.class), "checkArgumentCount", sig(void.class, JavaMethod.class, ThreadContext.class, String.class, IRubyObject[].class, int.class));

            mv.aloadMany(0, 1, 2, 3, 4);
            for (int i = 0; i < scope.getRequiredArgs(); i++) {
                mv.aload(5);
                mv.ldc(i);
                mv.arrayload();
            }
            mv.aload(6);

            switch (scope.getRequiredArgs()) {
            case 0:
                signature = COMPILED_CALL_SIG_ZERO_BLOCK;
                break;
            case 1:
                signature = COMPILED_CALL_SIG_ONE_BLOCK;
                break;
            case 2:
                signature = COMPILED_CALL_SIG_TWO_BLOCK;
                break;
            case 3:
                signature = COMPILED_CALL_SIG_THREE_BLOCK;
                break;
            }

            mv.invokevirtual(invokerPath, "call", signature);
            mv.areturn();
            mv.end();

            // Define a second version that doesn't take a block, so we have unique code paths for both cases.
            switch (scope.getRequiredArgs()) {
            case 0:
                signature = COMPILED_CALL_SIG_ZERO;
                break;
            case 1:
                signature = COMPILED_CALL_SIG_ONE;
                break;
            case 2:
                signature = COMPILED_CALL_SIG_TWO;
                break;
            case 3:
                signature = COMPILED_CALL_SIG_THREE;
                break;
            }
            mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "call", signature, null, null);
            mv.start();

            mv.aloadMany(0, 1, 2, 3, 4);
            for (int i = 1; i <= scope.getRequiredArgs(); i++) {
                mv.aload(4 + i);
            }
            mv.getstatic(p(Block.class), "NULL_BLOCK", ci(Block.class));

            switch (scope.getRequiredArgs()) {
            case 0:
                signature = COMPILED_CALL_SIG_ZERO_BLOCK;
                break;
            case 1:
                signature = COMPILED_CALL_SIG_ONE_BLOCK;
                break;
            case 2:
                signature = COMPILED_CALL_SIG_TWO_BLOCK;
                break;
            case 3:
                signature = COMPILED_CALL_SIG_THREE_BLOCK;
                break;
            }

            mv.invokevirtual(invokerPath, "call", signature);
            mv.areturn();
            mv.end();

            mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "call", signature, null, null);
        }

        mv.start();

        boolean heapScoped = callConfig.scoping() != Scoping.None;
        boolean framed = callConfig.framing() != Framing.None;

        // save off callNumber if framed or scoped, for non-local returns
        int callNumberIndex = -1;
        if (framed || heapScoped) {
            mv.aload(1);
            mv.getfield(p(ThreadContext.class), "callNumber", ci(int.class));
            if (specificArity) {
                switch (scope.getRequiredArgs()) {
                case -1:
                    callNumberIndex = ARGS_INDEX + 1/*args*/ + 1/*block*/ + 1;
                    break;
                case 0:
                    callNumberIndex = ARGS_INDEX + 1/*block*/ + 1;
                    break;
                default:
                    callNumberIndex = ARGS_INDEX + scope.getRequiredArgs() + 1/*block*/ + 1;
                }
            } else {
                callNumberIndex = ARGS_INDEX + 1/*block*/ + 1;
            }
            mv.istore(callNumberIndex);
        }

        // invoke pre method stuff
        if (!callConfig.isNoop() || RubyInstanceConfig.FULL_TRACE_ENABLED) {
            if (specificArity) {
                invokeCallConfigPre(mv, COMPILED_SUPER_CLASS_NAME, scope.getRequiredArgs(), true, callConfig);
            } else {
                invokeCallConfigPre(mv, COMPILED_SUPER_CLASS_NAME, -1, true, callConfig);
            }
        }

        // pre-call trace
        int traceBoolIndex = -1;
        if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
            // load and store trace enabled flag
            if (specificArity) {
                switch (scope.getRequiredArgs()) {
                case -1:
                    traceBoolIndex = ARGS_INDEX + 1/*args*/ + 1/*block*/ + 2;
                    break;
                case 0:
                    traceBoolIndex = ARGS_INDEX + 1/*block*/ + 2;
                    break;
                default:
                    traceBoolIndex = ARGS_INDEX + scope.getRequiredArgs() + 1/*block*/ + 2;
                }
            } else {
                traceBoolIndex = ARGS_INDEX + 1/*block*/ + 2;
            }

            mv.aload(1);
            mv.invokevirtual(p(ThreadContext.class), "getRuntime", sig(Ruby.class));
            mv.invokevirtual(p(Ruby.class), "hasEventHooks", sig(boolean.class));
            mv.istore(traceBoolIndex);
            // tracing pre
            invokeTraceCompiledPre(mv, COMPILED_SUPER_CLASS_NAME, traceBoolIndex, filename, line);
        }

        Label tryBegin = new Label();
        Label tryEnd = new Label();
        Label doFinally = new Label();
        Label doReturnFinally = new Label();
        Label doRedoFinally = new Label();
        Label catchReturnJump = new Label();
        Label catchRedoJump = new Label();

        if (framed || heapScoped)   mv.trycatch(tryBegin, tryEnd, catchReturnJump, p(JumpException.ReturnJump.class));
        if (framed)                 mv.trycatch(tryBegin, tryEnd, catchRedoJump, p(JumpException.RedoJump.class));
        if (framed || heapScoped)   mv.trycatch(tryBegin, tryEnd, doFinally, null);
        if (framed || heapScoped)   mv.trycatch(catchReturnJump, doReturnFinally, doFinally, null);
        if (framed)                 mv.trycatch(catchRedoJump, doRedoFinally, doFinally, null);
        if (framed || heapScoped)   mv.label(tryBegin);

        // main body
        {
            mv.aload(0);
            // FIXME we want to eliminate these type casts when possible
            mv.getfield(invokerPath, "$scriptObject", ci(Object.class));
            mv.checkcast(className);
            mv.aloadMany(THREADCONTEXT_INDEX, RECEIVER_INDEX);
            if (specificArity) {
                for (int i = 0; i < scope.getRequiredArgs(); i++) {
                    mv.aload(ARGS_INDEX + i);
                }
                mv.aload(ARGS_INDEX + scope.getRequiredArgs());
                mv.invokestatic(className, method, Helpers.getStaticMethodSignature(className, scope.getRequiredArgs()));
            } else {
                mv.aloadMany(ARGS_INDEX, BLOCK_INDEX);
                mv.invokestatic(className, method, Helpers.getStaticMethodSignature(className, 4));
            }
        }
        if (framed || heapScoped) {
            mv.label(tryEnd);
        }

        // normal exit, perform finally and return
        {
            if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
                invokeTraceCompiledPost(mv, COMPILED_SUPER_CLASS_NAME, traceBoolIndex);
            }
            if (!callConfig.isNoop()) {
                invokeCallConfigPost(mv, COMPILED_SUPER_CLASS_NAME, callConfig);
            }
            mv.visitInsn(ARETURN);
        }

        // return jump handling
        if (framed || heapScoped) {
            mv.label(catchReturnJump);
            {
                mv.aload(0);
                mv.swap();
                mv.aload(1);
                mv.swap();
                mv.iload(callNumberIndex);
                mv.invokevirtual(COMPILED_SUPER_CLASS_NAME, "handleReturn", sig(IRubyObject.class, ThreadContext.class, JumpException.ReturnJump.class, int.class));
                mv.label(doReturnFinally);

                // finally
                if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
                    invokeTraceCompiledPost(mv, COMPILED_SUPER_CLASS_NAME, traceBoolIndex);
                }
                if (!callConfig.isNoop()) {
                    invokeCallConfigPost(mv, COMPILED_SUPER_CLASS_NAME, callConfig);
                }

                // return result if we're still good
                mv.areturn();
            }
        }

        if (framed) {
            // redo jump handling
            mv.label(catchRedoJump);
            {
                // clear the redo
                mv.pop();

                // get runtime, create jump error, and throw it
                mv.aload(1);
                mv.invokevirtual(p(ThreadContext.class), "getRuntime", sig(Ruby.class));
                mv.invokevirtual(p(Ruby.class), "newRedoLocalJumpError", sig(RaiseException.class));
                mv.label(doRedoFinally);

                // finally
                if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
                    invokeTraceCompiledPost(mv, COMPILED_SUPER_CLASS_NAME, traceBoolIndex);
                }
                if (!callConfig.isNoop()) {
                    invokeCallConfigPost(mv, COMPILED_SUPER_CLASS_NAME, callConfig);
                }

                // throw redo error if we're still good
                mv.athrow();
            }
        }

        // finally handling for abnormal exit
        if (framed || heapScoped) {
            mv.label(doFinally);

            //call post method stuff (exception raised)
            if (RubyInstanceConfig.FULL_TRACE_ENABLED) {
                invokeTraceCompiledPost(mv, COMPILED_SUPER_CLASS_NAME, traceBoolIndex);
            }
            if (!callConfig.isNoop()) {
                invokeCallConfigPost(mv, COMPILED_SUPER_CLASS_NAME, callConfig);
            }

            // rethrow exception
            mv.athrow(); // rethrow it
        }
        mv.end();

        return endCallOffline(cw);
    }
View Full Code Here

    @Override
    public byte[] getBlockCallbackOffline(String method, String file, int line, String classname) {
        String mname = getBlockCallbackName(classname, method);
        ClassWriter cw = createBlockCtor(mname, classname);
        SkinnyMethodAdapter mv = startBlockCall(cw);
        mv.aload(0);
        mv.getfield(mname, "$scriptObject", "L" + classname + ";");
        mv.aloadMany(1, 2, 3, 4);
        mv.invokestatic(classname, method, sig(
                IRubyObject.class, "L" + classname + ";", ThreadContext.class,
                        IRubyObject.class, IRubyObject.class, Block.class));
        mv.areturn();
        mv.end();

        mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "getFile", sig(String.class), null, null);
        mv.start();
        mv.ldc(file);
        mv.areturn();
        mv.end();

        mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "getLine", sig(int.class), null, null);
        mv.start();
        mv.ldc(line);
        mv.ireturn();
        mv.end();

        return endCallOffline(cw);
    }
View Full Code Here

    @Override
    public byte[] getBlockCallback19Offline(String method, String file, int line, String classname) {
        String mnamePath = getBlockCallbackName(classname, method);
        ClassWriter cw = createBlockCtor19(mnamePath, classname);
        SkinnyMethodAdapter mv = startBlockCall19(cw);
        mv.aload(0);
        mv.getfield(mnamePath, "$scriptObject", "L" + classname + ";");
        mv.aloadMany(1, 2, 3, 4);
        mv.invokestatic(classname, method, sig(
                IRubyObject.class, "L" + classname + ";", ThreadContext.class,
                        IRubyObject.class, IRubyObject[].class, Block.class));
        mv.areturn();
        mv.end();

        mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "getFile", sig(String.class), null, null);
        mv.start();
        mv.ldc(file);
        mv.areturn();
        mv.end();

        mv = new SkinnyMethodAdapter(cw, ACC_PUBLIC, "getLine", sig(int.class), null, null);
        mv.start();
        mv.ldc(line);
        mv.ireturn();
        mv.end();
       
        return endCallOffline(cw);
    }
View Full Code Here

       
        return endCallOffline(cw);
    }

    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;
    }
View Full Code Here

TOP

Related Classes of org.jruby.compiler.impl.SkinnyMethodAdapter

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.