blob: 3e90cc551d8b240ef4a27960ae73b46a4b50a1ee [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.flex.abc;
import org.apache.flex.abc.instructionlist.InstructionList;
import org.apache.flex.abc.semantics.ClassInfo;
import org.apache.flex.abc.semantics.ExceptionInfo;
import org.apache.flex.abc.semantics.InstanceInfo;
import org.apache.flex.abc.semantics.Instruction;
import org.apache.flex.abc.semantics.Label;
import org.apache.flex.abc.semantics.Metadata;
import org.apache.flex.abc.semantics.MethodBodyInfo;
import org.apache.flex.abc.semantics.MethodInfo;
import org.apache.flex.abc.semantics.Name;
import org.apache.flex.abc.semantics.Namespace;
import org.apache.flex.abc.semantics.Nsset;
import org.apache.flex.abc.semantics.ScriptInfo;
import org.apache.flex.abc.semantics.Trait;
import org.apache.flex.abc.semantics.Traits;
import org.apache.flex.abc.visitors.IABCVisitor;
import org.apache.flex.abc.visitors.IClassVisitor;
import org.apache.flex.abc.visitors.IMetadataVisitor;
import org.apache.flex.abc.visitors.IMethodBodyVisitor;
import org.apache.flex.abc.visitors.IMethodVisitor;
import org.apache.flex.abc.visitors.IScriptVisitor;
import org.apache.flex.abc.visitors.ITraitVisitor;
import org.apache.flex.abc.visitors.ITraitsVisitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class implements an IABCVisitor which will simply collect
* all of the structures of an ABC block, such as constant pools, method
* infos, class infos, etc into various pools so they can be processed later
* in a different order than the IABCVisitor events are received in.
*/
public class PoolingABCVisitor implements IABCVisitor
{
public PoolingABCVisitor ()
{
}
public void visit (int majorVersion, int minorVersion)
{
this.majorVersion = majorVersion;
this.minorVersion = minorVersion;
}
public IScriptVisitor visitScript ()
{
return new ScriptVisitor();
}
public IClassVisitor visitClass (InstanceInfo iinfo, ClassInfo cinfo)
{
return new ClassVisitor(iinfo, cinfo);
}
public IMethodVisitor visitMethod (MethodInfo minfo)
{
return new MethodVisitor(minfo);
}
@Override
public void visitPooledDouble (Double d)
{
this.doublePool.add(d);
}
@Override
public void visitPooledInt (Integer i)
{
this.intPool.add(i);
}
@Override
public void visitPooledMetadata (Metadata md)
{
this.metadataPool.add(md);
}
@Override
public void visitPooledName (Name n)
{
this.namePool.add(n);
}
@Override
public void visitPooledNamespace (Namespace ns)
{
this.nsPool.add(ns);
if (ns != null)
visitPooledString(ns.getVersionedName());
}
@Override
public void visitPooledNsSet (Nsset nss)
{
this.nssetPool.add(nss);
if (nss != null)
{
for (Namespace ns : nss)
{
visitPooledNamespace(ns);
}
}
}
@Override
public void visitPooledString (String s)
{
this.stringPool.add(s);
}
@Override
public void visitPooledUInt (Long l)
{
this.uintPool.add(l);
}
private int majorVersion;
private int minorVersion;
private final Pool<Name> namePool = new Pool<Name>(Pool.DefaultType.HasDefaultZero);
private final Pool<String> stringPool = new Pool<String>(Pool.DefaultType.HasDefaultZero);
private final Pool<Integer> intPool = new Pool<Integer>(Pool.DefaultType.HasDefaultZero);
private final Pool<Long> uintPool = new Pool<Long>(Pool.DefaultType.HasDefaultZero);
private final Pool<Double> doublePool = new Pool<Double>(Pool.DefaultType.HasDefaultZero);
private final Pool<Namespace> nsPool = new Pool<Namespace>(Pool.DefaultType.HasDefaultZero);
private final Pool<Nsset> nssetPool = new Pool<Nsset>(Pool.DefaultType.HasDefaultZero);
private final Pool<Metadata> metadataPool = new Pool<Metadata>(Pool.DefaultType.NoDefaultZero);
private List<ScriptInfo> scriptInfos = new ArrayList<ScriptInfo>();
private List<MethodBodyInfo> methodBodies = new ArrayList<MethodBodyInfo>();
private EntryOrderedStore<MethodInfo> methodInfos = new EntryOrderedStore<MethodInfo>();
private List<ClassVisitor> definedClasses = new ArrayList<ClassVisitor>();
private Map<MethodInfo, MethodBodyInfo> methodMap = new HashMap<MethodInfo, MethodBodyInfo>();
/**
* Major version of the ABC
*/
public int getMajorVersion ()
{
return majorVersion;
}
/**
* Minor version of the ABC
*/
public int getMinorVersion ()
{
return minorVersion;
}
/**
* Name pool, has default zero entry.
*/
public Pool<Name> getNamePool ()
{
return namePool;
}
/**
* String pool, has default zero entry.
*/
public Pool<String> getStringPool ()
{
return stringPool;
}
/**
* int pool, has default zero entry.
*/
public Pool<Integer> getIntPool ()
{
return intPool;
}
/**
* uint pool, has default zero entry.
*/
public Pool<Long> getUintPool ()
{
return uintPool;
}
/**
* double pool, has default zero entry.
*/
public Pool<Double> getDoublePool ()
{
return doublePool;
}
/**
* namespace pool, has default zero entry.
*/
public Pool<Namespace> getNsPool ()
{
return nsPool;
}
/**
* namespace set pool, has default zero entry.
*/
public Pool<Nsset> getNssetPool ()
{
return nssetPool;
}
/**
* metadata pool, does not have default zero entry.
*/
public Pool<Metadata> getMetadataPool ()
{
return metadataPool;
}
/**
* Get a list of the ScriptInfos
*/
public List<ScriptInfo> getScriptInfos ()
{
return scriptInfos;
}
/**
* Get a list of the method bodies
*/
public List<MethodBodyInfo> getMethodBodies ()
{
return methodBodies;
}
/**
* Get a list of the method infos
*/
public EntryOrderedStore<MethodInfo> getMethodInfos ()
{
return methodInfos;
}
/**
* Get a list of the defined classes
*/
public List<ClassVisitor> getDefinedClasses ()
{
return definedClasses;
}
/**
* Script visitor that adds its ScriptInfo to the
* list of ScriptInfos
*/
private class ScriptVisitor implements IScriptVisitor
{
ScriptVisitor ()
{
this.si = new ScriptInfo();
}
final ScriptInfo si;
@Override
public void visit ()
{
}
@Override
public void visitEnd ()
{
scriptInfos.add(this.si);
}
@Override
public void visitInit (MethodInfo init_method)
{
si.setInit(init_method);
}
@Override
public ITraitsVisitor visitTraits ()
{
return new TraitsVisitor(si.getTraits());
}
}
/**
* Class Visitor that adds itself to the list
* of defined classes
*/
protected class ClassVisitor implements IClassVisitor
{
ClassVisitor (InstanceInfo iinfo, ClassInfo cinfo)
{
this.classInfo = cinfo;
if (null == cinfo.classTraits)
cinfo.classTraits = new Traits();
this.classTraits = cinfo.classTraits;
this.instanceInfo = iinfo;
if (null == iinfo.traits)
iinfo.traits = new Traits();
this.instanceTraits = iinfo.traits;
if (null == iinfo.interfaceNames)
iinfo.interfaceNames = new Name[0];
}
ClassInfo classInfo;
Traits classTraits;
InstanceInfo instanceInfo;
Traits instanceTraits;
@Override
public void visit ()
{
}
@Override
public ITraitsVisitor visitClassTraits ()
{
return new TraitsVisitor(this.classTraits);
}
@Override
public ITraitsVisitor visitInstanceTraits ()
{
return new TraitsVisitor(this.instanceTraits);
}
@Override
public void visitEnd ()
{
definedClasses.add(this);
}
public InstanceInfo getInstanceInfo ()
{
return this.instanceInfo;
}
}
/**
* Traits Visitor that populates a Traits object
*/
private class TraitsVisitor implements ITraitsVisitor
{
TraitsVisitor (Traits traits)
{
this.traits = traits;
}
Traits traits;
@Override
public ITraitVisitor visitClassTrait (int kind, Name name, int slot_id, ClassInfo clazz)
{
Trait t = createTrait(kind, name);
if (slot_id != 0)
t.addAttr(Trait.TRAIT_SLOT, slot_id);
t.addAttr(Trait.TRAIT_CLASS, clazz);
return new TraitVisitor(t);
}
@Override
public ITraitVisitor visitMethodTrait (int kind, Name name, int dispId, MethodInfo method)
{
Trait t = createTrait(kind, name);
t.addAttr(Trait.TRAIT_METHOD, method);
if (dispId != 0)
t.addAttr(Trait.TRAIT_DISP, dispId);
return new TraitVisitor(t);
}
@Override
public ITraitVisitor visitSlotTrait (int kind, Name name, int slotId, Name slotType, Object slotValue)
{
Trait t = createTrait(kind, name);
t.addAttr(Trait.TRAIT_SLOT, slotId);
t.addAttr(Trait.TRAIT_TYPE, slotType);
t.addAttr(Trait.SLOT_VALUE, slotValue);
if (slotType != null)
visitPooledName(slotType);
return new TraitVisitor(t);
}
@Override
public void visit ()
{
}
@Override
public void visitEnd ()
{
}
@Override
public Traits getTraits ()
{
return this.traits;
}
private Trait createTrait (int kind, Name name)
{
Trait t = new Trait(kind, name);
traits.add(t);
return t;
}
}
/**
* Trait Visitor that creates a Trait object
*/
private class TraitVisitor implements ITraitVisitor
{
TraitVisitor (Trait t)
{
this.t = t;
}
Trait t;
@Override
public IMetadataVisitor visitMetadata (int count)
{
return new IMetadataVisitor()
{
@Override
public void visit (Metadata md)
{
t.addMetadata(md);
}
};
}
@Override
public void visitAttribute (String attr_name, Object attr_value)
{
this.t.addAttr(attr_name, attr_value);
}
@Override
public void visitStart ()
{
}
@Override
public void visitEnd ()
{
}
}
/**
* Method Body Visitor that adds its MethodBodyInfo to the list of method bodies
*/
private class MethodBodyVisitor implements IMethodBodyVisitor
{
MethodBodyVisitor (org.apache.flex.abc.semantics.MethodBodyInfo mbinfo)
{
this.mbi = mbinfo;
}
MethodBodyInfo mbi;
@Override
public void visit ()
{
}
@Override
public void visitEnd ()
{
methodBodies.add(mbi);
methodMap.put(mbi.getMethodInfo(), mbi);
}
@Override
public void visitInstruction (int opcode)
{
this.mbi.insn(opcode);
}
@Override
public void visitInstruction (int opcode, int immediate_operand)
{
this.mbi.insn(opcode, immediate_operand);
}
@Override
public void visitInstruction (int opcode, Object single_operand)
{
this.mbi.insn(opcode, single_operand);
}
@Override
public void visitInstruction (int opcode, Object[] operands)
{
this.mbi.insn(opcode, operands);
}
@Override
public void visitInstruction (Instruction insn)
{
this.mbi.insn(insn);
}
@Override
public ITraitsVisitor visitTraits ()
{
return new TraitsVisitor(this.mbi.getTraits());
}
@Override
public int visitException (Label from, Label to, Label target, Name ex_type, Name ex_var)
{
return mbi.addExceptionInfo(new ExceptionInfo(from, to, target, ex_type, ex_var));
}
@Override
public void visitInstructionList (InstructionList new_list)
{
mbi.setInstructionList(new_list);
}
@Override
public void labelCurrent (Label l)
{
mbi.labelCurrent(l);
}
@Override
public void labelNext (Label l)
{
mbi.labelNext(l);
}
}
/**
* Method Visitor that adds its MethodInfo to the list of MethodInfos
*/
private class MethodVisitor implements IMethodVisitor
{
MethodVisitor (MethodInfo mi)
{
assert (mi != null);
this.mi = mi;
}
final MethodInfo mi;
@Override
public void visit ()
{
methodInfos.add(mi);
}
@Override
public IMethodBodyVisitor visitBody (MethodBodyInfo mbi)
{
return new MethodBodyVisitor(mbi);
}
@Override
public void visitEnd ()
{
}
}
/**
* @return the class ID of the given ClassInfo.
* @throws IllegalArgumentException if the class is not found.
*/
protected int getClassId (ClassInfo info)
{
int id_index = 0;
for (ClassVisitor candidate : this.definedClasses)
{
if (candidate.classInfo == info)
return id_index;
else
id_index++;
}
throw new IllegalArgumentException("Unable to find ClassInfo index for " + info);
}
/**
* Get the corresponding MethodBodyInfo for a given MethodInfo
* @param mi the MethodInfo you want the body for
* @return the MethodBodyInfo which is the body of the given MethodInfo
*/
protected MethodBodyInfo getMethodBodyForMethodInfo (MethodInfo mi)
{
return methodMap.get(mi);
}
@Override
public void visitEnd ()
{
}
}