📄 membercodegen.java
字号:
if (s == null) break; // int[][][] a = new int[3][4][]; ++count; s.accept(this); if (exprType != INT) throw new CompileError("bad type for array size"); } String desc; exprType = type; arrayDim = dim; if (type == CLASS) { className = resolveClassName(classname); desc = toJvmArrayName(className, dim); } else desc = toJvmTypeName(type, dim); bytecode.addMultiNewarray(desc, count); } public void atCallExpr(CallExpr expr) throws CompileError { String mname = null; CtClass targetClass = null; ASTree method = expr.oprand1(); ASTList args = (ASTList)expr.oprand2(); boolean isStatic = false; boolean isSpecial = false; int aload0pos = -1; MemberResolver.Method cached = expr.getMethod(); if (method instanceof Member) { mname = ((Member)method).get(); targetClass = thisClass; if (inStaticMethod || (cached != null && cached.isStatic())) isStatic = true; // should be static else { aload0pos = bytecode.currentPc(); bytecode.addAload(0); // this } } else if (method instanceof Keyword) { // constructor isSpecial = true; mname = MethodInfo.nameInit; // <init> targetClass = thisClass; if (inStaticMethod) throw new CompileError("a constructor cannot be static"); else bytecode.addAload(0); // this if (((Keyword)method).get() == SUPER) targetClass = MemberResolver.getSuperclass(targetClass); } else if (method instanceof Expr) { Expr e = (Expr)method; mname = ((Symbol)e.oprand2()).get(); int op = e.getOperator(); if (op == MEMBER) { // static method targetClass = resolver.lookupClass(((Symbol)e.oprand1()).get(), false); isStatic = true; } else if (op == '.') { ASTree target = e.oprand1(); if (target instanceof Keyword) if (((Keyword)target).get() == SUPER) isSpecial = true; try { target.accept(this); } catch (NoFieldException nfe) { if (nfe.getExpr() != target) throw nfe; // it should be a static method. exprType = CLASS; arrayDim = 0; className = nfe.getField(); // JVM-internal resolver.recordPackage(className); isStatic = true; } if (arrayDim > 0) targetClass = resolver.lookupClass(javaLangObject, true); else if (exprType == CLASS /* && arrayDim == 0 */) targetClass = resolver.lookupClassByJvmName(className); else badMethod(); } else badMethod(); } else fatal(); atMethodCallCore(targetClass, mname, args, isStatic, isSpecial, aload0pos, cached); } private static void badMethod() throws CompileError { throw new CompileError("bad method"); } /* * atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew * * @param targetClass the class at which method lookup starts. * @param found not null if the method look has been already done. */ public void atMethodCallCore(CtClass targetClass, String mname, ASTList args, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError { int nargs = getMethodArgsLength(args); int[] types = new int[nargs]; int[] dims = new int[nargs]; String[] cnames = new String[nargs]; if (!isStatic && found != null && found.isStatic()) { bytecode.addOpcode(POP); isStatic = true; } int stack = bytecode.getStackDepth(); // generate code for evaluating arguments. atMethodArgs(args, types, dims, cnames); // used by invokeinterface int count = bytecode.getStackDepth() - stack + 1; if (found == null) found = resolver.lookupMethod(targetClass, thisClass, thisMethod, mname, types, dims, cnames); if (found == null) { String msg; if (mname.equals(MethodInfo.nameInit)) msg = "constructor not found"; else msg = "Method " + mname + " not found in " + targetClass.getName(); throw new CompileError(msg); } atMethodCallCore2(targetClass, mname, isStatic, isSpecial, aload0pos, count, found); } private void atMethodCallCore2(CtClass targetClass, String mname, boolean isStatic, boolean isSpecial, int aload0pos, int count, MemberResolver.Method found) throws CompileError { CtClass declClass = found.declaring; MethodInfo minfo = found.info; String desc = minfo.getDescriptor(); int acc = minfo.getAccessFlags(); if (mname.equals(MethodInfo.nameInit)) { isSpecial = true; if (declClass != targetClass) throw new CompileError("no such a constructor"); if (declClass != thisClass && AccessFlag.isPrivate(acc)) { desc = getAccessibleConstructor(desc, declClass, minfo); bytecode.addOpcode(Opcode.ACONST_NULL); // the last parameter } } else if (AccessFlag.isPrivate(acc)) if (declClass == thisClass) isSpecial = true; else { isSpecial = false; isStatic = true; String origDesc = desc; if ((acc & AccessFlag.STATIC) == 0) desc = Descriptor.insertParameter(declClass.getName(), origDesc); acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC; mname = getAccessiblePrivate(mname, origDesc, desc, minfo, declClass); } boolean popTarget = false; if ((acc & AccessFlag.STATIC) != 0) { if (!isStatic) { /* this method is static but the target object is on stack. It must be popped out. If aload0pos >= 0, then the target object was pushed by aload_0. It is overwritten by NOP. */ isStatic = true; if (aload0pos >= 0) bytecode.write(aload0pos, NOP); else popTarget = true; } bytecode.addInvokestatic(declClass, mname, desc); } else if (isSpecial) // if (isSpecial && notStatic(acc)) bytecode.addInvokespecial(declClass, mname, desc); else if (declClass.isInterface()) bytecode.addInvokeinterface(declClass, mname, desc, count); else if (isStatic) throw new CompileError(mname + " is not static"); else bytecode.addInvokevirtual(declClass, mname, desc); setReturnType(desc, isStatic, popTarget); } /* * Finds (or adds if necessary) a hidden accessor if the method * is in an enclosing class. * * @param desc the descriptor of the method. * @param declClass the class declaring the method. */ protected String getAccessiblePrivate(String methodName, String desc, String newDesc, MethodInfo minfo, CtClass declClass) throws CompileError { if (isEnclosing(declClass, thisClass)) { AccessorMaker maker = declClass.getAccessorMaker(); if (maker != null) return maker.getMethodAccessor(methodName, desc, newDesc, minfo); } throw new CompileError("Method " + methodName + " is private"); } /* * Finds (or adds if necessary) a hidden constructor if the given * constructor is in an enclosing class. * * @param desc the descriptor of the constructor. * @param declClass the class declaring the constructor. * @param minfo the method info of the constructor. * @return the descriptor of the hidden constructor. */ protected String getAccessibleConstructor(String desc, CtClass declClass, MethodInfo minfo) throws CompileError { if (isEnclosing(declClass, thisClass)) { AccessorMaker maker = declClass.getAccessorMaker(); if (maker != null) return maker.getConstructor(declClass, desc, minfo); } throw new CompileError("the called constructor is private in " + declClass.getName()); } private boolean isEnclosing(CtClass outer, CtClass inner) { try { while (inner != null) { inner = inner.getDeclaringClass(); if (inner == outer) return true; } } catch (NotFoundException e) {} return false; } public int getMethodArgsLength(ASTList args) { return ASTList.length(args); } public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError { int i = 0; while (args != null) { ASTree a = args.head(); a.accept(this); types[i] = exprType; dims[i] = arrayDim; cnames[i] = className; ++i; args = args.tail(); } } void setReturnType(String desc, boolean isStatic, boolean popTarget) throws CompileError { int i = desc.indexOf(')'); if (i < 0) badMethod(); char c = desc.charAt(++i); int dim = 0; while (c == '[') { ++dim; c = desc.charAt(++i); } arrayDim = dim; if (c == 'L') { int j = desc.indexOf(';', i + 1); if (j < 0) badMethod(); exprType = CLASS; className = desc.substring(i + 1, j); } else { exprType = MemberResolver.descToType(c); className = null; } int etype = exprType; if (isStatic) { if (popTarget) { if (is2word(etype, dim)) { bytecode.addOpcode(DUP2_X1); bytecode.addOpcode(POP2); bytecode.addOpcode(POP); } else if (etype == VOID) bytecode.addOpcode(POP); else { bytecode.addOpcode(SWAP); bytecode.addOpcode(POP); } } } } protected void atFieldAssign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError { CtField f = fieldAccess(left, false); boolean is_static = resultStatic; if (op != '=' && !is_static) bytecode.addOpcode(DUP); int fi; if (op == '=') { FieldInfo finfo = f.getFieldInfo2(); setFieldType(finfo); AccessorMaker maker = isAccessibleField(f, finfo); if (maker == null)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -