Implementation of Asmsupport Local variables

Source: Internet
Author: User
Tags dashed line

Implementation of local variables

[email protected] address

At the bytecode level, each method has a local variable array that stores the parameters of the current method, the variables declared within the method, and if the non-static method also stores a reference to the current method instance. When we use Java in peacetime, the size of this local variable is determined when the source code is compiled into class, so how to use this local variable more efficiently, and reasonably assign each variable in the local variable array position, Let's take a look at the following code, which shows how Asmsupport is planning for local variables.

代码1public void method(boolean bool) {     int prefix = 1;    if(bool)    {          double d = 2.12;        String   s = "string";        ...    }    else    {        char c = ‘a‘;        long l  = 1L;    }}

The code above is shown in a scoped way such as:

If you follow the procedural process, it is clear that there are two kinds of execution results. The IF statement block is executed when BOOL is true, when BOOL executes the ELSE statement block for false. If this is the local variable diagram of both cases

In the previous local variables, the first three variables are shared, and the variables after the first are changed, for both executions, although the variable types are declared differently, and the variable word length is different, because if and else two blocks are parallel, the last three locations in the local variable are common. Based on this situation, Asmsupport uses a tree structure to simulate and implement the relationship between the scope and local variables.

We'll revise the code above:

_代码2public void method(boolean bool, boolean bool2){    int prefix = 1;    if (bool)    {        double d = 2.12;        String s = "string";    }    else    {        if(bool2)        {            float f = 1;        }        char c = ‘a‘;        long l = 1L;    }}

We use squares to represent the blocks, the circles to represent local variables, and to give each block alias a tree structure.


Figure 1

Through this tree, we can accomplish two things:

1. Determine which variables occupy the local variable space relative to the variables we specify are REUSABLE

2. Determine which variables can be called in a program block

Reuse of local variable space

All of the variables in the method are stored in a local variable array, but if in Java code each declaration of a variable to a new position in the local variable, it is bound to cause a lot of wasted space, as we have shown above in code 1, it is necessary to some of the local variable space to be reused.

However, we combine the code 2 and Figure 1, the compiler will code 1 into a class file, the process of the compiler will convert the program into a byte code, then the order of the scan is the tree in Figure 1 to do the first sequence traversal (the first order traversal is actually for the binary tree, here the meaning is to first traverse the root node, The child nodes are then scanned in order from left to right, and the result is:

This->bool->bool2->prefix-if->d->s->else-if2->f->c->l

So how to judge the variable space can be reused, Asmsupport is doing this:

    • Execution of the prefix, the this,bool,bool2,prefix in order for it to allocate local invariant space, the subscript is: 0,1,2,3
    • Execute into if, still is for _d, S allocates space, because _d_ is double, so allocated space subscript is 4 and 5,S_ assigned to 6
    • Execution to IF2, this time found _d_ and _s_ These two variables of space I can be reused, because if and else is parallel, the same moment the same thread can not be executed at the same time to if and else, and IF2 is another child block, so it assigns F to subscript 4 space, The 4 position has been re-used by the variables D and S.
    • Continue to _c_ and _l_, found that the space just assigned to the F variable can be reused, because F is located in the program block is IF2, he is an else's self-program block, in the scope of this block declared variables only valid under the current scope, so the _C_ is assigned to subscript F The allocated space 4, at this time 4 position has been _d F c_ three variables shared; This is the continuation of the variable to L, because L is a long type of two words of space, also found that D occupies position 5 and s occupies a position of 6 is shareable, so the 5 and 6 location of the local variables assigned to L


Figure 2

Let's start by describing a few graphs:

    • Square: represents the program block, or it can be called the scope _
    • Circle: represents a variable, where the number represents the order in which the Asmsupport traverses the object, which we call the _ variable ordinal , followed by the expression _ variable name
    • Line: represents a block-program block, program block-a dependency between variables
    • Horizontal Rectangle: Represents the _ generation _ in this tree structure, and the number on the right of the rectangle indicates the number of generations, such as the first generation, the second generation
    • dashed line with arrows: Asmsupport path to variable creation traversal
    • ellipse between the vertical dashed line and the dashed line: used to divide each variable declaration and allocate the array of local variables for the variable, we call it the Tao, with the number in the ellipse, we call it _ 1, Tao 2_
    • table: array of local variables

Also note the following:

-Since the allocation of This,bool,bool2,prefix is very simple, here we incorporate the declaration of these variables into one lane 1
-Each time a variable is allocated space, it iterates through the array of member variables starting at 0, judging whether the currently declared variable can be taken with the traversed variable, and if it can be reused we will use the currently traversed subscript to assign to the currently declared variable.
The 2nd is the core problem is how to determine whether variable space can be reused.

We know that variables are actually stored in local variables, that is, in the table part, and we put the local variables stored in these tables to a logical tree structure, through this structure to determine whether the variable is reusable, once the variable can be reused then his variable space can be reused. Based on this tree structure and the diagram above, we can conclude that the variables can be reused by steps (the reuse of the variables is relative to the two variables), assuming we now determine whether the space of a variable can be reused by the B variable.

    • The traversal ordinal of a variable is interpreted less than the traversal ordinal of the B variable, if it is greater then it cannot be reused, otherwise it enters 2
    • If the generation of a is the same as the generation of B (in Figure II, it is the same generation value, for example, the variable d,s,c,l) and has the same parent, stating that it cannot be reused, and that different instructions allow reuse.
    • If the number of generations of a variable is greater than the number of generations of the B variable (compared to the F and C in two), then the space of a variable can be reused.
    • If the generation of a variable is less than the number of generations of the B variable (compared to D and F in the second), start with the B variable to get the elder (scope), until the elder is found and the number of generations of a variable is the same as the scope T, if a and t is the same parent can not be reused, if the parents are different
Determining which variables can be called in a program block

Here's how to tell if a variable can be reused, and here's how Asmsupport can tell which objects are being called by the current scope. In fact, this logic and judgment can be reused in the logic of the opposite, we think of the scope is a variable, and then determine whether it can be reused, can be reused to indicate that the scope cannot use the specified variable, otherwise it can be used. And in fact, if you are writing code, we can visually see that the variables defined in the parent scope can be called in the child scope, and here we will briefly describe the implementation logic, or follow the tree structure in figure asmsupport, assuming we need to determine if the A variable can be used in the S scope.

We can get the following judging method according to the serial number in Figure 2:

    • The traversal sequence number of a is greater than S.
    • If a and s have the same generation and have the same parent, then a can be used within the S scope
    • A cannot be used within the s scope if the generation of a is greater than the number of generations of s
    • If the generation of a is less than the number of generations of S, then the elder is obtained from the number of s generation, until the elder is found and the number of generations of a variable is the same as the scope T, if a and t is the same parent can use a in S, otherwise it cannot be used.
Code implementationArray of local variables

In Figure two we see the model of the local variable array, and in Asmsupport we use a list as the main container. At first we just store the latest variables in each location in this list, and when we store f in 4, we cover the previous d, similar to the process:


Figure 3

However, since we want to print out the current local variable state when producing each local variable operation instruction by "How to view asmsupport log file", it is easier for us to debug and track our own programs. So we're storing a custom class Localhistory object in the Local variables list container, each Localhistory object corresponds to a cell position in an array of local variables, and the local variable d in the second is a double type, which accounts for two units. Therefore, two Localhistory objects will be created, and the change history of local variables in the Localhistory class is stored in that location by a list, which is the structure of the local variables in our figure Ii.

These logic uses the Cn.wensiqun.asmsupport.utils.memory.LocalVariables and the Asmsupport code in the Implemented by Cn.wensiqun.asmsupport.utils.memory.LocalVariables.LocalHistory. The latter is an inner class of the former, and is a static private type that is used only internally by Localvariables.

Localvariables also has a function of printing the state of local variables, this part of the code is not the core of the implementation of local variables, so do not explain.

Logical abstraction of scopes and local variables

The core in Figure 2 is the tree structure of the scope and local variables, as each node in the tree, We define a parent class cn.wensiqun.asmsupport.core.utils.memory.Component for it, and then define the two subclasses of Component respectively Cn.wensiqun.asmsupport.core.utils.memory . Scope and cn.wensiqun.asmsupport.core.utils.memory.ScopeLogicVariable represent scopes and local variables. The hierarchy chart is as follows:

Component    |-Scope    |-ScopeLogicVariable_图4

Component

As a parent class, it is necessary to define some basic information, as follows:

    • locals: This is a reference to a Localvariabbles object
    • Generation: Stores the generation number of the node in the tree structure, corresponding to the transverse rectangle in Figure ii.
    • Componentorder: Indicates the order of occurrence, corresponding to the number in front of each node in Figure two
    • Parent: indicates a direct parental

The componentorder here is not a sequential number in figure two, and the second is implemented with the number of generations and points, similar to the following structure:


Figure 5

Then compare the order of the two component first point before the number, the number of large componentorder than the other componentorder, if equal to continue to compare the second point before the number and so on, such as "5.1 > 4", "6.1.1 > 5.2", "6.2 > 6.1.1". The implementation is implemented in the Comparecomponentorder method.

Scope

This class is an abstraction of the scope, which is the square part of our figure two. The following properties are primarily stored in this class:

    • Components : A list type that stores the child nodes of this
    • start:"reference bytecode label", used to delimit the starting position of the current scope
    • innerend:"reference bytecode label", used to delimit the end position of the current scope
    • outerend:"reference bytecode label", used to delimit the end position of the current scope

Components and start are better understood, as explained above. But what's the difference between Innerend and outerend? This involves the strategy of asmsupport generation scope, with a detailed reference to the Asmsupport scoping strategy.

Scopelogicvariable

This class is an abstraction of a local variable, represented as a circular section in Figure Ii. This class has some of the following properties:

    • String Name: variable Name
    • Type declaretype: declaring types of variables
    • Type actuallytype: The actual type of the variable
    • int[] Positions: The position of the array of local variables that the variable occupies
    • int Initstartpos: The starting position of a variable in a local variable
    • Boolean anonymous: Whether it is an anonymous variable
    • Label Specifiedstartlabel: The starting position of the scope where the variable is located
    • int compileorder: generate variable directives in bytecode compilation order

Some properties are explained here:

    • 1) Actuallytype: This property represents the actual type of the variable, but this property is not entirely able to determine the actual type of the variable, such as an object that I obtained by invoking the method, I can only use the return type of the method as Actualltype, but the type returned by the method is probably an interface, so this property is not recommended.
    • 2) Positions: This property is an array, because if the current variable is a double or a long type, it is a local variable space of two units, so here it is stored with arrays, To be sure, if there is a value inside the array, it must be continuous, for example [3,4], because the storage of the local variable space is a continuous storage. Of course, this array may also have no value, because in the above we have introduced, the variable space is possible to be reused, once his location is reused, here the array is changed, the positions of the third d variable is [4,5], to the fourth channel becomes 5, and the newly created variable C The positions becomes 4.
    • 3) Initstartpos: This represents the starting position of the variable in the local variable array, which is equal to the No. 0 value of the positions array in the original state, why it is the initial state, Before introducing positions, positions is always changing, so we assign the No. 0 value to the Initstartpos attribute at the first initialization of the positions.
    • 4) Anonymous: This property indicates whether the variable is anonymous, and once this property is true, the Name property is invalidated
    • 5) Compileorder: According to the above explanation, this property is similar to the property Componentorder of its parent class. There are two places where the difference is

