aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2024-09-09 10:23:46 +0200
committerMattias EngdegÄrd2024-09-09 10:30:02 +0200
commit87daaaf9a463720f2ec80201d8f1e41aa29bd7ce (patch)
treef5334f2695df4ff3997b71fe1c8fbd4bdf92208e
parent95371fa754260199a6ea3428721270a89c341928 (diff)
downloademacs-87daaaf9a463720f2ec80201d8f1e41aa29bd7ce.tar.gz
emacs-87daaaf9a463720f2ec80201d8f1e41aa29bd7ce.zip
Speed up LLDB support for debugging Emacs
* etc/emacs_lldb.py (Lisp_Object): Perform some numeric operations in Python instead of invoking LLDB for evaluation. Add lots of caches.
-rw-r--r--etc/emacs_lldb.py117
1 files changed, 79 insertions, 38 deletions
diff --git a/etc/emacs_lldb.py b/etc/emacs_lldb.py
index 219361faffd..8393fccf467 100644
--- a/etc/emacs_lldb.py
+++ b/etc/emacs_lldb.py
@@ -104,62 +104,103 @@ class Lisp_Object:
104 # the pvec_type enumerator if the object is a vector-like, as a 104 # the pvec_type enumerator if the object is a vector-like, as a
105 # string. 105 # string.
106 def init_lisp_types(self): 106 def init_lisp_types(self):
107 t = self.eval(f"(enum Lisp_Type)" 107 GCTYPEBITS = self.unsigned_const('GCTYPEBITS')
108 f"((EMACS_INT) {self.unsigned} " 108 self.lisp_type = self.tag_name(self.unsigned
109 f"& (1 << GCTYPEBITS) - 1)") 109 & ((1 << GCTYPEBITS) - 1))
110 self.lisp_type = enumerator_name(t)
111 if self.lisp_type == "Lisp_Vectorlike": 110 if self.lisp_type == "Lisp_Vectorlike":
112 self.pvec_type = "PVEC_NORMAL_VECTOR" 111 self.pvec_type = "PVEC_NORMAL_VECTOR"
113 vector = self.get_lisp_pointer("struct Lisp_Vector") 112 vector = self.get_lisp_pointer("struct Lisp_Vector")
114 size = vector.GetValueForExpressionPath("->header.size") 113 size = vector.GetValueForExpressionPath("->header.size")
115 size = size.GetValueAsUnsigned() 114 size = size.GetValueAsUnsigned()
116 pseudo = self.eval(f"{size} & PSEUDOVECTOR_FLAG") 115 PSEUDOVECTOR_FLAG = self.unsigned_const('PSEUDOVECTOR_FLAG')
117 if pseudo.GetValueAsUnsigned() != 0: 116 if size & PSEUDOVECTOR_FLAG:
118 typ = self.eval( 117 PVEC_TYPE_MASK = self.unsigned_const(
119 f"(enum pvec_type) (({size} " 118 'More_Lisp_Bits::PVEC_TYPE_MASK')
120 f"& More_Lisp_Bits::PVEC_TYPE_MASK) " 119 PSEUDOVECTOR_AREA_BITS = self.unsigned_const(
121 f">> More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS)") 120 'More_Lisp_Bits::PSEUDOVECTOR_AREA_BITS')
122 self.pvec_type = enumerator_name(typ) 121 pvec = (size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS
122 self.pvec_type = self.pvec_name(pvec)
123 123
124 # Initialize self.untagged according to lisp_type and pvec_type. 124 # Initialize self.untagged according to lisp_type and pvec_type.
125 def init_values(self): 125 def init_values(self):
126 if self.lisp_type == "Lisp_Symbol": 126 lt = self.lisp_type
127 if lt == "Lisp_Symbol":
127 offset = self.get_lisp_pointer("char").GetValueAsUnsigned() 128 offset = self.get_lisp_pointer("char").GetValueAsUnsigned()
128 self.untagged = self.eval(f"(struct Lisp_Symbol *)" 129 self.untagged = self.eval(
129 f" ((char *) &lispsym + {offset})", 130 f"(struct Lisp_Symbol *)((char *)&lispsym + {offset})")
130 True) 131 elif lt == "Lisp_String":
131 elif self.lisp_type == "Lisp_String": 132 self.untagged = self.get_lisp_pointer("struct Lisp_String")
132 self.untagged = self.get_lisp_pointer("struct Lisp_String", True) 133 elif lt == "Lisp_Vectorlike":
133 elif self.lisp_type == "Lisp_Vectorlike":
134 c_type = Lisp_Object.pvec2type[self.pvec_type] 134 c_type = Lisp_Object.pvec2type[self.pvec_type]
135 self.untagged = self.get_lisp_pointer(c_type, True) 135 self.untagged = self.get_lisp_pointer(c_type)
136 elif self.lisp_type == "Lisp_Cons": 136 elif lt == "Lisp_Cons":
137 self.untagged = self.get_lisp_pointer("struct Lisp_Cons", True) 137 self.untagged = self.get_lisp_pointer("struct Lisp_Cons")
138 elif self.lisp_type == "Lisp_Float": 138 elif lt == "Lisp_Float":
139 self.untagged = self.get_lisp_pointer("struct Lisp_Float", True) 139 self.untagged = self.get_lisp_pointer("struct Lisp_Float")
140 elif self.lisp_type in ("Lisp_Int0", "Lisp_Int1"): 140 elif lt in ("Lisp_Int0", "Lisp_Int1"):
141 self.untagged = self.eval(f"((EMACS_INT) {self.unsigned}) " 141 GCTYPEBITS = self.unsigned_const('GCTYPEBITS')
142 f">> (GCTYPEBITS - 1)", True) 142 x = self.unsigned >> (GCTYPEBITS - 1)
143 elif self.lisp_type == "Lisp_Type_Unused0": 143 self.untagged = self.eval(f"(EMACS_INT){x})")
144 elif lt == "Lisp_Type_Unused0":
144 self.untagged = self.unsigned 145 self.untagged = self.unsigned
145 else: 146 else:
146 assert False, f"Unknown Lisp type {self.lisp_type}" 147 assert False, f"Unknown Lisp type {self.lisp_type}"
147 148
149 # Get a numeric constant (unsigned).
150 const_cache = {}
151 def unsigned_const(self, name):
152 val = self.const_cache.get(name)
153 if val is None:
154 frame = self.tagged.GetFrame()
155 val = frame.EvaluateExpression(name).GetValueAsUnsigned()
156 self.const_cache[name] = val
157 return val
158
159 # Get the name of a Lisp_Object tag value, like "Lisp_String".
160 tag_cache = {}
161 def tag_name(self, tag):
162 name = self.tag_cache.get(tag)
163 if name is None:
164 frame = self.tagged.GetFrame()
165 val = frame.EvaluateExpression(f"(enum Lisp_Type){tag}")
166 name = enumerator_name(val)
167 self.tag_cache[tag] = name
168 return name
169
170 # Get the name of a pseudovector type tag, like "PVEC_HASH_TABLE".
171 pvec_cache = {}
172 def pvec_name(self, pvec):
173 name = self.pvec_cache.get(pvec)
174 if name is None:
175 frame = self.tagged.GetFrame()
176 val = frame.EvaluateExpression(f"(enum pvec_type){pvec}")
177 name = enumerator_name(val)
178 self.pvec_cache[pvec] = name
179 return name
180
148 # Evaluate EXPR in the context of the current frame. 181 # Evaluate EXPR in the context of the current frame.
149 def eval(self, expr, make_var=False): 182 eval_cache = {}
150 frame = self.tagged.GetFrame() 183 def eval(self, expr):
151 if make_var: 184 val = self.eval_cache.get(expr)
152 return frame.EvaluateExpression(expr) 185 if val is None:
153 options = lldb.SBExpressionOptions() 186 frame = self.tagged.GetFrame()
154 options.SetSuppressPersistentResult(True) 187 val = frame.EvaluateExpression(expr)
155 return frame.EvaluateExpression(expr, options) 188 self.eval_cache[expr] = val
189 return val
156 190
157 # Return an SBValue for this object denoting a pointer of type 191 # Return an SBValue for this object denoting a pointer of type
158 # TYP*. 192 # TYP*.
159 def get_lisp_pointer(self, typ, make_var=False): 193 lisp_ptr_cache = {}
160 return self.eval(f"({typ}*) (((EMACS_INT) " 194 def get_lisp_pointer(self, typ):
161 f"{self.unsigned}) & VALMASK)", 195 uns = self.unsigned
162 make_var) 196 ptr = self.lisp_ptr_cache.get((uns, typ))
197 if ptr is None:
198 VALMASK = self.unsigned_const('VALMASK')
199 frame = self.tagged.GetFrame()
200 ptr = frame.EvaluateExpression(
201 f"({typ}*)(EMACS_INT){uns & VALMASK}")
202 self.lisp_ptr_cache[(uns, typ)] = ptr
203 return ptr
163 204
164 # If this is a Lisp_String, return an SBValue for its string data. 205 # If this is a Lisp_String, return an SBValue for its string data.
165 # Return None otherwise. 206 # Return None otherwise.