Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (489)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (555)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  About using byte literals instead of int literals  (Read 3094 times)
0 Members and 1 Guest are viewing this topic.
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Posted 2008-12-01 21:22:17 »

I'm toying with using jasmin this year, writing my games in java assembler.
The common(?) advice to push two small values and multiply them instead of pushing a larger value seems to be false for most reasonable values (ie less than 2^15).

Say I need to push 640 and 480 for the size of my screen.. Using just bytes, this doesn't get much smaller than:
1  
2  
3  
4  
5  
6  
   bipush 10
   dup
   bipush 64
   imul                  
   bipush 48
   imul    


That's 9 bytes in total.

However, pushing shorts makes it take up just 6 bytes:
1  
2  
   sipush 640
   sipush 480



And the java code for that is just

1  
2  
a = 640;
b = 480;


It works for all values between -32768 and 32767.

Play Minecraft!
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 783
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2008-12-01 21:42:37 »

That entry in the wiki was created by me. (I assume you refer to that article)

I only used it when I had quite a few values, that could all roughly be divided by N, and then later be multiplied by N.

I recall that with 4 or 5 values, it could save 1 or 2 bytes in the compressed archive.

The effects of GZ are really unpredictable (doh), so even increasing your *.class a little, can gain you a few bytes in the *.jar

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #2 - Posted 2008-12-01 22:26:01 »

That's bordering on "try some shit, it might get smaller", and doesn't really belong on the wiki. sipush doesn't use the constant pool.

Play Minecraft!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #3 - Posted 2008-12-01 23:57:07 »

1  
2  
3  
4  
5  
6  
   bipush 10
   dup
   bipush 64
   imul                  
   bipush 48
   imul    


That's 9 bytes in total.

Wouldn't that leave 10 & 30720 on the operand stack, rather than 640 & 480 ?

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
bipush 10
// stack-> 10
dup
// stack-> 10, 10
bipush 64
// stack-> 10, 10, 64
imul
// stack-> 10, 640
bipush 48
// stack-> 10, 640, 48
imul
// stack-> 10, 30720


You're still right though, regarding sipush being much more efficient in that case.

However, it does get a little more complex - as it depends what you are doing with the constants,
as to what datatype & associated push instruction javac will use in the generated bytecode.

Take this common call for example:

1  
enableEvents(640);


javac will store 640 as a 8 byte value (because the parameter type is long) in the constants pool, and use ldc or ldc_w to retrieve it.
jasmin can help significiantly in this case:
1  
2  
sipush 640
i2l


Personally I don't think the semantics of java bytecode realy allow for much optimisation beyond what is expressable in the java syntax.
Therefore I don't think jasmin will be able to help very much - except for allowing you to hand-craft peep-hole optimisations.

But then, if you are only going to use it for making peep-hole optimisations, I think it'd be much more productive to automate them as part of the proguard optimisation/obfuscation step.
That way we can all benefit from them too Grin

:edit:

Thinking back, there was one other instance being able to mangle the bytecode helped me...
During the initialisation stage, I recall I was accessing the same object several times in succession - calling different methods on it. (Frame & GraphicsDevice instances I believe)
Anyhow, as the methods being invoked were void, I determined that it was safe to pull the Frame/GraphicsDevice reference onto the stack just once, and dup it for each future invocation that was going to be made.
This replaced a load of 2 byte 'aload x' instructions with 1 byte dup's.

However, this again is a peep-hole optimisation that I believe could be added to proguard without too much trouble.

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #4 - Posted 2008-12-02 08:42:14 »

Oops, you're right about that error, heh. Ok, 10 bytes then. Wink

About size-optimisations, I've got a runnable applet with start() and stop() support, event handling and pixel rendering down to under 1kb using jasmin.

For example, the keyDown and keyUp events become

1  
2  
3  
4  
5  
6  
7  
8  
9  
keyDown:
   iconst_1
   goto setKey

keyUp:
   iconst_0

setKey:
; Set keys[((KeyEvent)e).getKeyCode()] to the value on the stack


in java, you'd have to do something like:

1  
2  
3  
4  
5  
6  
7  
boolean down = false;
[...]
    case KeyEvent.KEY_PRESSED:
        down = true;
    case KeyEvent.KEY_RELEASED:
        keys[((KeyEvent)e).getKeyCode()] = down;
        break;


.. and that uses a lot more bytes as it stores down in a local variable.


Most of the fancy things I can do in jasmin instead of doing in java is stupid jsr/ret tricks, sinister gotos, and making assumptions about the stack that the compiler doesn't seem to want to do.
For instance, if you've got a lot of this.foo(), this.that(), this.setWidth()-calls, you can load this once, then dup, then dup2 several times until you've got the right amount on the stack.

Unfortunately, the fact that the stack has to be identical on an op code regardless of how you get there means that I can't use loops to process all data on the stack. That's a shame. Wink

Play Minecraft!
Offline Abuse

JGO Knight


Medals: 12


falling into the abyss of reality


« Reply #5 - Posted 2008-12-02 10:28:22 »

Perhaps you could keep the game coded in both jasmin & java, so by the end we can see how many bytes you've gained!

Either way, Good luck Grin

p.s.

There have been a few times i've wondered how easy it would be to make a byte code transformation that changed non-recursive method invocations into jsr/ret pairs.

Quote
Unfortunately, the fact that the stack has to be identical on an op code regardless of how you get there means that I can't use loops to process all data on the stack. That's a shame.

Have you tried turning off the VMs bytecode verification (java -noverify )?  Grin

Make Elite IV:Dangerous happen! Pledge your backing at KICKSTARTER here! https://dl.dropbox.com/u/54785909/EliteIVsmaller.png
Offline Markus_Persson

JGO Wizard


Medals: 14
Projects: 19


Mojang Specifications


« Reply #6 - Posted 2008-12-02 12:26:52 »

The way I'm doing is actually to write the stuff I need first in java, disassembling it to jasmin code, then knitting that into my assembler.
Doing method calls manually from scratch in java bytecodes is just too time consuming.

-noverify, while interesting, might not be the best idea. Wink
I've got a feeling the stack size restriction is there is so the jit can replace stack manipulation with hard coded memory offsets.

Play Minecraft!
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Nickropheliac (9 views)
2014-08-31 22:59:12

TehJavaDev (23 views)
2014-08-28 18:26:30

CopyableCougar4 (27 views)
2014-08-22 19:31:30

atombrot (40 views)
2014-08-19 09:29:53

Tekkerue (38 views)
2014-08-16 06:45:27

Tekkerue (34 views)
2014-08-16 06:22:17

Tekkerue (24 views)
2014-08-16 06:20:21

Tekkerue (34 views)
2014-08-16 06:12:11

Rayexar (72 views)
2014-08-11 02:49:23

BurntPizza (47 views)
2014-08-09 21:09:32
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!