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

📄 codegen.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): *   Norris Boyd *   Kemal Bayram *   Igor Bukanov *   Roger Lawrence *   Andi Vajda * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */package org.mozilla.javascript.optimizer;import org.mozilla.javascript.*;import org.mozilla.classfile.*;import java.util.*;import java.lang.reflect.Constructor;/** * This class generates code for a given IR tree. * * @author Norris Boyd * @author Roger Lawrence */public class Codegen extends Interpreter{    public Object compile(CompilerEnvirons compilerEnv,                          ScriptOrFnNode tree,                          String encodedSource,                          boolean returnFunction)    {        int serial;        synchronized (globalLock) {            serial = ++globalSerialClassCounter;        }        String mainClassName = "org.mozilla.javascript.gen.c"+serial;        byte[] mainClassBytes = compileToClassFile(compilerEnv, mainClassName,                                                   tree, encodedSource,                                                   returnFunction);        return new Object[] { mainClassName, mainClassBytes };    }    public Script createScriptObject(Object bytecode,                                     Object staticSecurityDomain)    {        Class cl = defineClass(bytecode, staticSecurityDomain);        Script script;        try {            script = (Script)cl.newInstance();        } catch (Exception ex) {            throw new RuntimeException                ("Unable to instantiate compiled class:"+ex.toString());        }        return script;    }    public Function createFunctionObject(Context cx, Scriptable scope,                                         Object bytecode,                                         Object staticSecurityDomain)    {        Class cl = defineClass(bytecode, staticSecurityDomain);        NativeFunction f;        try {            Constructor ctor = cl.getConstructors()[0];            Object[] initArgs = { scope, cx, new Integer(0) };            f = (NativeFunction)ctor.newInstance(initArgs);        } catch (Exception ex) {            throw new RuntimeException                ("Unable to instantiate compiled class:"+ex.toString());        }        return f;    }    private Class defineClass(Object bytecode,                              Object staticSecurityDomain)    {        Object[] nameBytesPair = (Object[])bytecode;        String className = (String)nameBytesPair[0];        byte[] classBytes = (byte[])nameBytesPair[1];        // The generated classes in this case refer only to Rhino classes        // which must be accessible through this class loader        ClassLoader rhinoLoader = getClass().getClassLoader();        GeneratedClassLoader loader;        loader = SecurityController.createLoader(rhinoLoader,                                                 staticSecurityDomain);        Exception e;        try {            Class cl = loader.defineClass(className, classBytes);            loader.linkClass(cl);            return cl;        } catch (SecurityException x) {            e = x;        } catch (IllegalArgumentException x) {            e = x;        }        throw new RuntimeException("Malformed optimizer package " + e);    }    byte[] compileToClassFile(CompilerEnvirons compilerEnv,                              String mainClassName,                              ScriptOrFnNode scriptOrFn,                              String encodedSource,                              boolean returnFunction)    {        this.compilerEnv = compilerEnv;        transform(scriptOrFn);        if (Token.printTrees) {            System.out.println(scriptOrFn.toStringTree(scriptOrFn));        }        if (returnFunction) {            scriptOrFn = scriptOrFn.getFunctionNode(0);        }        initScriptOrFnNodesData(scriptOrFn);        this.mainClassName = mainClassName;        mainClassSignature            = ClassFileWriter.classNameToSignature(mainClassName);        return generateCode(encodedSource);    }    private void transform(ScriptOrFnNode tree)    {        initOptFunctions_r(tree);        int optLevel = compilerEnv.getOptimizationLevel();        Hashtable possibleDirectCalls = null;        if (optLevel > 0) {           /*            * Collect all of the contained functions into a hashtable            * so that the call optimizer can access the class name & parameter            * count for any call it encounters            */            if (tree.getType() == Token.SCRIPT) {                int functionCount = tree.getFunctionCount();                for (int i = 0; i != functionCount; ++i) {                    OptFunctionNode ofn = OptFunctionNode.get(tree, i);                    if (ofn.fnode.getFunctionType()                        == FunctionNode.FUNCTION_STATEMENT)                    {                        String name = ofn.fnode.getFunctionName();                        if (name.length() != 0) {                            if (possibleDirectCalls == null) {                                possibleDirectCalls = new Hashtable();                            }                            possibleDirectCalls.put(name, ofn);                        }                    }                }            }        }        if (possibleDirectCalls != null) {            directCallTargets = new ObjArray();        }        OptTransformer ot = new OptTransformer(possibleDirectCalls,                                               directCallTargets);        ot.transform(tree);        if (optLevel > 0) {            (new Optimizer()).optimize(tree, optLevel);        }    }    private static void initOptFunctions_r(ScriptOrFnNode scriptOrFn)    {        for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) {            FunctionNode fn = scriptOrFn.getFunctionNode(i);            new OptFunctionNode(fn);            initOptFunctions_r(fn);        }    }    private void initScriptOrFnNodesData(ScriptOrFnNode scriptOrFn)    {        ObjArray x = new ObjArray();        collectScriptOrFnNodes_r(scriptOrFn, x);        int count = x.size();        scriptOrFnNodes = new ScriptOrFnNode[count];        x.toArray(scriptOrFnNodes);        scriptOrFnIndexes = new ObjToIntMap(count);        for (int i = 0; i != count; ++i) {            scriptOrFnIndexes.put(scriptOrFnNodes[i], i);        }    }    private static void collectScriptOrFnNodes_r(ScriptOrFnNode n,                                                 ObjArray x)    {        x.add(n);        int nestedCount = n.getFunctionCount();        for (int i = 0; i != nestedCount; ++i) {            collectScriptOrFnNodes_r(n.getFunctionNode(i), x);        }    }    private byte[] generateCode(String encodedSource)    {        boolean hasScript = (scriptOrFnNodes[0].getType() == Token.SCRIPT);        boolean hasFunctions = (scriptOrFnNodes.length > 1 || !hasScript);        String sourceFile = null;        if (compilerEnv.isGenerateDebugInfo()) {            sourceFile = scriptOrFnNodes[0].getSourceName();        }        ClassFileWriter cfw = new ClassFileWriter(mainClassName,                                                  SUPER_CLASS_NAME,                                                  sourceFile);        cfw.addField(ID_FIELD_NAME, "I",                     ClassFileWriter.ACC_PRIVATE);        cfw.addField(DIRECT_CALL_PARENT_FIELD, mainClassSignature,                     ClassFileWriter.ACC_PRIVATE);        cfw.addField(REGEXP_ARRAY_FIELD_NAME, REGEXP_ARRAY_FIELD_TYPE,                     ClassFileWriter.ACC_PRIVATE);        if (hasFunctions) {            generateFunctionConstructor(cfw);        }        if (hasScript) {            ScriptOrFnNode script = scriptOrFnNodes[0];            cfw.addInterface("org/mozilla/javascript/Script");            generateScriptCtor(cfw, script);            generateMain(cfw);            generateExecute(cfw, script);        }        generateCallMethod(cfw);        generateNativeFunctionOverrides(cfw, encodedSource);        int count = scriptOrFnNodes.length;        for (int i = 0; i != count; ++i) {            ScriptOrFnNode n = scriptOrFnNodes[i];            BodyCodegen bodygen = new BodyCodegen();            bodygen.cfw = cfw;            bodygen.codegen = this;            bodygen.compilerEnv = compilerEnv;            bodygen.scriptOrFn = n;            bodygen.generateBodyCode();            if (n.getType() == Token.FUNCTION) {                OptFunctionNode ofn = OptFunctionNode.get(n);                generateFunctionInit(cfw, ofn);                if (ofn.isTargetOfDirectCall()) {                    emitDirectConstructor(cfw, ofn);                }            }        }        if (directCallTargets != null) {            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));

⌨️ 快捷键说明

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