Changeset 11693


Ignore:
Timestamp:
03/01/09 20:47:49 (14 years ago)
Author:
ehuelsmann
Message:

Make boxing/unboxing more efficient: Instead of "calling the boxing function from the one which maps to lisp values only
to discard the value-box (the object in which the value has been boxed) right afterwards", don't box when not required.

The change is realised by delegating the boxing and translating code-paths to a helper function which boxes/translates
upon request using JavaObject?.getInstance(object, translated).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/Java.java

    r11692 r11693  
    145145    //               derived from the instance.
    146146    //
     147
     148    private static final LispObject jfield(Primitive fun, LispObject[] args, boolean translate)
     149            throws ConditionThrowable
     150    {
     151        if (args.length < 2 || args.length > 4)
     152            error(new WrongNumberOfArgumentsException(fun));
     153        String fieldName = null;
     154        Class c;
     155        Field f;
     156        Class fieldType;
     157        Object instance = null;
     158        try {
     159            if (args[1] instanceof AbstractString) {
     160                // Cases 1-5.
     161                fieldName = args[1].getStringValue();
     162                c = javaClass(args[0]);
     163            } else {
     164                // Cases 6 and 7.
     165                fieldName = args[0].getStringValue();
     166                instance = JavaObject.getObject(args[1]);
     167                c = instance.getClass();
     168            }
     169            f = c.getField(fieldName);
     170            fieldType = f.getType();
     171            switch (args.length) {
     172                case 2:
     173                    // Cases 1 and 6.
     174                    break;
     175                case 3:
     176                    // Cases 2,3, and 7.
     177                    if (instance == null) {
     178                        // Cases 2 and 3.
     179                        if (args[2] instanceof JavaObject) {
     180                            // Case 2.
     181                            instance = JavaObject.getObject(args[2]);
     182                            break;
     183                        } else {
     184                            // Case 3.
     185                            f.set(null,args[2].javaInstance(fieldType));
     186                            return args[2];
     187                        }
     188                    } else {
     189                        // Case 7.
     190                        f.set(instance,args[2].javaInstance(fieldType));
     191                        return args[2];
     192                    }
     193                case 4:
     194                    // Cases 4 and 5.
     195                    if (args[2] != NIL) {
     196                        // Case 4.
     197                        instance = JavaObject.getObject(args[2]);
     198                    }
     199                    f.set(instance,args[3].javaInstance(fieldType));
     200                    return args[3];
     201            }
     202            return JavaObject.getInstance(f.get(instance), translate);
     203        }
     204        catch (NoSuchFieldException e) {
     205            error(new LispError("no such field"));
     206        }
     207        catch (SecurityException e) {
     208            error(new LispError("inaccessible field"));
     209        }
     210        catch (IllegalAccessException e) {
     211            error(new LispError("illegal access"));
     212        }
     213        catch (IllegalArgumentException e) {
     214            error(new LispError("illegal argument"));
     215        }
     216        catch (Throwable t) {
     217            error(new LispError(getMessage(t)));
     218        }
     219        // Not reached.
     220        return NIL;
     221    }
     222
    147223    private static final Primitive JFIELD =
    148224        new Primitive("jfield", PACKAGE_JAVA, true,
     
    152228        public LispObject execute(LispObject[] args) throws ConditionThrowable
    153229        {
    154             return JavaObject.getInstance((JFIELD_RAW.execute(args)).javaInstance(), true);
     230            return jfield(this, args, true);
    155231        }
    156232    };
     
    164240        public LispObject execute(LispObject[] args) throws ConditionThrowable
    165241        {
    166             if (args.length < 2 || args.length > 4)
    167                 error(new WrongNumberOfArgumentsException(this));
    168             String fieldName = null;
    169             Class c;
    170             Field f;
    171             Class fieldType;
    172             Object instance = null;
    173             try {
    174                 if (args[1] instanceof AbstractString) {
    175                     // Cases 1-5.
    176                     fieldName = args[1].getStringValue();
    177                     c = javaClass(args[0]);
    178                 } else {
    179                     // Cases 6 and 7.
    180                     fieldName = args[0].getStringValue();
    181                     instance = JavaObject.getObject(args[1]);
    182                     c = instance.getClass();
    183                 }
    184                 f = c.getField(fieldName);
    185                 fieldType = f.getType();
    186                 switch (args.length) {
    187                     case 2:
    188                         // Cases 1 and 6.
    189                         break;
    190                     case 3:
    191                         // Cases 2,3, and 7.
    192                         if (instance == null) {
    193                             // Cases 2 and 3.
    194                             if (args[2] instanceof JavaObject) {
    195                                 // Case 2.
    196                                 instance = JavaObject.getObject(args[2]);
    197                                 break;
    198                             } else {
    199                                 // Case 3.
    200                                 f.set(null,args[2].javaInstance(fieldType));
    201                                 return args[2];
    202                             }
    203                         } else {
    204                             // Case 7.
    205                             f.set(instance,args[2].javaInstance(fieldType));
    206                             return args[2];
    207                         }
    208                     case 4:
    209                         // Cases 4 and 5.
    210                         if (args[2] != NIL) {
    211                             // Case 4.
    212                             instance = JavaObject.getObject(args[2]);
    213                         }
    214                         f.set(instance,args[3].javaInstance(fieldType));
    215                         return args[3];
    216                 }
    217                 return JavaObject.getInstance(f.get(instance));
    218             }
    219             catch (NoSuchFieldException e) {
    220                 error(new LispError("no such field"));
    221             }
    222             catch (SecurityException e) {
    223                 error(new LispError("inaccessible field"));
    224             }
    225             catch (IllegalAccessException e) {
    226                 error(new LispError("illegal access"));
    227             }
    228             catch (IllegalArgumentException e) {
    229                 error(new LispError("illegal argument"));
    230             }
    231             catch (Throwable t) {
    232                 error(new LispError(getMessage(t)));
    233             }
    234             // Not reached.
    235             return NIL;
     242            return jfield(this, args, false);
    236243        }
    237244    };
     
    340347    };
    341348
     349    private static final LispObject jstatic(Primitive fun, LispObject[] args, boolean translate)
     350            throws ConditionThrowable
     351    {
     352        if (args.length < 2)
     353            error(new WrongNumberOfArgumentsException(fun));
     354        try {
     355            Method m = null;
     356            LispObject methodRef = args[0];
     357            if (methodRef instanceof JavaObject) {
     358                Object obj = ((JavaObject)methodRef).getObject();
     359                if (obj instanceof Method)
     360                    m = (Method) obj;
     361            } else if (methodRef instanceof AbstractString) {
     362                Class c = javaClass(args[1]);
     363                if (c != null) {
     364                    String methodName = methodRef.getStringValue();
     365                    Method[] methods = c.getMethods();
     366                    int argCount = args.length - 2;
     367                    for (int i = 0; i < methods.length; i++) {
     368                        Method method = methods[i];
     369                        if (!Modifier.isStatic(method.getModifiers())
     370                            || method.getParameterTypes().length != argCount)
     371                            continue;
     372                        if (method.getName().equals(methodName)) {
     373                            m = method;
     374                            break;
     375                        }
     376                    }
     377                    if (m == null)
     378                        error(new LispError("no such method"));
     379                }
     380            } else
     381                error(new TypeError("wrong type: " + methodRef));
     382            Object[] methodArgs = new Object[args.length-2];
     383            Class[] argTypes = m.getParameterTypes();
     384            for (int i = 2; i < args.length; i++) {
     385                LispObject arg = args[i];
     386                if (arg == NIL)
     387                    methodArgs[i-2] = null;
     388                else
     389                    methodArgs[i-2] = arg.javaInstance(argTypes[i-2]);
     390            }
     391            Object result = m.invoke(null, methodArgs);
     392            return JavaObject.getInstance(result, translate);
     393        }
     394        catch (Throwable t) {
     395            if (t instanceof InvocationTargetException)
     396                t = t.getCause();
     397            Symbol condition = getCondition(t.getClass());
     398            if (condition == null)
     399                error(new JavaException(t));
     400            else
     401                Symbol.SIGNAL.execute(
     402                    condition,
     403                    Keyword.CAUSE,
     404                    JavaObject.getInstance(t),
     405                    Keyword.FORMAT_CONTROL,
     406                    new SimpleString(getMessage(t)));
     407        }
     408        // Not reached.
     409        return NIL;
     410    }
     411
    342412    // ### jstatic method class &rest args
    343413    private static final Primitive JSTATIC =
     
    347417        public LispObject execute(LispObject[] args) throws ConditionThrowable
    348418        {
    349             return JavaObject.getInstance((JSTATIC_RAW.execute(args)).javaInstance(), true);
     419            return jstatic(this, args, true);
    350420        }
    351421    };
     
    359429        public LispObject execute(LispObject[] args) throws ConditionThrowable
    360430        {
    361             if (args.length < 2)
    362                 error(new WrongNumberOfArgumentsException(this));
    363             try {
    364                 Method m = null;
    365                 LispObject methodRef = args[0];
    366                 if (methodRef instanceof JavaObject) {
    367                     Object obj = ((JavaObject)methodRef).getObject();
    368                     if (obj instanceof Method)
    369                         m = (Method) obj;
    370                 } else if (methodRef instanceof AbstractString) {
    371                     Class c = javaClass(args[1]);
    372                     if (c != null) {
    373                         String methodName = methodRef.getStringValue();
    374                         Method[] methods = c.getMethods();
    375                         int argCount = args.length - 2;
    376                         for (int i = 0; i < methods.length; i++) {
    377                             Method method = methods[i];
    378                             if (!Modifier.isStatic(method.getModifiers())
    379                                 || method.getParameterTypes().length != argCount)
    380                                 continue;
    381                             if (method.getName().equals(methodName)) {
    382                                 m = method;
    383                                 break;
    384                             }
    385                         }
    386                         if (m == null)
    387                             error(new LispError("no such method"));
    388                     }
    389                 } else
    390                     error(new TypeError("wrong type: " + methodRef));
    391                 Object[] methodArgs = new Object[args.length-2];
    392                 Class[] argTypes = m.getParameterTypes();
    393                 for (int i = 2; i < args.length; i++) {
    394                     LispObject arg = args[i];
    395                     if (arg == NIL)
    396                         methodArgs[i-2] = null;
    397                     else
    398                         methodArgs[i-2] = arg.javaInstance(argTypes[i-2]);
    399                 }
    400                 Object result = m.invoke(null, methodArgs);
    401                 return JavaObject.getInstance(result);
    402             }
    403             catch (Throwable t) {
    404                 if (t instanceof InvocationTargetException)
    405                     t = t.getCause();
    406                 Symbol condition = getCondition(t.getClass());
    407                 if (condition == null)
    408                     error(new JavaException(t));
    409                 else
    410                     Symbol.SIGNAL.execute(
    411                         condition,
    412                         Keyword.CAUSE,
    413                         JavaObject.getInstance(t),
    414                         Keyword.FORMAT_CONTROL,
    415                         new SimpleString(getMessage(t)));
    416             }
    417             // Not reached.
    418             return NIL;
     431            return jstatic(this, args, false);
    419432        }
    420433    };
     
    488501    };
    489502
     503    private static final LispObject jarray_ref(Primitive fun, LispObject[] args, boolean translate)
     504            throws ConditionThrowable
     505    {
     506        if (args.length < 2)
     507            error(new WrongNumberOfArgumentsException(fun));
     508        try {
     509            Object a = args[0].javaInstance();
     510            for (int i = 1; i<args.length - 1; i++)
     511                a = Array.get(a, ((Integer)args[i].javaInstance()).intValue());
     512            return JavaObject.getInstance(Array.get(a,
     513                    ((Integer)args[args.length - 1].javaInstance()).intValue()), translate);
     514        }
     515        catch (Throwable t) {
     516            Symbol condition = getCondition(t.getClass());
     517            if (condition == null)
     518                error(new JavaException(t));
     519            else
     520                Symbol.SIGNAL.execute(
     521                    condition,
     522                    Keyword.CAUSE,
     523                    JavaObject.getInstance(t),
     524                    Keyword.FORMAT_CONTROL,
     525                    new SimpleString(getMessage(t)));
     526        }
     527        // Not reached.
     528        return NIL;
     529    }
     530
    490531    // ### jarray-ref java-array &rest indices
    491532    private static final Primitive JARRAY_REF =
     
    496537        public LispObject execute(LispObject[] args) throws ConditionThrowable
    497538        {
    498             return JavaObject.getInstance((JARRAY_REF_RAW.execute(args)).javaInstance(), true);
     539            return jarray_ref(this, args, true);
    499540        }
    500541    };
     
    508549        public LispObject execute(LispObject[] args) throws ConditionThrowable
    509550        {
    510             if (args.length < 2)
     551            return jarray_ref(this, args, false);
     552        }
     553    };
     554
     555    // ### jarray-set java-array new-value &rest indices
     556    private static final Primitive JARRAY_SET =
     557        new Primitive("jarray-set", PACKAGE_JAVA, true,
     558                      "java-array new-value &rest indices")
     559    {
     560        @Override
     561        public LispObject execute(LispObject[] args) throws ConditionThrowable
     562        {
     563            if (args.length < 3)
    511564                error(new WrongNumberOfArgumentsException(this));
    512565            try {
    513566                Object a = args[0].javaInstance();
    514                 for (int i = 1; i<args.length - 1; i++)
     567                LispObject v = args[1];
     568                for (int i = 2; i<args.length - 1; i++)
    515569                    a = Array.get(a, ((Integer)args[i].javaInstance()).intValue());
    516                 return JavaObject.getInstance(Array.get(a, ((Integer)args[args.length - 1].javaInstance()).intValue()));
     570                Array.set(a, ((Integer)args[args.length - 1].javaInstance()).intValue(), v.javaInstance());
     571                return v;
    517572            }
    518573            catch (Throwable t) {
     
    533588    };
    534589
    535     // ### jarray-set java-array new-value &rest indices
    536     private static final Primitive JARRAY_SET =
    537         new Primitive("jarray-set", PACKAGE_JAVA, true,
    538                       "java-array new-value &rest indices")
    539     {
    540         @Override
    541         public LispObject execute(LispObject[] args) throws ConditionThrowable
    542         {
    543             if (args.length < 3)
    544                 error(new WrongNumberOfArgumentsException(this));
    545             try {
    546                 Object a = args[0].javaInstance();
    547                 LispObject v = args[1];
    548                 for (int i = 2; i<args.length - 1; i++)
    549                     a = Array.get(a, ((Integer)args[i].javaInstance()).intValue());
    550                 Array.set(a, ((Integer)args[args.length - 1].javaInstance()).intValue(), v.javaInstance());
    551                 return v;
    552             }
    553             catch (Throwable t) {
    554                 Symbol condition = getCondition(t.getClass());
    555                 if (condition == null)
    556                     error(new JavaException(t));
    557                 else
    558                     Symbol.SIGNAL.execute(
    559                         condition,
    560                         Keyword.CAUSE,
    561                         JavaObject.getInstance(t),
    562                         Keyword.FORMAT_CONTROL,
    563                         new SimpleString(getMessage(t)));
    564             }
    565             // Not reached.
    566             return NIL;
    567         }
    568     };
    569 
    570590    // ### jcall method instance &rest args
    571591    // Calls makeLispObject() to convert the result to an appropriate Lisp type.
     
    576596        public LispObject execute(LispObject[] args) throws ConditionThrowable
    577597        {
    578             if (args.length < 2)
    579                 error(new WrongNumberOfArgumentsException(this));
    580             return JavaObject.getInstance(jcall(args), true);
     598            return jcall(this, args, true);
    581599        }
    582600    };
     
    591609        public LispObject execute(LispObject[] args) throws ConditionThrowable
    592610        {
    593             if (args.length < 2)
    594                 error(new WrongNumberOfArgumentsException(this));
    595             return JavaObject.getInstance(jcall(args));
    596         }
    597     };
    598 
    599     private static Object jcall(LispObject[] args) throws ConditionThrowable
    600     {
    601         Debug.assertTrue(args.length >= 2); // Verified by callers.
     611            return jcall(this, args, false);
     612        }
     613    };
     614
     615    private static LispObject jcall(Primitive fun, LispObject[] args, boolean translate)
     616            throws ConditionThrowable
     617    {
     618        if (args.length < 2)
     619            error(new WrongNumberOfArgumentsException(fun));
    602620        final LispObject methodArg = args[0];
    603621        final LispObject instanceArg = args[1];
     
    631649                    methodArgs[i-2] = arg.javaInstance(argTypes[i-2]);
    632650            }
    633             return method.invoke(instance, methodArgs);
     651            return JavaObject.getInstance(method.invoke(instance, methodArgs), translate);
    634652        }
    635653        catch (ConditionThrowable t) {
Note: See TracChangeset for help on using the changeset viewer.