1. 11 Mar, 2020 1 commit
  2. 09 Mar, 2020 2 commits
    • Mark's avatar
      jstatic: check narrowing for explicit method reference · 04191d57
      Mark authored
      The arguments for to an explicitly referenced static Java method
      taking java.lang.Byte java.lang.Short parameters that can be narrowed
      from fixnums or java.lang.Integer parameters that can narrowed from
      bignums without losing information.
      
      All such invocations should now error if such an invocation would
      truncate information on coercion.
      
      TODO: provide a way (or argument for JCOERCE) for the user to
      explictly request such narrowing even if it loses information, an
      often utilized technique on the JVM when dealing with data types that
      don't work well with the JVM primitive types, such as using the signed
      byte for bit twiddling.
      
      TODO: do the same for JCALL, hopefully refactoring the code.
      04191d57
    • Mark's avatar
      asdf: update to asdf-3.3.4 · 682dbaf8
      Mark authored
      682dbaf8
  3. 07 Feb, 2020 2 commits
  4. 02 Jan, 2020 1 commit
  5. 19 Dec, 2019 1 commit
  6. 15 Dec, 2019 1 commit
    • Mark's avatar
      I've looked into this issue at length now and I think I have something worth · 72a5d761
      Mark authored
      discussing and potentially trying[0] . The root issue here lies in how ABCL
      converts its CL representation of integers to Java, as well as its conversion
      of Java primitives to other Java primitives.
      
      ABCL's common superclass for all objects (LispObject) includes two methods to
      convert the lisp object to a Java representation: LispObject.javaInstance() and
      LispObject.javaInstance(Class). LispObject.javaInstance(Class) presumably tries
      to convert the internal representation to the type represented by the Class
      passed in. In practice, this seems to be primarily used for Java primitive
      types. The current implementation of these methods in ABCL's internal Bignum,
      DoubleFloat, SingleFloat, Fixnum, LispCharacter, and JavaObject, do not seem to
      have all the required permutations necessary to support all of the possible Java
      primitive converting operations.
      
      Even for instances where a conversion /is/ implemented (such as
      Fixnum.javaInstance(Short) where a Short would be returned), the method lookup
      strategy in Java.findMethod (which boils down to what Java.isAssignable does)
      doesn't find the method with the Short parameter. Instead it uses normal rules
      in the Java Language spec and only looks for methods that potentially /widen/
      primitives, and disallows any narrowing without an explicit narrowing cast (and
      in Brad's example, the literal 16 or 32 is represented by Fixnum, which converts
      to java.lang.Integer). I think the original intention is to have such methods be
      called using jcoerce, such as:
      
      (jcoerce 32 (jclass "short"))
      or
      (jcoerce 32 (jclass "java.lang.Short"))
      
      This fails in the current implementation, I believe due to a bug in
      JavaObject(Object, Class) constructor. This only does one type of conversion, to
      java.lang.Byte, if the intended class is Byte and the Object implements Number.
      
      For jcoerce to work with all primitives, all possible primitive operations need
      to be covered in JavaObject(Object, Class).
      
      I have attached a patch that adds these conversions to JavaObject(Object,
      Class). However, I've also changed other places where these primitive
      conversions are done for consistency. My rule of thumb has been that the Java
      Language Specification rules[1] should be followed, and the /only/ time a
      /narrowing/ conversion is allowed where information can potentially be lost, is
      through the JavaObject(Object, Class) constructor (in Lisp land, called using
      the (java:jcoerce) function).
      
      As such, the patch also changes the implementation classes Bignum, DoubleFloat,
      SingleFloat, Fixnum, Character, and JavaObject, to support all possible
      primitive /widening/ conversions. Their implementations of
      LispObject.javaInstance(Class) continue to signal type errors for conversions
      that cannot be performend, but also now for all narrowing operations. Previously
      /some/ of these classes allowed /some/ narrowing conversions to happen. I think
      a case could be made for each of these LispObject implementations to allow any
      primitve conversion. The disadvantage is not knowing an information reducing
      operation potentially occurred (and is counter to the behavior of not finding
      narrowing methods such as Brad's original example) -- at the very least if all
      primitive narrowing operations /were/ allowed from Fixnum.javaInstance(Class)
      for example, a compiler warning should be emitted (though I'm not sure how that
      would be implemented).
      
      The following patch may break code that relies on the one conversion that has
      worked in the past (to byte, in the JavaObject(Object, Class) constructor. In
      fact, this patch breaks swank. To fix your swank, modify your swank's abcl.lisp
      to include the now required jcoerce call (in the octets-to-jbytes function): the
      jstatic call should now look like:
      ... (around line 191)
               do (java:jstatic (java:jmethod "java.lang.reflect.Array"  "setByte"
                                 "java.lang.Object" "int" "byte")
                                "java.lang.reflect.Array"
                                bytes i (java:jcoerce byte "byte")))
      
      What are your thoughts? I dislike backwards incompatible changes like this, but
      I think the impact is probably low due to the fact that method resolution used
      rules to only find widening conversions, and the fact that short and byte are
      not as commonly used in method calls.
      
      Previously, (jfield) and (jproperty) uses would also not signal a type error
      unless LispObject.javaInstance(Class) did not support the conversion (and like
      mentioned previously, some classes did some primitive narrowing operations).
      Uses of these fields will now (consistently) with method calls, error on
      narrowing conversions unless coerced.
      
      Try the patch (but make sure to modify your swank!)...
      
      Now my old example works like the following:
      (jstatic "reverseBytes" "java.lang.Short" (jcoerce #x7f "short"))
      
      Note also that the patch didn't break any new tests.  I ran tests via:
      (require 'asdf)
      (load "~/quicklisp/setup.lisp")
      (asdf:initialize-source-registry
       `(:source-registry (:directory ,*default-pathname-defaults*) :inherit-configuration))
      (asdf:test-system :abcl)
      
      
      -Mark
      
      [0] See patch attached (against latest master of https://github.com/armedbear/abcl)
         (3a54c91f)
      
      [1] Widening Primitve Conversion
         https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html#jls-5.1.2
      72a5d761
  7. 29 Nov, 2019 1 commit
  8. 25 Nov, 2019 2 commits
  9. 22 Nov, 2019 2 commits
  10. 01 Nov, 2019 18 commits
  11. 29 Mar, 2019 2 commits
  12. 30 May, 2018 2 commits
  13. 07 May, 2018 2 commits
  14. 23 Apr, 2018 2 commits
  15. 01 Apr, 2018 1 commit