From 1f44fa3ac17ceacc753019092bc50436c77ddcfa Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 14 Sep 2021 18:23:39 +0100 Subject: [PATCH] Revert "[Dexter] Improve performance by evaluating expressions only when needed" Reverted due to build failure on greendragon lldb build. This reverts commit 9bbc0c1ffb47f9cf4c9d8e9a0e8100002fe5aafb. --- .../dexter/dex/command/CommandBase.py | 3 --- .../dex/command/commands/DexExpectProgramState.py | 22 ++++--------------- .../dex/command/commands/DexExpectWatchBase.py | 8 +++---- .../dexter/dex/debugger/DebuggerBase.py | 15 ------------- .../dexter/dex/debugger/dbgeng/dbgeng.py | 12 +++-------- .../dexter/dex/debugger/lldb/LLDB.py | 20 ++++++----------- .../dex/debugger/visualstudio/VisualStudio.py | 25 +++++++++------------- 7 files changed, 26 insertions(+), 79 deletions(-) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/CommandBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/CommandBase.py index fdeb97f..49e9086 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/CommandBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/CommandBase.py @@ -10,11 +10,8 @@ which will then be executed by DExTer during debugging. """ import abc -from collections import namedtuple from typing import List -StepExpectInfo = namedtuple('StepExpectInfo', 'expression, path, frame_idx, line_range') - class CommandBase(object, metaclass=abc.ABCMeta): def __init__(self): self.path = None diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py index 24b760a..26f97b6 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectProgramState.py @@ -10,7 +10,7 @@ during execution. from itertools import chain -from dex.command.CommandBase import CommandBase, StepExpectInfo +from dex.command.CommandBase import CommandBase from dex.dextIR import ProgramState, SourceLocation, StackFrame, DextIR def frame_from_dict(source: dict) -> StackFrame: @@ -56,23 +56,9 @@ class DexExpectProgramState(CommandBase): return __class__.__name__ def get_watches(self): - frame_expects = set() - for idx, frame in enumerate(self.expected_program_state.frames): - path = (frame.location.path if - frame.location and frame.location.path else self.path) - line_range = ( - range(frame.location.lineno, frame.location.lineno + 1) - if frame.location and frame.location.lineno else None) - for watch in frame.watches: - frame_expects.add( - StepExpectInfo( - expression=watch, - path=path, - frame_idx=idx, - line_range=line_range - ) - ) - return frame_expects + frame_expects = chain.from_iterable(frame.watches + for frame in self.expected_program_state.frames) + return set(frame_expects) def eval(self, step_collection: DextIR) -> bool: for step in step_collection.steps: diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py index 1c2d544..e892f01 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/command/commands/DexExpectWatchBase.py @@ -12,13 +12,11 @@ import abc import difflib import os -from collections import namedtuple -from dex.command.CommandBase import CommandBase, StepExpectInfo +from dex.command.CommandBase import CommandBase from dex.command.StepValueInfo import StepValueInfo - class DexExpectWatchBase(CommandBase): def __init__(self, *args, **kwargs): if len(args) < 2: @@ -70,7 +68,7 @@ class DexExpectWatchBase(CommandBase): def get_watches(self): - return [StepExpectInfo(self.expression, self.path, 0, range(self._from_line, self._to_line + 1))] + return [self.expression] @property def line_range(self): @@ -151,11 +149,11 @@ class DexExpectWatchBase(CommandBase): return differences def eval(self, step_collection): - assert os.path.exists(self.path) for step in step_collection.steps: loc = step.current_location if (loc.path and os.path.exists(loc.path) and + os.path.exists(self.path) and os.path.samefile(loc.path, self.path) and loc.lineno in self.line_range): try: diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py index a795b3b0..c31be77 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py @@ -13,26 +13,11 @@ import traceback import unittest from types import SimpleNamespace -from dex.command.CommandBase import StepExpectInfo from dex.dextIR import DebuggerIR, FrameIR, LocIR, StepIR, ValueIR from dex.utils.Exceptions import DebuggerException from dex.utils.Exceptions import NotYetLoadedDebuggerException from dex.utils.ReturnCode import ReturnCode -def watch_is_active(watch_info: StepExpectInfo, path, frame_idx, line_no): - _, watch_path, watch_frame_idx, watch_line_range = watch_info - # If this watch should only be active for a specific file... - if watch_path and os.path.isfile(watch_path): - # If the current path does not match the expected file, this watch is - # not active. - if not (path and os.path.isfile(path) and - os.path.samefile(path, watch_path)): - return False - if watch_frame_idx != frame_idx: - return False - if watch_line_range and line_no not in list(watch_line_range): - return False - return True class DebuggerBase(object, metaclass=abc.ABCMeta): def __init__(self, context): diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py index 2b13398..c95aa54 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py @@ -9,7 +9,7 @@ import sys import os import platform -from dex.debugger.DebuggerBase import DebuggerBase, watch_is_active +from dex.debugger.DebuggerBase import DebuggerBase from dex.dextIR import FrameIR, LocIR, StepIR, StopReason, ValueIR from dex.dextIR import ProgramState, StackFrame, SourceLocation from dex.utils.Exceptions import DebuggerException, LoadDebuggerException @@ -133,14 +133,8 @@ class DbgEng(DebuggerBase): column=0), watches={}) for expr in map( - # Filter out watches that are not active in the current frame, - # and then evaluate all the active watches. - lambda watch_info, idx=i: - self.evaluate_expression(watch_info.expression, idx), - filter( - lambda watch_info, idx=i, line_no=loc.lineno, path=loc.path: - watch_is_active(watch_info, path, idx, line_no), - watches)): + lambda watch, idx=i: self.evaluate_expression(watch, idx), + watches): state_frame.watches[expr.expression] = expr state_frames.append(state_frame) diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py index 410e31f..e8e8939 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py @@ -12,7 +12,7 @@ import os from subprocess import CalledProcessError, check_output, STDOUT import sys -from dex.debugger.DebuggerBase import DebuggerBase, watch_is_active +from dex.debugger.DebuggerBase import DebuggerBase from dex.dextIR import FrameIR, LocIR, StepIR, StopReason, ValueIR from dex.dextIR import StackFrame, SourceLocation, ProgramState from dex.utils.Exceptions import DebuggerException, LoadDebuggerException @@ -208,7 +208,6 @@ class LLDB(DebuggerBase): 'column': sb_line.GetColumn() } loc = LocIR(**loc_dict) - valid_loc_for_watch = loc.path and os.path.exists(loc.path) frame = FrameIR( function=function, is_inlined=sb_frame.IsInlined(), loc=loc) @@ -224,18 +223,11 @@ class LLDB(DebuggerBase): is_inlined=frame.is_inlined, location=SourceLocation(**loc_dict), watches={}) - if valid_loc_for_watch: - for expr in map( - # Filter out watches that are not active in the current frame, - # and then evaluate all the active watches. - lambda watch_info, idx=i: - self.evaluate_expression(watch_info.expression, idx), - filter( - lambda watch_info, idx=i, line_no=loc.lineno, loc_path=loc.path: - watch_is_active(watch_info, loc_path, idx, line_no), - watches)): - state_frame.watches[expr.expression] = expr - state_frames.append(state_frame) + for expr in map( + lambda watch, idx=i: self.evaluate_expression(watch, idx), + watches): + state_frame.watches[expr.expression] = expr + state_frames.append(state_frame) if len(frames) == 1 and frames[0].function is None: frames = [] diff --git a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py index e36b353..b4558e2 100644 --- a/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py +++ b/cross-project-tests/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py @@ -11,10 +11,10 @@ import imp import os import sys from pathlib import PurePath -from collections import defaultdict, namedtuple +from collections import namedtuple +from collections import defaultdict -from dex.command.CommandBase import StepExpectInfo -from dex.debugger.DebuggerBase import DebuggerBase, watch_is_active +from dex.debugger.DebuggerBase import DebuggerBase from dex.dextIR import FrameIR, LocIR, StepIR, StopReason, ValueIR from dex.dextIR import StackFrame, SourceLocation, ProgramState from dex.utils.Exceptions import Error, LoadDebuggerException @@ -244,9 +244,6 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst state_frames = [] - loc = LocIR(**self._location) - valid_loc_for_watch = loc.path and os.path.exists(loc.path) - for idx, sf in enumerate(stackframes): frame = FrameIR( function=self._sanitize_function_name(sf.FunctionName), @@ -257,20 +254,20 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst if any(name in fname for name in self.frames_below_main): break + state_frame = StackFrame(function=frame.function, is_inlined=frame.is_inlined, watches={}) - if valid_loc_for_watch and idx == 0: - for watch_info in watches: - if watch_is_active(watch_info, loc.path, idx, loc.lineno): - watch_expr = watch_info.expression - state_frame.watches[watch_expr] = self.evaluate_expression(watch_expr, idx) + for watch in watches: + state_frame.watches[watch] = self.evaluate_expression( + watch, idx) state_frames.append(state_frame) frames.append(frame) + loc = LocIR(**self._location) if frames: frames[0].loc = loc state_frames[0].location = SourceLocation(**self._location) @@ -301,11 +298,9 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst ] def evaluate_expression(self, expression, frame_idx=0) -> ValueIR: - if frame_idx != 0: - self.set_current_stack_frame(frame_idx) + self.set_current_stack_frame(frame_idx) result = self._debugger.GetExpression(expression) - if frame_idx != 0: - self.set_current_stack_frame(0) + self.set_current_stack_frame(0) value = result.Value is_optimized_away = any(s in value for s in [ -- 2.7.4