📄 jvstcodegen.java
字号:
else { a.accept(this); types[i] = exprType; dims[i] = arrayDim; cnames[i] = className; ++i; } args = args.tail(); } } /* public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError { if (!isParamListName(args)) { super.atMethodArgs(args, types, dims, cnames); return; } CtClass[] params = paramTypeList; if (params == null) return; int n = params.length; int regno = indexOfParam1(); for (int i = 0; i < n; ++i) { CtClass p = params[i]; regno += bytecode.addLoad(regno, p); setType(p); types[i] = exprType; dims[i] = arrayDim; cnames[i] = className; } } */ /* called by Javac#recordSpecialProceed(). */ void compileInvokeSpecial(ASTree target, String classname, String methodname, String descriptor, ASTList args) throws CompileError { target.accept(this); int nargs = getMethodArgsLength(args); atMethodArgs(args, new int[nargs], new int[nargs], new String[nargs]); bytecode.addInvokespecial(classname, methodname, descriptor); setReturnType(descriptor, false, false); addNullIfVoid(); } /* * Makes it valid to write "return <expr>;" for a void method. */ protected void atReturnStmnt(Stmnt st) throws CompileError { ASTree result = st.getLeft(); if (result != null && returnType == CtClass.voidType) { compileExpr(result); if (is2word(exprType, arrayDim)) bytecode.addOpcode(POP2); else if (exprType != VOID) bytecode.addOpcode(POP); result = null; } atReturnStmnt2(result); } /** * Makes a cast to the return type ($r) available. * It also enables $_. * * <p>If the return type is void, ($r) does nothing. * The type of $_ is java.lang.Object. * * @param resultName null if $_ is not used. * @return -1 or the variable index assigned to $_. */ public int recordReturnType(CtClass type, String castName, String resultName, SymbolTable tbl) throws CompileError { returnType = type; returnCastName = castName; returnVarName = resultName; if (resultName == null) return -1; else { int varNo = getMaxLocals(); int locals = varNo + recordVar(type, resultName, varNo, tbl); setMaxLocals(locals); return varNo; } } /** * Makes $type available. */ public void recordType(CtClass t) { dollarType = t; } /** * Makes method parameters $0, $1, ..., $args, $$, and $class available. * $0 is equivalent to THIS if the method is not static. Otherwise, * if the method is static, then $0 is not available. */ public int recordParams(CtClass[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl) throws CompileError { return recordParams(params, isStatic, prefix, paramVarName, paramsName, !isStatic, 0, getThisName(), tbl); } /** * Makes method parameters $0, $1, ..., $args, $$, and $class available. * $0 is available only if use0 is true. It might not be equivalent * to THIS. * * @param params the parameter types (the types of $1, $2, ..) * @param prefix it must be "$" (the first letter of $0, $1, ...) * @param paramVarName it must be "$args" * @param paramsName it must be "$$" * @param use0 true if $0 is used. * @param paramBase the register number of $0 (use0 is true) * or $1 (otherwise). * @param target the class of $0. If use0 is false, target * can be null. The value of "target" is also used * as the name of the type represented by $class. * @param isStatic true if the method in which the compiled bytecode * is embedded is static. */ public int recordParams(CtClass[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, boolean use0, int paramBase, String target, SymbolTable tbl) throws CompileError { int varNo; paramTypeList = params; paramArrayName = paramVarName; paramListName = paramsName; paramVarBase = paramBase; useParam0 = use0; if (target != null) param0Type = MemberResolver.jvmToJavaName(target); inStaticMethod = isStatic; varNo = paramBase; if (use0) { String varName = prefix + "0"; Declarator decl = new Declarator(CLASS, MemberResolver.javaToJvmName(target), 0, varNo++, new Symbol(varName)); tbl.append(varName, decl); } for (int i = 0; i < params.length; ++i) varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl); if (getMaxLocals() < varNo) setMaxLocals(varNo); return varNo; } /** * Makes the given variable name available. * * @param type variable type * @param varName variable name */ public int recordVariable(CtClass type, String varName, SymbolTable tbl) throws CompileError { if (varName == null) return -1; else { int varNo = getMaxLocals(); int locals = varNo + recordVar(type, varName, varNo, tbl); setMaxLocals(locals); return varNo; } } private int recordVar(CtClass cc, String varName, int varNo, SymbolTable tbl) throws CompileError { if (cc == CtClass.voidType) { exprType = CLASS; arrayDim = 0; className = jvmJavaLangObject; } else setType(cc); Declarator decl = new Declarator(exprType, className, arrayDim, varNo, new Symbol(varName)); tbl.append(varName, decl); return is2word(exprType, arrayDim) ? 2 : 1; } /** * Makes the given variable name available. * * @param typeDesc the type descriptor of the variable * @param varName variable name * @param varNo an index into the local variable array */ public void recordVariable(String typeDesc, String varName, int varNo, SymbolTable tbl) throws CompileError { char c; int dim = 0; while ((c = typeDesc.charAt(dim)) == '[') ++dim; int type = MemberResolver.descToType(c); String cname = null; if (type == CLASS) { if (dim == 0) cname = typeDesc.substring(1, typeDesc.length() - 1); else cname = typeDesc.substring(dim + 1, typeDesc.length() - 1); } Declarator decl = new Declarator(type, cname, dim, varNo, new Symbol(varName)); tbl.append(varName, decl); } /* compileParameterList() returns the stack size used * by the produced code. * * This method correctly computes the max_stack value. * * @param regno the index of the local variable in which * the first argument is received. * (0: static method, 1: regular method.) */ public static int compileParameterList(Bytecode code, CtClass[] params, int regno) { if (params == null) { code.addIconst(0); // iconst_0 code.addAnewarray(javaLangObject); // anewarray Object return 1; } else { CtClass[] args = new CtClass[1]; int n = params.length; code.addIconst(n); // iconst_<n> code.addAnewarray(javaLangObject); // anewarray Object for (int i = 0; i < n; ++i) { code.addOpcode(Bytecode.DUP); // dup code.addIconst(i); // iconst_<i> if (params[i].isPrimitive()) { CtPrimitiveType pt = (CtPrimitiveType)params[i]; String wrapper = pt.getWrapperName(); code.addNew(wrapper); // new <wrapper> code.addOpcode(Bytecode.DUP); // dup int s = code.addLoad(regno, pt); // ?load <regno> regno += s; args[0] = pt; code.addInvokespecial(wrapper, "<init>", Descriptor.ofMethod(CtClass.voidType, args)); // invokespecial } else { code.addAload(regno); // aload <regno> ++regno; } code.addOpcode(Bytecode.AASTORE); // aastore } return 8; } } protected void compileUnwrapValue(CtClass type, Bytecode code) throws CompileError { if (type == CtClass.voidType) { addNullIfVoid(); return; } if (exprType == VOID) throw new CompileError("invalid type for " + returnCastName); if (type instanceof CtPrimitiveType) { CtPrimitiveType pt = (CtPrimitiveType)type; // pt is not voidType. String wrapper = pt.getWrapperName(); code.addCheckcast(wrapper); code.addInvokevirtual(wrapper, pt.getGetMethodName(), pt.getGetMethodDescriptor()); setType(type); } else { code.addCheckcast(type); setType(type); } } /* Sets exprType, arrayDim, and className; * If type is void, then this method does nothing. */ public void setType(CtClass type) throws CompileError { setType(type, 0); } private void setType(CtClass type, int dim) throws CompileError { if (type.isPrimitive()) { CtPrimitiveType pt = (CtPrimitiveType)type; exprType = MemberResolver.descToType(pt.getDescriptor()); arrayDim = dim; className = null; } else if (type.isArray()) try { setType(type.getComponentType(), dim + 1); } catch (NotFoundException e) { throw new CompileError("undefined type: " + type.getName()); } else { exprType = CLASS; arrayDim = dim; className = MemberResolver.javaToJvmName(type.getName()); } } /* Performs implicit coercion from exprType to type. */ public void doNumCast(CtClass type) throws CompileError { if (arrayDim == 0 && !isRefType(exprType)) if (type instanceof CtPrimitiveType) { CtPrimitiveType pt = (CtPrimitiveType)type; atNumCastExpr(exprType, MemberResolver.descToType(pt.getDescriptor())); } else throw new CompileError("type mismatch"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -