The main idea is to make DatagramChannel and *SocketChannel behave in
a way that more closely matches the standard, e.g. allow binding
sockets to addresses without necessarily listening on those addresses
and accept null addresses where appropriate. It also avoids multiple
redundant DNS lookups.
This commit also implements CharBuffer and BindException, and adds the
Readable interface.
c2bfba9 introduced a regression such that building against a non-Avian
class library failed due to avian.Cell not being added to the library.
Since avian.Continuations depends on that class, the build broke.
Since the function in question is the only one on the call stack above
the reset method, there's no need to invoke the captured continuation
-- we get the same effect by just returning normally, and it's more
efficient that way.
Turns out Function can do the jobs of both CallbackReceiver and
FunctionReceiver, so I've removed the latter two.
Also, shift and reset should work with a combination of types, not
just a single type, so I've expanded their generic signatures.
I've been told by knowledgeable people that it is impossible to
implement composable continuations (AKA delimited continuations AKA
shift/reset) in terms of call-with-current-continuation. Since I
don't yet understand why that is, I figured it would help my
understanding to attempt it and see how it fails.
There's more work to do to derive all the properties of a given class
from its code source (e.g. JAR file), but this at least ensures that
ClassLoader.getPackage will actually return something non-null when
appropriate.
classpath-common.h's getDeclaringClass was trying to look up
non-existing classes, which led to an abort, and I don't even know
what Class.getDeclaredClasses was trying to do, but it was ugly and
wrong.
The various Architecture::nextFrame implementations were not walking
the stack correctly when a StackOverflowError was thrown. The
throwStackOverflow thunk is called before the frame of the most
recently called method has been fully created, and because tails=true
builds use a different calling convention, we need to treat this
situation carefully when building a stack trace or unwinding.
Otherwise, we will skip past all the java frames to the next native
frame, which is what was happening.
Tail call and dead code optimizations can cause code after a throw to
be eliminated, which confuses findUnwindTarget because it doesn't know
what code is throwing the exception. So we need at least one
instruction to follow the call to the throw_ thunk. Previously, we
only added such an instruction when we knew the throw was the last
instruction in the bytecode, but it turns out there are other cases
where it is needed, including certain try/finally situations.
This is the simplest possible ConcurrentHashMap I could come up with
that works and is actually concurrent in the way one would expect.
It's pretty unconventional, being based on a persistent red-black
tree, and not particularly memory-efficient or cache-friendly. I
think this is a good place to start, though, and it should perform
reasonably well for most workloads. Patches for a more efficient
implementation are welcome!
I also implemented AtomicReferenceArray, since I was using it in my
first, naive attempt to implement ConcurrentHashMap.
I had to do a bit of refactoring, including moving some non-standard
stuff from java.util.Collections to avian.Data so I could make it
available to code outside the java.util package, which is why I had to
modify several unrelated files.