internal virtual LambdaForm SpreadArgumentsForm(int pos, Class arrayType, int arrayLength) { Class elementType = arrayType.ComponentType; Class erasedArrayType = arrayType; if (!elementType.Primitive) { erasedArrayType = typeof(Object[]); } BasicType bt = basicType(elementType); int elementTypeKey = bt.ordinal(); if (bt.basicTypeClass() != elementType) { if (elementType.Primitive) { elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); } } Transform key = Transform.Of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - arrayLength + 1); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); assert(pos <= MethodType.MAX_JVM_ARITY); assert(pos + arrayLength <= LambdaForm.Arity_Renamed); assert(pos > 0); // cannot spread the MH arg itself Name spreadParam = new Name(L_TYPE); Name checkSpread = new Name(MethodHandleImpl.Lazy.NF_checkSpreadArgument, spreadParam, arrayLength); // insert the new expressions int exprPos = LambdaForm.Arity(); buf.InsertExpression(exprPos++, checkSpread); // adjust the arguments MethodHandle aload = MethodHandles.ArrayElementGetter(erasedArrayType); for (int i = 0; i < arrayLength; i++) { Name loadArgument = new Name(aload, spreadParam, i); buf.InsertExpression(exprPos + i, loadArgument); buf.ReplaceParameterByCopy(pos + i, exprPos + i); } buf.InsertParameter(pos, spreadParam); form = buf.EndEdit(); return(PutInCache(key, form)); }
internal virtual LambdaForm FilterArgumentForm(int pos, BasicType newType) { Transform key = Transform.Of(Transform.Kind.FILTER_ARG, pos, newType.ordinal()); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed); assert(form.ParameterType(pos) == newType); return(form); } BasicType oldType = LambdaForm.ParameterType(pos); MethodType filterType = MethodType.MethodType(oldType.basicTypeClass(), newType.basicTypeClass()); form = MakeArgumentCombinationForm(pos, filterType, false, false); return(PutInCache(key, form)); }
internal virtual LambdaForm AddArgumentForm(int pos, BasicType type) { Transform key = Transform.Of(Transform.Kind.ADD_ARG, pos, type.ordinal()); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed + 1); assert(form.ParameterType(pos) == type); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); buf.InsertParameter(pos, new Name(type)); form = buf.EndEdit(); return(PutInCache(key, form)); }
internal virtual LambdaForm FilterReturnForm(BasicType newType, bool constantZero) { Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN); Transform key = Transform.Of(kind, newType.ordinal()); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed); assert(form.ReturnType() == newType); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); int insPos = LambdaForm.Names.Length; Name callFilter; if (constantZero) { // Synthesize a constant zero value for the given type. if (newType == V_TYPE) { callFilter = null; } else { callFilter = new Name(constantZero(newType)); } } else { BoundMethodHandle.SpeciesData oldData = OldSpeciesData(); BoundMethodHandle.SpeciesData newData = NewSpeciesData(L_TYPE); // The newly created LF will run with a different BMH. // Switch over any pre-existing BMH field references to the new BMH class. Name oldBaseAddress = LambdaForm.Parameter(0); // BMH holding the values buf.ReplaceFunctions(oldData.GetterFunctions(), newData.GetterFunctions(), oldBaseAddress); Name newBaseAddress = oldBaseAddress.withConstraint(newData); buf.RenameParameter(0, newBaseAddress); Name getFilter = new Name(newData.GetterFunction(oldData.FieldCount()), newBaseAddress); buf.InsertExpression(insPos++, getFilter); BasicType oldType = LambdaForm.ReturnType(); if (oldType == V_TYPE) { MethodType filterType = MethodType.MethodType(newType.basicTypeClass()); callFilter = new Name(filterType, getFilter); } else { MethodType filterType = MethodType.MethodType(newType.basicTypeClass(), oldType.basicTypeClass()); callFilter = new Name(filterType, getFilter, LambdaForm.Names[LambdaForm.Result]); } } if (callFilter != null) { buf.InsertExpression(insPos++, callFilter); } buf.Result = callFilter; form = buf.EndEdit(); return(PutInCache(key, form)); }
internal virtual LambdaForm CollectArgumentArrayForm(int pos, MethodHandle arrayCollector) { MethodType collectorType = arrayCollector.Type(); int collectorArity = collectorType.ParameterCount(); assert(arrayCollector.IntrinsicName() == Intrinsic.NEW_ARRAY); Class arrayType = collectorType.ReturnType(); Class elementType = arrayType.ComponentType; BasicType argType = basicType(elementType); int argTypeKey = argType.ordinal(); if (argType.basicTypeClass() != elementType) { // return null if it requires more metadata (like String[].class) if (!elementType.Primitive) { return(null); } argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); } assert(collectorType.ParameterList().Equals(Collections.NCopies(collectorArity, elementType))); Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY; Transform key = Transform.Of(kind, pos, collectorArity, argTypeKey); LambdaForm form = GetInCache(key); if (form != null) { assert(form.Arity_Renamed == LambdaForm.Arity_Renamed - 1 + collectorArity); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); assert(pos + 1 <= LambdaForm.Arity_Renamed); assert(pos > 0); // cannot filter the MH arg itself Name[] newParams = new Name[collectorArity]; for (int i = 0; i < collectorArity; i++) { newParams[i] = new Name(pos + i, argType); } Name callCombiner = new Name(arrayCollector, (Object[])newParams); //... // insert the new expression int exprPos = LambdaForm.Arity(); buf.InsertExpression(exprPos, callCombiner); // insert new arguments int argPos = pos + 1; // skip result parameter foreach (Name newParam in newParams) { buf.InsertParameter(argPos++, newParam); } assert(buf.LastIndexOf(callCombiner) == exprPos + newParams.Length); buf.ReplaceParameterByCopy(pos, exprPos + newParams.Length); form = buf.EndEdit(); return(PutInCache(key, form)); }