A. The model is different: Componentorder is a property structure that acts on our abstraction, in the tree structure of the two; Compileorder acts in a model that generates bytecode in a method, which can be thought of as a compilation sequence for each execution of an object in the execution queue. Sets the currently executed ordinal of the currently executing object in the Compileorder property.

B. Different functions: Componentorder is used to determine whether the variable can be reused, whether the variable is available in a scope, and compileorder to determine whether the current variable can be used by an operation, such as System.ou.println (Var), var is definitely created before calling the Println method, which means that the compileorder of Var is definitely smaller than the compileorder of println operation.

In addition to the properties, here are the methods for this class:

    • isshareable: This method passes the parameter var of a scopelogicvariable type, judging whether the current variable space can be passed to the parameter reuse, the concrete algorithm see "The reuse of local variable space" above
    • availablefor: Pass in a component to determine whether the current variable can be used in component, see "Determining which variables can be called in a program block" above
    • Issubof: Determines whether the current variable is a descendant of an incoming scope.
    • Store: The current variable is stored in an array of local variables.

The following store method is described here

    • Sets the number of local variables required by the current variable to C
    • to get C N . The
    • iterates through the array of local variables starting at 0, sets I as the number of traversal (starting from 0), and if a variable has not been traversed, set V (which we call Survivor Survivor) to enter 4 for the next object to traverse, otherwise enter 7.
    • If the space occupied by V can be reused by C , enter 5, otherwise enter 6
    • Delete V Positions the first position of the , and add I to the positions of C , and C Deposit to the I position of the local variable, so that n=n-1 , if N equals 0, jumps out of the loop, otherwise enters 3
    • if C and V are non-anonymous variables, the name of C and V are the same, if the same throw exception, otherwise enter 3
    • to this step, all the reusable variable space has been determined to complete, If n is still greater than 0, the n times C is placed at the end of the local variable, and the location of each deposit to the local variable array is added to the C in the positions . initstartpos equals positions for C in 8
    • The subscript is a value of 0.

Text description may be more jerky, the specific reference code Cn.wensiqun.asmsupport.utils.memory.ScopeLogicVariable.store (), with the above some of the columns of the operation and model can get the variable properties:

    • Name: variable Name
    • desc: Variable declaration type
    • Start : The starting position of the scope where the variable is located, corresponding to the start of the scope
    • End : The ending position of the scope where the variable is located, corresponding to the innerend of the scope
    • index: the variable is actually subscript in the local variable array, corresponding to the Initstartpos

Then call the methodvisitor.visitlocalvariable (name, desc, NULL, start, end, index) method, tell the compiler, in the start and end range, The space for the local variable position index is the DESC type and is called name. The third parameter of this method is the variable signature, which, if used with generics, but Asmsupport does not support generics, so this value is constant in Asmsupport.

Implementation of Asmsupport Local variables

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.