/// Editing methods for lambda forms. // Each editing method can (potentially) cache the edited LF so that it can be reused later. internal virtual LambdaForm BindArgumentForm(int pos) { Transform key = Transform.Of(Transform.Kind.BIND_ARG, pos); LambdaForm form = GetInCache(key); if (form != null) { assert(form.ParameterConstraint(0) == NewSpeciesData(LambdaForm.ParameterType(pos))); return(form); } LambdaFormBuffer buf = Buffer(); buf.StartEdit(); BoundMethodHandle.SpeciesData oldData = OldSpeciesData(); BoundMethodHandle.SpeciesData newData = NewSpeciesData(LambdaForm.ParameterType(pos)); Name oldBaseAddress = LambdaForm.Parameter(0);// BMH holding the values Name newBaseAddress; NamedFunction getter = newData.GetterFunction(oldData.FieldCount()); if (pos != 0) { // The newly created LF will run with a different BMH. // Switch over any pre-existing BMH field references to the new BMH class. buf.ReplaceFunctions(oldData.GetterFunctions(), newData.GetterFunctions(), oldBaseAddress); newBaseAddress = oldBaseAddress.withConstraint(newData); buf.RenameParameter(0, newBaseAddress); buf.ReplaceParameterByNewExpression(pos, new Name(getter, newBaseAddress)); } else { // cannot bind the MH arg itself, unless oldData is empty assert(oldData == BoundMethodHandle.SpeciesData.EMPTY); newBaseAddress = (new Name(L_TYPE)).withConstraint(newData); buf.ReplaceParameterByNewExpression(0, new Name(getter, newBaseAddress)); buf.InsertParameter(0, newBaseAddress); } 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)); }
private LambdaForm MakeArgumentCombinationForm(int pos, MethodType combinerType, bool keepArguments, bool dropResult) { LambdaFormBuffer buf = Buffer(); buf.StartEdit(); int combinerArity = combinerType.ParameterCount(); int resultArity = (dropResult ? 0 : 1); assert(pos <= MethodType.MAX_JVM_ARITY); assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= LambdaForm.Arity_Renamed); assert(pos > 0); // cannot filter the MH arg itself assert(combinerType == combinerType.BasicType()); assert(combinerType.ReturnType() != typeof(void) || dropResult); 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 getCombiner = new Name(newData.GetterFunction(oldData.FieldCount()), newBaseAddress); Object[] combinerArgs = new Object[1 + combinerArity]; combinerArgs[0] = getCombiner; Name[] newParams; if (keepArguments) { newParams = new Name[0]; System.Array.Copy(LambdaForm.Names, pos + resultArity, combinerArgs, 1, combinerArity); } else { newParams = new Name[combinerArity]; BasicType[] newTypes = basicTypes(combinerType.ParameterList()); for (int i = 0; i < newTypes.Length; i++) { newParams[i] = new Name(pos + i, newTypes[i]); } System.Array.Copy(newParams, 0, combinerArgs, 1, combinerArity); } Name callCombiner = new Name(combinerType, combinerArgs); // insert the two new expressions int exprPos = LambdaForm.Arity(); buf.InsertExpression(exprPos + 0, getCombiner); buf.InsertExpression(exprPos + 1, callCombiner); // insert new arguments, if needed int argPos = pos + resultArity; // skip result parameter foreach (Name newParam in newParams) { buf.InsertParameter(argPos++, newParam); } assert(buf.LastIndexOf(callCombiner) == exprPos + 1 + newParams.Length); if (!dropResult) { buf.ReplaceParameterByCopy(pos, exprPos + 1 + newParams.Length); } return(buf.EndEdit()); }