Re: Re: Re: Calculating Methods' Local Variable Sizes at Runtime

Nemo Caviani <[email protected]>
Newsgroups gmane.comp.java.objectweb.asm
Message-ID <[email protected]>
Hi Everyone,

please forget my previous email. I think I got it figured out! :-)

thanks for all the hints,
Nemo

On Sun, Apr 4, 2010 at 3:29 AM, Nemo Caviani <[email protected]> wrote:

> Eugene, Godmar, and Jorgen,
>
> Thank you very much for all your helps. All your helps where incredibly
> useful to me. Eugene, in particular the second part of your email about
> popping parameters from the local memory stack was exactly was I was
> wondering about. The first part on calculating the variable sizes I had
> already implemented but didn't quite know how to get the proper values for
> the variable.
>
> I need your last bit of advice to make sure that I am doing it the right
> way. so, here is the code that I have written so far. The
> PrefSignatureVisitor is a SignatureVisitor that returns the parsed list of
> method signatures and computes the size of primitive datatypes. The elements
> in the List returned by sigVisitor.getSigList() keep the type of input
> parameters to the method except for the last one that keeps the return type
> of the method. For the primitive data types, I only pop them up from the
> queue whereas for the non primitive data types I invoke the static method
> estimate to roughly measure their size. However, it throws exceptions when I
> execute it. Could you let me know about what I am doing wrong?
>
> sorry if the code is a bit messy. I am just trying to test it at the moment
> and I will really appreciate your help
>
> public void visitMethodInsn(int opcode, String owner, String name, String
> desc) {
>
>                 PrefSignatureVisitor sigVisitor =
> parseAndMeasureBandwidth(opcode, name, desc);
>
> if ((opcode == Opcodes.INVOKEVIRTUAL || opcode == Opcodes.INVOKEDYNAMIC ||
>                      opcode== Opcodes.INVOKEINTERFACE)){
>
> List<String> sigList = sigVisitor.getSigList();
> String[] sigNameArray = new String[sigList.size()];
>  int[] localVarIndxArray = new int[sigList.size()];
>
> for (int i = sigList.size() - 2; i >= 0; i--){
>
> String type = sigList.get(i);
> String varName = "tmp" + Integer.toString(i);
>  sigNameArray[i] = varName;
>
> if (type.length() == 1){
>
>  switch(type.charAt(0)){
> case 'Z':
> localVarIndxArray[i] = _lvs.newLocal(Type.BOOLEAN_TYPE);
>  this.visitVarInsn(Opcodes.ISTORE, localVarIndxArray[i]);
> break;
>  case 'C':
> localVarIndxArray[i] = _lvs.newLocal(Type.CHAR_TYPE);
>  this.visitVarInsn(Opcodes.ISTORE, localVarIndxArray[i]);
> break;
> case 'B':
>  localVarIndxArray[i] = _lvs.newLocal(Type.BYTE_TYPE);
> this.visitVarInsn(Opcodes.ISTORE, localVarIndxArray[i]);
>  break;
> case 'S':
> localVarIndxArray[i] = _lvs.newLocal(Type.SHORT_TYPE);
>  this.visitVarInsn(Opcodes.ISTORE, localVarIndxArray[i]);
> break;
>  case 'I':
> localVarIndxArray[i] = _lvs.newLocal(Type.INT_TYPE);
>  this.visitVarInsn(Opcodes.ISTORE, localVarIndxArray[i]);
> break;
> case 'F':
>  localVarIndxArray[i] = _lvs.newLocal(Type.FLOAT_TYPE);
> this.visitVarInsn(Opcodes.FSTORE, localVarIndxArray[i]);
>  break;
> case 'J':
> localVarIndxArray[i] = _lvs.newLocal(Type.LONG_TYPE);
>  this.visitVarInsn(Opcodes.LSTORE, localVarIndxArray[i]);
> break;
>  case 'D':
> localVarIndxArray[i] = _lvs.newLocal(Type.DOUBLE_TYPE);
>  this.visitVarInsn(Opcodes.DSTORE, localVarIndxArray[i]);
> break;
> }
>
> }else{
> localVarIndxArray[i] = _lvs.newLocal(Type.getObjectType(sigList.get(i)));
>  this.visitVarInsn(Opcodes.ASTORE, localVarIndxArray[i]);
> this.visitVarInsn(Opcodes.ALOAD, localVarIndxArray[i]);
>  this.visitMethodInsn(Opcodes.INVOKESTATIC,
> "ca/ubc/magic/memory/MemoryCounter", "estimate", "(Ljava/lang/Object;)J");
>  }
> }
>                         for (int i = 0; i < sigList.size() - 1; i++){
>  String type = sigList.get(i);
> if (type.length() == 1){
> switch(type.charAt(0)){
>  case 'Z':
> case 'C':
> case 'B':
>  case 'S':
> case 'I':
> this.visitVarInsn(Opcodes.ILOAD, localVarIndxArray[i]);
>  break;
> case 'F':
> this.visitVarInsn(Opcodes.FLOAD, localVarIndxArray[i]);
>  break;
> case 'J':
> this.visitVarInsn(Opcodes.LLOAD, localVarIndxArray[i]);
>  break;
> case 'D':
> this.visitVarInsn(Opcodes.DLOAD, localVarIndxArray[i]);
>  break;
> }
> } else
>  this.visitVarInsn(Opcodes.ALOAD, localVarIndxArray[i]);
> }
> }
>
> On Mon, Mar 29, 2010 at 5:00 PM, Eugene Kuleshov <[email protected]>wrote:
>
>> Nemo Caviani wrote:
>>
>>> yes, using visitLocalVariable I am able to identify the set of parameters
>>> passed to a method.
>>>
>>  You don't need visitLocalVariable() at all
>>
>>  What I can't figure out is how to get the actual values for these
>>> parameters off the stack to calculate their real sizes. I can figure out
>>> their names and their types from the method signature, and for the primitive
>>> types a lookup table can give me the size of their memory usage. What I
>>> don't know, is how to get the actual size of non-primitive parameters. If
>>> the nonprimitive type contains an array or a list, the length of the array
>>> or the list also size becomes a critical factor in figuring out the amount
>>> of space it uses.
>>>
>>  You should really do your home work and at least search on Google. But
>> here is the reference for you, it is a bit outdated and as  Godmar said it
>> is expensive to do it that way, but it is a start.
>> http://www.javaspecialists.eu/archive/Issue078.html
>>
>>  so if you or anyone in the list can give me a clue on how to access the
>>> actual value of a parameter from the local stack and calculate its size,
>>> that would be a great help to me indeed.
>>>
>>  You will kinda have to learn some Java bytecode for that.
>>  A naive, brute force method could be like the following:
>>
>>  Look at invokevirtual opcode. Documentation is here
>> http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc6.html#invokevirtual.Operation
>>
>>  At the visitMethodInsn(), the top of the stack will be like the
>> following:
>>  ... , objectref, arg1, arg2, ... , argN
>>  so argN is at the top of the stack (1 or 2 words depending on its type),
>> which you can get from the desc parameter of visitMethod(); then 2nd
>> parameter and so on, the last would be the object reference the method is
>> called on.
>>  So, you've got the stack figured out, now for each method parameter you
>> can create a new variable (for example, using LocalVariablesSorter or one of
>> its subclasses described in the ASM User guide book) and store value off the
>> stack into that variable using *store opcode corresponding to parameter
>> type.
>>  After that for each non-primitive parameter you can load value from the
>> variables you created and call your static helper method to figure out
>> sizes.
>>  Once you done with that, all you'll have to do is to load values from
>> those variables back into the stack, so invokevirtual instruction will get
>> the same stack as before your transformation.
>>
>>  There is some difference in handling invokevirtual, invokespecial,
>> invokestatic and invokeinterface instructions.
>>
>>  Obviously the above solution is suboptimal and can be heavily optimized,
>> e.g. to not create unnecessary variables in trivial cases with 1 to 4 method
>> parameters and for primitive parameters, e.g. using stack manipulation
>> bytecode instructions, but I will leave this exercise for you.
>>
>>  regards,
>>  Eugene
>>
>>
>>
>>
>> --
>> You receive this message as a subscriber of the [email protected] mailing list.
>> To unsubscribe: mailto:[email protected]
>> For general help: mailto:[email protected]?subject=help
>> OW2 mailing lists service home page: http://www.ow2.org/wws
>>
>>
>
message-footer.txt (text/plain, 238 B)
-- 
You receive this message as a subscriber of the [email protected] mailing list.
To unsubscribe: mailto:[email protected]
For general help: mailto:[email protected]?subject=help
OW2 mailing lists service home page: http://www.ow2.org/wws
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.