use of org.mvel2.optimizers.impl.refl.nodes.ArrayLength in project mvel by mikebrock.
the class ASMAccessorOptimizer method writeFunctionPointerStub.
private void writeFunctionPointerStub(Class c, Method m) {
ldcClassConstant(c);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getMethods", "()[Ljava/lang/reflect/Method;");
mv.visitVarInsn(ASTORE, 7);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ISTORE, 5);
mv.visitVarInsn(ALOAD, 7);
mv.visitInsn(ARRAYLENGTH);
mv.visitVarInsn(ISTORE, 6);
Label l1 = new Label();
mv.visitJumpInsn(GOTO, l1);
Label l2 = new Label();
mv.visitLabel(l2);
mv.visitVarInsn(ALOAD, 7);
mv.visitVarInsn(ILOAD, 5);
mv.visitInsn(AALOAD);
mv.visitVarInsn(ASTORE, 4);
Label l3 = new Label();
mv.visitLabel(l3);
mv.visitLdcInsn(m.getName());
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/reflect/Method", "getName", "()Ljava/lang/String;");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
Label l4 = new Label();
mv.visitJumpInsn(IFEQ, l4);
Label l5 = new Label();
mv.visitLabel(l5);
mv.visitVarInsn(ALOAD, 4);
mv.visitInsn(ARETURN);
mv.visitLabel(l4);
mv.visitIincInsn(5, 1);
mv.visitLabel(l1);
mv.visitVarInsn(ILOAD, 5);
mv.visitVarInsn(ILOAD, 6);
mv.visitJumpInsn(IF_ICMPLT, l2);
Label l6 = new Label();
mv.visitLabel(l6);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
// deferFinish = true;
}
use of org.mvel2.optimizers.impl.refl.nodes.ArrayLength in project mvel by mvel.
the class ASMAccessorOptimizer method getBeanProperty.
private Object getBeanProperty(Object ctx, String property) throws IllegalAccessException, InvocationTargetException {
assert debug("\n ** ENTER -> {bean: " + property + "; ctx=" + ctx + "}");
if ((pCtx == null ? currType : pCtx.getVarOrInputTypeOrNull(property)) == Object.class && !pCtx.isStrongTyping()) {
currType = null;
}
if (returnType != null && returnType.isPrimitive()) {
// noinspection unchecked
wrapPrimitive(returnType);
}
boolean classRef = false;
Class<?> cls;
if (ctx instanceof Class) {
if (MVEL.COMPILER_OPT_SUPPORT_JAVA_STYLE_CLASS_LITERALS && "class".equals(property)) {
ldcClassConstant((Class<?>) ctx);
return ctx;
}
cls = (Class<?>) ctx;
classRef = true;
} else if (ctx != null) {
cls = ctx.getClass();
} else {
cls = null;
}
if (hasPropertyHandler(cls)) {
PropertyHandler prop = getPropertyHandler(cls);
if (prop instanceof ProducesBytecode) {
((ProducesBytecode) prop).produceBytecodeGet(mv, property, variableFactory);
return prop.getProperty(property, ctx, variableFactory);
} else {
throw new RuntimeException("unable to compileShared: custom accessor does not support producing bytecode: " + prop.getClass().getName());
}
}
Member member = cls != null ? getFieldOrAccessor(cls, property) : null;
if (member != null && classRef && (member.getModifiers() & Modifier.STATIC) == 0) {
member = null;
}
if (member != null && hasGetListeners()) {
mv.visitVarInsn(ALOAD, 1);
mv.visitLdcInsn(member.getName());
mv.visitVarInsn(ALOAD, 3);
mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "integration/GlobalListenerFactory", "notifyGetListeners", "(Ljava/lang/Object;Ljava/lang/String;L" + NAMESPACE + "integration/VariableResolverFactory;)V");
notifyGetListeners(ctx, member.getName(), variableFactory);
}
if (first) {
if ("this".equals(property)) {
assert debug("ALOAD 2");
mv.visitVarInsn(ALOAD, 2);
return thisRef;
} else if (variableFactory != null && variableFactory.isResolveable(property)) {
if (variableFactory.isIndexedFactory() && variableFactory.isTarget(property)) {
int idx;
try {
loadVariableByIndex(idx = variableFactory.variableIndexOf(property));
} catch (Exception e) {
throw new OptimizationFailure(property);
}
return variableFactory.getIndexedVariableResolver(idx).getValue();
} else {
try {
loadVariableByName(property);
} catch (Exception e) {
throw new OptimizationFailure("critical error in JIT", e);
}
return variableFactory.getVariableResolver(property).getValue();
}
} else {
assert debug("ALOAD 1");
mv.visitVarInsn(ALOAD, 1);
}
}
if (member instanceof Field) {
return optimizeFieldMethodProperty(ctx, property, cls, member);
} else if (member != null) {
Object o;
if (first) {
assert debug("ALOAD 1 (B)");
mv.visitVarInsn(ALOAD, 1);
}
try {
o = ((Method) member).invoke(ctx, EMPTYARG);
if (returnType != member.getDeclaringClass()) {
assert debug("CHECKCAST " + getInternalName(member.getDeclaringClass()));
mv.visitTypeInsn(CHECKCAST, getInternalName(member.getDeclaringClass()));
}
returnType = ((Method) member).getReturnType();
if (member.getDeclaringClass().isInterface()) {
assert debug("INVOKEINTERFACE " + member.getName() + ":" + returnType);
mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(member.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
} else {
assert debug("INVOKEVIRTUAL " + member.getName() + ":" + returnType);
mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(member.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
}
} catch (IllegalAccessException e) {
Method iFaceMeth = determineActualTargetMethod((Method) member);
if (iFaceMeth == null)
throw new PropertyAccessException("could not access field: " + cls.getName() + "." + property, expr, st, e, pCtx);
assert debug("CHECKCAST " + getInternalName(iFaceMeth.getDeclaringClass()));
mv.visitTypeInsn(CHECKCAST, getInternalName(iFaceMeth.getDeclaringClass()));
returnType = iFaceMeth.getReturnType();
assert debug("INVOKEINTERFACE " + member.getName() + ":" + returnType);
mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(iFaceMeth.getDeclaringClass()), member.getName(), getMethodDescriptor((Method) member));
o = iFaceMeth.invoke(ctx, EMPTYARG);
} catch (IllegalArgumentException e) {
if (member.getDeclaringClass().equals(ctx)) {
try {
Class c = Class.forName(member.getDeclaringClass().getName() + "$" + property);
throw new CompileException("name collision between innerclass: " + c.getCanonicalName() + "; and bean accessor: " + property + " (" + member.toString() + ")", expr, tkStart);
} catch (ClassNotFoundException e2) {
// fallthru
}
}
throw e;
}
if (hasNullPropertyHandler()) {
if (o == null)
o = getNullPropertyHandler().getProperty(member.getName(), ctx, variableFactory);
writeOutNullHandler(member, 0);
}
currType = toNonPrimitiveType(returnType);
return o;
} else if (ctx instanceof Map && (((Map) ctx).containsKey(property) || nullSafe)) {
assert debug("CHECKCAST java/util/Map");
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
assert debug("LDC: \"" + property + "\"");
mv.visitLdcInsn(property);
assert debug("INVOKEINTERFACE: get");
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
return ((Map) ctx).get(property);
} else if (first && "this".equals(property)) {
assert debug("ALOAD 2");
// load the thisRef value.
mv.visitVarInsn(ALOAD, 2);
return this.thisRef;
} else if ("length".equals(property) && ctx.getClass().isArray()) {
anyArrayCheck(ctx.getClass());
assert debug("ARRAYLENGTH");
mv.visitInsn(ARRAYLENGTH);
wrapPrimitive(int.class);
return getLength(ctx);
} else if (LITERALS.containsKey(property)) {
Object lit = LITERALS.get(property);
if (lit instanceof Class) {
ldcClassConstant((Class) lit);
}
return lit;
} else {
Object ts = tryStaticAccess();
if (ts != null) {
if (ts instanceof Class) {
ldcClassConstant((Class) ts);
return ts;
} else if (ts instanceof Method) {
writeFunctionPointerStub(((Method) ts).getDeclaringClass(), (Method) ts);
return ts;
} else {
Field f = (Field) ts;
return optimizeFieldMethodProperty(ctx, property, cls, f);
}
} else if (ctx instanceof Class) {
/**
* This is our ugly support for function pointers. This works but needs to be re-thought out at some
* point.
*/
Class c = (Class) ctx;
for (Method m : c.getMethods()) {
if (property.equals(m.getName())) {
if (pCtx != null && pCtx.getParserConfiguration() != null ? pCtx.getParserConfiguration().isAllowNakedMethCall() : MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
assert debug("POP");
mv.visitInsn(POP);
assert debug("INVOKESTATIC " + m.getName());
mv.visitMethodInsn(INVOKESTATIC, getInternalName(m.getDeclaringClass()), m.getName(), getMethodDescriptor(m));
returnType = m.getReturnType();
return m.invoke(null, EMPTY_OBJ_ARR);
} else {
writeFunctionPointerStub(c, m);
return m;
}
}
}
try {
Class subClass = findClass(variableFactory, c.getName() + "$" + property, pCtx);
ldcClassConstant(subClass);
return subClass;
} catch (ClassNotFoundException cnfe) {
// fall through.
}
} else if (pCtx != null && pCtx.getParserConfiguration() != null ? pCtx.getParserConfiguration().isAllowNakedMethCall() : MVEL.COMPILER_OPT_ALLOW_NAKED_METH_CALL) {
return getMethod(ctx, property);
}
if (ctx == null) {
throw new PropertyAccessException("unresolvable property or identifier: " + property, expr, st, pCtx);
} else {
throw new PropertyAccessException("could not access: " + property + "; in class: " + ctx.getClass().getName(), expr, st, pCtx);
}
}
}
use of org.mvel2.optimizers.impl.refl.nodes.ArrayLength in project mvel by mvel.
the class ASMAccessorOptimizer method getMethod.
@SuppressWarnings({ "unchecked" })
private Object getMethod(Object ctx, String name) throws IllegalAccessException, InvocationTargetException {
assert debug("\n ** {method: " + name + "}");
int st = cursor;
String tk = cursor != end && expr[cursor] == '(' && ((cursor = balancedCapture(expr, cursor, '(')) - st) > 1 ? new String(expr, st + 1, cursor - st - 1) : "";
cursor++;
Object[] preConvArgs;
Object[] args;
Class[] argTypes;
ExecutableStatement[] es;
List<char[]> subtokens;
if (tk.length() == 0) {
args = preConvArgs = ParseTools.EMPTY_OBJ_ARR;
argTypes = ParseTools.EMPTY_CLS_ARR;
es = null;
subtokens = null;
} else {
subtokens = parseParameterList(tk.toCharArray(), 0, -1);
es = new ExecutableStatement[subtokens.size()];
args = new Object[subtokens.size()];
argTypes = new Class[subtokens.size()];
preConvArgs = new Object[es.length];
for (int i = 0; i < subtokens.size(); i++) {
assert debug("subtoken[" + i + "] { " + new String(subtokens.get(i)) + " }");
preConvArgs[i] = args[i] = (es[i] = (ExecutableStatement) subCompileExpression(subtokens.get(i), pCtx)).getValue(this.thisRef, this.thisRef, variableFactory);
if (es[i].isExplicitCast())
argTypes[i] = es[i].getKnownEgressType();
}
if (pCtx.isStrictTypeEnforcement()) {
for (int i = 0; i < args.length; i++) {
argTypes[i] = es[i].getKnownEgressType();
if (es[i] instanceof ExecutableLiteral && ((ExecutableLiteral) es[i]).getLiteral() == null) {
argTypes[i] = NullType.class;
}
}
} else {
for (int i = 0; i < args.length; i++) {
if (argTypes[i] != null)
continue;
if (es[i].getKnownEgressType() == Object.class) {
argTypes[i] = args[i] == null ? null : args[i].getClass();
} else {
argTypes[i] = es[i].getKnownEgressType();
}
}
}
}
if (first && variableFactory != null && variableFactory.isResolveable(name)) {
Object ptr = variableFactory.getVariableResolver(name).getValue();
if (ptr instanceof Method) {
ctx = ((Method) ptr).getDeclaringClass();
name = ((Method) ptr).getName();
} else if (ptr instanceof MethodStub) {
ctx = ((MethodStub) ptr).getClassReference();
name = ((MethodStub) ptr).getMethodName();
} else if (ptr instanceof FunctionInstance) {
if (es != null && es.length != 0) {
compiledInputs.addAll(Arrays.asList(es));
intPush(es.length);
assert debug("ANEWARRAY [" + es.length + "]");
mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
assert debug("ASTORE 4");
mv.visitVarInsn(ASTORE, 4);
for (int i = 0; i < es.length; i++) {
assert debug("ALOAD 4");
mv.visitVarInsn(ALOAD, 4);
intPush(i);
loadField(i);
assert debug("ALOAD 1");
mv.visitVarInsn(ALOAD, 1);
assert debug("ALOAD 3");
mv.visitIntInsn(ALOAD, 3);
assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
mv.visitMethodInsn(INVOKEINTERFACE, NAMESPACE + "compiler/ExecutableStatement", "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
assert debug("AASTORE");
mv.visitInsn(AASTORE);
}
} else {
assert debug("ACONST_NULL");
mv.visitInsn(ACONST_NULL);
assert debug("CHECKCAST java/lang/Object");
mv.visitTypeInsn(CHECKCAST, "[Ljava/lang/Object;");
assert debug("ASTORE 4");
mv.visitVarInsn(ASTORE, 4);
}
if (variableFactory.isIndexedFactory() && variableFactory.isTarget(name)) {
loadVariableByIndex(variableFactory.variableIndexOf(name));
} else {
loadVariableByName(name);
}
checkcast(FunctionInstance.class);
assert debug("ALOAD 1");
mv.visitVarInsn(ALOAD, 1);
assert debug("ALOAD 2");
mv.visitVarInsn(ALOAD, 2);
assert debug("ALOAD 3");
mv.visitVarInsn(ALOAD, 3);
assert debug("ALOAD 4");
mv.visitVarInsn(ALOAD, 4);
assert debug("INVOKEVIRTUAL Function.call");
mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(FunctionInstance.class), "call", "(Ljava/lang/Object;Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;[Ljava/lang/Object;)Ljava/lang/Object;");
return ((FunctionInstance) ptr).call(ctx, thisRef, variableFactory, args);
} else {
throw new OptimizationFailure("attempt to optimize a method call for a reference that does not point to a method: " + name + " (reference is type: " + (ctx != null ? ctx.getClass().getName() : null) + ")");
}
first = false;
} else if (returnType != null && returnType.isPrimitive()) {
// noinspection unchecked
wrapPrimitive(returnType);
}
/**
* If the target object is an instance of java.lang.Class itself then do not
* adjust the Class scope target.
*/
boolean classTarget = false;
Class<?> cls = currType != null ? currType : ((classTarget = ctx instanceof Class) ? (Class<?>) ctx : ctx.getClass());
currType = null;
Method m;
Class[] parameterTypes = null;
/**
* Try to find an instance method from the class target.
*/
if ((m = getBestCandidate(argTypes, name, cls, cls.getMethods(), false, classTarget)) != null) {
parameterTypes = m.getParameterTypes();
}
if (m == null && classTarget) {
/**
* If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
*/
if ((m = getBestCandidate(argTypes, name, cls, Class.class.getMethods(), false)) != null) {
parameterTypes = m.getParameterTypes();
}
}
// If we didn't find anything and the declared class is different from the actual one try also with the actual one
if (m == null && cls != ctx.getClass() && !(ctx instanceof Class)) {
cls = ctx.getClass();
if ((m = getBestCandidate(argTypes, name, cls, cls.getMethods(), false, classTarget)) != null) {
parameterTypes = m.getParameterTypes();
}
}
if (es != null && m != null && m.isVarArgs() && (es.length != parameterTypes.length || !(es[es.length - 1] instanceof ExecutableAccessor))) {
// normalize ExecutableStatement for varargs
ExecutableStatement[] varArgEs = new ExecutableStatement[parameterTypes.length];
int varArgStart = parameterTypes.length - 1;
for (int i = 0; i < varArgStart; i++) varArgEs[i] = es[i];
String varargsTypeName = parameterTypes[parameterTypes.length - 1].getComponentType().getName();
String varArgExpr;
if ("null".equals(tk)) {
// if null is the token no need for wrapping
varArgExpr = tk;
} else {
StringBuilder sb = new StringBuilder("new ").append(varargsTypeName).append("[] {");
for (int i = varArgStart; i < subtokens.size(); i++) {
sb.append(subtokens.get(i));
if (i < subtokens.size() - 1)
sb.append(",");
}
varArgExpr = sb.append("}").toString();
}
char[] token = varArgExpr.toCharArray();
varArgEs[varArgStart] = ((ExecutableStatement) subCompileExpression(token, pCtx));
es = varArgEs;
if (preConvArgs.length == parameterTypes.length - 1) {
// empty vararg
Object[] preConvArgsForVarArg = new Object[parameterTypes.length];
for (int i = 0; i < preConvArgs.length; i++) preConvArgsForVarArg[i] = preConvArgs[i];
preConvArgsForVarArg[parameterTypes.length - 1] = Array.newInstance(parameterTypes[parameterTypes.length - 1].getComponentType(), 0);
preConvArgs = preConvArgsForVarArg;
}
}
int inputsOffset = compiledInputs.size();
if (es != null) {
for (ExecutableStatement e : es) {
if (e instanceof ExecutableLiteral) {
continue;
}
compiledInputs.add(e);
}
}
if (first) {
assert debug("ALOAD 1 (D) ");
mv.visitVarInsn(ALOAD, 1);
}
if (m == null) {
StringAppender errorBuild = new StringAppender();
if (parameterTypes != null) {
for (int i = 0; i < args.length; i++) {
errorBuild.append(parameterTypes[i] != null ? parameterTypes[i].getClass().getName() : null);
if (i < args.length - 1)
errorBuild.append(", ");
}
}
if ("size".equals(name) && args.length == 0 && cls.isArray()) {
anyArrayCheck(cls);
assert debug("ARRAYLENGTH");
mv.visitInsn(ARRAYLENGTH);
wrapPrimitive(int.class);
return getLength(ctx);
}
throw new CompileException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]", expr, st);
} else {
m = getWidenedTarget(m);
if (es != null) {
ExecutableStatement cExpr;
for (int i = 0; i < es.length; i++) {
if ((cExpr = es[i]).getKnownIngressType() == null) {
cExpr.setKnownIngressType(parameterTypes[i]);
cExpr.computeTypeConversionRule();
}
if (!cExpr.isConvertableIngressEgress() && i < args.length) {
args[i] = convert(args[i], paramTypeVarArgsSafe(parameterTypes, i, m.isVarArgs()));
}
}
} else {
/**
* Coerce any types if required.
*/
for (int i = 0; i < args.length; i++) {
args[i] = convert(args[i], paramTypeVarArgsSafe(parameterTypes, i, m.isVarArgs()));
}
}
Class<?> declaringClass = m.getDeclaringClass();
if (m.getParameterTypes().length == 0) {
if ((m.getModifiers() & STATIC) != 0) {
assert debug("INVOKESTATIC " + m.getName());
mv.visitMethodInsn(INVOKESTATIC, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
} else {
assert debug("CHECKCAST " + getInternalName(declaringClass));
mv.visitTypeInsn(CHECKCAST, getInternalName(declaringClass));
if (declaringClass.isInterface()) {
assert debug("INVOKEINTERFACE " + m.getName());
mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
} else {
assert debug("INVOKEVIRTUAL " + m.getName());
mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
}
}
returnType = m.getReturnType();
stacksize++;
} else {
if ((m.getModifiers() & STATIC) == 0) {
assert debug("CHECKCAST " + getInternalName(declaringClass));
mv.visitTypeInsn(CHECKCAST, getInternalName(declaringClass));
}
for (int i = 0; es != null && i < es.length; i++) {
if (es[i] instanceof ExecutableLiteral) {
ExecutableLiteral literal = (ExecutableLiteral) es[i];
if (literal.getLiteral() == null) {
assert debug("ICONST_NULL");
mv.visitInsn(ACONST_NULL);
continue;
} else if (parameterTypes[i] == int.class && literal.intOptimized()) {
intPush(literal.getInteger32());
continue;
} else if (parameterTypes[i] == int.class && preConvArgs[i] instanceof Integer) {
intPush((Integer) preConvArgs[i]);
continue;
} else if (parameterTypes[i] == boolean.class) {
boolean bool = DataConversion.convert(literal.getLiteral(), Boolean.class);
assert debug(bool ? "ICONST_1" : "ICONST_0");
mv.visitInsn(bool ? ICONST_1 : ICONST_0);
continue;
} else {
Object lit = literal.getLiteral();
if (parameterTypes[i] == Object.class) {
if (isPrimitiveWrapper(lit.getClass())) {
if (lit.getClass() == Integer.class) {
intPush((Integer) lit);
} else {
assert debug("LDC " + lit);
mv.visitLdcInsn(lit);
}
wrapPrimitive(lit.getClass());
} else if (lit instanceof String) {
mv.visitLdcInsn(lit);
checkcast(Object.class);
}
continue;
} else if (canConvert(parameterTypes[i], lit.getClass())) {
Object c = convert(lit, parameterTypes[i]);
if (c instanceof Class) {
ldcClassConstant((Class) c);
} else {
assert debug("LDC " + lit + " (" + lit.getClass().getName() + ")");
mv.visitLdcInsn(c);
if (isPrimitiveWrapper(parameterTypes[i])) {
wrapPrimitive(lit.getClass());
}
}
continue;
} else {
throw new OptimizationNotSupported();
}
}
}
assert debug("ALOAD 0");
mv.visitVarInsn(ALOAD, 0);
assert debug("GETFIELD p" + inputsOffset);
mv.visitFieldInsn(GETFIELD, className, "p" + inputsOffset, "L" + NAMESPACE + "compiler/ExecutableStatement;");
inputsOffset++;
assert debug("ALOAD 2");
mv.visitVarInsn(ALOAD, 2);
assert debug("ALOAD 3");
mv.visitVarInsn(ALOAD, 3);
assert debug("INVOKEINTERFACE ExecutableStatement.getValue");
mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(ExecutableStatement.class), "getValue", "(Ljava/lang/Object;L" + NAMESPACE + "integration/VariableResolverFactory;)Ljava/lang/Object;");
if (parameterTypes[i].isPrimitive()) {
if (preConvArgs[i] == null || (parameterTypes[i] != String.class && !parameterTypes[i].isAssignableFrom(preConvArgs[i].getClass()))) {
ldcClassConstant(getWrapperClass(parameterTypes[i]));
assert debug("INVOKESTATIC DataConversion.convert");
mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
}
unwrapPrimitive(parameterTypes[i]);
} else if (preConvArgs[i] == null || (parameterTypes[i] != String.class && !parameterTypes[i].isAssignableFrom(preConvArgs[i].getClass()))) {
ldcClassConstant(parameterTypes[i]);
assert debug("INVOKESTATIC DataConversion.convert");
mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "DataConversion", "convert", "(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;");
assert debug("CHECKCAST " + getInternalName(parameterTypes[i]));
mv.visitTypeInsn(CHECKCAST, getInternalName(parameterTypes[i]));
} else if (parameterTypes[i] == String.class) {
assert debug("<<<DYNAMIC TYPE OPTIMIZATION STRING>>");
mv.visitVarInsn(ASTORE, 4);
Label jmp = new Label();
mv.visitVarInsn(ALOAD, 4);
mv.visitJumpInsn(IFNONNULL, jmp);
mv.visitInsn(ACONST_NULL);
Label jmp2 = new Label();
mv.visitJumpInsn(GOTO, jmp2);
mv.visitLabel(jmp);
mv.visitVarInsn(ALOAD, 4);
mv.visitMethodInsn(INVOKESTATIC, "java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;");
mv.visitLabel(jmp2);
} else {
assert debug("<<<DYNAMIC TYPING BYPASS>>>");
assert debug("<<<OPT. JUSTIFICATION " + parameterTypes[i] + "=" + preConvArgs[i].getClass() + ">>>");
assert debug("CHECKCAST " + getInternalName(parameterTypes[i]));
mv.visitTypeInsn(CHECKCAST, getInternalName(parameterTypes[i]));
}
}
if (m.isVarArgs() && (es == null || es.length == (parameterTypes.length - 1))) {
// The last parameter is a vararg and there is no value, create an empty array array
createArray(getBaseComponentType(parameterTypes[parameterTypes.length - 1]), 0);
}
if ((m.getModifiers() & STATIC) != 0) {
assert debug("INVOKESTATIC: " + m.getName());
mv.visitMethodInsn(INVOKESTATIC, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
} else {
if (declaringClass.isInterface()) {
assert debug("INVOKEINTERFACE: " + getInternalName(declaringClass) + "." + m.getName());
mv.visitMethodInsn(INVOKEINTERFACE, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
} else {
assert debug("INVOKEVIRTUAL: " + getInternalName(declaringClass) + "." + m.getName());
mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(declaringClass), m.getName(), getMethodDescriptor(m));
}
}
returnType = m.getReturnType();
stacksize++;
}
Object o = m.invoke(ctx, normalizeArgsForVarArgs(parameterTypes, args, m.isVarArgs()));
if (hasNullMethodHandler()) {
writeOutNullHandler(m, 1);
if (o == null)
o = getNullMethodHandler().getProperty(m.getName(), ctx, variableFactory);
}
currType = toNonPrimitiveType(m.getReturnType());
return o;
}
}
use of org.mvel2.optimizers.impl.refl.nodes.ArrayLength in project drools by kiegroup.
the class ConditionAnalyzer method analyzeAccessorInvocation.
private Invocation analyzeAccessorInvocation(AccessorNode accessorNode, ASTNode containingNode, Invocation formerInvocation, Class<?> variableType) {
if (accessorNode instanceof GetterAccessor) {
return new MethodInvocation(((GetterAccessor) accessorNode).getMethod(), variableType == null ? conditionClass : variableType.getName());
}
if (accessorNode instanceof MethodAccessor) {
MethodAccessor methodAccessor = (MethodAccessor) accessorNode;
Method method = methodAccessor.getMethod();
MethodInvocation invocation = new MethodInvocation(method);
boolean isVarArgs = method.isVarArgs();
readInvocationParams(invocation, methodAccessor.getParms(), methodAccessor.getParameterTypes(), isVarArgs);
return invocation;
}
if (accessorNode instanceof ConstructorAccessor) {
ConstructorAccessor constructorAccessor = (ConstructorAccessor) accessorNode;
Constructor constructor = constructorAccessor.getConstructor();
ConstructorInvocation invocation = new ConstructorInvocation(constructor);
readInvocationParams(invocation, constructorAccessor.getParameters(), constructorAccessor.getParameterTypes(), constructor.isVarArgs());
return invocation;
}
if (accessorNode instanceof ArrayAccessor) {
ArrayAccessor arrayAccessor = (ArrayAccessor) accessorNode;
return new ArrayAccessInvocation(formerInvocation != null ? formerInvocation.getReturnType() : Object[].class, new FixedExpression(int.class, arrayAccessor.getIndex()));
}
if (accessorNode instanceof ArrayAccessorNest) {
ArrayAccessorNest arrayAccessorNest = (ArrayAccessorNest) accessorNode;
ExecutableAccessor index = (ExecutableAccessor) arrayAccessorNest.getIndex();
return new ArrayAccessInvocation(formerInvocation != null ? formerInvocation.getReturnType() : Object[].class, analyzeNode(index.getNode()));
}
if (accessorNode instanceof ArrayLength) {
return new ArrayLengthInvocation();
}
if (accessorNode instanceof ListAccessor) {
Class<?> listType = getListType(formerInvocation);
ListAccessor listAccessor = (ListAccessor) accessorNode;
return new ListAccessInvocation(listType, new FixedExpression(int.class, listAccessor.getIndex()));
}
if (accessorNode instanceof ListAccessorNest) {
Class<?> listType = getListType(formerInvocation);
ListAccessorNest listAccessorNest = (ListAccessorNest) accessorNode;
ExecutableAccessor index = (ExecutableAccessor) listAccessorNest.getIndex();
return new ListAccessInvocation(listType, analyzeNode(index.getNode()));
}
if (accessorNode instanceof MapAccessor) {
MapAccessor mapAccessor = (MapAccessor) accessorNode;
return new MapAccessInvocation(Object.class, Object.class, new FixedExpression(Object.class, mapAccessor.getProperty()));
}
if (accessorNode instanceof MapAccessorNest) {
Class<?> keyType = Object.class;
Class<?> valueType = Object.class;
Type[] generics = getGenerics(formerInvocation);
if (generics != null && generics.length == 2 && generics[0] instanceof Class) {
keyType = (Class<?>) generics[0];
if (generics[1] instanceof Class)
valueType = (Class<?>) generics[1];
}
MapAccessorNest mapAccessor = (MapAccessorNest) accessorNode;
ExecutableStatement statement = mapAccessor.getProperty();
if (statement instanceof ExecutableLiteral) {
return new MapAccessInvocation(keyType, valueType, new FixedExpression(keyType, ((ExecutableLiteral) statement).getLiteral()));
} else {
return new MapAccessInvocation(keyType, valueType, analyzeNode(((ExecutableAccessor) statement).getNode()));
}
}
if (accessorNode instanceof FieldAccessor) {
return new FieldAccessInvocation(((FieldAccessor) accessorNode).getField());
}
if (accessorNode instanceof StaticVarAccessor) {
Field field = ((StaticVarAccessor) accessorNode).getField();
return new FieldAccessInvocation(field);
}
if (accessorNode instanceof ThisValueAccessor) {
return new ThisInvocation(accessorNode.getNextNode() == null ? containingNode.getEgressType() : Object.class);
}
throw new RuntimeException("Unknown AccessorNode type: " + accessorNode.getClass().getName());
}
use of org.mvel2.optimizers.impl.refl.nodes.ArrayLength in project mvel by mikebrock.
the class ReflectiveAccessorOptimizer method getMethod.
/**
* Find an appropriate method, execute it, and return it's response.
*
* @param ctx -
* @param name -
* @return -
* @throws Exception -
*/
@SuppressWarnings({ "unchecked" })
private Object getMethod(Object ctx, String name) throws Exception {
int st = cursor;
String tk = cursor != end && expr[cursor] == '(' && ((cursor = balancedCapture(expr, cursor, '(')) - st) > 1 ? new String(expr, st + 1, cursor - st - 1) : "";
cursor++;
Object[] args;
Class[] argTypes;
ExecutableStatement[] es;
if (tk.length() == 0) {
args = ParseTools.EMPTY_OBJ_ARR;
argTypes = ParseTools.EMPTY_CLS_ARR;
es = null;
} else {
List<char[]> subtokens = parseParameterList(tk.toCharArray(), 0, -1);
es = new ExecutableStatement[subtokens.size()];
args = new Object[subtokens.size()];
argTypes = new Class[subtokens.size()];
for (int i = 0; i < subtokens.size(); i++) {
try {
args[i] = (es[i] = (ExecutableStatement) subCompileExpression(subtokens.get(i), pCtx)).getValue(this.thisRef, thisRef, variableFactory);
} catch (CompileException e) {
throw ErrorUtil.rewriteIfNeeded(e, this.expr, this.start);
}
if (es[i].isExplicitCast())
argTypes[i] = es[i].getKnownEgressType();
}
if (pCtx.isStrictTypeEnforcement()) {
for (int i = 0; i < args.length; i++) {
argTypes[i] = es[i].getKnownEgressType();
}
} else {
for (int i = 0; i < args.length; i++) {
if (argTypes[i] != null)
continue;
if (es[i].getKnownEgressType() == Object.class) {
argTypes[i] = args[i] == null ? null : args[i].getClass();
} else {
argTypes[i] = es[i].getKnownEgressType();
}
}
}
}
if (first && variableFactory != null && variableFactory.isResolveable(name)) {
Object ptr = variableFactory.getVariableResolver(name).getValue();
if (ptr instanceof Method) {
ctx = ((Method) ptr).getDeclaringClass();
name = ((Method) ptr).getName();
} else if (ptr instanceof MethodStub) {
ctx = ((MethodStub) ptr).getClassReference();
name = ((MethodStub) ptr).getMethodName();
} else if (ptr instanceof Function) {
Function func = (Function) ptr;
if (!name.equals(func.getName())) {
getBeanProperty(ctx, name);
addAccessorNode(new DynamicFunctionAccessor(es));
} else {
addAccessorNode(new FunctionAccessor((Function) ptr, es));
}
return ((Function) ptr).call(ctx, thisRef, variableFactory, args);
} else {
throw new OptimizationFailure("attempt to optimize a method call for a reference that does not point to a method: " + name + " (reference is type: " + (ctx != null ? ctx.getClass().getName() : null) + ")");
}
first = false;
}
if (ctx == null) {
throw new PropertyAccessException("null pointer or function not found: " + name, this.expr, this.start);
}
boolean classTarget = false;
Class<?> cls = currType != null ? currType : ((classTarget = ctx instanceof Class) ? (Class<?>) ctx : ctx.getClass());
currType = null;
Method m;
Class[] parameterTypes = null;
if ((m = getBestCandidate(argTypes, name, cls, cls.getMethods(), false, classTarget)) != null) {
parameterTypes = m.getParameterTypes();
}
if (m == null && classTarget) {
/**
* If we didn't find anything, maybe we're looking for the actual java.lang.Class methods.
*/
if ((m = getBestCandidate(argTypes, name, cls, Class.class.getMethods(), false)) != null) {
parameterTypes = m.getParameterTypes();
}
}
if (m == null) {
StringAppender errorBuild = new StringAppender();
if ("size".equals(name) && args.length == 0 && cls.isArray()) {
addAccessorNode(new ArrayLength());
return getLength(ctx);
}
for (int i = 0; i < args.length; i++) {
errorBuild.append(args[i] != null ? args[i].getClass().getName() : null);
if (i < args.length - 1)
errorBuild.append(", ");
}
throw new PropertyAccessException("unable to resolve method: " + cls.getName() + "." + name + "(" + errorBuild.toString() + ") [arglength=" + args.length + "]", this.expr, this.st);
} else {
if (es != null) {
ExecutableStatement cExpr;
for (int i = 0; i < es.length; i++) {
cExpr = (ExecutableStatement) es[i];
if (cExpr.getKnownIngressType() == null) {
cExpr.setKnownIngressType(parameterTypes[i]);
cExpr.computeTypeConversionRule();
}
if (!cExpr.isConvertableIngressEgress()) {
args[i] = convert(args[i], parameterTypes[i]);
}
}
} else {
/**
* Coerce any types if required.
*/
for (int i = 0; i < args.length; i++) args[i] = convert(args[i], parameterTypes[i]);
}
Object o = getWidenedTarget(m).invoke(ctx, args);
if (hasNullMethodHandler()) {
addAccessorNode(new MethodAccessorNH(getWidenedTarget(m), (ExecutableStatement[]) es, getNullMethodHandler()));
if (o == null)
o = getNullMethodHandler().getProperty(m.getName(), ctx, variableFactory);
} else {
addAccessorNode(new MethodAccessor(getWidenedTarget(m), (ExecutableStatement[]) es));
}
/**
* return the response.
*/
return o;
}
}
Aggregations