1282 lines · 51.6 KB · Java
RawDownload
    private static MemberDefinition getClassLiteralCache(Environment env,                                                         Context ctx,                                                         String className,                                                         ClassDefinition c) {        // Given a class name, look for a static field to cache it.        //      className       lname        //      pkg.Foo         class$pkg$Foo        //      [Lpkg.Foo;      array$Lpkg$Foo        //      [[Lpkg.Foo;     array$$Lpkg$Foo        //      [I              array$I        //      [[I             array$$I        String lname;        if (!className.startsWith(SIG_ARRAY)) {            lname = prefixClass + className.replace('.', '$');        } else {            lname = prefixArray + className.substring(1);            lname = lname.replace(SIGC_ARRAY, '$'); // [[[I => array$$$I            if (className.endsWith(SIG_ENDCLASS)) {                // [Lpkg.Foo; => array$Lpkg$Foo                lname = lname.substring(0, lname.length() - 1);                lname = lname.replace('.', '$');            }            // else [I => array$I or some such; lname is already OK        }        Identifier fname = Identifier.lookup(lname);         // The class to put the cache in is now given as an argument.        //        // ClassDefinition c = ctx.field.getClassDefinition();        // while (c.isInnerClass()) {        //     c = c.getOuterClass();         MemberDefinition cfld;        try {            cfld = c.getVariable(env, fname, c);        } catch (ClassNotFound ee) {            return null;        } catch (AmbiguousMember ee) {            return null;        }         // Ignore inherited field.  Each top-level class        // containing a given class literal must have its own copy,        // both for reasons of binary compatibility and to prevent        // access violations should the superclass be in another        // package.  Part of fix 4106051.        if (cfld != null && cfld.getClassDefinition() == c) {            return cfld;        }         // Since each class now has its own copy, we might as well        // tighten up the access to private (previously default).        // Part of fix for 4106051.        // ** Temporarily retract this, as it tickles 4098316.        return env.makeMemberDefinition(env, c.getWhere(),                                        c, null,                                        M_STATIC | M_SYNTHETIC, // M_PRIVATE,                                        Type.tClassDesc, fname,                                        null, null, null);    }     private Expression makeClassLiteralCacheRef(Environment env, Context ctx,                                                MemberDefinition lookup,                                                MemberDefinition cfld,                                                String className) {        Expression ccls = new TypeExpression(where,                                             cfld.getClassDefinition()                                             .getType());        Expression cache = new FieldExpression(where, ccls, cfld);        Expression cacheOK =            new NotEqualExpression(where, cache.copyInline(ctx),                                   new NullExpression(where));        Expression lcls =            new TypeExpression(where, lookup.getClassDefinition() .getType());        Expression name = new StringExpression(where, className);        Expression namearg[] = { name };        Expression setCache = new MethodExpression(where, lcls,                                                   lookup, namearg);        setCache = new AssignExpression(where, cache.copyInline(ctx),                                        setCache);        return new ConditionalExpression(where, cacheOK, cache, setCache);    }     private Expression makeClassLiteralInlineRef(Environment env, Context ctx,                                                 MemberDefinition lookup,                                                 String className) {        Expression lcls =            new TypeExpression(where, lookup.getClassDefinition().getType());        Expression name = new StringExpression(where, className);        Expression namearg[] = { name };        Expression getClass = new MethodExpression(where, lcls,                                                   lookup, namearg);        return getClass;    }      /**     * Check if constant:  Will it inline away?     */    public boolean isConstant() {        if (implementation != null)            return implementation.isConstant();        if ((field != null)            && (right == null || right instanceof TypeExpression                || (right.op == THIS && right.where == where))) {            return field.isConstant();        }        return false;    }     /**     * Inline     */    public Expression inline(Environment env, Context ctx) {        if (implementation != null)            return implementation.inline(env, ctx);        // A field expression may have the side effect of causing        // a NullPointerException, so evaluate it even though        // the value is not needed.  Similarly, static field dereferences        // may cause class initialization, so they mustn't be omitted        // either.        //        // However, NullPointerException can't happen and initialization must        // already have occured if you are dotting into 'this'.  So        // allow fields of 'this' to be eliminated as a special case.        Expression e = inlineValue(env, ctx);        if (e instanceof FieldExpression) {            FieldExpression fe = (FieldExpression) e;            if ((fe.right != null) && (fe.right.op==THIS))                return null;            // It should be possible to split this into two checks: one using            // isNonNull() for non-statics and a different check for statics.            // That would make the inlining slightly less conservative by            // allowing, for example, dotting into String constants.            }        return e;    }    public Expression inlineValue(Environment env, Context ctx) {        if (implementation != null)            return implementation.inlineValue(env, ctx);        try {            if (field == null) {                return this;            }             if (field.isFinal()) {                Expression e = (Expression)field.getValue(env);                if ((e != null) && e.isConstant()) {                    // remove bogus line-number info                    e = e.copyInline(ctx);                    e.where = where;                    return new CommaExpression(where, right, e).inlineValue(env, ctx);                }            }             if (right != null) {                if (field.isStatic()) {                    Expression e = right.inline(env, ctx);                    right = null;                    if (e != null) {                        return new CommaExpression(where, e, this);                    }                } else {                    right = right.inlineValue(env, ctx);                }            }            return this;         } catch (ClassNotFound e) {            throw new CompilerError(e);        }    }    public Expression inlineLHS(Environment env, Context ctx) {        if (implementation != null)            return implementation.inlineLHS(env, ctx);        if (right != null) {            if (field.isStatic()) {                Expression e = right.inline(env, ctx);                right = null;                if (e != null) {                    return new CommaExpression(where, e, this);                }            } else {                right = right.inlineValue(env, ctx);            }        }        return this;    }     public Expression copyInline(Context ctx) {        if (implementation != null)            return implementation.copyInline(ctx);        return super.copyInline(ctx);    }     /**     * The cost of inlining this expression     */    public int costInline(int thresh, Environment env, Context ctx) {        if (implementation != null)            return implementation.costInline(thresh, env, ctx);        if (ctx == null) {            return 3 + ((right == null) ? 0                                        : right.costInline(thresh, env, ctx));        }        // ctxClass is the current class trying to inline this method        ClassDefinition ctxClass = ctx.field.getClassDefinition();        try {            // We only allow the inlining if the current class can access            // the field, the field's class, and right's declared type.            if (    ctxClass.permitInlinedAccess(env, field.getClassDeclaration())                 && ctxClass.permitInlinedAccess(env, field)) {                if (right == null) {                    return 3;                } else {                    ClassDeclaration rt = env.getClassDeclaration(right.type);                    if (ctxClass.permitInlinedAccess(env, rt)) {                        return 3 + right.costInline(thresh, env, ctx);                    }                }            }        } catch (ClassNotFound e) {        }        return thresh;    }     /**     * Code     */    int codeLValue(Environment env, Context ctx, Assembler asm) {        if (implementation != null)            throw new CompilerError("codeLValue");        if (field.isStatic()) {            if (right != null) {                right.code(env, ctx, asm);                return 1;            }            return 0;        }        right.codeValue(env, ctx, asm);        return 1;    }    void codeLoad(Environment env, Context ctx, Assembler asm) {        if (field == null) {            throw new CompilerError("should not be null");        }        if (field.isStatic()) {            asm.add(where, opc_getstatic, field);        } else {            asm.add(where, opc_getfield, field);        }    }    void codeStore(Environment env, Context ctx, Assembler asm) {        if (field.isStatic()) {            asm.add(where, opc_putstatic, field);        } else {            asm.add(where, opc_putfield, field);        }    }     public void codeValue(Environment env, Context ctx, Assembler asm) {        codeLValue(env, ctx, asm);        codeLoad(env, ctx, asm);    }     /**     * Print     */    public void print(PrintStream out) {        out.print("(");        if (right != null) {            right.print(out);        } else {            out.print("<empty>");        }        out.print("." + id + ")");        if (implementation != null) {            out.print("/IMPL=");            implementation.print(out);        }    }}

Lines 1001–1282 of 1282. Previous lines