Re: Java on the Apple2 and C64



David Schmenk wrote:
Michael J. Mahon wrote:

mdj wrote:

On Aug 10, 8:04 am, Tristan Mumford <xtristan.xmumf...@xxxxxxxxxxx>
wrote:


Tsk, you've totally missed the point...


To give me horrible nightmares?

Very good work though. I never would have expected anything Java within a
stone throw (or serial cable) of an 8-bitter.



Well really, the JVM isn't that far removed from the UCSD p-System it
was (partly) inspired by. The degree of inefficiency implied by the
degree of indirection inherent in object oriented programs probably
implies that the paradigm has little practical use on such a small
machine, whether bytecode interpreted or not.


However, the Apple II p-System is very heavily optimized for the
"under 64KB" environment. In particular, the bytecodes are very
tightly encoded to improve code compaction.

The encoding of Java bytecodes is much looser, and so should be
much less space efficient for typical under-64KB programs.


Both bytecodes seem to have a very similar stack based architecture. The p-system was designed to run in 64k, so many concessions had to be made to create a full IDE written in itself as well as I/O. Segment swapping was essential to getting just about anything to run. Java never really had that kind of constraint placed on it.

The interpretive stack machine is a common idea, but the encoding
of operators/operands is much different. P-code is very tight because
of the constraints imposed, while Java never had those constraints, and
therefore has larger limits, and thus less dense coding.

Looking at the NanoVM implementation and having looked at the code cc65 generates, I'm actually amazed and impressed that it works so well. I bet a hand tuned 6502 JVM implementation would be close in performance to the 6502 p-machine. Compiler differences would be interesting. One would think compiler technology had advanced in 20 years and the advantage a Java compiler would have by running on *big iron* vs. a p-system based Pascal compiler should give the edge to Java. An intriguing subject.

I would be very surprised to see *any* high-level implementation of
an interpreter get within a factor of two of the speed of a tuned
assembly version--particularly if the interpretive operations are
low semantic level, like "add 16-bit integer".

Applesoft, often maligned for its incomplete interpretive coding,
is actually relatively compact in its code representation--though
it pays for it in rutime inefficiencies. (I occasionally wonder
how much faster it would be if variable and statement addresses
were "backpatched" into the code during execution, eliminating the
painful linear searches to resolve them...)


I actually thought that was all the Applesoft compilers really did.

Pretty close--but most of them compile into strings of procedure
calls. It would be possible to keep all the interactive editing,
etc., of Applesoft but accelerate it with on-the-fly speedups
as statements were executed the first (or second) time.

If it serves to break the "Java/.NET/VM" languages are inefficient
meme, then this project has a practical use that I applaud.


Of course, interpretation is only inefficient when used in a way
that results in slower overall execution than not using it. If an
application can run slowly in an interpretive system, but cannot
run at all in a non-interpretive environment, then interpretation
is much faster. ;-)

In any memory-constrained system, there is a good chance that
interpretation, full or partial, can be used to increase code
compaction to a significant degree. In many cases, this might
make the difference between practicality and impracticality.

In fact, interpretation is just a particular way of factoring out
chunks of code that are frequently used. Other related methods
are threaded code and procedure calls.


I guess I have never been a fan of bytecoding. For the p-system, it was a way to port to many different architectures without undo effort. For Java, it was security. However, for a memory constrained environment, it seems interpreting a tokenized language gives the most space saving and flexibility. Having to compile to a bytecode ruins the interactivity and some semantics and still leaves you having to interpret the output, just at a lower level. If you're going to compile, then go all the way. If you're going to interpret, keep it close to the source. JIT compilation would have a lot more to work with using a tokenized representation vs somebody's notion of what a CPU should look like.

Well, that's what *I* would do if anyone asked.

The problem with compiling "all the way" is that it takes a lot more
space than a compact bytecode. Most of the semantics involve at least
16-bit arithmetic, so the usual tradeoff is to use JSRs to "execute
routines". At that point, Just using threaded code would eliminate
all the JSR opcodes, saving about 30% (of course, at the cost of a
couple of instructions per "operation".

Interpretation really pays off in two cases: 1) when it saves space
on code seldom (or never) executed--like error recovery code--and 2)
when the semantic level of the operations is relatively high, so that
the average interpretive operation is many machine instructions--
floating point and graphics operations come to mind.

In the first case, compressing necessary (but performance-irrelevant
code) allows more functions and more efficient implementation of the
functions that matter, and in the second case, the interpretive overhead
becomes a very small fraction of the total execution time.

The most efficient compilers I have ever encountered, in terms of space-
speed tradeoff, used a fluid mix of interpretation, threaded code, and
in-line code during compilation. (They compiled to full in-line code.)

Exactly which method to use for performing each function was determined
by careful profiling of the compiler. Saving space in infrequently used
parts of the code allowed more space for performance-critical parts to
be coded in-line.

-michael

NadaNet file server for Apple II computers!
Home page: http://members.aol.com/MJMahon/

"The wastebasket is our most important design
tool--and it's seriously underused."
.



Relevant Pages

  • Re: Java on the Apple2 and C64
    ... The encoding of Java bytecodes is much looser, ... One would think compiler technology had advanced in 20 years and the advantage a Java compiler would have by running on *big iron* vs. a p-system based Pascal compiler should give the edge to Java. ... run at all in a non-interpretive environment, then interpretation ...
    (comp.sys.apple2)
  • Re: C to Java Byte Code
    ... Your assertion seems to be that the claim that 'a C to bytecode compiler ... > There is no proof, and there is no evidence, and there won't be until you ... Java is ...
    (comp.programming)
  • Re: why python is slower than java?
    ... is there any other real reasons that Python is slower than Java? ... Bytecode is a binary that is portable between many ... The JIT compiler compiled java to both bytecode and native OS opcode. ...
    (comp.lang.python)
  • Re: Java VM Address Space
    ... By everyone else's definition of the word "compile" Java bytecode is ... A second stage of the compiler ... which mostly resemble the set written in the Java language. ... the four invoke opcodes could be said to ...
    (comp.lang.java.programmer)
  • Re: Delphi to bytecode compiler
    ... I wanted to do the same for my own language and wrote a library (still ... > I'm wondering what would be involved in making a Delphi to bytecode ... > compiler... ... > scope of the Java platform, enabling many languages to be used (just ...
    (comp.lang.java)