2016/03/24

00:35

Instead of having a single class per instruction, I can always split it up into groups. Then this way I do not need to worry much about having tons of classes. However some operations may be more difficult to find. However, I would say that having less classes with more meat would be the better alternative than very slim classes. It would require switch statements in the classes though. Those 256 classes would count twords the total class limit I will be imposing on the VM. Right now I have 250 classes total in all of my sources (well, 250 .java files). Plus some nearby operations have similar function and such. It would also mean that the cache reference array is a bit smaller too (which can be a good thing). There would also be less potentially stale reference objects in memory also. So if I set the shift to say 4, then I only need 32 elements.

10:02

I do not actually need unique IDs for basic optimizations. I can just have an active stack slot so to speak which points to preallocated registers and such. So I will need a list of native registers and such.

10:26

I will need a kind of a virtual working system which is lazy. Basically I work with virtual registers which may be in locals or on the stack, then I determine operations which are to be performed on them in a linear sequence. When the registers go away (they are overwritten) then they are stored before they are destroyed. Probably do not need to store them when memory barriers are hit because these are just registers. So instead of generating code that just copies from one place to another, adds some values, then stores that result into a temporary. It is basically just:

The result will exist purely virtually and will not be stored by default in most situations. However invoking a method will require that the value is stored somewhere if it is not consumed by the method call. Well, actually I might not even need to use the value at all. One could write byte code which adds a bunch of values together and then just pops the result meaning it was pointless. So even during method calls I do not store it. The only time I have to actually calculate the value is if it gets stored into a field (instance or static), called into a method, thrown, allocate a new object, allocate a new array (possibly even multidimensional), entering/exiting monitor. If some operator chains are simple say byte code adds 2 + 2 + v, I can just turn that into 4 + v. So if a bunch of math is performed on operations, I only really have to perform the work when it becomes visible to the outside of the method. This can be used for optimization and removing the bulk of Java's stack like nature and could result in smaller code being generated. It would require however that the position of exception handlers and the stack map table be known for optimal work. Because if values are calculated and it just turns out they are never worked with because some exception is tossed... Well actually if they are in a local they will stick around to excpetion handlers. So for each possible local variable state exists, there has to be one for each handler of exceptions. So it is possible that operator chains can be ambigious in this event. So I will have to specially handle exception handlers and operator chains. So I propose that if a local is written to when there is an actual exception handler that is present, that the operator chain is calculated. If there is no exception handler and then suddenly there becomes one, then all the operator chains associated with local values are calculated and code is generated for them.

Essentially this results in operator chains for register values, which can be used to determine how values are used and such.

I made a base class JVMNativeRegisters with stuff in JVMProgramOutput, so I could likely simplify things a bit. I could have special program outputters which can virtualize int/long/float/double operations if not supported. This would be needed for 8-bit and 16-bit systems where 32-bit integer math is not supported at all.

10:40

So implementing JVMNativeRegisters and the related stuff to it right now is a mistake before the operator chains.

12:55

Ok, so JVMNativeRegister goes by for now.

13:06

What I need to determine next is the best way to store the operation chains. I also need a way to minimal represent the entire state of the program with reduced memory usage. Currently I was planning to use a map which stored a value for each logical operation and its entire state. However, some states do not really differ from other operations. For example, if I just add value to the stack, there is only a single change which is that added value. So what I currently have would essentially copy the entire state when a small difference could be done instead. Although there would be a slight speed penalty, there would at least be less memory usage. It would be a very small amount of memory saving, but it could be just enough for it to be worth it. It also would not require massive redundent copies of everything also. Then with this state class for all the operations I can have the operator chains for all of the variables added also. Usually only a single instruction will change values, so I would not need to for example have all these copies of the same operator chain.

13:14

Another thing to consider with operator chains would be to instead of having it such as a = 2 + x + y + z, it is instead a = 2 + x, b = a + y, and c = b + z. This way previous operator chains could be changed while still having the same value at the very end. When a calculation is performed and a value is written then the operator chain would drop down and potentially be replaced. So they must be mutable for those given operations.

19:30

Yknow, Arrays and Collections have binary search algorithms, I should just use that to find things instead of inventing my own stuff.

20:05

Actually I could do a form of SSA with JVMProgramState with the operator chains.