Skip to content

Commit 629fd26

Browse files
committed
simplify the backtrace of include
Using the ability to delete functions, we can make this code a bit nicer and simpler. (similar to #33087)
1 parent 51b3227 commit 629fd26

File tree

7 files changed

+75
-93
lines changed

7 files changed

+75
-93
lines changed

base/Base.jl

+54-46
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ baremodule Base
44

55
using Core.Intrinsics, Core.IR
66

7+
const _included_files = Array{Tuple{Module,String},1}()
8+
function include(mod::Module, path::String)
9+
ccall(:jl_array_grow_end, Cvoid, (Any, UInt), _included_files, UInt(1))
10+
Core.arrayset(true, _included_files, (mod, ccall(:jl_prepend_cwd, Any, (Any,), path)), arraylen(_included_files))
11+
Core.println(path)
12+
ccall(:jl_uv_flush, Nothing, (Ptr{Nothing},), Core.io_pointer(Core.stdout))
13+
Core.include(mod, path)
14+
end
15+
include(path::String) = include(Base, path)
16+
717
const is_primary_base_module = ccall(:jl_module_parent, Ref{Module}, (Any,), Base) === Core.Main
818
ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Base, is_primary_base_module)
919

@@ -20,50 +30,6 @@ setproperty!(x::Tuple, f::Int, v) = setfield!(x, f, v) # to get a decent error
2030
getproperty(Core.@nospecialize(x), f::Symbol) = getfield(x, f)
2131
setproperty!(x, f::Symbol, v) = setfield!(x, f, convert(fieldtype(typeof(x), f), v))
2232

23-
function include_relative end
24-
function include(mod::Module, path::AbstractString)
25-
local result
26-
if INCLUDE_STATE === 1
27-
result = _include1(mod, path)
28-
elseif INCLUDE_STATE === 2
29-
result = _include(mod, path)
30-
elseif INCLUDE_STATE === 3
31-
result = include_relative(mod, path)
32-
end
33-
result
34-
end
35-
function include(path::AbstractString)
36-
local result
37-
if INCLUDE_STATE === 1
38-
result = _include1(Base, path)
39-
elseif INCLUDE_STATE === 2
40-
result = _include(Base, path)
41-
else
42-
# to help users avoid error (accidentally evaluating into Base), this is not allowed
43-
error("Base.include(string) is discontinued, use `include(fname)` or `Base.include(@__MODULE__, fname)` instead.")
44-
end
45-
result
46-
end
47-
const _included_files = Array{Tuple{Module,String},1}()
48-
function _include1(mod::Module, path)
49-
Core.Compiler.push!(_included_files, (mod, ccall(:jl_prepend_cwd, Any, (Any,), path)))
50-
Core.include(mod, path)
51-
end
52-
let SOURCE_PATH = ""
53-
# simple, race-y TLS, relative include
54-
global _include
55-
function _include(mod::Module, path)
56-
prev = SOURCE_PATH
57-
path = normpath(joinpath(dirname(prev), path))
58-
push!(_included_files, (mod, abspath(path)))
59-
SOURCE_PATH = path
60-
result = Core.include(mod, path)
61-
SOURCE_PATH = prev
62-
result
63-
end
64-
end
65-
INCLUDE_STATE = 1 # include = Core.include
66-
6733
include("coreio.jl")
6834

6935
eval(x) = Core.eval(Base, x)
@@ -279,7 +245,21 @@ using .Math
279245
const ()=sqrt
280246
const ()=cbrt
281247

282-
INCLUDE_STATE = 2 # include = _include (from lines above)
248+
# now switch to a simple, race-y TLS, relative include for the rest of Base
249+
delete_method(which(include, (Module, String)))
250+
let SOURCE_PATH = ""
251+
global function include(mod::Module, path::String)
252+
prev = SOURCE_PATH
253+
path = normpath(joinpath(dirname(prev), path))
254+
Core.println(path)
255+
ccall(:jl_uv_flush, Nothing, (Ptr{Nothing},), Core.io_pointer(Core.stdout))
256+
push!(_included_files, (mod, abspath(path)))
257+
SOURCE_PATH = path
258+
result = Core.include(mod, path)
259+
SOURCE_PATH = prev
260+
return result
261+
end
262+
end
283263

