private void AddAlwaysBranch(QueryBranch literalBranch, Opcode next)
 {
     if (OpcodeID.Branch == next.ID)
     {
         BranchOpcode opcode   = (BranchOpcode)next;
         OpcodeList   branches = opcode.Branches;
         for (int i = 0; i < branches.Count; i++)
         {
             Opcode opcode2 = branches[i];
             if (this.IsAlwaysBranch(opcode2))
             {
                 this.AlwaysBranches.AddInOrder(new QueryBranch(opcode2, literalBranch.ID));
             }
             else
             {
                 opcode2.Flags |= OpcodeFlags.NoContextCopy;
             }
         }
     }
     else if (this.IsAlwaysBranch(next))
     {
         this.AlwaysBranches.AddInOrder(new QueryBranch(next, literalBranch.ID));
     }
     else
     {
         next.Flags |= OpcodeFlags.NoContextCopy;
     }
 }
Beispiel #2
0
        internal void RemoveAlwaysBranch(Opcode opcode)
        {
            if (null == this.alwaysBranches)
            {
                return;
            }

            // Note: if the opcodes below are not in the alwaysBranches table, nothing will happen
            // So arbitrary calls are safe - just makes the removal processor slower (we'll speed it up if necessary)
            if (OpcodeID.Branch == opcode.ID)
            {
                OpcodeList branches = ((BranchOpcode)opcode).Branches;
                for (int i = 0; i < branches.Count; ++i)
                {
                    this.alwaysBranches.Remove(branches[i]);
                }
            }
            else
            {
                this.alwaysBranches.Remove(opcode);
            }
            if (0 == this.alwaysBranches.Count)
            {
                this.alwaysBranches = null;
            }
        }
Beispiel #3
0
 void AddAlwaysBranch(QueryBranch literalBranch, Opcode next)
 {
     if (OpcodeID.Branch == next.ID)
     {
         BranchOpcode opcode   = (BranchOpcode)next;
         OpcodeList   branches = opcode.Branches;
         for (int i = 0; i < branches.Count; ++i)
         {
             Opcode branch = branches[i];
             if (this.IsAlwaysBranch(branch))
             {
                 this.AlwaysBranches.AddInOrder(new QueryBranch(branch, literalBranch.ID));
             }
             else
             {
                 branch.Flags |= OpcodeFlags.NoContextCopy;
             }
         }
     }
     else
     {
         Fx.Assert(!next.TestFlag(OpcodeFlags.Branch), "");
         if (this.IsAlwaysBranch(next))
         {
             this.AlwaysBranches.AddInOrder(new QueryBranch(next, literalBranch.ID));
         }
         else
         {
             next.Flags |= OpcodeFlags.NoContextCopy;
         }
     }
 }
