maxim.porges
unread,Mar 26, 2009, 12:16:49 AM3/26/09Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to loom-as3
One of the tools I had to develop to figure out how to make Loom work
was a better version of the abcdump utility that comes with Tamarin.
The abcdump in Tamarin gives you much less information than Loom's
version, and I needed a lower level of detail to figure out what was
going on in the bytecode.
For simplicity, I implemented this new dump utility the toString()
method of the AbcFile domain object, so you can load the bytecode in
to the AbcFile and just trace it to get the dump of the file
structure, like in the code below. The ABC file embedded in the code
snippet was created by compiling a raw .as file with asc from the
command line. When Loom is finished it will include a utility that can
pull ABC blocks directly from a SWF.
[Embed(source="../../../main/flex/loom/template/DynamicSubClass.abc",
mimeType="application/octet-stream")]
private static var proxyTemplate : Class;
public static function getProxyTemplate() : ByteArray
{
return new proxyTemplate() as ByteArray;
}
public function testDumpProxyTemplate() : void
{
var proxyByteCode : ByteArray = getProxyTemplate();
var abcFile : AbcFile = new AbcDeserializer
(proxyByteCode).deserialize();
trace(abcFile);
}
Now for a quick description of the Loom objects. AbcFile is a domain
object filled with other domain objects representing the ConstantPool,
MethodInfo array, ClassInfo, InstanceInfo, MetaData, ScriptInfo, and
MethodBodies. This is a far cry from the code in the abcdump utility
in Tamarin, which is a 1700-line procedure that only prints strings
and doesn't produce any introspectable objects of any kind.
AbcFile can be reserialized back to bytecode with an AbcSerializer,
which is the symmetric opposite of AbcDeserializer. You can manipulate
the bytecode structure of a class defintion directly by adding to/
removing from/changing objects in an AbcFile, after which the
serializer will write them to a ByteArray. You can then load the
ByteArray in to the AVM with AbcClassLoader and get an instance-able
class definition, or write it somewhere else as you see fit. All this
stuff is done.
AbcFiles will be convertable to ClassDefinitions, which are the top-
level element of the introspection API. The nice thing about
ClassDefinition over the output from describeType() is that you can
introspect private functions and variables as well as public ones. The
ClassConverter utility object that performs this conversion is a work
in progress as I mentioned in my email earlier this week, but will
show up in an early point release of Loom.
Tracing the AbcFile instance from the code sample above produces the
traced class structure listed below. The opcodes are not printed in
the method bodies since I'm polishing off the opcode parser at the
moment. Once the opcodes are in there, this will be an invaluable tool
for determining if woven bytecode is properly structured; indeed, I've
already used it a lot so far to make sure Loom has been functioning
properly.
=========================================
Output from AbcFile's toString() method
=========================================
Integer Pool: 0
Uint Pool: 0
Double Pool: 0
String Pool:
*
loom.template:DynamicSubClass
Dictionary
DynamicSubClass.as$1
loom.template
loom.template:BaseClass
Object
flash.utils
__loomProxies
String
void
Function
methodName
Boolean
apply
MethodInvocation
methodCallOne
__loomProxyInvocation
int
Number
methodCallTwo
__loomSetClosure
DynamicSubClass
BaseClass
Namespace Pool:
Namespace[namespace::*]
Namespace[private::loom.template:DynamicSubClass]
Namespace[private::DynamicSubClass.as$1]
Namespace[public]
Namespace[public::loom.template]
Namespace[packageInternalNamespace::loom.template]
Namespace[protectedNamespace::loom.template:DynamicSubClass]
Namespace[staticProtectedNamespace::loom.template:DynamicSubClass]
Namespace[staticProtectedNamespace::loom.template:BaseClass]
Namespace[staticProtectedNamespace::Object]
Namespace[public::flash.utils]
Namespace[protectedNamespace::loom.template:BaseClass]
Namespace Set Pool:
[Namespace[namespace::*]]
[Namespace[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object], Namespace[public::flash.utils]]
[Namespace[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]
[Namespace[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object], Namespace
[protectedNamespace::loom.template:BaseClass]]
[Namespace[private::DynamicSubClass.as$1], Namespace[public],
Namespace[public::loom.template], Namespace
[packageInternalNamespace::loom.template]]
Multiname Pool:
QName[Namespace[namespace::*]:*]
Multiname[name=Dictionary, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object], Namespace[public::flash.utils]]]
Multiname[name=__loomProxies, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
QName[Namespace[public]:String]
Multiname_L[nsset=[Namespace[private::loom.template:DynamicSubClass],
Namespace[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
QName[Namespace[public]:void]
QName[Namespace[public]:Function]
Multiname[name=methodName, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
Multiname[name=Boolean, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
Multiname[name=apply, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
QName[Namespace[public::loom.template]:MethodInvocation]
Multiname[name=MethodInvocation, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
Multiname[name=methodCallOne, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object], Namespace
[protectedNamespace::loom.template:BaseClass]]]
Multiname[name=__loomProxyInvocation, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[protectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object]]]
QName[Namespace[public]:int]
QName[Namespace[public]:Number]
Multiname[name=methodCallTwo, nsset=[Namespace
[private::loom.template:DynamicSubClass], Namespace
[private::DynamicSubClass.as$1], Namespace[public], Namespace
[public::loom.template], Namespace
[packageInternalNamespace::loom.template], Namespace
[staticProtectedNamespace::loom.template:DynamicSubClass], Namespace
[staticProtectedNamespace::loom.template:BaseClass], Namespace
[staticProtectedNamespace::Object], Namespace
[protectedNamespace::loom.template:BaseClass]]]
QName[Namespace[public]:Object]
QName[Namespace[public]:methodCallTwo]
QName[Namespace[public]:methodCallOne]
QName[Namespace[public]:__loomSetClosure]
QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxies]
QName[Namespace[public::flash.utils]:Dictionary]
QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxyInvocation]
QName[Namespace[public::loom.template]:DynamicSubClass]
QName[Namespace[public::loom.template]:BaseClass]
Multiname[name=BaseClass, nsset=[Namespace[private::DynamicSubClass.as
$1], Namespace[public], Namespace[public::loom.template], Namespace
[packageInternalNamespace::loom.template]]]
Method Signatures (MethodInfo):
null function staticInitializer() : QName[Namespace[namespace::*]:*]
null function constructor(QName[Namespace[public]:String]) : QName
[Namespace[namespace::*]:*]
public function QName[Namespace[public]:__loomSetClosure](QName
[Namespace[public]:String], QName[Namespace[public]:Function]) : QName
[Namespace[public]:void]
private function QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxyInvocation](QName
[Namespace[public::loom.template]:MethodInvocation]) : QName[Namespace
[namespace::*]:*]
public function QName[Namespace[public]:methodCallOne](QName[Namespace
[public]:String], QName[Namespace[public]:Number]) : QName[Namespace
[public]:int]
public function QName[Namespace[public]:methodCallTwo](QName[Namespace
[public]:String], QName[Namespace[public]:Number], QName[Namespace
[public]:Object]) : QName[Namespace[public]:void]
null function scriptInitializer() : QName[Namespace[namespace::*]:*]
InstanceInfo[
className=QName[Namespace[public::loom.template]:DynamicSubClass]
superclassName=QName[Namespace[public::loom.template]:BaseClass]
isProtected=true
protectedNamespace=Namespace
[protectedNamespace::loom.template:DynamicSubClass]
interfaceCount=0
interfaces=
instanceInitializer=null function constructor(QName[Namespace
[public]:String]) : QName[Namespace[namespace::*]:*]
traits=[
MethodTrait[name=QName[Namespace[public]:methodCallTwo], metadata=,
dispositionId=0, method=public function QName[Namespace
[public]:methodCallTwo](QName[Namespace[public]:String], QName
[Namespace[public]:Number], QName[Namespace[public]:Object]) : QName
[Namespace[public]:void]]
MethodTrait[name=QName[Namespace[public]:methodCallOne], metadata=,
dispositionId=0, method=public function QName[Namespace
[public]:methodCallOne](QName[Namespace[public]:String], QName
[Namespace[public]:Number]) : QName[Namespace[public]:int]]
MethodTrait[name=QName[Namespace[public]:__loomSetClosure],
metadata=, dispositionId=0, method=public function QName[Namespace
[public]:__loomSetClosure](QName[Namespace[public]:String], QName
[Namespace[public]:Function]) : QName[Namespace[public]:void]]
SlotOrConstantTrait[name=QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxies], metadata=,
kind=slot, slot=0, typeName=QName[Namespace
[public::flash.utils]:Dictionary], vindex=0, vkind=null]
MethodTrait[name=QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxyInvocation],
metadata=, dispositionId=0, method=private function QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxyInvocation](QName
[Namespace[public::loom.template]:MethodInvocation]) : QName[Namespace
[namespace::*]:*]]
]
]
ClassInfo[
staticInitializer=null function staticInitializer() : QName[Namespace
[namespace::*]:*]
traits=[
]
]
ScriptInfo[
scriptInitializer=null function scriptInitializer() : QName[Namespace
[namespace::*]:*]
traits=[
ClassTrait[name=QName[Namespace
[public::loom.template]:DynamicSubClass], classSlotId=1, classIndex=0,
metadata=]
]
]
Methods Bodies:
null function staticInitializer() : QName[Namespace[namespace::*]:*]
{
//maxStack=1, localCount=1, initScopeDepth=4, maxScopeDepth=5
(3 opcodes)
}
traits=(no traits)
null function constructor(QName[Namespace[public]:String]) : QName
[Namespace[namespace::*]:*]
{
//maxStack=2, localCount=2, initScopeDepth=5, maxScopeDepth=6
(15 opcodes)
}
traits=(no traits)
public function QName[Namespace[public]:__loomSetClosure](QName
[Namespace[public]:String], QName[Namespace[public]:Function]) : QName
[Namespace[public]:void]
{
//maxStack=3, localCount=3, initScopeDepth=5, maxScopeDepth=6
(10 opcodes)
}
traits=(no traits)
private function QName[Namespace
[private::loom.template:DynamicSubClass]:__loomProxyInvocation](QName
[Namespace[public::loom.template]:MethodInvocation]) : QName[Namespace
[namespace::*]:*]
{
//maxStack=3, localCount=4, initScopeDepth=5, maxScopeDepth=6
(44 opcodes)
}
traits=(no traits)
public function QName[Namespace[public]:methodCallOne](QName[Namespace
[public]:String], QName[Namespace[public]:Number]) : QName[Namespace
[public]:int]
{
//maxStack=6, localCount=4, initScopeDepth=5, maxScopeDepth=6
(19 opcodes)
}
traits=(no traits)
public function QName[Namespace[public]:methodCallTwo](QName[Namespace
[public]:String], QName[Namespace[public]:Number], QName[Namespace
[public]:Object]) : QName[Namespace[public]:void]
{
//maxStack=6, localCount=5, initScopeDepth=5, maxScopeDepth=6
(21 opcodes)
}
traits=(no traits)
null function scriptInitializer() : QName[Namespace[namespace::*]:*]
{
//maxStack=2, localCount=1, initScopeDepth=1, maxScopeDepth=4
(25 opcodes)
}
traits=(no traits)