284264
# reduction along dims
285265
include("reducedim.jl") # macros in this file relies on string.jl
@@ -377,6 +357,34 @@ if isdefined(Core, :Compiler) && is_primary_base_module
377357
Docs.loaddocs(Core.Compiler.CoreDocs.DOCS)
378358
end
379359

360+
# finally, now make `include` point to the full version
361+
for m in methods(include)
362+
delete_method(m)
363+
end
364+
# These functions are duplicated in client.jl/include(::String) for
365+
# nicer stacktraces. Modifications here have to be backported there
366+
include(mod::Module, path::AbstractString) = include(mod, convert(String, path))
367+
function include(mod::Module, _path::String)
368+
path, prev = _include_dependency(mod, _path)
369+
for callback in include_callbacks # to preserve order, must come before Core.include
370+
invokelatest(callback, mod, path)
371+
end
372+
tls = task_local_storage()
373+
tls[:SOURCE_PATH] = path
374+
local result
375+
try
376+
# result = Core.include(mod, path)
377+
result = ccall(:jl_load_, Any, (Any, Any), mod, path)
378+
finally
379+
if prev === nothing
380+
delete!(tls, :SOURCE_PATH)
381+
else
382+
tls[:SOURCE_PATH] = prev
383+
end
384+
end
385+
return result
386+
end
387+
380388
end_base_include = time_ns()
381389

382390
if is_primary_base_module
@@ -405,7 +413,7 @@ function __init__()
405413
nothing
406414
end
407415

408-
INCLUDE_STATE = 3 # include = include_relative
416+
409417
end
410418

411419
const tot_time_stdlib = RefValue(0.0)

base/client.jl

+7-6
Original file line numberDiff line numberDiff line change
@@ -429,23 +429,24 @@ end
429429

430430
# MainInclude exists to hide Main.include and eval from `names(Main)`.
431431
baremodule MainInclude
432+
using ..Base
432433
# We inline the definition of include from loading.jl/include_relative to get one-frame stacktraces.
433434
# include(fname::AbstractString) = Main.Base.include(Main, fname)
434435
function include(fname::AbstractString)
435436
mod = Main
436-
isa(fname, String) || (fname = String(fname))
437-
path, prev = Main.Base._include_dependency(mod, fname)
438-
for callback in Main.Base.include_callbacks # to preserve order, must come before Core.include
439-
Main.Base.invokelatest(callback, mod, path)
437+
isa(fname, String) || (fname = convert(String, fname))
438+
path, prev = Base._include_dependency(mod, fname)
439+
for callback in Base.include_callbacks # to preserve order, must come before Core.include
440+
Base.invokelatest(callback, mod, path)
440441
end
441-
tls = Main.Base.task_local_storage()
442+
tls = Base.task_local_storage()
442443
tls[:SOURCE_PATH] = path
443444
local result
444445
try
445446
result = ccall(:jl_load_, Any, (Any, Any), mod, path)
446447
finally
447448
if prev === nothing
448-
Main.Base.delete!(tls, :SOURCE_PATH)
449+
Base.delete!(tls, :SOURCE_PATH)
449450
else
450451
tls[:SOURCE_PATH] = prev
451452
end

base/loading.jl

+1-24
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ function _require(pkg::PkgId)
10501050
ccall(:jl_set_module_uuid, Cvoid, (Any, NTuple{2, UInt64}), __toplevel__, uuid)
10511051
end
10521052
try
1053-
include_relative(__toplevel__, path)
1053+
include(__toplevel__, path)
10541054
return
10551055
finally
10561056
if uuid !== old_uuid
@@ -1092,29 +1092,6 @@ function source_dir()
10921092
return p === nothing ? pwd() : dirname(p)
10931093
end
10941094

