From 0d519e18acc1e9734d29146f8b903d813c6098ca Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 Jun 2016 21:51:13 -0400 Subject: [PATCH 1/4] reconnect REPL backend consumer reference to client.jl fix #6752 --- base/REPL.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/base/REPL.jl b/base/REPL.jl index 4f29b97d4f33c..977fb156bdfc4 100644 --- a/base/REPL.jl +++ b/base/REPL.jl @@ -163,6 +163,7 @@ function run_repl(repl::AbstractREPL, consumer = x->nothing) repl_channel = Channel(1) response_channel = Channel(1) backend = start_repl_backend(repl_channel, response_channel) + consumer(backend) run_frontend(repl, REPLBackendRef(repl_channel,response_channel)) return backend end From a0428882715583600811fc7c9953358fb739aa6f Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 Jun 2016 21:56:53 -0400 Subject: [PATCH 2/4] resolve compiler warnings --- src/gc-debug.c | 2 +- src/julia.h | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gc-debug.c b/src/gc-debug.c index 5175ac86d947d..e504a2a4ec749 100644 --- a/src/gc-debug.c +++ b/src/gc-debug.c @@ -472,6 +472,7 @@ void objprofile_printall(void) } #endif +#if defined(GC_TIME) || defined(GC_FINAL_STATS) STATIC_INLINE double jl_ns2ms(int64_t t) { return t / (double)1e6; @@ -482,7 +483,6 @@ STATIC_INLINE double jl_ns2s(int64_t t) return t / (double)1e9; } -#if defined(GC_TIME) || defined(GC_FINAL_STATS) static uint64_t gc_premark_end; static uint64_t gc_postmark_end; void gc_settime_premark_end(void) diff --git a/src/julia.h b/src/julia.h index 1aea33ae36abb..a8bf0bae84c36 100644 --- a/src/julia.h +++ b/src/julia.h @@ -70,14 +70,16 @@ extern "C" { typedef struct _jl_value_t jl_value_t; +struct _jl_taggedvalue_bits { + uintptr_t gc:2; +}; + struct _jl_taggedvalue_t { union { uintptr_t header; jl_taggedvalue_t *next; jl_value_t *type; // 16-byte aligned - struct { - uintptr_t gc:2; - } bits; + struct _jl_taggedvalue_bits bits; }; // jl_value_t value; }; From 041df161c42f71d659b4c1d2c139e918dce1dec7 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 Jun 2016 22:03:42 -0400 Subject: [PATCH 3/4] win: fix frontend printing of "#" fix #6016 --- src/flisp/print.c | 19 +++++++++++++++---- test/core.jl | 6 ++---- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/flisp/print.c b/src/flisp/print.c index f39472b1f505a..0d498fea117f9 100644 --- a/src/flisp/print.c +++ b/src/flisp/print.c @@ -636,17 +636,28 @@ static void cvalue_printdata(fl_context_t *fl_ctx, ios_t *f, void *data, numerictype_t nt = sym_to_numtype(fl_ctx, type); if (nt == N_NUMTYPES) { // These states should be context independent. - static size_t (*volatile jl_static_print)(ios_t*, void*) = 0; + static size_t (*volatile jl_static_print)(ios_t*, void*) = NULL; static volatile int init = 0; if (init == 0) { #if defined(RTLD_SELF) - jl_static_print = (size_t (*)(ios_t *, void *)) dlsym(RTLD_SELF, "jl_static_show"); + jl_static_print = (size_t (*)(ios_t*, void*)) + dlsym(RTLD_SELF, "jl_static_show"); #elif defined(RTLD_DEFAULT) - jl_static_print = (size_t (*)(ios_t *, void *)) dlsym(RTLD_DEFAULT, "jl_static_show"); + jl_static_print = (size_t (*)(ios_t*, void*)) + dlsym(RTLD_DEFAULT, "jl_static_show"); +#elif defined(_OS_WINDOWS_) + HMODULE handle; + if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, + (LPCWSTR)(&cvalue_printdata), + &handle)) { + jl_static_print = (size_t (*)(ios_t*, void*)) + GetProcAddress(handle, "jl_static_show"); + } #endif init = 1; } - if (jl_static_print != 0 && fl_ctx->jl_sym == type) { + if (jl_static_print != NULL && fl_ctx->jl_sym == type) { fl_ctx->HPOS += ios_printf(f, "#HPOS += jl_static_print(f, *(void**)data); fl_ctx->HPOS += ios_printf(f, ">"); diff --git a/test/core.jl b/test/core.jl index 434738762d341..bd7cfe0fb8d8b 100644 --- a/test/core.jl +++ b/test/core.jl @@ -1734,10 +1734,8 @@ let end # make sure front end can correctly print values to error messages -let - ex = expand(parse("\"a\"=1")) - @test ex == Expr(:error, "invalid assignment location \"\"a\"\"") || - ex == Expr(:error, "invalid assignment location \"#\"") +let ex = expand(parse("\"a\"=1")) + @test ex == Expr(:error, "invalid assignment location \"\"a\"\"") end # make sure that incomplete tags are detected correctly From ca6b83eb1941eec689e0a8766beeb84914b9ccd6 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 13 Jun 2016 23:43:37 -0400 Subject: [PATCH 4/4] define Core.IO types to provide STDOUT/STDERR early this expands the IO definitions that were in Core.Inference, and makes them more generically pluggable into the Base IO subsystem fix #12841 --- base/boot.jl | 38 +++++++++++++++++++++++++++++++++++- base/coreimg.jl | 18 ++++++++++------- base/coreio.jl | 31 +++++++++++++++++++++++++++++ base/essentials.jl | 2 -- base/exports.jl | 1 - base/libuv.jl | 6 +++--- base/process.jl | 15 --------------- base/show.jl | 1 - base/strings/io.jl | 3 --- base/sysimg.jl | 22 +++++++++++++++------ doc/devdocs/stdio.rst | 4 ++-- src/gf.c | 4 ++-- src/jl_uv.c | 18 ++++++++++++----- test/show.jl | 45 +++++++++++++++++++++++++++++++++++++------ 14 files changed, 154 insertions(+), 54 deletions(-) create mode 100644 base/coreio.jl diff --git a/base/boot.jl b/base/boot.jl index 19e245aefa20f..cac4eacccd061 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -127,7 +127,7 @@ export Signed, Int, Int8, Int16, Int32, Int64, Int128, Unsigned, UInt, UInt8, UInt16, UInt32, UInt64, UInt128, # string types - Char, DirectIndexString, AbstractString, String, + Char, DirectIndexString, AbstractString, String, IO, # errors BoundsError, DivideError, DomainError, Exception, InexactError, InterruptException, OutOfMemoryError, ReadOnlyMemoryError, OverflowError, @@ -319,6 +319,7 @@ Array{T}(::Type{T}, m::Int) = Array{T,1}(m) Array{T}(::Type{T}, m::Int,n::Int) = Array{T,2}(m,n) Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o) + # docsystem basics macro doc(x...) atdoc(x...) @@ -332,6 +333,41 @@ end atdoc = (str, expr) -> Expr(:escape, expr) atdoc!(λ) = global atdoc = λ + +# simple stand-alone print definitions for debugging +abstract IO +type CoreSTDOUT <: IO end +type CoreSTDERR <: IO end +const STDOUT = CoreSTDOUT() +const STDERR = CoreSTDERR() +io_pointer(::CoreSTDOUT) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stdout, Ptr{Void}), 1) +io_pointer(::CoreSTDERR) = Intrinsics.pointerref(Intrinsics.cglobal(:jl_uv_stderr, Ptr{Void}), 1) + +unsafe_write(io::IO, x::Ptr{UInt8}, nb::UInt) = + (ccall(:jl_uv_puts, Void, (Ptr{Void}, Ptr{UInt8}, UInt), io_pointer(io), x, nb); nb) +unsafe_write(io::IO, x::Ptr{UInt8}, nb::Int) = + (ccall(:jl_uv_puts, Void, (Ptr{Void}, Ptr{UInt8}, Int), io_pointer(io), x, nb); nb) +write(io::IO, x::UInt8) = + (ccall(:jl_uv_putb, Void, (Ptr{Void}, UInt8), io_pointer(io), x); 1) +function write(io::IO, x::String) + nb = sizeof(x.data) + unsafe_write(io, ccall(:jl_array_ptr, Ptr{UInt8}, (Any,), x.data), nb) + return nb +end + +show(io::IO, x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), io_pointer(io), x) +print(io::IO, x::Char) = ccall(:jl_uv_putc, Void, (Ptr{Void}, Char), io_pointer(io), x) +print(io::IO, x::String) = write(io, x) +print(io::IO, x::ANY) = show(io, x) +print(io::IO, x::ANY, a::ANY...) = (print(io, x); print(io, a...)) +println(io::IO) = write(io, 0x0a) # 0x0a = '\n' +println(io::IO, x::ANY...) = (print(io, x...); println(io)) + +show(a::ANY) = show(STDOUT, a) +print(a::ANY...) = print(STDOUT, a...) +println(a::ANY...) = println(STDOUT, a...) + + module TopModule # this defines the types that lowering expects to be defined in a (top) module # that are usually inherited from Core, but could be defined custom for a module diff --git a/base/coreimg.jl b/base/coreimg.jl index ff0e4928b404a..867a725490a04 100644 --- a/base/coreimg.jl +++ b/base/coreimg.jl @@ -2,6 +2,17 @@ Main.Core.eval(Main.Core, :(baremodule Inference using Core.TopModule, Core.Intrinsics +import Core: print, println, show, write, unsafe_write, STDOUT, STDERR +if false # show that the IO system is already (relatively) operational + print("HELLO") + println(" WORLD") + show("αβγ :)"); println() + println(STDERR, "TEST") + println(STDERR, STDERR) + println(STDERR, 'a') + println(STDERR, 'α') +end + ccall(:jl_set_istopmod, Void, (Bool,), false) eval(x) = Core.eval(Inference,x) @@ -9,13 +20,6 @@ eval(m,x) = Core.eval(m,x) include = Core.include -# simple print definitions for debugging. -show(x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), - pointerref(cglobal(:jl_uv_stdout,Ptr{Void}),1), x) -print(x::ANY) = show(x) -println(x::ANY) = ccall(:jl_, Void, (Any,), x) # includes a newline -print(a::ANY...) = for x=a; print(x); end - ## Load essential files and libraries include("essentials.jl") include("generator.jl") diff --git a/base/coreio.jl b/base/coreio.jl new file mode 100644 index 0000000000000..8e89c7fab4724 --- /dev/null +++ b/base/coreio.jl @@ -0,0 +1,31 @@ +# This file is a part of Julia. License is MIT: http://julialang.org/license + +show(x) = show(STDOUT::IO, x) +print(xs...) = print(STDOUT::IO, xs...) +println(xs...) = println(STDOUT::IO, xs...) +println(io::IO) = print(io, '\n') + +immutable DevNullStream <: IO end +const DevNull = DevNullStream() +isreadable(::DevNullStream) = false +iswritable(::DevNullStream) = true +isopen(::DevNullStream) = true +read(::DevNullStream, ::Type{UInt8}) = throw(EOFError()) +write(::DevNullStream, ::UInt8) = 1 +close(::DevNullStream) = nothing +flush(::DevNullStream) = nothing +wait_connected(::DevNullStream) = nothing +wait_readnb(::DevNullStream) = wait() +wait_readbyte(::DevNullStream) = wait() +wait_close(::DevNullStream) = wait() +eof(::DevNullStream) = true + +let CoreIO = Union{Core.CoreSTDOUT, Core.CoreSTDERR} + global write, unsafe_write + write(io::CoreIO, x::UInt8) = Core.write(io, x) + unsafe_write(io::CoreIO, x::Ptr{UInt8}, nb::UInt) = Core.unsafe_write(io, x, nb) +end + +STDIN = DevNull +STDOUT = Core.STDOUT +STDERR = Core.STDERR diff --git a/base/essentials.jl b/base/essentials.jl index 1d1ba215b1865..8ab11f6981433 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -1,7 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -abstract IO - typealias Callable Union{Function,DataType} const Bottom = Union{} diff --git a/base/exports.jl b/base/exports.jl index 68621d887f607..faed26b2ae28f 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -67,7 +67,6 @@ export UniformScaling, InsertionSort, IntSet, - IO, IOBuffer, IOStream, LinSpace, diff --git a/base/libuv.jl b/base/libuv.jl index 729394c90d1ef..9de035f4dd0d1 100644 --- a/base/libuv.jl +++ b/base/libuv.jl @@ -99,9 +99,9 @@ function reinit_stdio() global uv_jl_timercb = cfunction(uv_timercb, Void, (Ptr{Void},)) global uv_eventloop = ccall(:jl_global_event_loop, Ptr{Void}, ()) - global STDIN = init_stdio(ccall(:jl_stdin_stream ,Ptr{Void},())) - global STDOUT = init_stdio(ccall(:jl_stdout_stream,Ptr{Void},())) - global STDERR = init_stdio(ccall(:jl_stderr_stream,Ptr{Void},())) + global STDIN = init_stdio(ccall(:jl_stdin_stream, Ptr{Void}, ())) + global STDOUT = init_stdio(ccall(:jl_stdout_stream, Ptr{Void}, ())) + global STDERR = init_stdio(ccall(:jl_stderr_stream, Ptr{Void}, ())) end """ diff --git a/base/process.jl b/base/process.jl index 80b4bb005f554..e0b1a11e6c23a 100644 --- a/base/process.jl +++ b/base/process.jl @@ -147,21 +147,6 @@ immutable FileRedirect end end -immutable DevNullStream <: IO end -const DevNull = DevNullStream() -isreadable(::DevNullStream) = false -iswritable(::DevNullStream) = true -isopen(::DevNullStream) = true -read(::DevNullStream, ::Type{UInt8}) = throw(EOFError()) -write(::DevNullStream, ::UInt8) = 1 -close(::DevNullStream) = nothing -flush(::DevNullStream) = nothing -wait_connected(::DevNullStream) = nothing -wait_readnb(::DevNullStream) = wait() -wait_readbyte(::DevNullStream) = wait() -wait_close(::DevNullStream) = wait() -eof(::DevNullStream) = true - uvhandle(::DevNullStream) = C_NULL uvtype(::DevNullStream) = UV_STREAM diff --git a/base/show.jl b/base/show.jl index deacf6191ec02..492dda654f4b4 100644 --- a/base/show.jl +++ b/base/show.jl @@ -1,6 +1,5 @@ # This file is a part of Julia. License is MIT: http://julialang.org/license -show(x) = show(STDOUT::IO, x) print(io::IO, s::Symbol) = (write(io,s); nothing) immutable IOContext{IO_t <: IO} <: AbstractPipe diff --git a/base/strings/io.jl b/base/strings/io.jl index 6ab40972d5bfd..89a8c84b02ea0 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -24,9 +24,6 @@ end println(io::IO, xs...) = print(io, xs..., '\n') -print(xs...) = print(STDOUT, xs...) -println(xs...) = println(STDOUT, xs...) - ## conversion of general objects to strings ## function sprint(size::Integer, f::Function, args...; env=nothing) diff --git a/base/sysimg.jl b/base/sysimg.jl index 0991f6d58d2ea..7e4c71d4a4829 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -4,8 +4,8 @@ baremodule Base using Core.TopModule, Core.Intrinsics ccall(:jl_set_istopmod, Void, (Bool,), true) - include = Core.include +include("coreio.jl") eval(x) = Core.eval(Base,x) eval(m,x) = Core.eval(m,x) @@ -19,11 +19,21 @@ include("exports.jl") if false # simple print definitions for debugging. enable these if something # goes wrong during bootstrap before printing code is available. - show(x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), - pointerref(cglobal(:jl_uv_stdout,Ptr{Void}),1), x) - print(x::ANY) = show(x) - println(x::ANY) = ccall(:jl_, Void, (Any,), x) - print(a::ANY...) = for x=a; print(x); end + # otherwise, they just just eventually get (noisily) overwritten later + global show, print, println + show(io::IO, x::ANY) = Core.show(io, x) + print(io::IO, a::ANY...) = Core.print(io, a...) + println(io::IO, x::ANY...) = Core.println(io, x...) + if false # show that the IO system now (relatively) operational + print("HELLO") + println(" WORLD") + show("αβγ :)"); println() + println(STDERR, "TEST") + println(STDERR, STDERR) + println(STDERR, 'a') + println(STDERR, 'α') + show(STDOUT, 'α') + end end ## Load essential files and libraries diff --git a/doc/devdocs/stdio.rst b/doc/devdocs/stdio.rst index 93d7bb0b53be8..0bb6f6c242bbe 100644 --- a/doc/devdocs/stdio.rst +++ b/doc/devdocs/stdio.rst @@ -82,7 +82,7 @@ to be printed before this are routed to the standard C library In ``sys.c``, the :code:`JL_STD*` stream pointers are statically initialised to integer constants: ``STD*_FILENO (0, 1 and 2)``. In ``jl_uv.c`` the -:c:func:`jl_write` function checks its :code:`uv_stream_t* stream` +:c:func:`jl_uv_puts` function checks its :code:`uv_stream_t* stream` argument and calls :c:func:`fwrite` if stream is set to :c:macro:`STDOUT_FILENO` or :c:macro:`STDERR_FILENO`. @@ -118,7 +118,7 @@ to point to :c:type:`ios_t` streams. This is needed because :c:func:`jl_printf` caller :c:func:`jl_static_show` is passed an :code:`ios_t` stream by femtolisp's :c:func:`fl_print` function. -Julia's :c:func:`jl_write` function has special handling for this:: +Julia's :c:func:`jl_uv_puts` function has special handling for this:: if (stream->type > UV_HANDLE_TYPE_MAX) { return ios_write((ios_t*)stream, str, n); diff --git a/src/gf.c b/src/gf.c index a89fa88b57334..a56e3c6f306b9 100644 --- a/src/gf.c +++ b/src/gf.c @@ -954,11 +954,11 @@ void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args) (jl_value_t*)f, args }; - if (jl_base_module) { + if (fargs[0]) { jl_throw(jl_apply_generic(fargs, 3)); } else { - jl_printf((JL_STREAM*)STDERR_FILENO, "A method error occurred before the base module was defined. Aborting...\n"); + jl_printf((JL_STREAM*)STDERR_FILENO, "A method error occurred before the base MethodError type was defined. Aborting...\n"); jl_static_show((JL_STREAM*)STDERR_FILENO,(jl_value_t*)f); jl_printf((JL_STREAM*)STDERR_FILENO,"\n"); jl_static_show((JL_STREAM*)STDERR_FILENO,args); jl_printf((JL_STREAM*)STDERR_FILENO,"\n"); jl_bt_size = rec_backtrace(jl_bt_data, JL_MAX_BT_SIZE); diff --git a/src/jl_uv.c b/src/jl_uv.c index 4b6445e502666..fca9c9c86ec69 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -427,10 +427,7 @@ JL_DLLEXPORT void jl_uv_writecb(uv_write_t *req, int status) } } -// Note: jl_write() is called only by jl_vprintf(). -// See: doc/devdocs/stdio.rst - -static void jl_write(uv_stream_t *stream, const char *str, size_t n) +JL_DLLEXPORT void jl_uv_puts(uv_stream_t *stream, const char *str, size_t n) { assert(stream); static_assert(offsetof(uv_stream_t,type) == offsetof(ios_t,bm) && @@ -477,6 +474,17 @@ static void jl_write(uv_stream_t *stream, const char *str, size_t n) } } +JL_DLLEXPORT void jl_uv_putb(uv_stream_t *stream, uint8_t b) +{ + jl_uv_puts(stream, (char*)&b, 1); +} + +JL_DLLEXPORT void jl_uv_putc(uv_stream_t *stream, uint32_t wchar) +{ + char s[4]; + jl_uv_puts(stream, s, u8_wc_toutf8(s, wchar)); +} + extern int vasprintf(char **str, const char *fmt, va_list ap); JL_DLLEXPORT int jl_vprintf(uv_stream_t *s, const char *format, va_list args) @@ -493,7 +501,7 @@ JL_DLLEXPORT int jl_vprintf(uv_stream_t *s, const char *format, va_list args) c = vasprintf(&str, format, al); if (c >= 0) { - jl_write(s, str, c); + jl_uv_puts(s, str, c); free(str); } va_end(al); diff --git a/test/show.jl b/test/show.jl index 366bd96ad749a..ff9d1ec960d92 100644 --- a/test/show.jl +++ b/test/show.jl @@ -275,12 +275,45 @@ end @test repr(:(bitstype A B)) == ":(bitstype A B)" @test repr(:(bitstype 100 B)) == ":(bitstype 100 B)" -oldout = STDOUT -try - rd, wr = redirect_stdout() - @test dump(STDERR) == nothing -finally - redirect_stdout(oldout) +let oldout = STDOUT, olderr = STDERR + local rdout, wrout, rderr, wrerr, out, err, rd, wr + try + rd, wr = redirect_stdout() + @test dump(STDERR) == nothing + + # pr 16917 + rdout, wrout = redirect_stdout() + @test wrout === STDOUT + out = @async readstring(rdout) + rderr, wrerr = redirect_stderr() + @test wrerr === STDERR + err = @async readstring(rderr) + if !is_windows() + close(wrout) + close(wrerr) + end + for io in (Core.STDOUT, Core.STDERR) + Core.println(io, "TESTA") + println(io, "TESTB") + print(io, 'Α', 1) + Core.print(io, 'Β', 2) + Core.show(io, "A") + println(io) + end + Core.println("A") + Core.print("1", 2, 3.0) + Core.show("C") + Core.println() + redirect_stdout(oldout) + redirect_stderr(olderr) + close(wrout) + close(wrerr) + @test wait(out) == "TESTA\nTESTB\nΑ1Β2\"A\"\nA\n123\"C\"\n" + @test wait(err) == "TESTA\nTESTB\nΑ1Β2\"A\"\n" + finally + redirect_stdout(oldout) + redirect_stderr(olderr) + end end # issue #12960