/*
* Javassist, a Java-bytecode translator toolkit.
* Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. Alternatively, the contents of this file may be used under
* the terms of the GNU Lesser General Public License Version 2.1 or later,
* or the Apache License Version 2.0.
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*/
package javassist.convert;
import javassist.
CtClass;
import javassist.
CtMethod;
import javassist.
NotFoundException;
import javassist.bytecode.
BadBytecode;
import javassist.bytecode.
Bytecode;
import javassist.bytecode.
CodeAttribute;
import javassist.bytecode.
CodeIterator;
import javassist.bytecode.
ConstPool;
import javassist.bytecode.
Descriptor;
public class
TransformBefore extends
TransformCall {
protected
CtClass[]
parameterTypes;
protected int
locals;
protected int
maxLocals;
protected byte[]
saveCode,
loadCode;
public
TransformBefore(
Transformer next,
CtMethod origMethod,
CtMethod beforeMethod)
throws
NotFoundException
{
super(
next,
origMethod,
beforeMethod);
// override
methodDescriptor =
origMethod.
getMethodInfo2().
getDescriptor();
parameterTypes =
origMethod.
getParameterTypes();
locals = 0;
maxLocals = 0;
saveCode =
loadCode = null;
}
@
Override
public void
initialize(
ConstPool cp,
CodeAttribute attr) {
super.initialize(
cp,
attr);
locals = 0;
maxLocals =
attr.
getMaxLocals();
saveCode =
loadCode = null;
}
@
Override
protected int
match(int
c, int
pos,
CodeIterator iterator,
int
typedesc,
ConstPool cp) throws
BadBytecode
{
if (
newIndex == 0) {
String desc =
Descriptor.
ofParameters(
parameterTypes) + 'V';
desc =
Descriptor.
insertParameter(
classname,
desc);
int
nt =
cp.
addNameAndTypeInfo(
newMethodname,
desc);
int
ci =
cp.
addClassInfo(
newClassname);
newIndex =
cp.
addMethodrefInfo(
ci,
nt);
constPool =
cp;
}
if (
saveCode == null)
makeCode(
parameterTypes,
cp);
return
match2(
pos,
iterator);
}
protected int
match2(int
pos,
CodeIterator iterator) throws
BadBytecode {
iterator.
move(
pos);
iterator.
insert(
saveCode);
iterator.
insert(
loadCode);
int
p =
iterator.
insertGap(3);
iterator.
writeByte(
INVOKESTATIC,
p);
iterator.
write16bit(
newIndex,
p + 1);
iterator.
insert(
loadCode);
return
iterator.
next();
}
@
Override
public int
extraLocals() { return
locals; }
protected void
makeCode(
CtClass[]
paramTypes,
ConstPool cp) {
Bytecode save = new
Bytecode(
cp, 0, 0);
Bytecode load = new
Bytecode(
cp, 0, 0);
int
var =
maxLocals;
int
len = (
paramTypes == null) ? 0 :
paramTypes.length;
load.
addAload(
var);
makeCode2(
save,
load, 0,
len,
paramTypes,
var + 1);
save.
addAstore(
var);
saveCode =
save.
get();
loadCode =
load.
get();
}
private void
makeCode2(
Bytecode save,
Bytecode load,
int
i, int
n,
CtClass[]
paramTypes, int
var)
{
if (
i <
n) {
int
size =
load.
addLoad(
var,
paramTypes[
i]);
makeCode2(
save,
load,
i + 1,
n,
paramTypes,
var +
size);
save.
addStore(
var,
paramTypes[
i]);
}
else
locals =
var -
maxLocals;
}
}