internal GOpCall Merge(GOpCall gc) { /* * For the merge to be possible, calls to the same * Function should target the same GFunction. */ foreach (var kvp in gc.cfm) { Function f = kvp.Key; GFunction gf2 = kvp.Value; GFunction gf1; if (!cfm.TryGetValue(f, out gf1)) { continue; } if (gf1 != gf2) { return(null); } } /* * Compute the merged dispatcher. */ Dispatcher d3 = Dispatcher.Merge(dispatcher, gc.dispatcher); if (d3 == null) { return(null); } /* * Merge the maps. */ SortedDictionary <Function, GFunction> cfm3 = new SortedDictionary <Function, GFunction>(); foreach (var kvp in cfm) { cfm3[kvp.Key] = kvp.Value; } foreach (var kvp in gc.cfm) { cfm3[kvp.Key] = kvp.Value; } return(new GOpCall(fname, d3, cfm3)); }
/* * Merge the provided GFunctionInterpreted into this one. If the * merge is not possible, this instance is not modified, and * false is returned. */ bool Merge(GFunctionInterpreted gf) { /* * Normally, Merge() is not invoked for a distinct function, * but an extra test here is cheap. */ if (fi != gf.fi) { return(false); } /* * We first test the frames, but do not complete their * merge until the operation is confirmed. */ if (!frame.CanMerge(gf.frame)) { return(false); } /* * Since the two GFunctionInterpreted relate to the same * interpreted function, all opcodes are naturally * compatible, except possibly the Call opcodes, which * must be checked. */ GOp[] spec3 = new GOp[spec.Length]; for (int i = 0; i < spec.Length; i++) { GOp g1 = spec[i]; GOp g2 = gf.spec[i]; if ((g1 is GOpCall) && (g2 is GOpCall)) { GOpCall g3 = ((GOpCall)g1).Merge((GOpCall)g2); if (g3 == null) { return(false); } spec3[i] = g3; } else { if (g1 is GOpZero) { spec3[i] = g2; } else { spec3[i] = g1; } } } spec = spec3; AdjustJumps(); /* * Merge the frames. */ frame.Merge(gf.frame); return(true); }