com.google.dexmaker
Class Code

java.lang.Object
  extended by com.google.dexmaker.Code

public final class Code
extends java.lang.Object

Builds a sequence of instructions.

Locals

All data manipulation takes place in local variables. Each parameter gets its own local by default; access these using getParameter(int, com.google.dexmaker.TypeId). Non-static methods and constructors also have a this parameter; it's available as getThis(com.google.dexmaker.TypeId). Allocate a new local variable using newLocal(com.google.dexmaker.TypeId), and assign a default value to it with loadConstant(com.google.dexmaker.Local, T). Every local variable has a fixed type. This is either a primitive type (of any size) or a reference type. This class emits instructions appropriate to the types they operate on. Not all operations are local on all types; attempting to emit such an operation will fail with an unchecked exception.

Math and Bit Operations

Transform a single value into another related value using op(UnaryOp,Local,Local). Transform two values into a third value using op(BinaryOp,Local,Local,Local). In either overload the first Local parameter is where the result will be sent; the other Local parameters are the inputs.

Comparisons

There are three different comparison operations each with different constraints: There's no single operation to compare longs and jump, or to compare ints and store the result in a local. Accomplish these goals by chaining multiple operations together.

Branches, Labels and Returns

Basic control flow is expressed using jumps and labels. Each label must be marked exactly once and may be jumped to any number of times. Create a label using its constructor: new Label(), and mark it using mark(com.google.dexmaker.Label). All jumps to a label will execute instructions starting from that label. You can jump to a label that hasn't yet been marked (jumping forward) or to a label that has already been marked (jumping backward). Jump unconditionally with jump(com.google.dexmaker.Label) or conditionally based on a comparison using compare(Comparison,Label,Local,Local).

Most methods should contain either a return instruction. Void methods should use returnVoid(); non-void methods should use returnValue(com.google.dexmaker.Local) with a local whose return type matches the method's return type. Constructors are considered void methods and should call returnVoid(). Methods may make multiple returns. Methods containing no return statements must either loop infinitely or throw unconditionally; it is not legal to end a sequence of instructions without a jump, return or throw.

Throwing and Catching

This API uses labels to handle thrown exceptions, errors and throwables. Call addCatchClause(com.google.dexmaker.TypeId, com.google.dexmaker.Label) to register the target label and throwable class. All statements that follow will jump to that catch clause if they throw a Throwable assignable to that type. Use removeCatchClause(com.google.dexmaker.TypeId) to unregister the throwable class.

Throw an throwable by first assigning it to a local and then calling throwValue(com.google.dexmaker.Local). Control flow will jump to the nearest label assigned to a type assignable to the thrown type. In this context, "nearest" means the label requiring the fewest stack frames to be popped.

Calling methods

A method's caller must know its return type, name, parameters, and invoke kind. Lookup a method on a type using TypeId.getMethod(com.google.dexmaker.TypeId, java.lang.String, com.google.dexmaker.TypeId...). This is more onerous than Java language invokes, which can infer the target method using the target object and parameters. There are four invoke kinds: All invoke methods take a local for the return value. For void methods this local is unused and may be null.

Field Access

Read static fields using sget(com.google.dexmaker.FieldId, com.google.dexmaker.Local); write them using sput(com.google.dexmaker.FieldId, com.google.dexmaker.Local). For instance values you'll need to specify the declaring instance; use getThis(com.google.dexmaker.TypeId) in an instance method to use this. Read instance values using iget(com.google.dexmaker.FieldId, com.google.dexmaker.Local, com.google.dexmaker.Local) and write them with iput(com.google.dexmaker.FieldId, com.google.dexmaker.Local, com.google.dexmaker.Local).

Array Access

Allocate an array using newArray(com.google.dexmaker.Local, com.google.dexmaker.Local). Read an array's length with arrayLength(com.google.dexmaker.Local, com.google.dexmaker.Local) and its elements with aget(com.google.dexmaker.Local, com.google.dexmaker.Local, com.google.dexmaker.Local). Write an array's elements with aput(com.google.dexmaker.Local, com.google.dexmaker.Local, com.google.dexmaker.Local).

Types

Use cast(com.google.dexmaker.Local, com.google.dexmaker.Local) to perform either a numeric cast or a type cast. Interrogate the type of a value in a local using instanceOfType(com.google.dexmaker.Local, com.google.dexmaker.Local, com.google.dexmaker.TypeId).


Method Summary
 void addCatchClause(TypeId<?> throwable, Label catchClause)
           
 void aget(Local<?> target, Local<?> array, Local<java.lang.Integer> index)
           
 void aput(Local<?> array, Local<java.lang.Integer> index, Local<?> source)
           
<T> void
arrayLength(Local<java.lang.Integer> target, Local<T> array)
           
 void cast(Local<?> target, Local<?> source)
          Performs either a numeric cast or a type cast.
<T> void
compare(Comparison comparison, Label trueLabel, Local<T> a, Local<T> b)
          Compare ints or references.
<T extends java.lang.Number>
void
compareFloatingPoint(Local<java.lang.Integer> target, Local<T> a, Local<T> b, int nanValue)
          Compare floats or doubles.
 void compareLongs(Local<java.lang.Integer> target, Local<java.lang.Long> a, Local<java.lang.Long> b)
          Compare longs.
<T> Local<T>
getParameter(int index, TypeId<T> type)
           
<T> Local<T>
getThis(TypeId<T> type)
           
<D,V> void
iget(FieldId<D,V> fieldId, Local<V> target, Local<D> instance)
           
 void instanceOfType(Local<?> target, Local<?> source, TypeId<?> type)
           
<D,R> void
invokeDirect(MethodId<D,R> method, Local<? super R> target, Local<? extends D> object, Local<?>... args)
           
<D,R> void
invokeInterface(MethodId<D,R> method, Local<? super R> target, Local<? extends D> object, Local<?>... args)
           
<R> void
invokeStatic(MethodId<?,R> method, Local<? super R> target, Local<?>... args)
           
<D,R> void
invokeSuper(MethodId<D,R> method, Local<? super R> target, Local<? extends D> object, Local<?>... args)
           
<D,R> void
invokeVirtual(MethodId<D,R> method, Local<? super R> target, Local<? extends D> object, Local<?>... args)
           
<D,V> void
iput(FieldId<D,V> fieldId, Local<D> instance, Local<V> source)
           
 void jump(Label target)
           
<T> void
loadConstant(Local<T> target, T value)
           
 void mark(Label label)
          Start defining instructions for the named label.
<T> void
newArray(Local<T> target, Local<java.lang.Integer> length)
           
<T> void
newInstance(Local<T> target, MethodId<T,java.lang.Void> constructor, Local<?>... args)
           
<T> Local<T>
newLocal(TypeId<T> type)
           
<T> void
op(BinaryOp op, Local<T> target, Local<T> a, Local<T> b)
           
<T> void
op(UnaryOp op, Local<T> target, Local<T> source)
           
 Label removeCatchClause(TypeId<?> throwable)
           
 void returnValue(Local<?> result)
           
 void returnVoid()
           
<V> void
sget(FieldId<?,V> fieldId, Local<V> target)
           
<V> void
sput(FieldId<?,V> fieldId, Local<V> source)
           
 void throwValue(Local<?> throwable)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Method Detail

newLocal

public <T> Local<T> newLocal(TypeId<T> type)

getParameter

public <T> Local<T> getParameter(int index,
                                 TypeId<T> type)

getThis

public <T> Local<T> getThis(TypeId<T> type)

mark

public void mark(Label label)
Start defining instructions for the named label.


jump

public void jump(Label target)

addCatchClause

public void addCatchClause(TypeId<?> throwable,
                           Label catchClause)

removeCatchClause

public Label removeCatchClause(TypeId<?> throwable)

throwValue

public void throwValue(Local<?> throwable)

loadConstant

public <T> void loadConstant(Local<T> target,
                             T value)

op

public <T> void op(UnaryOp op,
                   Local<T> target,
                   Local<T> source)

op

public <T> void op(BinaryOp op,
                   Local<T> target,
                   Local<T> a,
                   Local<T> b)

compare

public <T> void compare(Comparison comparison,
                        Label trueLabel,
                        Local<T> a,
                        Local<T> b)
Compare ints or references. If the comparison is true, execution jumps to trueLabel. If it is false, execution continues to the next instruction.


compareFloatingPoint

public <T extends java.lang.Number> void compareFloatingPoint(Local<java.lang.Integer> target,
                                                              Local<T> a,
                                                              Local<T> b,
                                                              int nanValue)
Compare floats or doubles.


compareLongs

public void compareLongs(Local<java.lang.Integer> target,
                         Local<java.lang.Long> a,
                         Local<java.lang.Long> b)
Compare longs.


iget

public <D,V> void iget(FieldId<D,V> fieldId,
                       Local<V> target,
                       Local<D> instance)

iput

public <D,V> void iput(FieldId<D,V> fieldId,
                       Local<D> instance,
                       Local<V> source)

sget

public <V> void sget(FieldId<?,V> fieldId,
                     Local<V> target)

sput

public <V> void sput(FieldId<?,V> fieldId,
                     Local<V> source)

newInstance

public <T> void newInstance(Local<T> target,
                            MethodId<T,java.lang.Void> constructor,
                            Local<?>... args)

invokeStatic

public <R> void invokeStatic(MethodId<?,R> method,
                             Local<? super R> target,
                             Local<?>... args)

invokeVirtual

public <D,R> void invokeVirtual(MethodId<D,R> method,
                                Local<? super R> target,
                                Local<? extends D> object,
                                Local<?>... args)

invokeDirect

public <D,R> void invokeDirect(MethodId<D,R> method,
                               Local<? super R> target,
                               Local<? extends D> object,
                               Local<?>... args)

invokeSuper

public <D,R> void invokeSuper(MethodId<D,R> method,
                              Local<? super R> target,
                              Local<? extends D> object,
                              Local<?>... args)

invokeInterface

public <D,R> void invokeInterface(MethodId<D,R> method,
                                  Local<? super R> target,
                                  Local<? extends D> object,
                                  Local<?>... args)

instanceOfType

public void instanceOfType(Local<?> target,
                           Local<?> source,
                           TypeId<?> type)

cast

public void cast(Local<?> target,
                 Local<?> source)
Performs either a numeric cast or a type cast.

Numeric Casts

Converts a primitive to a different representation. Numeric casts may be lossy. For example, converting the double 1.8d to an integer yields 1, losing the fractional part. Converting the integer 0x12345678 to a short yields 0x5678, losing the high bytes. The following numeric casts are supported:

FromTo
intbyte, char, short, long, float, double
longint, float, double
floatint, long, double
doubleint, long, float

For some primitive conversions it will be necessary to chain multiple cast operations. For example, to go from float to short one would first cast float to int and then int to short.

Numeric casts never throw ClassCastException.

Type Casts

Checks that a reference value is assignable to the target type. If it is assignable it is copied to the target local. If it is not assignable a ClassCastException is thrown.


arrayLength

public <T> void arrayLength(Local<java.lang.Integer> target,
                            Local<T> array)

newArray

public <T> void newArray(Local<T> target,
                         Local<java.lang.Integer> length)

aget

public void aget(Local<?> target,
                 Local<?> array,
                 Local<java.lang.Integer> index)

aput

public void aput(Local<?> array,
                 Local<java.lang.Integer> index,
                 Local<?> source)

returnVoid

public void returnVoid()

returnValue

public void returnValue(Local<?> result)