Example #1
0
        private static void DoBinarySearch(MethodJumpEmittingContext context, int l, int r)
        {
            var il = context.il;

            if (l > r)
            {
                il.Br(context.retNullLabel);
                return;
            }
            if (r - l + 1 <= 3)
            {
                // just bunch of ifs
                for (; l <= r; l++)
                {
                    il.Ldarg(1);                         // stack: [key]
                    il.Ldarg(0);                         // stack: [key, this]
                    il.Ldfld(context.context.keys[l]);   // stack: [key, this.keys[l]]
                    var nextLabel = il.DefineLabel("next");
                    il.Bne_Un(nextLabel);                // if(key != this.keys[l]) goto next; stack: []
                    il.Ldarg(0);                         // stack: [this]
                    il.Ldfld(context.context.values[l]); // stack: [this.values[l]]
                    il.Ret();
                    il.MarkLabel(nextLabel);
                }
                il.Br(context.retNullLabel);
            }
            else
            {
                int m = (l + r) / 2;

                il.Ldarg(1);                         // stack: [key]
                il.Ldarg(0);                         // stack: [key, this]
                il.Ldfld(context.context.keys[m]);   // stack: [key, this.keys[m]]
                var nextLabel = il.DefineLabel("next");
                il.Bne_Un(nextLabel);                // if(key != this.keys[m]) goto next; stack: []
                il.Ldarg(0);                         // stack: [this]
                il.Ldfld(context.context.values[m]); // stack: [this.values[m]]
                il.Ret();

                il.MarkLabel(nextLabel);
                il.Ldarg(1);                       // stack: [key]
                il.Ldarg(0);                       // stack: [key, this]
                il.Ldfld(context.context.keys[m]); // stack: [key, this.keys[m]]
                var goLeftLabel = il.DefineLabel("goLeft");
                il.Blt(goLeftLabel, false);        // if(key < this.keys[m]]) goto goLeft; stack: []
                DoBinarySearch(context, m + 1, r);

                il.MarkLabel(goLeftLabel);
                DoBinarySearch(context, l, m - 1);
            }
        }
Example #2
0
        private static void BuildJump(TypeBuilder typeBuilder, int n, Context context)
        {
            var method = typeBuilder.DefineMethod("Jump", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(MethodCallNode), new[] { typeof(int) });

            using (var il = new GroboIL(method))
            {
                var retNullLabel    = il.DefineLabel("retNull");
                var emittingContext = new MethodJumpEmittingContext
                {
                    context      = context,
                    il           = il,
                    retNullLabel = retNullLabel
                };
                DoBinarySearch(emittingContext, 0, n - 1);
                il.MarkLabel(retNullLabel);
                il.Ldnull();
                il.Ret();
            }
            typeBuilder.DefineMethodOverride(method, typeof(MethodCallNodeEdges).GetMethod(method.Name, BindingFlags.Public | BindingFlags.Instance));
        }