From 6e20e35ab7e0980d3fea418b913643343f210387 Mon Sep 17 00:00:00 2001 From: Albert Meltzer <7529386+kitbellew@users.noreply.github.com> Date: Sat, 27 Apr 2024 00:48:44 +0300 Subject: [PATCH] BestFirstSearch: switch to Long as State key State column is unlikely to exceed 24 bits (or 16+ mln bytes), but even in cases when it might, a given token (that is, at a given State depth) cannot conceivably be formatted at two different column values which are a multiple of 2^24 bytes apart. Hence, let's form state key by keeping indentation (just like before) at 8 bits, limiting column to 24 bits and combining with depth in the remaining 32 bits (and this combining is what ensures no hash conflict). --- .../org/scalafmt/internal/BestFirstSearch.scala | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala index 4ba29df290..c144665ebb 100644 --- a/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala +++ b/scalafmt-core/shared/src/main/scala/org/scalafmt/internal/BestFirstSearch.scala @@ -49,8 +49,6 @@ private class BestFirstSearch private ( val visits = new Array[Int](tokens.length) var keepSlowStates = !pruneSlowStates - type StateHash = Long - /** Returns true if it's OK to skip over state. */ def shouldEnterState(curr: State): Boolean = keepSlowStates || @@ -70,10 +68,7 @@ private class BestFirstSearch private ( } } else None - def stateColumnKey(state: State): StateHash = state.column << 8 | - state.indentation - - val memo = mutable.Map.empty[(Int, StateHash), State] + private val memo = mutable.Map.empty[Long, State] def shortestPathMemo( start: State, @@ -81,10 +76,9 @@ private class BestFirstSearch private ( depth: Int, maxCost: Int, ): Option[State] = { - val key = (start.depth, stateColumnKey(start)) - val cachedState = memo.get(key) - if (cachedState.nonEmpty) cachedState - else { + val key = (start.indentation & 0xffL) | (start.column & 0xffffffL) << 8 | + (start.depth & 0xffffffffL) << 32 + memo.get(key).orElse { // Only update state if it reached stop. val nextState = shortestPath(start, stop, depth, maxCost) if (null == nextState) None