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; } }
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; } }
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; } } }
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; } } }
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); }
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)); }