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