@@ -11,7 +11,7 @@ using UUIDs
11
11
using Random. DSFMT
12
12
using InteractiveUtils
13
13
14
- export @enter , @make_stack , @interpret , Compiled, JuliaStackFrame
14
+ export @enter , @make_stack , @interpret , Compiled, JuliaStackFrame, Breakpoints, breakpoint
15
15
16
16
module CompiledCalls
17
17
# This module is for handling intrinsics that must be compiled (llvmcall)
47
47
48
48
"""
49
49
`JuliaFrameCode` holds static information about a method or toplevel code.
50
- One `JuliaFrameCode` can be shared by many `JuliaFrameState ` calling frames.
50
+ One `JuliaFrameCode` can be shared by many `JuliaStackFrame ` calling frames.
51
51
52
52
Important fields:
53
53
- `scope`: the `Method` or `Module` in which this frame is to be evaluated
@@ -61,6 +61,7 @@ struct JuliaFrameCode
61
61
scope:: Union{Method,Module}
62
62
code:: CodeInfo
63
63
methodtables:: Vector{Union{Compiled,TypeMapEntry}} # line-by-line method tables for generic-function :call Exprs
64
+ breakpoints:: Vector{Tuple{Bool,Function}} # (isactive, condition)
64
65
used:: BitSet
65
66
wrapper:: Bool
66
67
generator:: Bool
@@ -69,7 +70,7 @@ struct JuliaFrameCode
69
70
end
70
71
71
72
function JuliaFrameCode (frame:: JuliaFrameCode ; wrapper = frame. wrapper, generator= frame. generator, fullpath= frame. fullpath)
72
- JuliaFrameCode (frame. scope, frame. code, frame. methodtables, frame. used,
73
+ JuliaFrameCode (frame. scope, frame. code, frame. methodtables, frame. breakpoints, frame . used,
73
74
wrapper, generator, fullpath)
74
75
end
75
76
@@ -80,8 +81,9 @@ function JuliaFrameCode(scope, code::CodeInfo; wrapper=false, generator=false, f
80
81
code = copy_codeinfo (code)
81
82
methodtables = Vector {Union{Compiled,TypeMapEntry}} (undef, length (code. code))
82
83
end
84
+ breakpoints = Vector {Tuple{Bool,Function}} (undef, length (code. code))
83
85
used = find_used (code)
84
- return JuliaFrameCode (scope, code, methodtables, used, wrapper, generator, fullpath)
86
+ return JuliaFrameCode (scope, code, methodtables, breakpoints, used, wrapper, generator, fullpath)
85
87
end
86
88
87
89
"""
@@ -211,6 +213,16 @@ function is_generated(meth)
211
213
isdefined (meth, :generator )
212
214
end
213
215
216
+ function sparam_syms (meth:: Method )
217
+ s = Symbol[]
218
+ sig = meth. sig
219
+ while sig isa UnionAll
220
+ push! (s, Symbol (sig. var. name))
221
+ sig = sig. body
222
+ end
223
+ return s
224
+ end
225
+
214
226
function namedtuple (kwargs)
215
227
names, types, vals = Symbol[], [], []
216
228
for pr in kwargs
@@ -269,6 +281,48 @@ function prepare_args(@nospecialize(f), allargs, kwargs)
269
281
return f, allargs
270
282
end
271
283
284
+ function prepare_framecode (method:: Method , argtypes; enter_generated= false )
285
+ sig = method. sig
286
+ isa (method, TypeMapEntry) && (method = method. func)
287
+ if method. module == Core. Compiler || method. module == Base. Threads || method ∈ compiled_methods
288
+ return Compiled ()
289
+ end
290
+ # Get static parameters
291
+ (ti, lenv:: SimpleVector ) = ccall (:jl_type_intersection_with_env , Any, (Any, Any),
292
+ argtypes, sig):: SimpleVector
293
+ enter_generated &= is_generated (method)
294
+ if is_generated (method) && ! enter_generated
295
+ framecode = get (genframedict, (method, argtypes), nothing )
296
+ else
297
+ framecode = get (framedict, method, nothing )
298
+ end
299
+ if framecode === nothing
300
+ if is_generated (method) && ! enter_generated
301
+ # If we're stepping into a staged function, we need to use
302
+ # the specialization, rather than stepping through the
303
+ # unspecialized method.
304
+ code = Core. Compiler. get_staged (Core. Compiler. code_for_method (method, argtypes, lenv, typemax (UInt), false ))
305
+ code === nothing && return nothing
306
+ generator = false
307
+ else
308
+ if is_generated (method)
309
+ code = get_source (method. generator)
310
+ generator = true
311
+ else
312
+ code = get_source (method)
313
+ generator = false
314
+ end
315
+ end
316
+ framecode = JuliaFrameCode (method, code; generator= generator)
317
+ if is_generated (method) && ! enter_generated
318
+ genframedict[(method, argtypes)] = framecode
319
+ else
320
+ framedict[method] = framecode
321
+ end
322
+ end
323
+ return framecode, lenv
324
+ end
325
+
272
326
function whichtt (tt)
273
327
m = ccall (:jl_gf_invoke_lookup , Any, (Any, UInt), tt, typemax (UInt))
274
328
m === nothing && return nothing
@@ -328,47 +382,17 @@ function prepare_call(@nospecialize(f), allargs; enter_generated = false)
328
382
f (allargs[2 : end ]. .. )
329
383
end
330
384
args = allargs
331
- sig = method. sig
332
- isa (method, TypeMapEntry) && (method = method. func)
333
- if method. module == Core. Compiler || method. module == Base. Threads || method ∈ compiled_methods
334
- return Compiled ()
335
- end
336
- # Get static parameters
337
- (ti, lenv:: SimpleVector ) = ccall (:jl_type_intersection_with_env , Any, (Any, Any),
338
- argtypes, sig):: SimpleVector
339
- enter_generated &= is_generated (method)
340
- if is_generated (method) && ! enter_generated
341
- framecode = get (genframedict, (method, argtypes), nothing )
342
- else
343
- framecode = get (framedict, method, nothing )
385
+ ret = prepare_framecode (method, argtypes; enter_generated= enter_generated)
386
+ # Exceptional returns
387
+ if ret === nothing
388
+ # The generator threw an error. Let's generate the same error by calling it.
389
+ f (allargs[2 : end ]. .. )
344
390
end
345
- if framecode === nothing
346
- if is_generated (method) && ! enter_generated
347
- # If we're stepping into a staged function, we need to use
348
- # the specialization, rather than stepping through the
349
- # unspecialized method.
350
- code = Core. Compiler. get_staged (Core. Compiler. code_for_method (method, argtypes, lenv, typemax (UInt), false ))
351
- generator = false
352
- if code === nothing
353
- # The generator threw an error. Let's generate the same error by calling it.
354
- f (allargs[2 : end ]. .. )
355
- end
356
- else
357
- if is_generated (method)
358
- args = Any[_Typeof (a) for a in args]
359
- code = get_source (method. generator)
360
- generator = true
361
- else
362
- code = get_source (method)
363
- generator = false
364
- end
365
- end
366
- framecode = JuliaFrameCode (method, code; generator= generator)
367
- if is_generated (method) && ! enter_generated
368
- genframedict[(method, argtypes)] = framecode
369
- else
370
- framedict[method] = framecode
371
- end
391
+ isa (ret, Compiled) && return ret
392
+ # Typical return
393
+ framecode, lenv = ret
394
+ if is_generated (method) && enter_generated
395
+ args = Any[_Typeof (a) for a in args]
372
396
end
373
397
return framecode, args, lenv, argtypes
374
398
end
@@ -793,6 +817,7 @@ function prepare_locals(framecode, argvals::Vector{Any})
793
817
pc = Ref (JuliaProgramCounter (1 ))
794
818
end
795
819
for i = 1 : meth. nargs
820
+ last_reference[framecode. code. slotnames[i]] = i
796
821
if meth. isva && i == meth. nargs
797
822
locals[i] = nargs < i ? Some {Any} (()) : (let i= i; Some {Any} (ntuple (k-> argvals[i+ k- 1 ], nargs- i+ 1 )); end )
798
823
break
@@ -1083,6 +1108,10 @@ function __init__()
1083
1108
set_compiled_methods ()
1084
1109
end
1085
1110
1111
+ include (" breakpoints.jl" )
1112
+ using . Breakpoints
1113
+ using . Breakpoints: shouldbreak, Breakpoint
1114
+
1086
1115
include (" precompile.jl" )
1087
1116
_precompile_ ()
1088
1117
0 commit comments