⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegen.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            cfw.addDLoad(5 + (i * 3));        }        cfw.addALoad(4 + argCount * 3);        cfw.addInvoke(ByteCode.INVOKESTATIC,                      mainClassName,                      getBodyMethodName(ofn.fnode),                      getBodyMethodSignature(ofn.fnode));        int exitLabel = cfw.acquireLabel();        cfw.add(ByteCode.DUP); // make a copy of direct call result        cfw.add(ByteCode.INSTANCEOF, "org/mozilla/javascript/Scriptable");        cfw.add(ByteCode.IFEQ, exitLabel);        // cast direct call result        cfw.add(ByteCode.CHECKCAST, "org/mozilla/javascript/Scriptable");        cfw.add(ByteCode.ARETURN);        cfw.markLabel(exitLabel);        cfw.addALoad(firstLocal);        cfw.add(ByteCode.ARETURN);        cfw.stopMethod((short)(firstLocal + 1));    }    private void generateCallMethod(ClassFileWriter cfw)    {        cfw.startMethod("call",                        "(Lorg/mozilla/javascript/Context;" +                        "Lorg/mozilla/javascript/Scriptable;" +                        "Lorg/mozilla/javascript/Scriptable;" +                        "[Ljava/lang/Object;)Ljava/lang/Object;",                        (short)(ClassFileWriter.ACC_PUBLIC                                | ClassFileWriter.ACC_FINAL));        // Generate code for:        // if (!ScriptRuntime.hasTopCall(cx)) {        //     return ScriptRuntime.doTopCall(this, cx, scope, thisObj, args);        // }        int nonTopCallLabel = cfw.acquireLabel();        cfw.addALoad(1); //cx        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/ScriptRuntime",                      "hasTopCall",                      "(Lorg/mozilla/javascript/Context;"                      +")Z");        cfw.add(ByteCode.IFNE, nonTopCallLabel);        cfw.addALoad(0);        cfw.addALoad(1);        cfw.addALoad(2);        cfw.addALoad(3);        cfw.addALoad(4);        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/ScriptRuntime",                      "doTopCall",                      "(Lorg/mozilla/javascript/Callable;"                      +"Lorg/mozilla/javascript/Context;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +"[Ljava/lang/Object;"                      +")Ljava/lang/Object;");        cfw.add(ByteCode.ARETURN);        cfw.markLabel(nonTopCallLabel);        // No generate switch to call the real methods        cfw.addALoad(0);        cfw.addALoad(1);        cfw.addALoad(2);        cfw.addALoad(3);        cfw.addALoad(4);        int end = scriptOrFnNodes.length;        boolean generateSwitch = (2 <= end);        int switchStart = 0;        int switchStackTop = 0;        if (generateSwitch) {            cfw.addLoadThis();            cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I");            // do switch from (1,  end - 1) mapping 0 to            // the default case            switchStart = cfw.addTableSwitch(1, end - 1);        }        for (int i = 0; i != end; ++i) {            ScriptOrFnNode n = scriptOrFnNodes[i];            if (generateSwitch) {                if (i == 0) {                    cfw.markTableSwitchDefault(switchStart);                    switchStackTop = cfw.getStackTop();                } else {                    cfw.markTableSwitchCase(switchStart, i - 1,                                            switchStackTop);                }            }            if (n.getType() == Token.FUNCTION) {                OptFunctionNode ofn = OptFunctionNode.get(n);                if (ofn.isTargetOfDirectCall()) {                    int pcount = ofn.fnode.getParamCount();                    if (pcount != 0) {                        // loop invariant:                        // stack top == arguments array from addALoad4()                        for (int p = 0; p != pcount; ++p) {                            cfw.add(ByteCode.ARRAYLENGTH);                            cfw.addPush(p);                            int undefArg = cfw.acquireLabel();                            int beyond = cfw.acquireLabel();                            cfw.add(ByteCode.IF_ICMPLE, undefArg);                            // get array[p]                            cfw.addALoad(4);                            cfw.addPush(p);                            cfw.add(ByteCode.AALOAD);                            cfw.add(ByteCode.GOTO, beyond);                            cfw.markLabel(undefArg);                            pushUndefined(cfw);                            cfw.markLabel(beyond);                            // Only one push                            cfw.adjustStackTop(-1);                            cfw.addPush(0.0);                            // restore invariant                            cfw.addALoad(4);                        }                    }                }            }            cfw.addInvoke(ByteCode.INVOKESTATIC,                          mainClassName,                          getBodyMethodName(n),                          getBodyMethodSignature(n));            cfw.add(ByteCode.ARETURN);        }        cfw.stopMethod((short)5);        // 5: this, cx, scope, js this, args[]    }    private void generateMain(ClassFileWriter cfw)    {        cfw.startMethod("main", "([Ljava/lang/String;)V",                        (short)(ClassFileWriter.ACC_PUBLIC                                | ClassFileWriter.ACC_STATIC));        // load new ScriptImpl()        cfw.add(ByteCode.NEW, cfw.getClassName());        cfw.add(ByteCode.DUP);        cfw.addInvoke(ByteCode.INVOKESPECIAL, cfw.getClassName(),                      "<init>", "()V");         // load 'args'        cfw.add(ByteCode.ALOAD_0);        // Call mainMethodClass.main(Script script, String[] args)        cfw.addInvoke(ByteCode.INVOKESTATIC,                      mainMethodClass,                      "main",                      "(Lorg/mozilla/javascript/Script;[Ljava/lang/String;)V");        cfw.add(ByteCode.RETURN);        // 1 = String[] args        cfw.stopMethod((short)1);    }    private void generateExecute(ClassFileWriter cfw, ScriptOrFnNode script)    {        cfw.startMethod("exec",                        "(Lorg/mozilla/javascript/Context;"                        +"Lorg/mozilla/javascript/Scriptable;"                        +")Ljava/lang/Object;",                        (short)(ClassFileWriter.ACC_PUBLIC                                | ClassFileWriter.ACC_FINAL));        final int CONTEXT_ARG = 1;        final int SCOPE_ARG = 2;        cfw.addLoadThis();        cfw.addALoad(CONTEXT_ARG);        cfw.addALoad(SCOPE_ARG);        cfw.add(ByteCode.DUP);        cfw.add(ByteCode.ACONST_NULL);        cfw.addInvoke(ByteCode.INVOKEVIRTUAL,                      cfw.getClassName(),                      "call",                      "(Lorg/mozilla/javascript/Context;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +"[Ljava/lang/Object;"                      +")Ljava/lang/Object;");        cfw.add(ByteCode.ARETURN);        // 3 = this + context + scope        cfw.stopMethod((short)3);    }    private void generateScriptCtor(ClassFileWriter cfw,                                    ScriptOrFnNode script)    {        cfw.startMethod("<init>", "()V", ClassFileWriter.ACC_PUBLIC);        cfw.addLoadThis();        cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME,                      "<init>", "()V");        // set id to 0        cfw.addLoadThis();        cfw.addPush(0);        cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I");        cfw.add(ByteCode.RETURN);        // 1 parameter = this        cfw.stopMethod((short)1);    }    private void generateFunctionConstructor(ClassFileWriter cfw)    {        final int SCOPE_ARG = 1;        final int CONTEXT_ARG = 2;        final int ID_ARG = 3;        cfw.startMethod("<init>", FUNCTION_CONSTRUCTOR_SIGNATURE,                        ClassFileWriter.ACC_PUBLIC);        cfw.addALoad(0);        cfw.addInvoke(ByteCode.INVOKESPECIAL, SUPER_CLASS_NAME,                      "<init>", "()V");        cfw.addLoadThis();        cfw.addILoad(ID_ARG);        cfw.add(ByteCode.PUTFIELD, cfw.getClassName(), ID_FIELD_NAME, "I");        cfw.addLoadThis();        cfw.addALoad(CONTEXT_ARG);        cfw.addALoad(SCOPE_ARG);        int start = (scriptOrFnNodes[0].getType() == Token.SCRIPT) ? 1 : 0;        int end = scriptOrFnNodes.length;        if (start == end) throw badTree();        boolean generateSwitch = (2 <= end - start);        int switchStart = 0;        int switchStackTop = 0;        if (generateSwitch) {            cfw.addILoad(ID_ARG);            // do switch from (start + 1,  end - 1) mapping start to            // the default case            switchStart = cfw.addTableSwitch(start + 1, end - 1);        }        for (int i = start; i != end; ++i) {            if (generateSwitch) {                if (i == start) {                    cfw.markTableSwitchDefault(switchStart);                    switchStackTop = cfw.getStackTop();                } else {                    cfw.markTableSwitchCase(switchStart, i - 1 - start,                                            switchStackTop);                }            }            OptFunctionNode ofn = OptFunctionNode.get(scriptOrFnNodes[i]);            cfw.addInvoke(ByteCode.INVOKEVIRTUAL,                          mainClassName,                          getFunctionInitMethodName(ofn),                          FUNCTION_INIT_SIGNATURE);            cfw.add(ByteCode.RETURN);        }        // 4 = this + scope + context + id        cfw.stopMethod((short)4);    }    private void generateFunctionInit(ClassFileWriter cfw,                                      OptFunctionNode ofn)    {        final int CONTEXT_ARG = 1;        final int SCOPE_ARG = 2;        cfw.startMethod(getFunctionInitMethodName(ofn),                        FUNCTION_INIT_SIGNATURE,                        (short)(ClassFileWriter.ACC_PRIVATE                                | ClassFileWriter.ACC_FINAL));        // Call NativeFunction.initScriptFunction        cfw.addLoadThis();        cfw.addALoad(CONTEXT_ARG);        cfw.addALoad(SCOPE_ARG);        cfw.addInvoke(ByteCode.INVOKEVIRTUAL,                      "org/mozilla/javascript/NativeFunction",                      "initScriptFunction",                      "(Lorg/mozilla/javascript/Context;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +")V");        // precompile all regexp literals        int regexpCount = ofn.fnode.getRegexpCount();        if (regexpCount != 0) {            cfw.addLoadThis();            pushRegExpArray(cfw, ofn.fnode, CONTEXT_ARG, SCOPE_ARG);            cfw.add(ByteCode.PUTFIELD, mainClassName,                    REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE);        }        cfw.add(ByteCode.RETURN);        // 3 = (scriptThis/functionRef) + scope + context        cfw.stopMethod((short)3);    }    private void generateNativeFunctionOverrides(ClassFileWriter cfw,                                                 String encodedSource)    {        // Override NativeFunction.getLanguageVersion() with        // public int getLanguageVersion() { return <version-constant>; }        cfw.startMethod("getLanguageVersion", "()I",                        ClassFileWriter.ACC_PUBLIC);        cfw.addPush(compilerEnv.getLanguageVersion());        cfw.add(ByteCode.IRETURN);        // 1: this and no argument or locals        cfw.stopMethod((short)1);        // The rest of NativeFunction overrides require specific code for each        // script/function id        final int Do_getFunctionName      = 0;        final int Do_getParamCount        = 1;        final int Do_getParamAndVarCount  = 2;        final int Do_getParamOrVarName    = 3;        final int Do_getEncodedSource     = 4;        final int SWITCH_COUNT            = 5;        for (int methodIndex = 0; methodIndex != SWITCH_COUNT; ++methodIndex) {            if (methodIndex == Do_getEncodedSource && encodedSource == null) {                continue;            }            // Generate:            //   prologue;            //   switch over function id to implement function-specific action            //   epilogue            short metodLocals;            switch (methodIndex) {              case Do_getFunctionName:                metodLocals = 1; // Only this                cfw.startMethod("getFunctionName", "()Ljava/lang/String;",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamCount:                metodLocals = 1; // Only this                cfw.startMethod("getParamCount", "()I",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamAndVarCount:                metodLocals = 1; // Only this                cfw.startMethod("getParamAndVarCount", "()I",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamOrVarName:                metodLocals = 1 + 1; // this + paramOrVarIndex

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -