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

📄 codegen.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
                cfw.startMethod("getParamOrVarName", "(I)Ljava/lang/String;",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getEncodedSource:                metodLocals = 1; // Only this                cfw.startMethod("getEncodedSource", "()Ljava/lang/String;",                                ClassFileWriter.ACC_PUBLIC);                cfw.addPush(encodedSource);                break;              default:                throw Kit.codeBug();            }            int count = scriptOrFnNodes.length;            int switchStart = 0;            int switchStackTop = 0;            if (count > 1) {                // Generate switch but only if there is more then one                // script/function                cfw.addLoadThis();                cfw.add(ByteCode.GETFIELD, cfw.getClassName(),                        ID_FIELD_NAME, "I");                // do switch from 1 .. count - 1 mapping 0 to the default case                switchStart = cfw.addTableSwitch(1, count - 1);            }            for (int i = 0; i != count; ++i) {                ScriptOrFnNode n = scriptOrFnNodes[i];                if (i == 0) {                    if (count > 1) {                        cfw.markTableSwitchDefault(switchStart);                        switchStackTop = cfw.getStackTop();                    }                } else {                    cfw.markTableSwitchCase(switchStart, i - 1,                                            switchStackTop);                }                // Impelemnet method-specific switch code                switch (methodIndex) {                  case Do_getFunctionName:                    // Push function name                    if (n.getType() == Token.SCRIPT) {                        cfw.addPush("");                    } else {                        String name = ((FunctionNode)n).getFunctionName();                        cfw.addPush(name);                    }                    cfw.add(ByteCode.ARETURN);                    break;                  case Do_getParamCount:                    // Push number of defined parameters                    cfw.addPush(n.getParamCount());                    cfw.add(ByteCode.IRETURN);                    break;                  case Do_getParamAndVarCount:                    // Push number of defined parameters and declared variables                    cfw.addPush(n.getParamAndVarCount());                    cfw.add(ByteCode.IRETURN);                    break;                  case Do_getParamOrVarName:                    // Push name of parameter using another switch                    // over paramAndVarCount                    int paramAndVarCount = n.getParamAndVarCount();                    if (paramAndVarCount == 0) {                        // The runtime should never call the method in this                        // case but to make bytecode verifier happy return null                        // as throwing execption takes more code                        cfw.add(ByteCode.ACONST_NULL);                        cfw.add(ByteCode.ARETURN);                    } else if (paramAndVarCount == 1) {                        // As above do not check for valid index but always                        // return the name of the first param                        cfw.addPush(n.getParamOrVarName(0));                        cfw.add(ByteCode.ARETURN);                    } else {                        // Do switch over getParamOrVarName                        cfw.addILoad(1); // param or var index                        // do switch from 1 .. paramAndVarCount - 1 mapping 0                        // to the default case                        int paramSwitchStart = cfw.addTableSwitch(                                                   1, paramAndVarCount - 1);                        for (int j = 0; j != paramAndVarCount; ++j) {                            if (cfw.getStackTop() != 0) Kit.codeBug();                            String s = n.getParamOrVarName(j);                            if (j == 0) {                                cfw.markTableSwitchDefault(paramSwitchStart);                            } else {                                cfw.markTableSwitchCase(paramSwitchStart, j - 1,                                                        0);                            }                            cfw.addPush(s);                            cfw.add(ByteCode.ARETURN);                        }                    }                    break;                  case Do_getEncodedSource:                    // Push number encoded source start and end                    // to prepare for encodedSource.substring(start, end)                    cfw.addPush(n.getEncodedSourceStart());                    cfw.addPush(n.getEncodedSourceEnd());                    cfw.addInvoke(ByteCode.INVOKEVIRTUAL,                                  "java/lang/String",                                  "substring",                                  "(II)Ljava/lang/String;");                    cfw.add(ByteCode.ARETURN);                    break;                  default:                    throw Kit.codeBug();                }            }            cfw.stopMethod(metodLocals);        }    }    private void emitRegExpInit(ClassFileWriter cfw)    {        // precompile all regexp literals        int totalRegCount = 0;        for (int i = 0; i != scriptOrFnNodes.length; ++i) {            totalRegCount += scriptOrFnNodes[i].getRegexpCount();        }        if (totalRegCount == 0) {            return;        }        cfw.startMethod(REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE,            (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE                    | ClassFileWriter.ACC_SYNCHRONIZED));        cfw.addField("_reInitDone", "Z",                     (short)(ClassFileWriter.ACC_STATIC                             | ClassFileWriter.ACC_PRIVATE));        cfw.add(ByteCode.GETSTATIC, mainClassName, "_reInitDone", "Z");        int doInit = cfw.acquireLabel();        cfw.add(ByteCode.IFEQ, doInit);        cfw.add(ByteCode.RETURN);        cfw.markLabel(doInit);        for (int i = 0; i != scriptOrFnNodes.length; ++i) {            ScriptOrFnNode n = scriptOrFnNodes[i];            int regCount = n.getRegexpCount();            for (int j = 0; j != regCount; ++j) {                String reFieldName = getCompiledRegexpName(n, j);                String reFieldType = "Ljava/lang/Object;";                String reString = n.getRegexpString(j);                String reFlags = n.getRegexpFlags(j);                cfw.addField(reFieldName, reFieldType,                             (short)(ClassFileWriter.ACC_STATIC                                     | ClassFileWriter.ACC_PRIVATE));                cfw.addALoad(0); // proxy                cfw.addALoad(1); // context                cfw.addPush(reString);                if (reFlags == null) {                    cfw.add(ByteCode.ACONST_NULL);                } else {                    cfw.addPush(reFlags);                }                cfw.addInvoke(ByteCode.INVOKEINTERFACE,                              "org/mozilla/javascript/RegExpProxy",                              "compileRegExp",                              "(Lorg/mozilla/javascript/Context;"                              +"Ljava/lang/String;Ljava/lang/String;"                              +")Ljava/lang/Object;");                cfw.add(ByteCode.PUTSTATIC, mainClassName,                        reFieldName, reFieldType);            }        }        cfw.addPush(1);        cfw.add(ByteCode.PUTSTATIC, mainClassName, "_reInitDone", "Z");        cfw.add(ByteCode.RETURN);        cfw.stopMethod((short)2);    }    private void emitConstantDudeInitializers(ClassFileWriter cfw)    {        int N = itsConstantListSize;        if (N == 0)            return;        cfw.startMethod("<clinit>", "()V",            (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_FINAL));        double[] array = itsConstantList;        for (int i = 0; i != N; ++i) {            double num = array[i];            String constantName = "_k" + i;            String constantType = getStaticConstantWrapperType(num);            cfw.addField(constantName, constantType,                         (short)(ClassFileWriter.ACC_STATIC                                 | ClassFileWriter.ACC_PRIVATE));            int inum = (int)num;            if (inum == num) {                cfw.add(ByteCode.NEW, "java/lang/Integer");                cfw.add(ByteCode.DUP);                cfw.addPush(inum);                cfw.addInvoke(ByteCode.INVOKESPECIAL, "java/lang/Integer",                              "<init>", "(I)V");            } else {                cfw.addPush(num);                addDoubleWrap(cfw);            }            cfw.add(ByteCode.PUTSTATIC, mainClassName,                    constantName, constantType);        }        cfw.add(ByteCode.RETURN);        cfw.stopMethod((short)0);    }    void pushRegExpArray(ClassFileWriter cfw, ScriptOrFnNode n,                         int contextArg, int scopeArg)    {        int regexpCount = n.getRegexpCount();        if (regexpCount == 0) throw badTree();        cfw.addPush(regexpCount);        cfw.add(ByteCode.ANEWARRAY, "java/lang/Object");        cfw.addALoad(contextArg);        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/ScriptRuntime",                      "checkRegExpProxy",                      "(Lorg/mozilla/javascript/Context;"                      +")Lorg/mozilla/javascript/RegExpProxy;");        // Stack: proxy, array        cfw.add(ByteCode.DUP);        cfw.addALoad(contextArg);        cfw.addInvoke(ByteCode.INVOKESTATIC, mainClassName,                      REGEXP_INIT_METHOD_NAME, REGEXP_INIT_METHOD_SIGNATURE);        for (int i = 0; i != regexpCount; ++i) {            // Stack: proxy, array            cfw.add(ByteCode.DUP2);            cfw.addALoad(contextArg);            cfw.addALoad(scopeArg);            cfw.add(ByteCode.GETSTATIC, mainClassName,                    getCompiledRegexpName(n, i), "Ljava/lang/Object;");            // Stack: compiledRegExp, scope, cx, proxy, array, proxy, array            cfw.addInvoke(ByteCode.INVOKEINTERFACE,                          "org/mozilla/javascript/RegExpProxy",                          "wrapRegExp",                          "(Lorg/mozilla/javascript/Context;"                          +"Lorg/mozilla/javascript/Scriptable;"                          +"Ljava/lang/Object;"                          +")Lorg/mozilla/javascript/Scriptable;");            // Stack: wrappedRegExp, array, proxy, array            cfw.addPush(i);            cfw.add(ByteCode.SWAP);            cfw.add(ByteCode.AASTORE);            // Stack: proxy, array        }        // remove proxy        cfw.add(ByteCode.POP);    }    void pushNumberAsObject(ClassFileWriter cfw, double num)    {        if (num == 0.0) {            if (1 / num > 0) {                // +0.0                cfw.add(ByteCode.GETSTATIC,                        "org/mozilla/javascript/optimizer/OptRuntime",                        "zeroObj", "Ljava/lang/Double;");            } else {                cfw.addPush(num);                addDoubleWrap(cfw);            }        } else if (num == 1.0) {            cfw.add(ByteCode.GETSTATIC,                    "org/mozilla/javascript/optimizer/OptRuntime",                    "oneObj", "Ljava/lang/Double;");            return;        } else if (num == -1.0) {            cfw.add(ByteCode.GETSTATIC,                    "org/mozilla/javascript/optimizer/OptRuntime",                    "minusOneObj", "Ljava/lang/Double;");        } else if (num != num) {            cfw.add(ByteCode.GETSTATIC,                    "org/mozilla/javascript/ScriptRuntime",                    "NaNobj", "Ljava/lang/Double;");        } else if (itsConstantListSize >= 2000) {            // There appears to be a limit in the JVM on either the number            // of static fields in a class or the size of the class            // initializer. Either way, we can't have any more than 2000            // statically init'd constants.            cfw.addPush(num);            addDoubleWrap(cfw);        } else {            int N = itsConstantListSize;            int index = 0;            if (N == 0) {                itsConstantList = new double[64];            } else {                double[] array = itsConstantList;                while (index != N && array[index] != num) {                    ++index;                }                if (N == array.length) {                    array = new double[N * 2];                    System.arraycopy(itsConstantList, 0, array, 0, N);                    itsConstantList = array;                }            }            if (index == N) {                itsConstantList[N] = num;                itsConstantListSize = N + 1;            }            String constantName = "_k" + index;            String constantType = getStaticConstantWrapperType(num);            cfw.add(ByteCode.GETSTATIC, mainClassName,                    constantName, constantType);        }    }    private static void addDoubleWrap(ClassFileWriter cfw)    {        cfw.addInvoke(ByteCode.INVOKESTATIC,                      "org/mozilla/javascript/optimizer/OptRuntime",                      "wrapDouble", "(D)Ljava/lang/Double;");    }    private static String getStaticConstantWrapperType(double num)    {        String constantType;        int inum = (int)num;        if (inum == num) {            return "Ljava/lang/Integer;";        } else {            return "Ljava/lang/Double;";        }    }    static void pushUndefined(ClassFileWriter cfw)    {        cfw.add(ByteCode.GETSTATIC, "org/mozilla/javascript/Undefined",                "instance", "Ljava/lang/Object;");    }

⌨️ 快捷键说明

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