// See StringConcatFactory in jdk sources private static List <Exprent> ExtractParameters(List <PooledConstant> bootstrapArguments , InvocationExprent expr) { List <Exprent> parameters = expr.GetLstParameters(); if (bootstrapArguments != null) { PooledConstant constant = bootstrapArguments[0]; if (constant.type == ICodeConstants.CONSTANT_String) { string recipe = ((PrimitiveConstant)constant).GetString(); List <Exprent> res = new List <Exprent>(); StringBuilder acc = new StringBuilder(); int parameterId = 0; for (int i = 0; i < recipe.Length; i++) { char c = recipe[i]; if (c == Tag_Const || c == Tag_Arg) { // Detected a special tag, flush all accumulated characters // as a constant first: if (acc.Length > 0) { res.Add(new ConstExprent(VarType.Vartype_String, acc.ToString(), expr.bytecode)); acc.Length = 0; } if (c == Tag_Const) { } // skip for now if (c == Tag_Arg) { res.Add(parameters[parameterId++]); } } else { // Not a special characters, this is a constant embedded into // the recipe itself. acc.Append(c); } } // Flush the remaining characters as constant: if (acc.Length > 0) { res.Add(new ConstExprent(VarType.Vartype_String, acc.ToString(), expr.bytecode)); } return(res); } } return(new List <Exprent>(parameters)); }
public InvocationExprent(int opcode, LinkConstant cn, List <PooledConstant> bootstrapArguments , ListStack <Exprent> stack, HashSet <int> bytecodeOffsets) : this() { name = cn.elementname; classname = cn.classname; this.bootstrapArguments = bootstrapArguments; switch (opcode) { case ICodeConstants.opc_invokestatic: { invocationTyp = Invoke_Static; break; } case ICodeConstants.opc_invokespecial: { invocationTyp = Invoke_Special; break; } case ICodeConstants.opc_invokevirtual: { invocationTyp = Invoke_Virtual; break; } case ICodeConstants.opc_invokeinterface: { invocationTyp = Invoke_Interface; break; } case ICodeConstants.opc_invokedynamic: { invocationTyp = Invoke_Dynamic; classname = "java/lang/Class"; // dummy class name invokeDynamicClassSuffix = "##Lambda_" + cn.index1 + "_" + cn.index2; break; } } if (ICodeConstants.Init_Name.Equals(name)) { functype = Typ_Init; } else if (ICodeConstants.Clinit_Name.Equals(name)) { functype = Typ_Clinit; } stringDescriptor = cn.descriptor; descriptor = MethodDescriptor.ParseDescriptor(cn.descriptor); foreach (VarType ignored in descriptor.@params) { lstParameters.Add(0, stack.Pop()); } if (opcode == ICodeConstants.opc_invokedynamic) { int dynamicInvocationType = -1; if (bootstrapArguments != null) { if (bootstrapArguments.Count > 1) { // INVOKEDYNAMIC is used not only for lambdas PooledConstant link = bootstrapArguments[1]; if (link is LinkConstant) { dynamicInvocationType = ((LinkConstant)link).index1; } } } if (dynamicInvocationType == ICodeConstants.CONSTANT_MethodHandle_REF_invokeStatic) { isStatic__ = true; } else if (!(lstParameters.Count == 0)) { // FIXME: remove the first parameter completely from the list. It's the object type for a virtual lambda method. instance = lstParameters[0]; } } else if (opcode == ICodeConstants.opc_invokestatic) { isStatic__ = true; } else { instance = stack.Pop(); } AddBytecodeOffsets(bytecodeOffsets); }