bo0liu / as3-commons

Automatically exported from code.google.com/p/as3-commons
0 stars 0 forks source link

How should pushstring be used 1.0-RC4 #67

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
I am trying to push a string onto the stack using an IMethodBuilder. I have 
tried the following methods

   methodBuilder.addOpcode( Opcode.pushstring, [ "myString" ] );

but when I run this I get the following error

Error #1032: Cpool index 0 is out of range 0.
VerifyError: Error #1032: Cpool index 0 is out of range 0.

I then tried this

  classBuilder.constantPool = new ConstantPool();
  var index:int = classBuilder.constantPool.addString( "myString" );
  methodBuilder.addOpcode( Opcode.pushstring, [ index ] );

But then the bytecode library complains that 

Wrong opcode argument type for opcode [Opcode(value=44,name=pushstring)], 
expected [class String], but got 1

The AVM2 documentation is clear that pushstring should push an index into from 
the constant pool and so in a way the second method seems more correct.

What is the expected usage pattern for this or is this a bug?

Original issue reported on code.google.com by conrad.w...@gmail.com on 7 Aug 2011 at 2:39

GoogleCodeExporter commented 9 years ago
the Opcode.pushstring accepts indeed a String as an argument, the string that 
is passed in is supposed to be added to the constantpool automatically when the 
class is being serialized.
Can you post an example app that demonstrates the bug perhaps? Maybe this is a 
regression bug or something...

Original comment by ihatelivelyids on 7 Aug 2011 at 3:00

GoogleCodeExporter commented 9 years ago
if you check out the latest sources from SVN and check the test project, take a 
look at AbcBuilderTest.testBuildClassWithMethod().
I'm using pushstring there in a very simple testcase, perhaps you can glean 
from that where things go wrong in your case?

cheers,

Roland

Original comment by ihatelivelyids on 7 Aug 2011 at 3:18

GoogleCodeExporter commented 9 years ago
OK,

I've managed to isolate the behaviour - this flexunit 4 style test shows you 
the problem - 

It is not caused by the pushstring.

It is caused by pushdouble with the argument 0 - I have verified that this also 
happens with pushint too. If I change the value to 1 then it all works as 
expected.

Do you have an if statement somewhere like this 

if ( value )...

where value is normally an object you are testing for null - if so this will 
fail if you get a legitimate number who's value is 0.

If I get time I will look into it tomorrow - but this is a major showstopper 
for me at the moment :-(

package
{
    import flash.events.Event;
    import flash.system.ApplicationDomain;

    import org.as3commons.bytecode.abc.enum.Opcode;
    import org.as3commons.bytecode.emit.IClassBuilder;
    import org.as3commons.bytecode.emit.IMethodBuilder;
    import org.as3commons.bytecode.emit.impl.AbcBuilder;
    import org.flexunit.asserts.assertNotNull;
    import org.flexunit.asserts.assertTrue;
    import org.flexunit.async.Async;

    public class ByteCodeTest
    {

        private var _abcBuilder:AbcBuilder;

        public function ByteCodeTest()
        {
        }

        [Before]
        public function setUp():void
        {
            _abcBuilder = new AbcBuilder();
        }

        [Test(async)]
        public function testBuildClassWithMethod():void
        {
            Async.handleEvent( this, _abcBuilder, Event.COMPLETE, testMethod, 1000 );
            var classBuilder:IClassBuilder = _abcBuilder.definePackage( "com.myclasses.test" ).defineClass( "MyMethodTest" );
            var methodBuilder:IMethodBuilder = classBuilder.defineMethod();

            methodBuilder.name = "testMe";
            methodBuilder.returnType = "Number";

            methodBuilder.addOpcode( Opcode.getlocal_0 );
            methodBuilder.addOpcode( Opcode.pushscope );

            methodBuilder.addOpcode( Opcode.pushdouble, [ 0 ] );

            methodBuilder.addOpcode( Opcode.returnvalue );
            _abcBuilder.buildAndLoad();
        }

        private function testMethod( event:Event, length:uint ):void
        {
            var cls:Class = ApplicationDomain.currentDomain.getDefinition( "com.myclasses.test.MyMethodTest" ) as Class;
            assertNotNull( cls );
            var instance:Object = new cls();
            assertNotNull( instance );

            var result:Boolean = instance.testMe();
            assertTrue( result == 0 );
        }

    }
}

Original comment by conrad.w...@gmail.com on 7 Aug 2011 at 6:14

GoogleCodeExporter commented 9 years ago
Ok, I've reproduced the bug in a unit test as well. I'm going to try and figure 
out what's the deal, I'll let you know what I found out.
Thanks for reporting the issue, this seems to be a very low-level problem that 
would potentially affect a lot of code out there!

Cheers,

Roland

Original comment by ihatelivelyids on 7 Aug 2011 at 6:31

GoogleCodeExporter commented 9 years ago
Hi again,

I think I fixed it. It was a misinterpretation of the avm specs, this is what 
it has to say about the number zero:

"The “0” entry of the integer array is not present in 
the abcFile; it represents the zero value for the purposes of providing values 
for optional parameters and field initialization."

So, the first value is a "special" zero, until now the constantpool was 
initialized with 0's being the first items in the integer, uint and double 
pools, I now added a "special" entry as well. So now if a "normal" zero is 
added it will return a valid index in the constant pool.

The changes are available in the trunk, if you can confirm your code is working 
now I can set this issue to fixed.

Thanks again for bringing this up!

cheers,

Roland

Original comment by ihatelivelyids on 7 Aug 2011 at 6:48

GoogleCodeExporter commented 9 years ago
I have installed the trunk version of the bytecode swc and I no longer have the 
issue. Brilliant!

The reason I am picking up these bugs is that I am really trying to push a few 
boundaries :-) I am talking about the AVM2 at three different conferences in 
the coming months and one of the main tools that I will be demonstrating is of 
course AS3Commons bytecode. :-)

I'll let you know when my code is available for you to look at.

Thanks for such a prompt fix - really helps me move my talk forward  

Original comment by conrad.w...@gmail.com on 7 Aug 2011 at 8:58

GoogleCodeExporter commented 9 years ago
Hey there,

great to hear your code is working now! I'm looking forward to seeing what 
you're up to! And good luck with your conference presentations!

cheers,

Roland Zwaga

Original comment by ihatelivelyids on 7 Aug 2011 at 9:46