From ed618470e6531d6cab8bf2f456cb5fe1b96f556c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 20 Nov 2017 22:54:31 +0100 Subject: [PATCH 1/3] Fix #3515: Do not save tasty in .class with -YemitTasty Only emit .tasty file --- compiler/src/dotty/tools/backend/jvm/GenBCode.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index 0705839ea504..fe6e92f1757b 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -223,9 +223,7 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter if (claszSymbol.isClass) // @DarkDimius is this test needed here? for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) { - val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, binary) val store = if (mirrorC ne null) mirrorC else plainC - store.visitAttribute(dataAttr) if (ctx.settings.emitTasty.value) { val outTastyFile = getFileForClassfile(outF, store.name, ".tasty") val outstream = new DataOutputStream(outTastyFile.bufferedOutput) @@ -233,6 +231,8 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter try outstream.write(binary) finally outstream.close() } else { + val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, binary) + store.visitAttribute(dataAttr) // Create an empty file to signal that a tasty section exist in the corresponding .class // This is much cheaper and simpler to check than doing classfile parsing getFileForClassfile(outF, store.name, ".hasTasty") From 41f6215c2c7754f0a4b7b8bead4b3466c7d6c15a Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 22 Nov 2017 15:17:07 +0100 Subject: [PATCH 2/3] Load tasty from .tasty file if compiled with -YemmitTasty --- .../dotty/tools/backend/jvm/GenBCode.scala | 30 +++++++++++-------- .../dotc/core/classfile/ClassfileParser.scala | 10 +++++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala index fe6e92f1757b..0c6015fa304d 100644 --- a/compiler/src/dotty/tools/backend/jvm/GenBCode.scala +++ b/compiler/src/dotty/tools/backend/jvm/GenBCode.scala @@ -224,19 +224,23 @@ class GenBCodePipeline(val entryPoints: List[Symbol], val int: DottyBackendInter if (claszSymbol.isClass) // @DarkDimius is this test needed here? for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) { val store = if (mirrorC ne null) mirrorC else plainC - if (ctx.settings.emitTasty.value) { - val outTastyFile = getFileForClassfile(outF, store.name, ".tasty") - val outstream = new DataOutputStream(outTastyFile.bufferedOutput) - - try outstream.write(binary) - finally outstream.close() - } else { - val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, binary) - store.visitAttribute(dataAttr) - // Create an empty file to signal that a tasty section exist in the corresponding .class - // This is much cheaper and simpler to check than doing classfile parsing - getFileForClassfile(outF, store.name, ".hasTasty") - } + val tasty = + if (ctx.settings.emitTasty.value) { + val outTastyFile = getFileForClassfile(outF, store.name, ".tasty") + val outstream = new DataOutputStream(outTastyFile.bufferedOutput) + try outstream.write(binary) + finally outstream.close() + // TASTY attribute is created but 0 bytes are stored in it. + // A TASTY attribute has length 0 if and only if the .tasty file exists. + Array.empty[Byte] + } else { + // Create an empty file to signal that a tasty section exist in the corresponding .class + // This is much cheaper and simpler to check than doing classfile parsing + getFileForClassfile(outF, store.name, ".hasTasty") + binary + } + val dataAttr = new CustomAttr(nme.TASTYATTR.mangledString, tasty) + store.visitAttribute(dataAttr) } // -------------- bean info class, if needed -------------- diff --git a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala index 483153091f03..e13311ddeb4d 100644 --- a/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala +++ b/compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala @@ -13,7 +13,7 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch import typer.Checking.checkNonCyclic -import io.AbstractFile +import io.{AbstractFile, PlainFile} import scala.util.control.NonFatal object ClassfileParser { @@ -781,7 +781,13 @@ class ClassfileParser( if (scan(tpnme.TASTYATTR)) { val attrLen = in.nextInt - return unpickleTASTY(in.nextBytes(attrLen)) + if (attrLen == 0) { + // A tasty attribute implies the existence of the .tasty file + val file = new PlainFile(io.File(classfile.jpath).changeExtension("tasty")) + if (file.exists) return unpickleTASTY(new AbstractFileReader(file).nextBytes(file.sizeOption.get)) + else ctx.error("Could not find " + file) + } + else return unpickleTASTY(in.nextBytes(attrLen)) } if (scan(tpnme.ScalaATTR) && !scalaUnpickleWhitelist.contains(classRoot.name)) { From a667aa074b81bc713120d72f2569e4704474b522 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 22 Nov 2017 17:49:41 +0100 Subject: [PATCH 3/3] Add -YemitTasty pos test --- compiler/test/dotty/tools/dotc/CompilationTests.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index cc69e927e26f..cf9b12c26bd7 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -96,6 +96,7 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("../tests/pos-scala2", scala2Mode) + compileFilesInDir("../tests/pos", defaultOptions) + compileFilesInDir("../tests/pos-deep-subtype", allowDeepSubtypes) + + compileDir("../tests/pos/i1137-1", defaultOptions and "-YemitTasty") + compileFile( // succeeds despite -Xfatal-warnings because of -nowarn "../tests/neg/customArgs/xfatalWarnings.scala",