diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-08-19 11:55:15 +0200 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-08-19 11:55:15 +0200 |
commit | ac7e1026090cf0895e03717e715ce25015263175 (patch) | |
tree | 8d0f48f7e8fdf65eb86d623e2a23843b478c4c68 | |
parent | b5759efa364791a6b66865b05538549078f97aa1 (diff) | |
parent | fceae7084cc196e37bb8cf9efa96b994c0d73738 (diff) | |
download | scala-ac7e1026090cf0895e03717e715ce25015263175.tar.gz scala-ac7e1026090cf0895e03717e715ce25015263175.tar.bz2 scala-ac7e1026090cf0895e03717e715ce25015263175.zip |
Merge pull request #3860 from gourlaysama/wip/t7710-backport
[backport] SI-7710 fix memory performance of RegexParsers in jdk7u6+
-rw-r--r-- | bincompat-forward.whitelist.conf | 6 | ||||
-rw-r--r-- | src/library/scala/util/parsing/combinator/RegexParsers.scala | 4 | ||||
-rw-r--r-- | src/library/scala/util/parsing/combinator/SubSequence.scala | 32 |
3 files changed, 39 insertions, 3 deletions
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 7879ecfd84..d8a91f3ae8 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -177,7 +177,11 @@ filter { { matchName="scala.reflect.runtime.JavaMirrors#JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$followStatic" problemName=MissingMethodProblem + }, + { + # only accessible from util.parsing.combinator package + matchName="scala.util.parsing.combinator.SubSequence" + problemName=MissingClassProblem } - ] } diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala index d17d0cac8d..5f2c07c2ef 100644 --- a/src/library/scala/util/parsing/combinator/RegexParsers.scala +++ b/src/library/scala/util/parsing/combinator/RegexParsers.scala @@ -72,7 +72,7 @@ trait RegexParsers extends Parsers { */ protected def handleWhiteSpace(source: java.lang.CharSequence, offset: Int): Int = if (skipWhitespace) - (whiteSpace findPrefixMatchOf (source.subSequence(offset, source.length))) match { + (whiteSpace findPrefixMatchOf (new SubSequence(source, offset))) match { case Some(matched) => offset + matched.end case None => offset } @@ -106,7 +106,7 @@ trait RegexParsers extends Parsers { val source = in.source val offset = in.offset val start = handleWhiteSpace(source, offset) - (r findPrefixMatchOf (source.subSequence(start, source.length))) match { + (r findPrefixMatchOf (new SubSequence(source, start))) match { case Some(matched) => Success(source.subSequence(start, start + matched.end).toString, in.drop(start + matched.end - offset)) diff --git a/src/library/scala/util/parsing/combinator/SubSequence.scala b/src/library/scala/util/parsing/combinator/SubSequence.scala new file mode 100644 index 0000000000..79c8acac0f --- /dev/null +++ b/src/library/scala/util/parsing/combinator/SubSequence.scala @@ -0,0 +1,32 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2006-2013, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + +package scala +package util.parsing.combinator + +// A shallow wrapper over another CharSequence (usually a String) +// +// See SI-7710: in jdk7u6 String.subSequence stopped sharing the char array of the original +// string and began copying it. +// RegexParsers calls subSequence twice per input character: that's a lot of array copying! +private[combinator] class SubSequence(s: CharSequence, start: Int, val length: Int) extends CharSequence { + def this(s: CharSequence, start: Int) = this(s, start, s.length - start) + + def charAt(i: Int) = + if (i >= 0 && i < length) s.charAt(start + i) else throw new IndexOutOfBoundsException(s"index: $i, length: $length") + + def subSequence(_start: Int, _end: Int) = { + if (_start < 0 || _end < 0 || _end > length || _start > _end) + throw new IndexOutOfBoundsException(s"start: ${_start}, end: ${_end}, length: $length") + + new SubSequence(s, start + _start, _end - _start) + } + + override def toString = s.subSequence(start, start + length).toString +} |