Beispiel #1
0
    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));
    }
Beispiel #2
0
    /*
     * 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);
    }