Skip to content

Commit

Permalink
Replace helper class compilation with precompiled class loading
Browse files Browse the repository at this point in the history
Remove runInDebuggerThread helper method because it causes misunderstanding on which thread the action will be dispatched
  • Loading branch information
Soarex16 committed Apr 29, 2022
1 parent 4668757 commit 06a6931
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 46 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// Copyright 2000-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.streams.trace.breakpoint

import com.intellij.debugger.engine.DebugProcessImpl
import com.intellij.debugger.engine.DebuggerManagerThreadImpl
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.engine.events.DebuggerCommandImpl
import com.intellij.debugger.impl.PrioritizedTask
import com.intellij.openapi.diagnostic.logger
import com.sun.jdi.ClassNotPreparedException
import com.sun.jdi.Method
Expand All @@ -16,22 +12,6 @@ private val LOG = logger<DebuggerUtils>()
* @author Shumaf Lovpache
*/
object DebuggerUtils {
fun runInDebuggerThread(debugProcess: DebugProcessImpl, action: () -> Unit) {
val command = object : DebuggerCommandImpl(PrioritizedTask.Priority.NORMAL) {
override fun action() {
action()
}
}

val managerThread = debugProcess.managerThread
if (DebuggerManagerThreadImpl.isManagerThread()) {
managerThread.invoke(command)
}
else {
managerThread.schedule(command)
}
}

fun findVmMethod(evaluationContext: EvaluationContextImpl, signature: MethodSignature): Method? {
val fqClassName = signature.containingClass
val vmClass = evaluationContext.loadClass(fqClassName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ import com.intellij.openapi.compiler.ClassObject

object HelperClassUtils {
const val STREAM_DEBUGGER_UTILS_CLASS_NAME = "com.intellij.debugger.streams.generated.java.StreamDebuggerUtils"
const val STREAM_DEBUGGER_UTILS_SOURCE = "/classes/StreamDebuggerUtils.java.txt"
const val STREAM_DEBUGGER_UTILS_CLASS_FILE = "/classes/compiled/StreamDebuggerUtils.class"

fun getCompiledHelperClass(context: EvaluationContextImpl, resourceName: String, className: String): ClassObject? = javaClass
fun compileClass(context: EvaluationContextImpl, resourceName: String, className: String): ClassObject? = javaClass
.getResourceAsStream(resourceName).use {
if (it == null) throw CodeCompilationException("Could not load $resourceName")

val source = it.bufferedReader().readText()
return compileJavaCode(className, source, context)
}

fun getStreamDebuggerUtilsClass(context: EvaluationContextImpl) = getCompiledHelperClass(
context,
STREAM_DEBUGGER_UTILS_SOURCE,
STREAM_DEBUGGER_UTILS_CLASS_NAME
fun getCompiledClass(resourceName: String): ByteArray? = javaClass
.getResourceAsStream(resourceName)
?.readAllBytes()

fun getStreamDebuggerUtilsClass() = getCompiledClass(
STREAM_DEBUGGER_UTILS_CLASS_FILE
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ package com.intellij.debugger.streams.trace.breakpoint

import com.intellij.debugger.engine.JavaDebugProcess
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.engine.events.DebuggerCommandImpl
import com.intellij.debugger.impl.ClassLoadingUtils
import com.intellij.debugger.impl.PrioritizedTask
import com.intellij.debugger.streams.StreamDebuggerBundle
import com.intellij.debugger.streams.trace.StreamTracer
import com.intellij.debugger.streams.trace.TraceResultInterpreter
import com.intellij.debugger.streams.trace.TracingCallback
import com.intellij.debugger.streams.trace.breakpoint.DebuggerUtils.runInDebuggerThread
import com.intellij.debugger.streams.trace.breakpoint.HelperClassUtils.getCompiledHelperClass
import com.intellij.debugger.streams.trace.breakpoint.HelperClassUtils.getCompiledClass
import com.intellij.debugger.streams.trace.breakpoint.collector.*
import com.intellij.debugger.streams.trace.breakpoint.ex.BreakpointPlaceNotFoundException
import com.intellij.debugger.streams.trace.breakpoint.ex.BreakpointTracingException
import com.intellij.debugger.streams.trace.breakpoint.formatter.StreamTraceFormatter
import com.intellij.debugger.streams.trace.breakpoint.formatter.StreamTraceFormatterImpl
import com.intellij.debugger.streams.wrapper.StreamChain
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.diagnostic.logger
import com.intellij.xdebugger.XDebugSession

Expand All @@ -29,9 +31,13 @@ class MethodBreakpointTracer(private val session: XDebugSession,
private val resultInterpreter: TraceResultInterpreter) : StreamTracer {
override fun trace(chain: StreamChain, callback: TracingCallback) {
val xDebugProcess = session.debugProcess as? JavaDebugProcess ?: return
runInDebuggerThread(xDebugProcess.debuggerSession.process) {
trace(xDebugProcess, chain, callback)
val runTraceCommand = object : DebuggerCommandImpl(PrioritizedTask.Priority.NORMAL) {
override fun action() {
trace(xDebugProcess, chain, callback)
}
}
val debuggerManagerThread = xDebugProcess.debuggerSession.process.managerThread
debuggerManagerThread.schedule(runTraceCommand)
}

private fun trace(debugProcess: JavaDebugProcess, chain: StreamChain, callback: TracingCallback) {
Expand All @@ -43,7 +49,8 @@ class MethodBreakpointTracer(private val session: XDebugSession,
val executionCallback = TracingCallbackWrapper(chain, callback, resultInterpreter, traceFormatter)
val locations = try {
breakpointResolver.findBreakpointPlaces(chain)
} catch (e: BreakpointPlaceNotFoundException) {
}
catch (e: BreakpointPlaceNotFoundException) {
executionCallback.breakpointSetupFailed(e)
return
}
Expand Down Expand Up @@ -78,7 +85,8 @@ class MethodBreakpointTracer(private val session: XDebugSession,
// if qualifier expression is variable we need to replace it in current stack frame
val qualifierExpressionValue = breakpointFactory.replaceQualifierExpressionValue()
null // TODO: восстанавливать значение qualifierExpression после вычисления стрима
} else {
}
else {
// set additional breakpoint as for an intermediate operation
breakpointFactory
.createProducerStepBreakpoint(locations.qualifierExpressionMethod)
Expand All @@ -98,16 +106,16 @@ class MethodBreakpointTracer(private val session: XDebugSession,
private fun createValueManager(context: EvaluationContextImpl): ValueManager {
val container = ValueManagerImpl(context)
container.registerBytecodeFactory(OBJECT_COLLECTOR_CLASS_NAME) {
getCompiledHelperClass(context, OBJECT_COLLECTOR_SOURCE, OBJECT_COLLECTOR_CLASS_NAME)!!.content
getCompiledClass(OBJECT_COLLECTOR_CLASS_FILE)
}
container.registerBytecodeFactory(INT_COLLECTOR_CLASS_NAME) {
getCompiledHelperClass(context, INT_COLLECTOR_SOURCE, INT_COLLECTOR_CLASS_NAME)!!.content
getCompiledClass(INT_COLLECTOR_CLASS_FILE)
}
container.registerBytecodeFactory(LONG_COLLECTOR_CLASS_NAME) {
getCompiledHelperClass(context, LONG_COLLECTOR_SOURCE, LONG_COLLECTOR_CLASS_NAME)!!.content
getCompiledClass(LONG_COLLECTOR_CLASS_FILE)
}
container.registerBytecodeFactory(DOUBLE_COLLECTOR_CLASS_NAME) {
getCompiledHelperClass(context, DOUBLE_COLLECTOR_SOURCE, DOUBLE_COLLECTOR_CLASS_NAME)!!.content
getCompiledClass(DOUBLE_COLLECTOR_CLASS_FILE)
}
return container
}
Expand Down Expand Up @@ -136,24 +144,26 @@ class MethodBreakpointTracer(private val session: XDebugSession,
}
catch (t: Throwable) {
// TODO: change trace expression field
tracingCallback.evaluationFailed("", StreamDebuggerBundle.message("evaluation.failed.cannot.interpret.result", t.message!!))
runInEdt {
tracingCallback.evaluationFailed("", StreamDebuggerBundle.message("evaluation.failed.cannot.interpret.result", t.message!!))
}
throw t
}
// TODO: clear value manager when window closed
tracingCallback.evaluated(interpretedResult, context)
runInEdt { tracingCallback.evaluated(interpretedResult, context) }
}

override fun breakpointSetupFailed(e: Throwable) {
override fun breakpointSetupFailed(e: Throwable) = runInEdt {
tracingCallback.evaluationFailed("", StreamDebuggerBundle.message("evaluation.failed.cannot.find.places.for.breakpoints"))
LOG.error(e)
}

override fun tracingSetupFailed(e: Throwable) {
override fun tracingSetupFailed(e: Throwable) = runInEdt {
tracingCallback.evaluationFailed("", StreamDebuggerBundle.message("evaluation.failed.cannot.initialize.breakpoints"))
LOG.error(e)
}

override fun streamExecutionFailed(e: Throwable) {
override fun streamExecutionFailed(e: Throwable) = runInEdt {
tracingCallback.evaluationFailed("", StreamDebuggerBundle.message("evaluation.failed.exception.occurred.during.stream.execution"))
LOG.error(e)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const val INT_COLLECTOR_CLASS_NAME = "com.intellij.debugger.streams.generated.ja
const val LONG_COLLECTOR_CLASS_NAME = "com.intellij.debugger.streams.generated.java.collector.LongCollector"
const val DOUBLE_COLLECTOR_CLASS_NAME = "com.intellij.debugger.streams.generated.java.collector.DoubleCollector"

const val OBJECT_COLLECTOR_SOURCE = "/classes/ObjectCollector.java.txt"
const val INT_COLLECTOR_SOURCE = "/classes/IntCollector.java.txt"
const val LONG_COLLECTOR_SOURCE = "/classes/LongCollector.java.txt"
const val DOUBLE_COLLECTOR_SOURCE = "/classes/DoubleCollector.java.txt"
const val OBJECT_COLLECTOR_CLASS_FILE = "/classes/compiled/ObjectCollector.class"
const val INT_COLLECTOR_CLASS_FILE = "/classes/compiled/IntCollector.class"
const val LONG_COLLECTOR_CLASS_FILE = "/classes/compiled/LongCollector.class"
const val DOUBLE_COLLECTOR_CLASS_FILE = "/classes/compiled/DoubleCollector.class"

const val COLLECTOR_SIGNATURE = "(Ljava/util/Map;Ljava/util/concurrent/atomic/AtomicInteger;)V"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import com.sun.jdi.Value
open class PeekTraceFormatter(private val valueManager: ValueManager) : TraceFormatter {
private val helperClass = valueManager.watch {
defineClass(STREAM_DEBUGGER_UTILS_CLASS_NAME) {
getStreamDebuggerUtilsClass(evaluationContext)?.content
getStreamDebuggerUtilsClass()
}
}

Expand Down

0 comments on commit 06a6931

Please sign in to comment.