📄 codegen.java
字号:
(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) { 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;"); } int getIndex(ScriptOrFnNode n) { return scriptOrFnIndexes.getExisting(n); } static String getDirectTargetFieldName(int i) { return "_dt" + i; } String getDirectCtorName(ScriptOrFnNode n) { return "_n"+getIndex(n); } String getBodyMethodName(ScriptOrFnNode n) { return "_c"+getIndex(n); } String getBodyMethodSignature(ScriptOrFnNode n) { StringBuffer sb = new StringBuffer(); sb.append('('); sb.append(mainClassSignature); sb.append("Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Scriptable;"); if (n.getType() == Token.FUNCTION) { OptFunctionNode ofn = OptFunctionNode.get(n); if (ofn.isTargetOfDirectCall()) { int pCount = ofn.fnode.getParamCount(); for (int i = 0; i != pCount; i++) { sb.append("Ljava/lang/Object;D"); } } } sb.append("[Ljava/lang/Object;)Ljava/lang/Object;"); return sb.toString(); } String getFunctionInitMethodName(OptFunctionNode ofn) { return "_i"+getIndex(ofn.fnode); } String getCompiledRegexpName(ScriptOrFnNode n, int regexpIndex) { return "_re"+getIndex(n)+"_"+regexpIndex; } static RuntimeException badTree() { throw new RuntimeException("Bad tree in codegen"); } void setMainMethodClass(String className) { mainMethodClass = className; } static final String DEFAULT_MAIN_METHOD_CLASS = "org.mozilla.javascript.optimizer.OptRuntime"; private static final String SUPER_CLASS_NAME = "org.mozilla.javascript.NativeFunction"; static final String DIRECT_CALL_PARENT_FIELD = "_dcp"; private static final String ID_FIELD_NAME = "_id"; private static final String REGEXP_INIT_METHOD_NAME = "_reInit"; private static final String REGEXP_INIT_METHOD_SIGNATURE = "(Lorg/mozilla/javascript/RegExpProxy;" +"Lorg/mozilla/javascript/Context;" +")V"; static final String REGEXP_ARRAY_FIELD_NAME = "_re"; static final String REGEXP_ARRAY_FIELD_TYPE = "[Ljava/lang/Object;"; static final String FUNCTION_INIT_SIGNATURE = "(Lorg/mozilla/javascript/Context;" +"Lorg/mozilla/javascript/Scriptable;" +")V"; static final String FUNCTION_CONSTRUCTOR_SIGNATURE = "(Lorg/mozilla/javascript/Scriptable;" +"Lorg/mozilla/javascript/Context;I)V"; private static final Object globalLock = new Object(); private static int globalSerialClassCounter; private CompilerEnvirons compilerEnv; private ObjArray directCallTargets; ScriptOrFnNode[] scriptOrFnNodes; private ObjToIntMap scriptOrFnIndexes; private String mainMethodClass = DEFAULT_MAIN_METHOD_CLASS; String mainClassName; String mainClassSignature; private double[] itsConstantList; private int itsConstantListSize;}class BodyCodegen{ void generateBodyCode() { isGenerator = Codegen.isGenerator(scriptOrFn); // generate the body of the current function or script object initBodyGeneration(); if (isGenerator) { // All functions in the generated bytecode have a unique name. Every // generator has a unique prefix followed by _gen String type = "(" + codegen.mainClassSignature + "Lorg/mozilla/javascript/Context;" + "Lorg/mozilla/javascript/Scriptable;" + "Ljava/lang/Object;" + "Ljava/lang/Object;I)Ljava/lang/Object;"; cfw.startMethod(codegen.getBodyMethodName(scriptOrFn) + "_gen", type, (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); } else { cfw.startMethod(codegen.getBodyMethodName(scriptOrFn), codegen.getBodyMethodSignature(scriptOrFn), (short)(ClassFileWriter.ACC_STATIC | ClassFileWriter.ACC_PRIVATE)); } generatePrologue(); Node treeTop; if (fnCurrent != null) { treeTop = scriptOrFn.getLastChild(); } else { treeTop = scriptOrFn; } generateStatement(treeTop); generateEpilogue(); cfw.stopMethod((short)(localsMax + 1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -