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

📄 codegen.java

📁 這是一個javascript 的 interpreter是了解 web browser的好材料
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
        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 Do_getParamOrVarConst   = 5;        final int SWITCH_COUNT            = 6;        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 methodLocals;            switch (methodIndex) {              case Do_getFunctionName:                methodLocals = 1; // Only this                cfw.startMethod("getFunctionName", "()Ljava/lang/String;",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamCount:                methodLocals = 1; // Only this                cfw.startMethod("getParamCount", "()I",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamAndVarCount:                methodLocals = 1; // Only this                cfw.startMethod("getParamAndVarCount", "()I",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamOrVarName:                methodLocals = 1 + 1; // this + paramOrVarIndex                cfw.startMethod("getParamOrVarName", "(I)Ljava/lang/String;",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getParamOrVarConst:                methodLocals = 1 + 1 + 1; // this + paramOrVarName                cfw.startMethod("getParamOrVarConst", "(I)Z",                                ClassFileWriter.ACC_PUBLIC);                break;              case Do_getEncodedSource:                methodLocals = 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_getParamOrVarConst:                        // Push name of parameter using another switch                        // over paramAndVarCount                        paramAndVarCount = n.getParamAndVarCount();                        boolean [] constness = n.getParamAndVarConst();                        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.ICONST_0);                            cfw.add(ByteCode.IRETURN);                        } else if (paramAndVarCount == 1) {                            // As above do not check for valid index but always                            // return the name of the first param                            cfw.addPush(constness[0]);                            cfw.add(ByteCode.IRETURN);                        } 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();                                if (j == 0) {                                    cfw.markTableSwitchDefault(paramSwitchStart);                                } else {                                    cfw.markTableSwitchCase(paramSwitchStart, j - 1,                                                            0);                                }                                cfw.addPush(constness[j]);                                cfw.add(ByteCode.IRETURN);                            }                        }                      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(methodLocals);        }    }    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,

⌨️ 快捷键说明

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