diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/RuleIndex.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/RuleIndex.kt index c903f564..76fdc02c 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/RuleIndex.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/RuleIndex.kt @@ -20,9 +20,7 @@ import jetbrains.mps.logic.reactor.evaluation.ConstraintOccurrence import jetbrains.mps.logic.reactor.logical.Logical import jetbrains.mps.logic.reactor.logical.MetaLogical import jetbrains.mps.logic.reactor.program.* -import jetbrains.mps.logic.reactor.util.TermTrie -import jetbrains.mps.logic.reactor.util.allSetBits -import jetbrains.mps.logic.reactor.util.termTrie +import jetbrains.mps.logic.reactor.util.* import jetbrains.mps.unification.Term import java.util.* import kotlin.collections.ArrayList @@ -47,6 +45,12 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { // invariant: rulesList.size == slotMasksList.size private val slotMasksList = ArrayList() + /** the bit set that is going to be reused for all calls to [select] */ + private val ruleIndices = BitSet(rulesList.size) + + /** the bit set to be used for temporary processing within [select]*/ + private val andRuleIndices = BitSet(rulesList.size) + init { buildIndex(handlers) } @@ -58,7 +62,10 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { */ fun forOccurrence(occ: ConstraintOccurrence): Iterable { val ruleIndices = symbol2index[occ.constraint().symbol()]?.select(occ) ?: return emptyList() - return ruleIndices.allSetBits().map { idx -> rulesList[idx] } + val result = ArrayList() + val it = ruleIndices.allSetBits() + while (it.hasNext()) result.add(rulesList[it.next()]) + return result } /** @@ -66,9 +73,13 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { */ fun forOccurrenceWithMask(occ: ConstraintOccurrence): Iterable> { val ruleBits = symbol2index[occ.constraint().symbol()]?.select(occ) ?: return emptyList() - return ruleBits.allSetBits().mapNotNull { ruleBit -> - slotMasksList[ruleBit][occ]?.let { mask -> rulesList[ruleBit] to mask } + val result = ArrayList>() + val it = ruleBits.allSetBits() + while (it.hasNext()) { + val ruleBit = it.next() + slotMasksList[ruleBit][occ]?.let { mask -> result.add(rulesList[ruleBit] to mask) } } + return result } override fun iterator(): Iterator = rulesList.iterator() @@ -107,12 +118,12 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { fun update(cst: Constraint, posInHead: Int) { symbol2mask.getOrPut(cst.symbol()) { BitSet() }.set(posInHead) } - /** * When null is returned, there can be no match for this constraint */ operator fun get(occ: ConstraintOccurrence): BitSet? = symbol2mask[occ.constraint().symbol()] + } /** @@ -162,7 +173,6 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { // initially select all rules val upToBit = rulesList.size - val ruleIndices = BitSet(rulesList.size) ruleIndices.set(0, upToBit) for ((idx, arg) in occ.arguments().withIndex()) { @@ -174,35 +184,20 @@ class RuleIndex(handlers: Iterable) : Iterable, RuleLookup { continue } + andRuleIndices.clear(0, upToBit) + andRuleIndices.or(wildcardIndices) + val argVal = if (arg is Logical<*>) arg.findRoot().value() else arg when (argVal) { - is Term -> { - val bits = wildcardIndices.clone() as BitSet - for (i in termIndices.lookupValues(argVal)) { - bits.set(i) - } - ruleIndices.and(bits) - } - is Any -> { - if (value2indices.containsKey(argVal)) { - // ensure only rules with either matching values or wildcard arguments get selected - val bits = wildcardIndices.clone() as BitSet - bits.or(value2indices[argVal]) - ruleIndices.and(bits) - - } else { - ruleIndices.and(wildcardIndices) - } - } - else -> { - /* never happens */ - throw NullPointerException() - } + is Term -> + termIndices.lookupValues(argVal).forEach { andRuleIndices.set(it) } + is Any -> + // ensure only rules with either matching values or wildcard arguments get selected + if (value2indices.containsKey(argVal)) andRuleIndices.or(value2indices[argVal]) } + ruleIndices.and(andRuleIndices) - if (ruleIndices.isEmpty) { - break - } + if (ruleIndices.isEmpty) break } return ruleIndices diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt index f042ddc2..5f821682 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/ReteRuleMatcherImpl.kt @@ -72,7 +72,9 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher { if (thisMetaIndices == null || thatMetaIndices == null) return true if (thisMetaIndices.cardinality() != 0 && thatMetaIndices.cardinality() != 0) { - for (shared in thisMetaIndices.copyApply { and(thatMetaIndices) }.allSetBits()) { + val it = thisMetaIndices.copyApply { and(thatMetaIndices) }.allSetBits() + while (it.hasNext()) { + val shared = it.next() if (!createOccurrenceMatcher().match(this.getSubst(shared), that.getSubst(shared))) return false } } @@ -327,8 +329,10 @@ internal class ReteRuleMatcherImpl(val rule: Rule) : RuleMatcher { skipOccIndices.clear(occIdx) val alphaNodes = arrayListOf() - for (posInHead in mask.allSetBits()) { + val it = mask.allSetBits() + while (it.hasNext()){ + val posInHead = it.next() val matcher = createOccurrenceMatcher(emptySubst()) if (matcher.matches(head[posInHead], occ)) { alphaNodes.add(AlphaNode(occ, posInHead, matcher.substitution())) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/RuleMatcherImpl.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/RuleMatcherImpl.kt index 46b021f9..239e7fc5 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/RuleMatcherImpl.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/RuleMatcherImpl.kt @@ -108,7 +108,9 @@ internal class RuleMatcherImpl(private val ruleLookup: RuleLookup, fun expand(occ: Occurrence, genId: Int, matchingVacant: BitSet): List = unrelatedOrNull(occ)?.let { n -> ArrayList().also { expanded -> - for (headIdx in matchingVacant.allSetBits()) { + val it = matchingVacant.allSetBits() + while (it.hasNext()) { + val headIdx = it.next() createOccurrenceMatcher(subst).run { if (matches(head[headIdx], occ)) { expanded.add(ActiveMatchNode(substitution(), n, occ, headIdx, genId)) diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/StateFrame.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/StateFrame.kt index 44abb8e8..1c861e4a 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/StateFrame.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/core/internal/StateFrame.kt @@ -45,9 +45,9 @@ internal class StateFrame private constructor(val state: ProcessingStateImpl) : private var observers: PersMap>, ConsList> = Maps.of() - private val activatedOccurrences = ArrayList() + private val activatedOccurrences = ArrayList(4) - private val deactivatedOccurrences = ArrayList() + private val deactivatedOccurrences = ArrayList(4) constructor(state: ProcessingStateImpl, dispatcher: Dispatcher) : this(state) { this.dispatchingFront = dispatcher.front() diff --git a/reactor/Core/src/jetbrains/mps/logic/reactor/util/BitSet.kt b/reactor/Core/src/jetbrains/mps/logic/reactor/util/BitSet.kt index d00f6b85..f311a938 100644 --- a/reactor/Core/src/jetbrains/mps/logic/reactor/util/BitSet.kt +++ b/reactor/Core/src/jetbrains/mps/logic/reactor/util/BitSet.kt @@ -16,7 +16,9 @@ package jetbrains.mps.logic.reactor.util +import gnu.trove.iterator.TIntIterator import java.util.* +import kotlin.NoSuchElementException /** * @author Fedor Isakov @@ -28,7 +30,7 @@ inline fun BitSet.copyApply (f: BitSet.() -> Unit): BitSet = fun bitSetOfOnes(size: Int): BitSet = BitSet(size).apply { set(0, size) } -fun bitSet(setBit: Int): BitSet= +fun bitSet(setBit: Int): BitSet = BitSet().apply { set(setBit) } fun bitSet(setBits: Iterable): BitSet= @@ -40,22 +42,21 @@ fun BitSet.setBit(bit: Int): BitSet = fun BitSet.clearBit(bit: Int): BitSet = (clone() as BitSet).apply { clear(bit) } -fun BitSet.allSetBits(): Iterable = object : Iterable { - override fun iterator(): Iterator = object : Iterator { - var next = nextSetBit(0); +fun BitSet.allSetBits(): TIntIterator = object : TIntIterator { - override fun hasNext(): Boolean = next != -1; + var next = nextSetBit(0); - override fun next(): Int = - if (next != -1) { - val ret = next - next = nextSetBit(next + 1) - ret - } else { - throw NoSuchElementException() - } - } + override fun hasNext(): Boolean = next != -1; + + override fun next(): Int = + if (next != -1) { + val ret = next + next = nextSetBit(next + 1) + ret + } else { + throw NoSuchElementException() + } + + override fun remove() = + throw UnsupportedOperationException() } - - -