Skip to content

When the AVM Pukes…

After many long nights of coding, Loom is finally at the point where it is capable of weaving bytecode. I started weaving dynamic proxies this week using the Loom API  and for the most part, everything worked first try - which was killer.

However, I hit an issue last night that I just could not figure out. I had weaved all the opcodes correctly for a method Loom weaves in to dynamic proxies called proxyInvocation(). This method handles the lookup of interceptors and the handoff of method invocations to them, or defers to the superclass implementation of a method in the event that no interceptor has been registered. However, I was getting a stack underflow error from the AVM runtime, which looked like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
verify loom.template::BaseClass/http://loom.ninjitsoft.com::proxyInvocation()
                       stack:
                       scope: [global Object$ loom.template::BaseClass$]
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 0:getlocal0
                       stack: loom.template::BaseClass
                       scope: [global Object$ loom.template::BaseClass$]
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 1:pushscope
                       stack:
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 2:getlocal0
                       stack: loom.template::BaseClass
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 3:getproperty http://loom.ninjitsoft.com::handlerMappings
                       stack: flash.utils::Dictionary?
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 5:getlocal1
                       stack: flash.utils::Dictionary? loom.template::MethodInvocation?
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 6:getproperty {public}::methodName
                       stack: flash.utils::Dictionary? String?
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 8:getproperty {public}::[]
                       stack: *
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 10:coerce Function
                       stack: Function?
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *
 12:setlocal3
                       stack:
                       scope: [global Object$ loom.template::BaseClass$] loom.template::BaseClass
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * Function?
 13:returnvalue
VerifyError: Error #1024: Stack underflow occurred.
 
	at loom.template::BaseClass/http://loom.ninjitsoft.com::proxyInvocation()
	at <anonymous>()[/Users/mporges/Documents/code/workspace/loom/src/test/flex/loom/util/DynamicProxyFactoryTest.as:58]
	at flash.events::EventDispatcher/dispatchEventFunction()
	at flash.events::EventDispatcher/dispatchEvent()
	at <anonymous>()[/Users/mporges/Documents/code/workspace/loom/src/main/flex/loom/swf/AbcClassLoader.as:111]

It turns out that the error was caused by me removing some opcodes to try to debug another stack underflow error, which I’ll talk about in a second. What I wanted to do in this post was show how the AVM communicates when you have not written your opcode blocks properly, since it took me a second to understand this last night.

Let’s take a look at the first message that was printed out.

5
6
7
8
 0:getlocal0
                       stack: loom.template::BaseClass
                       scope: [global Object$ loom.template::BaseClass$]
                        locals: loom.template::BaseClass loom.template::MethodInvocation? * *

From what I can tell. this says that the getlocal0 opcode was found. The three lines afterwards show you the objects on the stack, the objects in scope, and the local variables on the local stack. This format is repeated for all the opcodes the AVM interpreted up to the error.

In the case of the full error listing above, returnvalue returns whatever is on the stack, which is currently nothing. Since I had removed some opcodes to try to figure out what was going on, I removed the opcodes that pushed a value on to the stack for returnvalue to return. So, that was the issue.

The root cause of my full error (which I have not posted the error output from) was that my opcode parser had the arguments for the callproperty opcode transposed. Since both arguments to this opcode are u30s, this error did not show up in my serialize/deserialize tests. I flipped the arguments around to their correct order, regenerated the compiled ABC dump for the method I was attempting to weave, and was able to see that the arguments I was supposed to be passing to callproperty were different. Once I fixed the call to callproperty, the code in proxyInvocation() started working.

I’ve only got a few items to address in the dynamic proxies before the public beta: I need to rewire the static initializer to reflect the modified object inheritance tree, replace the opcodes for all the methods with calls to proxyInvocation() and flip their override flags on, and switch out the class and superclass names in the instance info for the class. After that, we’ll be in AOP-land.

Tagged ,

Flex Camp Miami Update

Today, the attendees at Flex Camp Miami got an overview of the inner workings of the AVM and Loom. You can read the details on my other blog.

Tagged

Getting There…

Just a quick update to say that work is progressing nicely on the Loom library. I’m currently working on polishing the API so that it’s easier to create dynamic class definitions without having a deep understanding of the AVM2 spec.

Tagged

Loom Presentation at Flex Camp Miami

An early look at Loom is going to be presented at Flex Camp Miami. We’ll also be discussing the AVM2 spec and taking a look at Tamarin. There are lots of other great talks, so take a look at the agenda and register!

Tagged

Google Code Project Created

Well, it’s official - the Loom project has a home on Google Code. There’s no source in it yet, but there will be once I’m ready to release it to the world. Stay tuned…

Tagged