Skip to content

Commit

Permalink
Sync with master, do some refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nikolay-egorov committed Nov 25, 2021
1 parent b85ac51 commit d0d5a1d
Show file tree
Hide file tree
Showing 14 changed files with 681 additions and 1,062 deletions.
4 changes: 1 addition & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ plugins {

val deploy: Configuration by configurations.creating

val serializationFlagProperty = "jupyter.serialization.enabled"

deploy.apply {
exclude("org.jetbrains.kotlinx", "kotlinx-serialization-json-jvm")
exclude("org.jetbrains.kotlinx", "kotlinx-serialization-core-jvm")
Expand Down Expand Up @@ -117,7 +115,7 @@ tasks {
"junit.jupiter.execution.parallel.enabled" to doParallelTesting.toString() as Any,
"junit.jupiter.execution.parallel.mode.default" to "concurrent",
"junit.jupiter.execution.parallel.mode.classes.default" to "concurrent",
serializationFlagProperty to "true"
"jupyter.serialization.enabled" to "true"
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package org.jetbrains.kotlinx.jupyter.api

import java.lang.reflect.Field
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.isAccessible

interface VariableState {
Expand Down Expand Up @@ -34,16 +33,17 @@ data class VariableStateImpl(
try {
value.toString()
} catch (e: Throwable) {
if (e is StackOverflowError) {
isRecursive = true
}
"${value::class.simpleName}: [exception thrown: $e]"
}
}
}
override var isRecursive: Boolean = false
private var isLargeForString: Boolean = false

private val valCache = VariableStateCache<Result<Any?>> (
{
oldValue, newValue ->
private val valCache = VariableStateCache<Result<Any?>>(
{ oldValue, newValue ->
oldValue.getOrNull() !== newValue.getOrNull()
},
{
Expand All @@ -63,75 +63,50 @@ data class VariableStateImpl(
}
}

override val stringValue: String? get() = stringCache.get()
override val stringValue: String? get() = stringCache.getOrNull()

override val value: Result<Any?> get() = valCache.get()

companion object {
private fun <T : KProperty<*>, R> T.asAccessible(action: (T) -> R): R {
@SuppressWarnings("DEPRECATED")
private fun <R> Field.asAccessible(action: (Field) -> R): R {
val wasAccessible = isAccessible
isAccessible = true
val res = action(this)
isAccessible = wasAccessible
return res
}
}
private val customDelegate = DependentLazyDelegate {
fun getRecursiveObjectName(): String {
val kClassName = cachedValue.getOrNull()!!::class.simpleName
return "$kClassName: recursive structure"
}
if (cachedValue.getOrNull() == null) {
return@DependentLazyDelegate null
}
handleIfRecursiveStructure()
try {
cachedValue.getOrNull().toString()
isRecursive = false
isLargeForString = false
} catch (e: VirtualMachineError) {
when (e) {
is StackOverflowError -> {
isRecursive = true
}
is OutOfMemoryError -> {
isLargeForString = true
}
else -> {
return@DependentLazyDelegate null
}
}
}
}

private class VariableStateCache<T>(
val equalityChecker: (T, T) -> Boolean = { x, y -> x == y },
val calculate: (T?) -> T
) {
private var cachedVal: T? = null
private var shouldRenew: Boolean = true
private class VariableStateCache<T>(
val equalityChecker: (T, T) -> Boolean = { x, y -> x == y },
val calculate: (T?) -> T
) {
private var cachedVal: T? = null
private var shouldRenew: Boolean = true

fun getOrNull(): T? {
return if (shouldRenew) {
calculate(cachedVal).also {
cachedVal = it
shouldRenew = false
fun getOrNull(): T? {
return if (shouldRenew) {
calculate(cachedVal).also {
cachedVal = it
shouldRenew = false
}
} else {
cachedVal
}
} else {
cachedVal
}
}

fun get(): T = getOrNull()!!
fun get(): T = getOrNull()!!

fun update() {
shouldRenew = true
}
fun update() {
shouldRenew = true
}

fun forceUpdate(): Boolean {
val oldVal = getOrNull()
update()
val newVal = get()
return oldVal != null && equalityChecker(oldVal, newVal)
fun forceUpdate(): Boolean {
val oldVal = getOrNull()
update()
val newVal = get()
return oldVal != null && equalityChecker(oldVal, newVal)
}
}
}
7 changes: 1 addition & 6 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/apiImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.jetbrains.kotlinx.jupyter.api.RenderersProcessor
import org.jetbrains.kotlinx.jupyter.api.ResultsAccessor
import org.jetbrains.kotlinx.jupyter.api.VariableState
import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryResolutionRequest
import org.jetbrains.kotlinx.jupyter.repl.InternalEvaluator
import org.jetbrains.kotlinx.jupyter.repl.impl.SharedReplContext

class DisplayResultWrapper private constructor(
Expand Down Expand Up @@ -152,16 +153,10 @@ class NotebookImpl(
get() = JavaRuntime

fun updateVariablesState(evaluator: InternalEvaluator) {
variablesState += evaluator.variablesHolder
currentCellVariables = evaluator.cellVariables
_unchangedVariables.clear()
_unchangedVariables.addAll(evaluator.getUnchangedVariables())
}

fun updateVariablesState(varsStateUpdate: Map<String, VariableState>) {
variablesState += varsStateUpdate
}

fun variablesReportAsHTML(): String {
return generateHTMLVarsReport(variablesState)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ enum class MessageType(val contentClass: KClass<out MessageContent>) {
LIST_ERRORS_REQUEST(ListErrorsRequest::class),
LIST_ERRORS_REPLY(ListErrorsReply::class),

SERIALIZATION_REQUEST(SerializationRequest::class),
SERIALIZATION_REPLY(SerializationReply::class);
// from Serialization_Request
VARIABLES_VIEW_REQUEST(SerializationRequest::class),
VARIABLES_VIEW_REPLY(SerializationReply::class);

val type: String
get() = name.lowercase()
Expand Down
8 changes: 4 additions & 4 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/protocol.kt
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,8 @@ fun JupyterConnection.Socket.shellMessagesHandler(msg: Message, repl: ReplForJup
return
}
log.debug("Message type in CommOpen: $msg, ${msg.type}")
val data = content.data ?: return sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY))
if (data.isEmpty()) return sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY))
val data = content.data ?: return sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY))
if (data.isEmpty()) return sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY))
log.debug("Message data: $data")
val messageContent = getVariablesDescriptorsFromJson(data)
connection.launchJob {
Expand Down Expand Up @@ -348,10 +348,10 @@ fun JupyterConnection.Socket.shellMessagesHandler(msg: Message, repl: ReplForJup
connection.launchJob {
if (content.topLevelDescriptorName.isNotEmpty()) {
repl.serializeVariables(content.topLevelDescriptorName, content.descriptorsState, commID = content.commId, content.pathToDescriptor) { result ->
sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY, content = result))
sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY, content = result))
}
} else {
sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY, content = null))
sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY, content = null))
}
}
}
Expand Down
7 changes: 3 additions & 4 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,8 @@ class ReplForJupyterImpl(
} ?: emptyList()

