775 lines · 26.1 KB · Java
RawDownload
                MemberDefinition f1 =                    stClsDef.matchMethod(env, sourceClass, idValueOf, argType1);                asm.add(where, opc_invokestatic, f1);            }            // FIX FOR 4030173            // If the argument was null, then value is "null", but if the            // argument was not null, 'toString' was called and could have            // returned null.  We call 'valueOf' again to make sure that            // the result is a non-null string.  See JLS 15.17.1.1.  The            // approach taken here minimizes code size -- open code would            // be faster.  The 'toString' method for an array class cannot            // be overridden, thus we know that it will never return null.            if (!type.inMask(TM_ARRAY|TM_NULL)) {                Type argType2[] = {Type.tString};                MemberDefinition f2 =                    stClsDef.matchMethod(env, sourceClass, idValueOf, argType2);                asm.add(where, opc_invokestatic, f2);            }        } else {            // Primitive type            Type argType[] = {type};            MemberDefinition f =                stClsDef.matchMethod(env, sourceClass, idValueOf, argType);            asm.add(where, opc_invokestatic, f);        }    }     /**     * Convert this expression to a string and append it to the string     * buffer on the top of the stack.     * If the needBuffer argument is true, the string buffer needs to be     * created, initialized, and pushed on the stack, first.     */    void codeAppend(Environment env, Context ctx, Assembler asm,                    ClassDeclaration sbClass, boolean needBuffer)            throws ClassNotFound, AmbiguousMember    {        ClassDefinition sourceClass = ctx.field.getClassDefinition();        ClassDefinition sbClsDef = sbClass.getClassDefinition(env);        MemberDefinition f;        if (needBuffer) {            // need to create the string buffer            asm.add(where, opc_new, sbClass); // create the class            asm.add(where, opc_dup);            if (equals("")) {                // make an empty string buffer                f = sbClsDef.matchMethod(env, sourceClass, idInit);            } else {                // optimize by initializing the buffer with the string                codeValue(env, ctx, asm);                ensureString(env, ctx, asm);                Type argType[] = {Type.tString};                f = sbClsDef.matchMethod(env, sourceClass, idInit, argType);            }            asm.add(where, opc_invokespecial, f);        } else {            // append this item to the string buffer            codeValue(env, ctx, asm);            // FIX FOR 4071548            // 'StringBuffer.append' converts its argument as if by            // 'valueOf', treating character arrays specially.  This            // violates JLS 15.17.1.1, which requires that concatenation            // convert non-primitive arguments using 'toString'.  We force            // the treatment of all reference types as type 'Object', thus            // invoking an overloading of 'append' that has the required            // semantics.            Type argType[] =                { (type.inMask(TM_REFERENCE) && type != Type.tString)                  ? Type.tObject                  : type };            f = sbClsDef.matchMethod(env, sourceClass, idAppend, argType);            asm.add(where, opc_invokevirtual, f);        }    }     /**     * Code     */    void codeDup(Environment env, Context ctx, Assembler asm, int items, int depth) {        switch (items) {          case 0:            return;           case 1:            switch (depth) {              case 0:                asm.add(where, opc_dup);                return;              case 1:                asm.add(where, opc_dup_x1);                return;              case 2:                asm.add(where, opc_dup_x2);                return;             }            break;          case 2:            switch (depth) {              case 0:                asm.add(where, opc_dup2);                return;              case 1:                asm.add(where, opc_dup2_x1);                return;              case 2:                asm.add(where, opc_dup2_x2);                return;             }            break;        }        throw new CompilerError("can't dup: " + items + ", " + depth);    }     void codeConversion(Environment env, Context ctx, Assembler asm, Type f, Type t) {        int from = f.getTypeCode();        int to = t.getTypeCode();         switch (to) {          case TC_BOOLEAN:            if (from != TC_BOOLEAN) {                break;            }            return;          case TC_BYTE:            if (from != TC_BYTE) {                codeConversion(env, ctx, asm, f, Type.tInt);                asm.add(where, opc_i2b);            }            return;          case TC_CHAR:            if (from != TC_CHAR) {                codeConversion(env, ctx, asm, f, Type.tInt);                asm.add(where, opc_i2c);            }            return;          case TC_SHORT:            if (from != TC_SHORT) {                codeConversion(env, ctx, asm, f, Type.tInt);                asm.add(where, opc_i2s);            }            return;          case TC_INT:            switch (from) {              case TC_BYTE:              case TC_CHAR:              case TC_SHORT:              case TC_INT:                return;              case TC_LONG:                asm.add(where, opc_l2i);                return;              case TC_FLOAT:                asm.add(where, opc_f2i);                return;              case TC_DOUBLE:                asm.add(where, opc_d2i);                return;            }            break;          case TC_LONG:            switch (from) {              case TC_BYTE:              case TC_CHAR:              case TC_SHORT:              case TC_INT:                asm.add(where, opc_i2l);                return;              case TC_LONG:                return;              case TC_FLOAT:                asm.add(where, opc_f2l);                return;              case TC_DOUBLE:                asm.add(where, opc_d2l);                return;            }            break;          case TC_FLOAT:            switch (from) {              case TC_BYTE:              case TC_CHAR:              case TC_SHORT:              case TC_INT:                asm.add(where, opc_i2f);                return;              case TC_LONG:                asm.add(where, opc_l2f);                return;              case TC_FLOAT:                return;              case TC_DOUBLE:                asm.add(where, opc_d2f);                return;            }            break;          case TC_DOUBLE:            switch (from) {              case TC_BYTE:              case TC_CHAR:              case TC_SHORT:              case TC_INT:                asm.add(where, opc_i2d);                return;              case TC_LONG:                asm.add(where, opc_l2d);                return;              case TC_FLOAT:                asm.add(where, opc_f2d);                return;              case TC_DOUBLE:                return;            }            break;           case TC_CLASS:            switch (from) {              case TC_NULL:                return;              case TC_CLASS:              case TC_ARRAY:                try {                    if (!env.implicitCast(f, t)) {                        asm.add(where, opc_checkcast, env.getClassDeclaration(t));                    }                } catch (ClassNotFound e) {                    throw new CompilerError(e);                }                return;            }             break;           case TC_ARRAY:            switch (from) {              case TC_NULL:                return;              case TC_CLASS:              case TC_ARRAY:                try {                    if (!env.implicitCast(f, t)) {                        asm.add(where, opc_checkcast, t);                    }                    return;                } catch (ClassNotFound e) {                    throw new CompilerError(e);                }            }            break;        }        throw new CompilerError("codeConversion: " + from + ", " + to);    }     /**     * Check if the first thing is a constructor invocation     */    public Expression firstConstructor() {        return null;    }     /**     * Create a copy of the expression for method inlining     */    public Expression copyInline(Context ctx) {        return (Expression)clone();    }     /**     * Print     */    public void print(PrintStream out) {        out.print(opNames[op]);    }}

Lines 501–775 of 775. Previous lines