📄 transinner.java
字号:
* Construct definition of an access constructor. * @param pos The source code position of the definition. * @param constr The private constructor. * @param accessor The access method for the constructor. */ Tree accessConstructorDef(int pos, Symbol constr, MethodSymbol accessor) { make.at(pos); MethodDef md = make.MethodDef(accessor, accessor.externalType(), null); Ident callee = make.Ident(names._this); callee.sym = constr; callee.type = constr.type; md.body = make.Block(0, List.make( make.Call( make.App(callee, make.Idents(md.params.reverse().tail.reverse()))))); return md; } /** * A scope containing all free variable proxies for currently translated * class, as well as its this$n symbol (if needed). * Proxy scopes are nested in the same way classes are. * Inside a constructor, proxies and any this$n symbol are duplicated * in an additional innermost scope, where they represent the constructor * parameters. */ Scope proxies; /** * A stack containing the this$n field of the currently translated * classes (if needed) in innermost first order. * Inside a constructor, proxies and any this$n symbol are duplicated * in an additional innermost scope, where they represent the constructor * parameters. */ List outerThisStack; /** * The name of a free variable proxy. */ Name proxyName(Name name) { return names.fromString("val$" + name); } /** * Proxy definitions for all free variables in given list, in reverse order. * @param pos The source code position of the definition. * @param freevars The free variables. * @param owner The class in which the definitions go. */ List freevarDefs(int pos, List freevars, Symbol owner) { long flags = FINAL | SYNTHETIC; if (owner.kind == TYP && target.ordinal < Target.JDK1_4_2.ordinal) flags |= PRIVATE; List defs = VarDef.emptyList; for (List l = freevars; l.nonEmpty(); l = l.tail) { VarSymbol v = (Symbol.VarSymbol) l.head; VarSymbol proxy = new VarSymbol(flags, proxyName(v.name), v.erasure(), owner); proxies.enter(proxy); VarDef vd = make.at(pos).VarDef(proxy, null); vd.vartype = access(vd.vartype); defs = defs.prepend(vd); } return defs; } /** * The name of a this$n field * @param target The class referenced by the this$n field */ Name outerThisName(Type target) { Type t = target.outer(); int nestingLevel = 0; while (t.tag == CLASS) { t = t.outer(); nestingLevel++; } return names.fromString("this$" + nestingLevel); } /** * Definition for this$n field. * @param pos The source code position of the definition. * @param owner The class in which the definition goes. */ VarDef outerThisDef(int pos, Symbol owner) { long flags = FINAL | SYNTHETIC; if (owner.kind == TYP && target.ordinal < Target.JDK1_4_2.ordinal) flags |= PRIVATE; Type target = owner.enclClass().type.outer().erasure(); VarSymbol outerThis = new VarSymbol(flags, outerThisName(target), target, owner); outerThisStack = outerThisStack.prepend(outerThis); VarDef vd = make.at(pos).VarDef(outerThis, null); vd.vartype = access(vd.vartype); return vd; } /** * Return a list of trees that load the free variables in given list, * in reverse order. * @param pos The source code position to be used for the trees. * @param freevars The list of free variables. */ List loadFreevars(int pos, List freevars) { List args = Tree.emptyList; for (List l = freevars; l.nonEmpty(); l = l.tail) args = args.prepend(loadFreevar(pos, (Symbol.VarSymbol) l.head)); return args; } Tree loadFreevar(int pos, VarSymbol v) { return access(v, make.at(pos).Ident(v), null, false); } /** * Construct a tree simulating the expression <C.this>. * @param pos The source code position to be used for the tree. * @param c The qualifier class. */ Tree makeThis(int pos, TypeSymbol c) { if (currentClass == c) { return make.at(pos).This(c.erasure()); } else { return makeOuterThis(pos, c); } } /** * Construct a tree that represents the outer instance * <C.this>. Never pick the current `this'. * @param pos The source code position to be used for the tree. * @param c The qualifier class. */ Tree makeOuterThis(int pos, TypeSymbol c) { List ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c.toJava()); assert false; return make.Ident(syms.nullConst); } VarSymbol ot = (Symbol.VarSymbol) ots.head; Tree tree = access(make.at(pos).Ident(ot)); TypeSymbol otc = ot.type.tsym; while (otc != c) { do { ots = ots.tail; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c.toJava()); assert false; return tree; } ot = (Symbol.VarSymbol) ots.head; } while (ot.owner != otc) ; if (otc.owner.kind != PCK && !otc.hasOuterInstance()) { chk.earlyRefError(pos, c); assert false; return make.Ident(syms.nullConst); } tree = access(make.at(pos).Select(tree, ot)); otc = ot.type.tsym; } return tree; } /** * Construct a tree that represents the closest outer instance * <C.this> such that the given symbol is a member of C. * @param pos The source code position to be used for the tree. * @param sym The accessed symbol. * @param preciseMatch should we accept a type that is a subtype of * sym's owner, even if it doesn't contain sym * due to hiding, overriding, or non-inheritance * due to protection? */ Tree makeOwnerThis(int pos, Symbol sym, boolean preciseMatch) { Symbol c = sym.owner; if (preciseMatch ? sym.isMemberOf(currentClass) : currentClass.isSubClass(sym.owner)) { return make.at(pos).This(c.erasure()); } else { List ots = outerThisStack; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c.toJava()); assert false; return make.Ident(syms.nullConst); } VarSymbol ot = (Symbol.VarSymbol) ots.head; Tree tree = access(make.at(pos).Ident(ot)); TypeSymbol otc = ot.type.tsym; while (!(preciseMatch ? sym.isMemberOf(otc) : otc.isSubClass(sym.owner))) { do { ots = ots.tail; if (ots.isEmpty()) { log.error(pos, "no.encl.instance.of.type.in.scope", c.toJava()); assert false; return tree; } ot = (Symbol.VarSymbol) ots.head; } while (ot.owner != otc) ; tree = access(make.at(pos).Select(tree, ot)); otc = ot.type.tsym; } return tree; } } /** * Return tree simulating the the assignment <this.name = name>, where * name is the name of a free variable. */ Tree initField(int pos, Name name) { Scope.Entry e = proxies.lookup(name); Symbol rhs = e.sym; assert rhs.owner.kind == MTH; Symbol lhs = e.next().sym; assert rhs.owner.owner == lhs.owner; make.at(pos); return make.Exec( make.Assign(make.Select(make.This(lhs.owner.erasure()), lhs), make.Ident(rhs)).setType(lhs.erasure())); } /** * Return tree simulating the the assignment <this.this$n = this$n>. */ Tree initOuterThis(int pos) { VarSymbol rhs = (Symbol.VarSymbol) outerThisStack.head; assert rhs.owner.kind == MTH; VarSymbol lhs = (Symbol.VarSymbol) outerThisStack.tail.head; assert rhs.owner.owner == lhs.owner; make.at(pos); return make.Exec( make.Assign(make.Select(make.This(lhs.owner.erasure()), lhs), make.Ident(rhs)).setType(lhs.erasure())); } /** * Return the symbol of a class to contain a cache of * compiler-generated statics such as class$ and the * $assertionsDisabled flag. We create an anonymous nested class * unless one exists and return its symbol. However, for * backward compatibility in 1.4 and earlier we use the * top-level class. */ private ClassSymbol outerCacheClass() { ClassSymbol clazz = outermostClassDef.sym; if ((clazz.flags() & INTERFACE) == 0 && target.ordinal < Target.JDK1_4_2.ordinal) return clazz; Scope s = clazz.members(); for (Scope.Entry e = s.elems; e != null; e = e.sibling) if (e.sym.kind == TYP && e.sym.name == names.empty && (e.sym.flags() & INTERFACE) == 0) return (ClassSymbol) e.sym; return makeEmptyClass(STATIC | SYNTHETIC, clazz); } /** * Return symbol for "class$" method. If there is no method definition * for class$, construct one as follows: * * class class$(String x0) { * try { * return Class.forName(x0); * } catch (ClassNotFoundException x1) { * throw new NoClassDefFoundError(x1.getMessage()); * } * } */ private MethodSymbol classDollarSym(int pos) { ClassSymbol outerCacheClass = outerCacheClass(); MethodSymbol classDollarSym = (MethodSymbol) lookupSynthetic(names.classDollar, outerCacheClass.members()); if (classDollarSym == null) { classDollarSym = new MethodSymbol(STATIC | SYNTHETIC, names.classDollar, new MethodType(Type.emptyList.prepend(syms.stringType), syms.classType, Type.emptyList, syms.methodClass), outerCacheClass); enterSynthetic(pos, classDollarSym, outerCacheClass.members()); MethodDef md = make.MethodDef(classDollarSym, null); try { md.body = classDollarSymBody(pos, md); } catch (CompletionFailure ex) { md.body = make.Block(0, Tree.emptyList); chk.completionError(pos, ex); } ClassDef outerCacheClassDef = classDef(outerCacheClass); outerCacheClassDef.defs = outerCacheClassDef.defs.prepend(md); } return classDollarSym; } /** * Generate code for class$(String name). */ Block classDollarSymBody(int pos, MethodDef md) { MethodSymbol classDollarSym = md.sym; ClassSymbol outerCacheClass = (ClassSymbol) classDollarSym.owner; Tree returnResult; if (target.ordinal >= Target.JDK1_4_2.ordinal) { VarSymbol clsym = new VarSymbol(STATIC | SYNTHETIC, names.fromString("cl$"), syms.classLoaderType, outerCacheClass); enterSynthetic(pos, clsym, outerCacheClass.members()); VarDef cldef = make.VarDef(clsym, null); ClassDef outerCacheClassDef = classDef(outerCacheClass); outerCacheClassDef.defs = outerCacheClassDef.defs.prepend(cldef); Tree newcache = make.NewArray(make.Type(outerCacheClass.type), Tree.emptyList.prepend( make.Literal(Type.INT, new Integer(0)).setType(syms.intType)) , null); newcache.type = new ArrayType(outerCacheClass.type, syms.arrayClass); Symbol forNameSym = rs.resolveInternalMethod(make.pos, attrEnv, syms.classType, names.forName, Type.emptyList.prepend(syms.classLoaderType).prepend( syms.booleanType).prepend(syms.stringType)); Tree clvalue = make.Conditional( makeBinary(Tree.EQ, make.Ident(clsym), make.Ident(syms.nullConst)), make.Assign(make.Ident(clsym), makeCall( makeCall(makeCall(newcache, names.getClass, Tree.emptyList), names.getComponentType, Tree.emptyList), names.getClassLoader, Tree.emptyList)).setType( syms.classLoaderType), make.Ident(clsym)).setType(syms.classLoaderType); List args = Tree.emptyList.prepend(clvalue).prepend( make.Ident(syms.falseConst)).prepend( make.Ident(((Tree.VarDef) md.params.head).sym)); returnResult = make.Block(0, Tree.emptyList.prepend( make.Call(make.App(make.Ident(forNameSym), args)))); } else { Symbol forNameSym = rs.resolveInternalMethod(make.pos, attrEnv, syms.classType, names.forName, Type.emptyList.prepend(syms.stringType)); returnResult = make.Block(0, Tree.emptyList.prepend( make.Call( make.App(make.QualIdent(forNameSym), List.make(make.Ident(((Tree.VarDef) md.params.head).sym)))))); } VarSymbol catchParam = new VarSymbol(0, make.paramName(1), syms.classNotFoundExceptionType, classDollarSym); Tree rethrow; if (target.ordinal >= Target.JDK1_4.ordinal) { Tree throwExpr = makeCall( makeNewClass(syms.noClassDefFoundErrorType, Tree.emptyList), names.initCause, Tree.emptyList.prepend(make.Ident(catchParam))); rethrow = make.Throw(throwExpr); } else { Symbol getMessageSym = rs.resolveInternalMethod(make.pos, attrEnv, syms.classNotFoundExceptionType, names.getMessage, Type.emptyList);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -