-
Notifications
You must be signed in to change notification settings - Fork 256
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java: Unboxed primitives #472
Java: Unboxed primitives #472
Conversation
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Could you push a branch for the |
!! Good idea, done. |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
c65c196
to
ec6a81d
Compare
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Hi @lukemaurer! I'm excited to review this but it's a really large change set. Is there any chance you could break it up into 2 or even 3 different PRs in sequence, given the high-level breakdown you gave? |
I can, though it's a bit of a bumpy road in places—in particular, DafnySequence.java gets overhauled twice. I'll try and rearrange things so there's not too much to re-review. |
Primitive types are now represented by the actual primitives, in unboxed form. Unsigned types are represented by their signed counterparts; UInt and friends are no more (this was a previous patch). To represent an array of unknown type, the dafny.Array<T> class is introduced. It is *only* used when the type T is an unknown parameter, to avoid the overhead of an object for each array. (Multi-dimensional arrays always use the corresponding dafny.Array{n} classes, since we need the object anyway to remember the dimensions.) The tricky thing here is coercing, say, byte[] to dafny.Array<Byte> when calling a generic method expecting dafny.Array<T>, and coercing in the other direction if a method returns a generic array.
Several fixes to the handling of arrays, especially their interaction with sequences. ByteArrayDafnySequence is now folded into ArrayDafnySequence, which is now backed by a dafny.Array. Also it now takes the element type descriptor as an argument so that the correct array can be created (this will break extern code).
Since an extern class may be one whose source code the user can't change, and since the default value of a class is almost always null so an explicit _type function isn't necessary, Java now does what the other backends do and dynamically looks for a static _type method for any extern class. This may be a performance issue. TODO: Consider a WeakHashMap from java.lang.Class to dafny.Type (or some sort of dafny.TypeFunction in the case of a generic type) to save on reflection.
A couple of small issues look to be having outsized influence: Create() loops over BigInteger and converts each to an int rather than looping over ints and creating a BigInteger for each; the latter is much faster. Also, LazyDafnySequence doesn't override verbatimString(), which was causing concatenated DafnySequence<Character>s to be very slow in converting to strings.
d3bb417
to
5245c1f
Compare
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
Okay, done: There's now #521 (largely unrelated but other changes build on it), #522, #523, and #524. Unfortunately, there's a bit of churn in DafnySequence still ...) |
Thanks @lukemaurer, this is much more digestible now! :) I'll start with #521 and go from there. |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
There was a fatal flaw in the scheme that encoded an array of generic type T as a `dafny.Array<T>` and an array of known type as a plain array: While we can unwrap a returned array as necessary to coerce from, say, `dafny.Array<Integer>` to `int[]`, we cannot expect to do the same for a `dafny.Array<T>` somewhere inside a class or datatype. The only alternative that doesn't add overhead to the known-element-type case is to represent an array of a type parameter as a `java.lang.Object` (since, sadly, primitive arrays and object arrays share no other superclass). Generated code will still be type-correct since the compiler knows which `java.lang.Object`s are arrays of which type, and we can use the `dafny.Type<T>` object passed into a generic method to perform array operations. The `dafny.Array` class is retained for convenience in programming but is no longer used by generated code.
cb11756
to
2cac926
Compare
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
This looks spurious (something to do with thread scheduling). It WFM, at any rate. |
Known issue: #454 :( |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
AWS CodeBuild CI Report
Powered by github-codebuild-logs, available on the AWS Serverless Application Repository |
This is a PR against a new branch, java-type-descriptors, rather than master. I tried changing it before merging, but github gave me a scary warning. So, instead, I'll merge this into the java-type-descriptors branch, and will then merge that into master. |
(Depends on #524.)
This would have been easy if it weren't for the unfortunate interaction between primitives, arrays, and generics in Java. Namely, a method taking a
T[]
can't take abyte[]
, becauseT
can only stand for a reference type. Thus the only type that can stand for an array of any type isjava.lang.Object
. We need a fast way to create and operate on arrays of arbitrary type, and Java does not provide it (most methods ofjava.lang.reflect.Array
are very slow). This was a three-step process:Introduce lvalue abstraction #523: In the base
Compiler
class, introduce a general system for turning assignments into calls to setter methods so that an assignment to an array of unknown type can be expressed as a method call. (Java already needed this; its implementation of trait fields was buggy.)Introduce Type objects to Java runtime #524: Replace the strings used for type descriptors with objects, which are much faster and more type-safe. (This also fixes existing bugs.)
This PR: Have all primitive types appear in unboxed form where possible (that is, when the type isn't a parameter). Represent a generic array as a
java.lang.Object
and use the correspondingdafny.Type
for array operations.