Beispiel #4
0
 internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
 {
     if (tree == null)
     {
         this.lastOpcode = newBlock.Last;
         return(newBlock.First);
     }
     this.diverger = new Diverger(tree, newBlock.First);
     if (!this.diverger.Find())
     {
         this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
         return(tree);
     }
     if (this.diverger.TreeOpcode == null)
     {
         this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
     }
     else
     {
         this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
     }
     this.lastOpcode = newBlock.Last;
     if (this.diverger.InsertOpcode.IsMultipleResult())
     {
         if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
         {
             OpcodeList branches = ((BranchOpcode)this.diverger.TreeOpcode).Branches;
             int        num      = 0;
             int        count    = branches.Count;
             while (num < count)
             {
                 if (branches[num].IsMultipleResult())
                 {
                     this.lastOpcode = branches[num];
                     break;
                 }
                 num++;
             }
         }
         else if (this.diverger.TreeOpcode.IsMultipleResult())
         {
             this.lastOpcode = this.diverger.TreeOpcode;
         }
     }
     this.FixupJumps();
     return(tree);
 }
        private bool IsAlwaysBranch(Opcode next)
        {
            JumpIfOpcode opcode = next as JumpIfOpcode;

            if (opcode != null)
            {
                if (opcode.Test)
                {
                    Opcode opcode3;
                    Opcode jump = opcode.Jump;
                    if (jump == null)
                    {
                        return(false);
                    }
                    if (jump.TestFlag(OpcodeFlags.Branch))
                    {
                        OpcodeList branches = ((BranchOpcode)jump).Branches;
                        for (int i = 0; i < branches.Count; i++)
                        {
                            opcode3 = branches[i].Next;
                            if ((opcode3 != null) && !opcode3.TestFlag(OpcodeFlags.Result))
                            {
                                return(true);
                            }
                        }
                        return(false);
                    }
                    opcode3 = opcode.Jump.Next;
                    if ((opcode3 != null) && opcode3.TestFlag(OpcodeFlags.Result))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            if (OpcodeID.BlockEnd == next.ID)
            {
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }
            return(!next.TestFlag(OpcodeFlags.Result));
        }
 internal void RemoveAlwaysBranch(Opcode opcode)
 {
     if (this.alwaysBranches != null)
     {
         if (OpcodeID.Branch == opcode.ID)
         {
             OpcodeList branches = ((BranchOpcode)opcode).Branches;
             for (int i = 0; i < branches.Count; i++)
             {
                 this.alwaysBranches.Remove(branches[i]);
             }
         }
         else
         {
             this.alwaysBranches.Remove(opcode);
         }
         if (this.alwaysBranches.Count == 0)
         {
             this.alwaysBranches = null;
         }
     }
 }
Beispiel #7
0
 internal BranchOpcode(OpcodeID id) : base(id)
 {
     base.flags   |= OpcodeFlags.Branch;
     this.branches = new OpcodeList(2);
 }
 internal BranchOpcode(OpcodeID id) : base(id)
 {
     base.flags |= OpcodeFlags.Branch;
     this.branches = new OpcodeList(2);
 }
        internal Opcode Build(Opcode tree, OpcodeBlock newBlock)
        {
            if (null == tree)
            {
                this.lastOpcode = newBlock.Last;
                return(newBlock.First);
            }

            this.diverger = new Diverger(tree, newBlock.First);

            if (!this.diverger.Find())
            {
                // The opcodes in newBlock already have equivalents or identical opcodes
                // in the query tree that can do the job
                Fx.Assert(this.diverger.TreePath.Count > 0, "");
                this.lastOpcode = this.diverger.TreePath[this.diverger.TreePath.Count - 1];
                return(tree);
            }

            Fx.Assert(this.diverger.TreePath.Count == this.diverger.InsertPath.Count, "");

            // We can reuse opcodes upto this.diverger.TreePath[this.diverger.TreePath.Count - 1]
            // The remainder of the code in newBlock must be executed as is...
            if (null == this.diverger.TreeOpcode)
            {
                // We reached a leaf in the query tree
                // Simply add the remainder of the inserted code to the end of the tree path..
                this.diverger.TreePath[this.diverger.TreePath.Count - 1].Attach(this.diverger.InsertOpcode);
            }
            else
            {
                // Merge in the remaider of the new code block into the query tree
                // The first diverging opcodes follow the last entry in each path
                this.diverger.TreeOpcode.Add(this.diverger.InsertOpcode);
            }

            this.lastOpcode = newBlock.Last;
            if (this.diverger.InsertOpcode.IsMultipleResult())
            {
                // The complete new block was merged in, except for the the actual result opcode, which never
                // automatically merges. This means that the new block found all of its opcodes in common with
                // the tree
                if (OpcodeID.Branch == this.diverger.TreeOpcode.ID)
                {
                    OpcodeList branches = (((BranchOpcode)this.diverger.TreeOpcode).Branches);
                    for (int i = 0, count = branches.Count; i < count; ++i)
                    {
                        if (branches[i].IsMultipleResult())
                        {
                            this.lastOpcode = branches[i];
                            break;
                        }
                    }
                }
                else if (this.diverger.TreeOpcode.IsMultipleResult())
                {
                    this.lastOpcode = this.diverger.TreeOpcode;
                }
            }

            // Since we'll be diverging, any jumps that preceeded and leapt past the divergence point
            // will have to be branched
            this.FixupJumps();

            return(tree);
        }
Beispiel #10
0
        bool IsAlwaysBranch(Opcode next)
        {
            Fx.Assert(null != next, "");

            // Opcodes subsequent to matching literals must obviously be branched to.
            // The question is whether we should branch to the opcodes following those literals that do *not* match.
            // Naturally, the answer depends on the sort of opcode that succeeds the literal.
            //
            // If the literal is within a boolean conjunction, the succeeding opcode will either be a JumpIfNot
            // Or a BlockEnd.
            //
            // -If the JumpIfNot is multiway, then always evaluate if it contains ANY non-result only opcodes.
            // -If JumpIfNot(False) -i.e. AND - only evaluate if the opcode succeeding the jump is NOT a result opcode.
            // -If JumpIfNot(True) - i.e. OR - always evaluate
            //
            // -If BlockEnd - evaluate only if not followed by a result
            //
            // When branching for matching literals, we push trues onto the ValueStack corresponding to the items that
            // matched. When branching for non-matching literals, we push ALL FALSE values... and then eval.

            // is it a the termination of a conditional?
            JumpIfOpcode jump = next as JumpIfOpcode;

            if (null != jump)
            {
                // Is the conditional JumpIfNot(False) = i.e. OR?
                if (!jump.Test)
                {
                    return(true);
                }

                // Does the conditional actually jump to anything? Should never be the case, but paranoia demands..
                Opcode jumpTo = jump.Jump;
                if (null == jumpTo)
                {
                    return(false);
                }

                // Lets see where the jump will take us
                Opcode postJump;
                if (jumpTo.TestFlag(OpcodeFlags.Branch))
                {
                    // Multiway jump
                    OpcodeList branches = ((BranchOpcode)jumpTo).Branches;
                    for (int i = 0; i < branches.Count; ++i)
                    {
                        postJump = branches[i].Next;
                        if (null != postJump && !postJump.TestFlag(OpcodeFlags.Result))
                        {
                            // There is at least one jump here that leads to a non-result.
                            // For now, this dooms everybody to being branched to, whether or not their respective literals
                            // matched
                            return(true);
                        }
                    }
                    return(false);
                }

                // single jump
                postJump = jump.Jump.Next;
                if (null != postJump && postJump.TestFlag(OpcodeFlags.Result))
                {
                    return(false);
                }

                return(true);
            }

            // If the next opcode is a BlockEnd, then only bother processing if what follows the block is not a result
            if (OpcodeID.BlockEnd == next.ID)
            {
                Fx.Assert(null != next.Next, "");
                return(!next.Next.TestFlag(OpcodeFlags.Result));
            }

            // The literal is not inside a boolean conjunction
            // If the literal is not followed by a result, then we must do further processing after the branch
            return(!next.TestFlag(OpcodeFlags.Result));
        }