From ce96c1b9a8e6ceea164ac5e27a4672e382190bae Mon Sep 17 00:00:00 2001 From: Sergey Rostov Date: Thu, 7 Jun 2018 11:02:33 +0300 Subject: [PATCH] jps, daemon: fix javascript inline functions tracking inline function hash should computed after compilation --- .../compilerRunner/KotlinCompilerRunner.kt | 10 ++- .../CompilerCallbackServicesFacadeServer.kt | 11 +-- .../daemon/daemon-common/build.gradle.kts | 1 + .../common/CompilerCallbackServicesFacade.kt | 3 +- .../kotlin/daemon/CompileServiceImpl.kt | 2 +- .../RemoteIncrementalResultsConsumer.kt | 22 +++++- .../js/IncrementalResultsConsumer.kt | 67 +++++++++++++------ 7 files changed, 82 insertions(+), 34 deletions(-) diff --git a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt index ca4b7936496..98bae152818 100644 --- a/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt +++ b/compiler/compiler-runner/src/org/jetbrains/kotlin/compilerRunner/KotlinCompilerRunner.kt @@ -58,9 +58,15 @@ abstract class KotlinCompilerRunner { clientAliveFlagFile: File, sessionAliveFlagFile: File, environment: Env, - daemonOptions: DaemonOptions = configureDaemonOptions() + daemonOptions: DaemonOptions = configureDaemonOptions(), + additionalJvmParams: Array = arrayOf() ): CompileServiceSession? { - val daemonJVMOptions = configureDaemonJVMOptions(inheritMemoryLimits = true, inheritOtherJvmOptions = false, inheritAdditionalProperties = true) + val daemonJVMOptions = configureDaemonJVMOptions( + additionalParams = *additionalJvmParams, + inheritMemoryLimits = true, + inheritOtherJvmOptions = false, + inheritAdditionalProperties = true + ) val daemonReportMessages = ArrayList() val daemonReportingTargets = DaemonReportingTargets(messages = daemonReportMessages) diff --git a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt index 217e0be12cf..fb3ee0d1c92 100644 --- a/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt +++ b/compiler/daemon/daemon-client/src/org/jetbrains/kotlin/daemon/client/CompilerCallbackServicesFacadeServer.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.incremental.components.LookupInfo import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.js.IncrementalDataProvider import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer +import org.jetbrains.kotlin.incremental.js.JsInlineFunctionHash import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.modules.TargetId @@ -128,14 +129,8 @@ open class CompilerCallbackServicesFacadeServer( incrementalResultsConsumer!!.processPackagePart(File(sourceFilePath), packagePartMetadata, binaryAst) } - override fun incrementalResultsConsumer_processInlineFunction( - sourceFilePath: String, - fqName: String, - inlineFunction: Any, - line: Int, - column: Int - ) { - incrementalResultsConsumer!!.processInlineFunction(File(sourceFilePath), fqName, inlineFunction, line, column) + override fun incrementalResultsConsumer_processInlineFunctions(functions: Collection) { + incrementalResultsConsumer!!.processInlineFunctions(functions) } override fun incrementalDataProvider_getHeaderMetadata(): ByteArray = incrementalDataProvider!!.headerMetadata diff --git a/compiler/daemon/daemon-common/build.gradle.kts b/compiler/daemon/daemon-common/build.gradle.kts index ccc33b3b637..81398cc6b66 100644 --- a/compiler/daemon/daemon-common/build.gradle.kts +++ b/compiler/daemon/daemon-common/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { compile(project(":compiler:util")) compile(project(":compiler:cli-common")) compile(projectDist(":kotlin-stdlib")) + compileOnly(project(":js:js.frontend")) compileOnly(intellijCoreDep()) { includeJars("intellij-core") } compileOnly(intellijDep()) { includeIntellijCoreJarDependencies(project) } } diff --git a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt index df4d56690c2..c2f9d4e9f1a 100644 --- a/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt +++ b/compiler/daemon/daemon-common/src/org/jetbrains/kotlin/daemon/common/CompilerCallbackServicesFacade.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.daemon.common import org.jetbrains.kotlin.incremental.components.LookupInfo +import org.jetbrains.kotlin.incremental.js.JsInlineFunctionHash import org.jetbrains.kotlin.load.kotlin.incremental.components.JvmPackagePartProto import org.jetbrains.kotlin.modules.TargetId import java.io.Serializable @@ -109,7 +110,7 @@ interface CompilerCallbackServicesFacade : Remote { fun incrementalResultsConsumer_processPackagePart(sourceFilePath: String, packagePartMetadata: ByteArray, binaryAst: ByteArray) @Throws(RemoteException::class) - fun incrementalResultsConsumer_processInlineFunction(sourceFilePath: String, fqName: String, inlineFunction: Any, line: Int, column: Int) + fun incrementalResultsConsumer_processInlineFunctions(functions: Collection) // --------------------------------------------------- // IncrementalDataProvider (js) diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt index c5fa9d963f4..1fe167002e4 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/CompileServiceImpl.kt @@ -951,7 +951,7 @@ class CompileServiceImpl( builder.register(ExpectActualTracker::class.java, RemoteExpectActualTracker(facade, rpcProfiler)) } if (facade.hasIncrementalResultsConsumer()) { - builder.register(IncrementalResultsConsumer::class.java, RemoteIncrementalResultsConsumer(facade, rpcProfiler)) + builder.register(IncrementalResultsConsumer::class.java, RemoteIncrementalResultsConsumer(facade, eventManager, rpcProfiler)) } if (facade.hasIncrementalDataProvider()) { builder.register(IncrementalDataProvider::class.java, RemoteIncrementalDataProvider(facade, rpcProfiler)) diff --git a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt index 93e3016e1c9..f5457bb2bed 100644 --- a/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt +++ b/compiler/daemon/src/org/jetbrains/kotlin/daemon/RemoteIncrementalResultsConsumer.kt @@ -7,11 +7,17 @@ package org.jetbrains.kotlin.daemon import org.jetbrains.kotlin.daemon.common.CompilerCallbackServicesFacade import org.jetbrains.kotlin.daemon.common.Profiler +import org.jetbrains.kotlin.incremental.js.FunctionWithSourceInfo import org.jetbrains.kotlin.incremental.js.IncrementalResultsConsumer +import org.jetbrains.kotlin.incremental.js.JsInlineFunctionHash import java.io.File -class RemoteIncrementalResultsConsumer(val facade: CompilerCallbackServicesFacade, val rpcProfiler: Profiler) : +class RemoteIncrementalResultsConsumer(val facade: CompilerCallbackServicesFacade, eventManager: EventManager, val rpcProfiler: Profiler) : IncrementalResultsConsumer { + init { + eventManager.onCompilationFinished(this::flush) + } + override fun processHeader(headerMetadata: ByteArray) { rpcProfiler.withMeasure(this) { facade.incrementalResultsConsumer_processHeader(headerMetadata) @@ -24,9 +30,21 @@ class RemoteIncrementalResultsConsumer(val facade: CompilerCallbackServicesFacad } } + private class JsInlineFunction(val sourceFilePath: String, val fqName: String, val inlineFunction: FunctionWithSourceInfo) + + private val deferInlineFuncs = mutableListOf() + override fun processInlineFunction(sourceFile: File, fqName: String, inlineFunction: Any, line: Int, column: Int) { + deferInlineFuncs.add(JsInlineFunction(sourceFile.path, fqName, FunctionWithSourceInfo(inlineFunction, line, column))) + } + + override fun processInlineFunctions(functions: Collection) = error("Should not be called in Daemon Server") + + fun flush() { rpcProfiler.withMeasure(this) { - facade.incrementalResultsConsumer_processInlineFunction(sourceFile.path, fqName, inlineFunction.toString(), line, column) + facade.incrementalResultsConsumer_processInlineFunctions(deferInlineFuncs.map { + JsInlineFunctionHash(it.sourceFilePath, it.fqName, it.inlineFunction.md5) + }) } } } diff --git a/js/js.frontend/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt b/js/js.frontend/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt index 73f4bf4a478..6449d0e1b99 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/incremental/js/IncrementalResultsConsumer.kt @@ -17,18 +17,35 @@ package org.jetbrains.kotlin.incremental.js import java.io.File +import java.io.Serializable import java.security.MessageDigest interface IncrementalResultsConsumer { /** processes new header metadata (serialized [JsProtoBuf.Header]) */ fun processHeader(headerMetadata: ByteArray) + /** processes new package part metadata and binary tree for compiled source file */ fun processPackagePart(sourceFile: File, packagePartMetadata: ByteArray, binaryAst: ByteArray) - /** [inlineFunction] is expected to be a body of inline function (an instance of [JsNode]), + + /** + * [inlineFunction] is expected to be a body of inline function (an instance of [JsNode]), * but [Any] is used to avoid classloader conflicts in tests where the compiler is isolated - * (such as [JsProtoComparisonTestGenerated]) + * (such as [JsProtoComparisonTestGenerated]). */ fun processInlineFunction(sourceFile: File, fqName: String, inlineFunction: Any, line: Int, column: Int) + + /** + * Alternative to [processInlineFunction]: record all inline functions after it was processed. + * Used in daemon RPC. + */ + fun processInlineFunctions(functions: Collection) +} + +class JsInlineFunctionHash(val sourceFilePath: String, val fqName: String, val inlineFunctionMd5Hash: Long): Serializable + +class FunctionWithSourceInfo(val expression: Any, val line: Int, val column: Int) { + val md5: Long + get() = "($line:$column)$expression".toByteArray().md5() } class IncrementalResultsConsumerImpl : IncrementalResultsConsumer { @@ -39,22 +56,27 @@ class IncrementalResultsConsumerImpl : IncrementalResultsConsumer { val packageParts: Map get() = _packageParts - private class FunctionWithSourceInfo(val expression: Any, val line: Int, val column: Int) - private val _inlineFuncs = hashMapOf>() + private val _deferInlineFuncs = hashMapOf>() + private var _processedInlineFuncs: Collection? = null val inlineFunctions: Map> get() { - val result = HashMap>(_inlineFuncs.size) + val result = HashMap>(_deferInlineFuncs.size) - for ((file, inlineFnsFromFile) in _inlineFuncs) { + for ((file, inlineFnsFromFile) in _deferInlineFuncs) { val functionsHashes = HashMap(inlineFnsFromFile.size) for ((fqName, fn) in inlineFnsFromFile) { - functionsHashes[fqName] = "(${fn.line}:${fn.column})${fn.expression}".toByteArray().md5() + functionsHashes[fqName] = fn.md5 } result[file] = functionsHashes } + _processedInlineFuncs?.forEach { + val fileFunctions = result.getOrPut(File(it.sourceFilePath)) { mutableMapOf() } + fileFunctions[it.fqName] = it.inlineFunctionMd5Hash + } + return result } @@ -66,21 +88,26 @@ class IncrementalResultsConsumerImpl : IncrementalResultsConsumer { _packageParts.put(sourceFile, TranslationResultValue(packagePartMetadata, binaryAst)) } - override fun processInlineFunction(sourceFile: File, fqName: String, inlineFunction: Any, line: Int, column: Int) { - val mapForSource = _inlineFuncs.getOrPut(sourceFile) { hashMapOf() } - mapForSource[fqName] = FunctionWithSourceInfo(inlineFunction, line, column) + override fun processInlineFunctions(functions: Collection) { + check(_processedInlineFuncs == null) + _processedInlineFuncs = functions } - private fun ByteArray.md5(): Long { - val d = MessageDigest.getInstance("MD5").digest(this)!! - return ((d[0].toLong() and 0xFFL) - or ((d[1].toLong() and 0xFFL) shl 8) - or ((d[2].toLong() and 0xFFL) shl 16) - or ((d[3].toLong() and 0xFFL) shl 24) - or ((d[4].toLong() and 0xFFL) shl 32) - or ((d[5].toLong() and 0xFFL) shl 40) - or ((d[6].toLong() and 0xFFL) shl 48) - or ((d[7].toLong() and 0xFFL) shl 56)) + override fun processInlineFunction(sourceFile: File, fqName: String, inlineFunction: Any, line: Int, column: Int) { + val mapForSource = _deferInlineFuncs.getOrPut(sourceFile) { hashMapOf() } + mapForSource[fqName] = FunctionWithSourceInfo(inlineFunction, line, column) } } +private fun ByteArray.md5(): Long { + val d = MessageDigest.getInstance("MD5").digest(this)!! + return ((d[0].toLong() and 0xFFL) + or ((d[1].toLong() and 0xFFL) shl 8) + or ((d[2].toLong() and 0xFFL) shl 16) + or ((d[3].toLong() and 0xFFL) shl 24) + or ((d[4].toLong() and 0xFFL) shl 32) + or ((d[5].toLong() and 0xFFL) shl 40) + or ((d[6].toLong() and 0xFFL) shl 48) + or ((d[7].toLong() and 0xFFL) shl 56)) +} +