1095-
# These functions are duplicated in client.jl/include(::String) for
1096-
# nicer stacktraces. Modifications here have to be backported there
1097-
include_relative(mod::Module, path::AbstractString) = include_relative(mod, String(path))
1098-
function include_relative(mod::Module, _path::String)
1099-
path, prev = _include_dependency(mod, _path)
1100-
for callback in include_callbacks # to preserve order, must come before Core.include
1101-
invokelatest(callback, mod, path)
1102-
end
1103-
tls = task_local_storage()
1104-
tls[:SOURCE_PATH] = path
1105-
local result
1106-
try
1107-
result = Core.include(mod, path)
1108-
finally
1109-
if prev === nothing
1110-
delete!(tls, :SOURCE_PATH)
1111-
else
1112-
tls[:SOURCE_PATH] = prev
1113-
end
1114-
end
1115-
return result
1116-
end
1117-
11181095
"""
11191096
Base.include([m::Module,] path::AbstractString)
11201097

src/jl_uv.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ static void uv_flush_callback(uv_write_t *req, int status)
157157
// Turn a normal write into a blocking write (primarily for use from C and gdb).
158158
// Warning: This calls uv_run, so it can have unbounded side-effects.
159159
// Be care where you call it from! - the libuv loop is also not reentrant.
160-
void jl_uv_flush(uv_stream_t *stream)
160+
JL_DLLEXPORT void jl_uv_flush(uv_stream_t *stream)
161161
{
162162
if (stream == (void*)STDIN_FILENO ||
163163
stream == (void*)STDOUT_FILENO ||

src/rtutils.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -496,16 +496,18 @@ JL_DLLEXPORT void jl_flush_cstdio(void) JL_NOTSAFEPOINT
496496

497497
JL_DLLEXPORT jl_value_t *jl_stdout_obj(void) JL_NOTSAFEPOINT
498498
{
499-
if (jl_base_module == NULL) return NULL;
500-
jl_value_t *stdout_obj = jl_get_module_binding(jl_base_module, jl_symbol("stdout"))->value;
501-
return stdout_obj;
499+
if (jl_base_module == NULL)
500+
return NULL;
501+
jl_binding_t *stdout_obj = jl_get_module_binding(jl_base_module, jl_symbol("stdout"));
502+
return stdout_obj ? stdout_obj->value : NULL;
502503
}
503504

504505
JL_DLLEXPORT jl_value_t *jl_stderr_obj(void) JL_NOTSAFEPOINT
505506
{
506-
if (jl_base_module == NULL) return NULL;
507-
jl_value_t *stderr_obj = jl_get_module_binding(jl_base_module, jl_symbol("stderr"))->value;
508-
return stderr_obj;
507+
if (jl_base_module == NULL)
508+
return NULL;
509+
jl_binding_t *stderr_obj = jl_get_module_binding(jl_base_module, jl_symbol("stderr"));
510+
return stderr_obj ? stderr_obj->value : NULL;
509511
}
510512

511513
// toys for debugging ---------------------------------------------------------

src/toplevel.c

-6
Original file line numberDiff line numberDiff line change
@@ -865,12 +865,6 @@ JL_DLLEXPORT jl_value_t *jl_infer_thunk(jl_code_info_t *thk, jl_module_t *m)
865865

866866
JL_DLLEXPORT jl_value_t *jl_load(jl_module_t *module, const char *fname)
867867
{
868-
if (module->istopmod) {
869-
jl_printf(JL_STDOUT, "%s\r\n", fname);
870-
#ifdef _OS_WINDOWS_
871-
jl_uv_flush(JL_STDOUT);
872-
#endif
873-
}
874868
uv_stat_t stbuf;
875869
if (jl_stat(fname, (char*)&stbuf) != 0 || (stbuf.st_mode & S_IFMT) != S_IFREG) {
876870
jl_errorf("could not open file %s", fname);

test/precompile.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,11 @@ try
144144
missing, missing, missing,
145145
missing, missing, 6]
146146
147-
let some_method = which(Base.include, (String,))
147+
let some_method = which(Base.include, (Module, String,))
148148
# global const some_method // FIXME: support for serializing a direct reference to an external Method not implemented
149149
global const some_linfo =
150150
ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt),
151-
some_method, Tuple{typeof(Base.include), String}, Core.svec(), typemax(UInt))
151+
some_method, Tuple{typeof(Base.include), Module, String}, Core.svec(), typemax(UInt))
152152
end
153153
154154
g() = override(1.0)
@@ -287,10 +287,10 @@ try
287287
Val{3},
288288
Val{nothing}},
289289
0:25)
290-
some_method = which(Base.include, (String,))
290+
some_method = which(Base.include, (Module, String,))
291291
some_linfo =
292292
ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any, UInt),
293-
some_method, Tuple{typeof(Base.include), String}, Core.svec(), typemax(UInt))
293+
some_method, Tuple{typeof(Base.include), Module, String}, Core.svec(), typemax(UInt))
294294
@test Foo.some_linfo::Core.MethodInstance === some_linfo
295295

296296
ft = Base.datatype_fieldtypes

0 commit comments

Comments
 (0)