notebook.updateVariablesState(internalEvaluator)
// printVars()
// printUsagesInfo(jupyterId, cellVariables[jupyterId - 1])
val variablesCells: Map<String, Int> = notebook.variablesState.mapValues { internalEvaluator.findVariableCell(it.key) }
val variablesCells: Map<String, Int?> = notebook.variablesState.mapValues { internalEvaluator.findVariableCell(it.key) }
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState, oldDeclarations, variablesCells, notebook.unchangedVariables)

GlobalScope.launch(Dispatchers.Default) {
Expand Down Expand Up @@ -576,8 +575,8 @@ class ReplForJupyterImpl(
private fun doSerializeVariables(args: SerializationArgs): SerializationReply {
val resultMap = mutableMapOf<String, SerializedVariablesState>()
val cellId = if (args.cellId != -1) args.cellId else {
val watcherInfo = internalEvaluator.findVariableCell(args.topLevelVarName) + 1
val finalAns = if (watcherInfo == - 1) 1 else watcherInfo
val watcherInfo = internalEvaluator.findVariableCell(args.topLevelVarName)
val finalAns = if (watcherInfo == null) 1 else watcherInfo + 1
finalAns
}
args.descriptorsState.forEach { (name, state) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ interface InternalEvaluator {
/**
* Get a cellId where a particular variable is declared
*/
fun findVariableCell(variableName: String): Int
fun findVariableCell(variableName: String): Int?

fun getVariablesDeclarationInfo(): Map<String, Int>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ import org.jetbrains.kotlinx.jupyter.exceptions.ReplCompilerException
import org.jetbrains.kotlinx.jupyter.repl.ContextUpdater
import org.jetbrains.kotlinx.jupyter.repl.InternalEvalResult
import org.jetbrains.kotlinx.jupyter.repl.InternalEvaluator
import org.jetbrains.kotlinx.jupyter.repl.InternalVariablesMarkersProcessor
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import org.jetbrains.kotlinx.jupyter.repl.InternalVariablesMarkersProcessor
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty1
import kotlin.reflect.full.declaredMemberProperties
import kotlin.script.experimental.api.ResultValue
Expand Down Expand Up @@ -170,18 +169,28 @@ internal class InternalEvaluatorImpl(
val kClass = target.scriptClass ?: return emptyMap()
val cellClassInstance = target.scriptInstance!!

val fields = kClass.declaredMemberProperties
val fields = kClass.java.declaredFields
// ignore implementation details of top level like script instance and result value
val kProperties = kClass.declaredMemberProperties.associateBy { it.name }

return mutableMapOf<String, VariableStateImpl>().apply {
val addedDeclarations = mutableSetOf<String>()
for (property in fields) {
@Suppress("UNCHECKED_CAST")
property as KProperty1<Any, *>
if (internalVariablesMarkersProcessor.isInternal(property)) continue

val state = VariableStateImpl(property, cellClassInstance)

val isInternalKProperty = kProperties[property.name]?.let {
@Suppress("UNCHECKED_CAST")
it as KProperty1<Any, *>
internalVariablesMarkersProcessor.isInternal(it)
}

if (isInternalKProperty == true || !kProperties.contains(property.name)) continue

variablesWatcher.addDeclaration(cellId, property.name)
addedDeclarations.add(property.name)

// it was val, now it's var
if (property is KMutableProperty1) {
if (isValField(property)) {
variablesHolder.remove(property.name)
} else {
variablesHolder[property.name] = state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ class VariablesSerializer(
clearOldData(currentCellId, cellVariables)
}

fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, oldDeclarations: Map<String, Int>, variablesCells: Map<String, Int>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, oldDeclarations: Map<String, Int>, variablesCells: Map<String, Int?>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
if (!isSerializationActive) return emptyMap()

if (variablesState.isEmpty()) {
Expand Down
2 changes: 0 additions & 2 deletions src/main/kotlin/org/jetbrains/kotlinx/jupyter/util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,12 @@ class VariablesUsagesPerCellWatcher<K : Any, V : Any> {
private val unchangedVariables: MutableSet<V> = mutableSetOf()

fun removeOldDeclarations(address: K, newDeclarations: Set<V>) {
// removeIf?
cellVariables[address]?.forEach {
val predicate = newDeclarations.contains(it) && variablesDeclarationInfo[it] != address
if (predicate) {
variablesDeclarationInfo.remove(it)
unchangedVariables.remove(it)
}
// predicate
}

// add old declarations as unchanged
Expand Down
Loading

0 comments on commit d0d5a1d

Please sign in to comment.