Hacking java bytecode
cory.li
cory.li
If there's nothing about the language in which the source must be written in but only that it compiles to JVM bytecode that meets the requirements, I'd be very tempted to write most or almost all of it in bytecode... java.lang.ClassLoader is allowed and it provides some useful methods for that purpose. ;-)
At each block’s exit, a checkpoint is injected with the block’s total cost. During live execution, these checkpoints increment the AI’s internal total bytecode counter. If at any checkpoint the running tally exceeds GameConstants.BYTECODE_LIMIT, the AI’s execution is halted and execution of the next robot’s AI begins.
That sounds to me like it might be possible to squeeze in some more extra instructions at the end.
>In order to hard limit each team’s total computation, yet guarantee equal computation resources to each team, each team is given a bytecode limit, and their code is instrumented and allowed to run only up to that limit before it is halted.
They want to give each team equal cpu time, but when you have a bytecode that has instructions like invokevirtual and multianewarray the execution time isn't' exactly similar. And then there is the story about how in 2007 to make things easier the engine counted the bytecodes of various standard library methods as a predetermined fixed number no matter what happened. So of course someone put A* inside string.matches with a regular expression. (http://realgl.blogspot.com/2013/08/battlecode.html).
Sadly whenever I hear about Battlecode I hear stories about how people abused and broke the bytecode limitation to get more cpu resources than everyone else not about how they solved the problem straight up better than everyone else.
Isn't the whole idea behind the "hacker" movement to exploit the boundaries of the rules?
Not quite. GOTO allowed you to jump anywhere in the code, for any reason, at any time. Java's Label only really allows you to break out of a loop and jump to a label that was previously defined before that loop.
It's mainly used for breaking out of a set of nested loops on some condition.
Tail-Recursive functions would be a far better solution.
And almost every loop can be replaced with a simple map, fold, or filter.
For example Lua 5.1 and recent JS implementations have a proper recursive tail call implementation. The Lua manual explains it: "Without proper tail calls, each user move would create a new stack level. After some number of moves, there would be a stack overflow. With proper tail calls, there is no limit to the number of moves that a user can make, because each move actually performs a goto to another function, not a conventional call." -- http://www.lua.org/pil/6.3.html
public class Foo{
public static void main(String[] args){
http://news.ycombinator.com/
System.out.println("hello kitd");
}
}
because http: is a label, and // starts a comment. public class OhLord {
public static void main(String[] args){
free: {
I: want: to: break free;
}
System.out.println("yeah!");
}
}[1] http://dso.thecoverofnight.com/posts/2014/04/radare-java-int...
>>There are some who may scoff at bytecode optimization, reasoning that it’s a worthless skill for modern computer science, especially those working in high-level languages. Understanding what the compiler emits however is a skill still very much alive and well in embedded programming, FPGA programming, and other performance-oriented disciplines.
A few more use-cases are with building instrumentation modules, profilers besides byte-code analytic for automated-binary-audits,obfuscation amongst others.
Most of the interesting bits happen in RoboMethodTree.
http://sebastien.lebreton.free.fr/blog/index.php?/categories...
The IKVM.NET blog covers a lot of low-level details as the author implements 'JVM on .NET CLR':