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

📄 codegen.java

📁 這是一個javascript 的 interpreter是了解 web browser的好材料
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            int N = directCallTargets.size();            for (int j = 0; j != N; ++j) {                cfw.addField(getDirectTargetFieldName(j),                             mainClassSignature,                             ClassFileWriter.ACC_PRIVATE);            }        }        emitRegExpInit(cfw);        emitConstantDudeInitializers(cfw);        return cfw.toByteArray();    }    private void emitDirectConstructor(ClassFileWriter cfw,                                       OptFunctionNode ofn)    {/*    we generate ..        Scriptable directConstruct(<directCallArgs>) {            Scriptable newInstance = createObject(cx, scope);            Object val = <body-name>(cx, scope, newInstance, <directCallArgs>);            if (val instanceof Scriptable) {                return (Scriptable) val;            }            return newInstance;        }*/        cfw.startMethod(getDirectCtorName(ofn.fnode),                        getBodyMethodSignature(ofn.fnode),                        (short)(ClassFileWriter.ACC_STATIC                                | ClassFileWriter.ACC_PRIVATE));        int argCount = ofn.fnode.getParamCount();        int firstLocal = (4 + argCount * 3) + 1;        cfw.addALoad(0); // this        cfw.addALoad(1); // cx        cfw.addALoad(2); // scope        cfw.addInvoke(ByteCode.INVOKEVIRTUAL,                      "org/mozilla/javascript/BaseFunction",                      "createObject",                      "(Lorg/mozilla/javascript/Context;"                      +"Lorg/mozilla/javascript/Scriptable;"                      +")Lorg/mozilla/javascript/Scriptable;");        cfw.addAStore(firstLocal);        cfw.addALoad(0);        cfw.addALoad(1);        cfw.addALoad(2);        cfw.addALoad(firstLocal);        for (int i = 0; i < argCount; i++) {            cfw.addALoad(4 + (i * 3));            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));    }    static boolean isGenerator(ScriptOrFnNode node)    {        return (node.getType() == Token.FUNCTION ) &&                ((FunctionNode)node).isGenerator();    }    // How dispatch to generators works:    // Two methods are generated corresponding to a user-written generator.    // One of these creates a generator object (NativeGenerator), which is    // returned to the user. The other method contains all of the body code    // of the generator.    // When a user calls a generator, the call() method dispatches control to    // to the method that creates the NativeGenerator object. Subsequently when    // the user invokes .next(), .send() or any such method on the generator    // object, the resumeGenerator() below dispatches the call to the    // method corresponding to the generator body. As a matter of convention    // the generator body is given the name of the generator activation function    // appended by "_gen".    private void generateResumeGenerator(ClassFileWriter cfw)    {        boolean hasGenerators = false;        for (int i=0; i < scriptOrFnNodes.length; i++) {            if (isGenerator(scriptOrFnNodes[i]))            	hasGenerators = true;        }        // if there are no generators defined, we don't implement a        // resumeGenerator(). The base class provides a default implementation.         if (!hasGenerators)            return;        cfw.startMethod("resumeGenerator",                        "(Lorg/mozilla/javascript/Context;" +                        "Lorg/mozilla/javascript/Scriptable;" +                        "ILjava/lang/Object;" +                        "Ljava/lang/Object;)Ljava/lang/Object;",                        (short)(ClassFileWriter.ACC_PUBLIC                                | ClassFileWriter.ACC_FINAL));        // load arguments for dispatch to the corresponding *_gen method         cfw.addALoad(0);        cfw.addALoad(1);        cfw.addALoad(2);        cfw.addALoad(4);        cfw.addALoad(5);        cfw.addILoad(3);        cfw.addLoadThis();        cfw.add(ByteCode.GETFIELD, cfw.getClassName(), ID_FIELD_NAME, "I");        int startSwitch = cfw.addTableSwitch(0, scriptOrFnNodes.length - 1);        cfw.markTableSwitchDefault(startSwitch);        int endlabel = cfw.acquireLabel();        for (int i = 0; i < scriptOrFnNodes.length; i++) {            ScriptOrFnNode n = scriptOrFnNodes[i];            cfw.markTableSwitchCase(startSwitch, i, (short)6);            if (isGenerator(n)) {                String type = "(" +                              mainClassSignature +                              "Lorg/mozilla/javascript/Context;" +                              "Lorg/mozilla/javascript/Scriptable;" +                              "Ljava/lang/Object;" +                              "Ljava/lang/Object;I)Ljava/lang/Object;";                cfw.addInvoke(ByteCode.INVOKESTATIC,                              mainClassName,                              getBodyMethodName(n) + "_gen",                              type);                cfw.add(ByteCode.ARETURN);            } else {                cfw.add(ByteCode.GOTO, endlabel);            }        }        cfw.markLabel(endlabel);        pushUndefined(cfw);        cfw.add(ByteCode.ARETURN);        // this method uses as many locals as there are arguments (hence 6)        cfw.stopMethod((short)6);    }    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);        // Now 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)    {        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)    {        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)    {

⌨️ 快捷键说明

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