diff --git a/Makefile b/Makefile index 63fd179e83346..cbca19fb7a7fc 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,8 @@ $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys0.ji: @$(QUIET_JULIA) cd base && \ $(call spawn,$(JULIA_EXECUTABLE)) -bf sysimg.jl mv $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys0.ji + $(call spawn,$(BUILD)/bin/llc) -filetype=obj -relocation-model=pic -o sysimg0.o $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.bc + $(CXX) -shared -fPIC -L$(BUILD)/lib -o $(BUILD)/lib/sysimg0.$(SHLIB_EXT) sysimg0.o -Wl,-undefined,dynamic_lookup -lgrisu -lrandom -lgmp -lpcre $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys.ji: VERSION base/*.jl base/pkg/*.jl base/linalg/*.jl base/sparse/*.jl $(BUILD)/share/julia/helpdb.jl $(BUILD)/share/man/man1/julia.1 $(BUILD)/$(JL_PRIVATE_LIBDIR)/sys0.ji @$(QUIET_JULIA) cd base && \ @@ -240,7 +242,7 @@ clean: | $(CLEAN_TARGETS) @$(MAKE) -C base clean @$(MAKE) -C src clean @$(MAKE) -C ui clean - for repltype in "basic" "readline"; do \ + for repltype in "basic" "readline"; do \ rm -f usr/bin/julia-debug-$${repltype}; \ rm -f usr/bin/julia-$${repltype}; \ done diff --git a/base/precompile.jl b/base/precompile.jl new file mode 100644 index 0000000000000..69e35f161f0cd --- /dev/null +++ b/base/precompile.jl @@ -0,0 +1,162 @@ +include = include_from_node1 + +# prime method cache with some things we know we'll need right after startup +precompile(pwd, ()) +precompile(fdio, (Int32,)) +precompile(ProcessGroup, (Int, Array{Any,1}, Array{Any,1})) +precompile(next, (Dict{Any,Any}, Int)) +precompile(start, (Dict{Any,Any},)) +precompile(perform_work, ()) +precompile(isempty, (Array{Any,1},)) +precompile(getindex, (Dict{Any,Any}, Int32)) +precompile(event_loop, (Bool,)) +precompile(_start, ()) +precompile(process_options, (Array{Any,1},)) +precompile(run_repl, ()) +precompile(any, (Function, Array{Any,1})) +precompile(Dict{Any,Any}, (Int,)) +precompile(Set, ()) +precompile(setindex!, (Dict{Any,Any}, Bool, Cmd)) +precompile(rehash, (Dict{Any,Any}, Int)) +precompile(wait, (Int32,)) +precompile(systemerror, (Symbol, Bool)) +precompile(SystemError, (ASCIIString,)) +precompile(has, (EnvHash, ASCIIString)) +precompile(parse_input_line, (ASCIIString,)) +precompile(cmp, (Int32, Int32)) +precompile(min, (Int32, Int32)) +precompile(==, (ASCIIString, ASCIIString)) +precompile(arg_gen, (ASCIIString,)) +precompile(Random.librandom_init, ()) +precompile(Random.srand, (ASCIIString, Int)) +precompile(Random.srand, (Uint64,)) +precompile(open, (ASCIIString, Bool, Bool, Bool, Bool)) +precompile(done, (IntSet, Int64)) +precompile(next, (IntSet, Int64)) +precompile(ht_keyindex, (Dict{Any,Any}, Int32)) +precompile(perform_work, (Task,)) +precompile(notify_full, (RemoteValue,)) +precompile(notify_empty, (RemoteValue,)) +precompile(work_result, (RemoteValue,)) +precompile(take, (RemoteValue,)) +precompile(wait_full, (RemoteValue,)) +precompile(enq_work, (Task,)) +precompile(string, (Int,)) +precompile(parseint, (Type{Int}, ASCIIString, Int)) +precompile(repeat, (ASCIIString, Int)) +precompile(KeyError, (Int,)) +precompile(show, (Float64,)) +precompile(match, (Regex, ASCIIString)) +precompile(length, (ASCIIString,)) +precompile(alignment, (Float64,)) +precompile(repl_callback, (Expr, Int)) +precompile(istaskdone, (Task,)) +precompile(int, (Uint64,)) +precompile(copy, (Bool,)) +precompile(bool, (Bool,)) +precompile(bool, (RemoteRef,)) +precompile(wait, (RemoteRef,)) +precompile(hash, (RemoteRef,)) +precompile(take, (RemoteRef,)) +precompile(bitmix, (Int, Int)) +precompile(bitmix, (Uint, Int)) +precompile(bitmix, (Uint64, Int64)) +precompile(hash, (Int,)) +precompile(isequal, (Symbol, Symbol)) +precompile(isequal, (Bool, Bool)) +precompile(get, (EnvHash, ASCIIString, ASCIIString)) +precompile(rr2id, (RemoteRef,)) +precompile(isequal, (RemoteRef, WeakRef)) +precompile(isequal, (RemoteRef, RemoteRef)) +precompile(_ieval, (Symbol,)) +precompile(static_convert, (Nothing, Nothing)) +precompile(setindex!, (Array{Any,1}, WeakRef, Int)) +precompile(isequal, ((Int,Int),(Int,Int))) +precompile(isequal, (Int,Int)) +precompile(RemoteRef, (Int, Int, Int)) +precompile(eval_user_input, (Expr, Bool)) +precompile(print, (Float64,)) +precompile(a2t, (Array{Any,1},)) +precompile(flush, (IOStream,)) +precompile(getindex, (Type{ByteString}, ASCIIString, ASCIIString)) +precompile(bytestring, (ASCIIString,)) +precompile(int, (Int,)) +precompile(uint, (Uint,)) +precompile(_atexit, ()) +precompile(read, (IOStream, Array{Uint32,1})) +precompile(hex, (Char, Int)) +precompile(abs, (Char,)) +precompile(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) +precompile(length, (Range1{Int},)) +precompile(start, (Range1{Int},)) +precompile(done, (Range1{Int},Int)) +precompile(next, (Range1{Int},Int)) +precompile(IOStream, (ASCIIString, Array{Uint8,1})) +precompile(mk_tupleref, (SymbolNode, Int)) +precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) +precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) +precompile(occurs_more, (Bool, Function, Int)) +precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) +precompile(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) +precompile(convert, (Type{Module}, Module)) +precompile(effect_free, (Expr,)) +precompile(effect_free, (TopNode,)) +precompile(abspath, (ASCIIString,)) +precompile(isabspath, (ASCIIString,)) +precompile(split, (ASCIIString,)) +precompile(split, (ASCIIString, ASCIIString, Int, Bool)) +precompile(split, (ASCIIString, Regex, Int, Bool)) +precompile(print_joined, (IOBuffer, Array{String,1}, ASCIIString)) +precompile(beginswith, (ASCIIString, ASCIIString)) +precompile(resolve_globals, (Symbol, Module, Module, Vector{Any}, Vector{Any})) +precompile(resolve_globals, (SymbolNode, Module, Module, Vector{Any}, Vector{Any})) +precompile(BitArray, (Int,)) +precompile(getindex, (BitArray{1}, Int,)) +precompile(setindex!, (BitArray{1}, Bool, Int,)) +precompile(fill!, (BitArray{1}, Bool)) +precompile(pop!, (Array{Any,1},)) +precompile(unshift!, (Array{Any,1}, Task)) +precompile(nnz, (BitArray{1},)) +precompile(get_chunks_id, (Int,)) +precompile(occurs_more, (Uint8, Function, Int)) +precompile(abstract_eval_arg, (Uint8, ObjectIdDict, StaticVarInfo)) +precompile(occurs_outside_tupleref, (Function, Symbol, StaticVarInfo, Int)) +precompile(search, (ASCIIString, Regex, Int)) +precompile(setindex!, (Vector{Any}, Uint8, Int)) +precompile(setindex!, (Vector{Any}, Vector{Any}, Int)) +precompile(first, (Range1{Int},)) +precompile(last, (Range1{Int},)) +precompile(isempty, (ASCIIString,)) +precompile(normpath, (ASCIIString,)) +precompile(print, (ASCIIString,)) +precompile(println, (TTY,)) +precompile(print, (TTY,Char)) +precompile(==, (Bool,Bool)) +precompile(try_include, (ASCIIString,)) +precompile(isfile, (ASCIIString,)) +precompile(include_from_node1, (ASCIIString,)) +precompile(source_path, (Nothing,)) +precompile(task_local_storage, ()) +precompile(atexit, (Function,)) +precompile(print, (TTY, ASCIIString)) +precompile(close, (TTY,)) +precompile(read_buffer, (TTY,Int)) +precompile(put, (RemoteRef, Any)) +precompile(getpid, ()) +precompile(print, (IOStream, Int32)) +precompile(show, (IOStream, Int32)) +precompile(open, (ASCIIString, ASCIIString)) +precompile(readline, (ASCIIString,)) +precompile(endof, (Array{Any,1},)) +precompile(sym_replace, (Uint8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) +precompile(isslotempty, (Dict{Any,Any}, Int)) +precompile(setindex!, (Array{Uint8,1}, Uint8, Int)) +precompile(get, (Dict{Any,Any}, Symbol, ASCIIString)) +precompile(*, (ASCIIString, ASCIIString, ASCIIString)) +precompile(chop, (ASCIIString,)) +precompile(ismatch, (Regex, ASCIIString)) +precompile(!=, (Bool, Bool)) +precompile(nextind, (ASCIIString, Int)) +precompile(delete_var!, (Expr, Symbol)) +precompile(close, (IOStream,)) +precompile(haskey, (ObjectIdDict, Symbol)) diff --git a/base/sysimg.jl b/base/sysimg.jl index d224d39e521ff..6d5ea9d434c88 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -217,168 +217,7 @@ include("graphics.jl") include("profile.jl") importall .Profile -include = include_from_node1 - -# prime method cache with some things we know we'll need right after startup -precompile(pwd, ()) -precompile(fdio, (Int32,)) -precompile(ProcessGroup, (Int, Array{Any,1}, Array{Any,1})) -precompile(next, (Dict{Any,Any}, Int)) -precompile(start, (Dict{Any,Any},)) -precompile(perform_work, ()) -precompile(isempty, (Array{Any,1},)) -precompile(getindex, (Dict{Any,Any}, Int32)) -precompile(event_loop, (Bool,)) -precompile(_start, ()) -precompile(process_options, (Array{Any,1},)) -precompile(run_repl, ()) -precompile(any, (Function, Array{Any,1})) -precompile(Dict{Any,Any}, (Int,)) -precompile(Set, ()) -precompile(setindex!, (Dict{Any,Any}, Bool, Cmd)) -precompile(rehash, (Dict{Any,Any}, Int)) -precompile(wait, (Int32,)) -precompile(systemerror, (Symbol, Bool)) -precompile(SystemError, (ASCIIString,)) -precompile(has, (EnvHash, ASCIIString)) -precompile(parse_input_line, (ASCIIString,)) -precompile(cmp, (Int32, Int32)) -precompile(min, (Int32, Int32)) -precompile(==, (ASCIIString, ASCIIString)) -precompile(arg_gen, (ASCIIString,)) -precompile(Random.librandom_init, ()) -precompile(Random.srand, (ASCIIString, Int)) -precompile(Random.srand, (Uint64,)) -precompile(open, (ASCIIString, Bool, Bool, Bool, Bool)) -precompile(done, (IntSet, Int64)) -precompile(next, (IntSet, Int64)) -precompile(ht_keyindex, (Dict{Any,Any}, Int32)) -precompile(perform_work, (Task,)) -precompile(notify_full, (RemoteValue,)) -precompile(notify_empty, (RemoteValue,)) -precompile(work_result, (RemoteValue,)) -precompile(take, (RemoteValue,)) -precompile(wait_full, (RemoteValue,)) -precompile(enq_work, (Task,)) -precompile(string, (Int,)) -precompile(parseint, (Type{Int}, ASCIIString, Int)) -precompile(repeat, (ASCIIString, Int)) -precompile(KeyError, (Int,)) -precompile(show, (Float64,)) -precompile(match, (Regex, ASCIIString)) -precompile(length, (ASCIIString,)) -precompile(alignment, (Float64,)) -precompile(repl_callback, (Expr, Int)) -precompile(istaskdone, (Task,)) -precompile(int, (Uint64,)) -precompile(copy, (Bool,)) -precompile(bool, (Bool,)) -precompile(bool, (RemoteRef,)) -precompile(wait, (RemoteRef,)) -precompile(hash, (RemoteRef,)) -precompile(take, (RemoteRef,)) -precompile(bitmix, (Int, Int)) -precompile(bitmix, (Uint, Int)) -precompile(bitmix, (Uint64, Int64)) -precompile(hash, (Int,)) -precompile(isequal, (Symbol, Symbol)) -precompile(isequal, (Bool, Bool)) -precompile(get, (EnvHash, ASCIIString, ASCIIString)) -precompile(rr2id, (RemoteRef,)) -precompile(isequal, (RemoteRef, WeakRef)) -precompile(isequal, (RemoteRef, RemoteRef)) -precompile(_ieval, (Symbol,)) -precompile(static_convert, (Nothing, Nothing)) -precompile(setindex!, (Array{Any,1}, WeakRef, Int)) -precompile(isequal, ((Int,Int),(Int,Int))) -precompile(isequal, (Int,Int)) -precompile(RemoteRef, (Int, Int, Int)) -precompile(eval_user_input, (Expr, Bool)) -precompile(print, (Float64,)) -precompile(a2t, (Array{Any,1},)) -precompile(flush, (IOStream,)) -precompile(getindex, (Type{ByteString}, ASCIIString, ASCIIString)) -precompile(bytestring, (ASCIIString,)) -precompile(int, (Int,)) -precompile(uint, (Uint,)) -precompile(_atexit, ()) -precompile(read, (IOStream, Array{Uint32,1})) -precompile(hex, (Char, Int)) -precompile(abs, (Char,)) -precompile(abstract_eval, (LambdaStaticData, ObjectIdDict, StaticVarInfo)) -precompile(length, (Range1{Int},)) -precompile(start, (Range1{Int},)) -precompile(done, (Range1{Int},Int)) -precompile(next, (Range1{Int},Int)) -precompile(IOStream, (ASCIIString, Array{Uint8,1})) -precompile(mk_tupleref, (SymbolNode, Int)) -precompile(abstract_interpret, (Bool, ObjectIdDict, StaticVarInfo)) -precompile(eval_annotate, (LambdaStaticData, ObjectIdDict, StaticVarInfo, ObjectIdDict, Array{Any,1})) -precompile(occurs_more, (Bool, Function, Int)) -precompile(isconstantfunc, (SymbolNode, StaticVarInfo)) -precompile(CallStack, (Expr, Module, (Nothing,), EmptyCallStack)) -precompile(convert, (Type{Module}, Module)) -precompile(effect_free, (Expr,)) -precompile(effect_free, (TopNode,)) -precompile(abspath, (ASCIIString,)) -precompile(isabspath, (ASCIIString,)) -precompile(split, (ASCIIString,)) -precompile(split, (ASCIIString, ASCIIString, Int, Bool)) -precompile(split, (ASCIIString, Regex, Int, Bool)) -precompile(print_joined, (IOBuffer, Array{String,1}, ASCIIString)) -precompile(beginswith, (ASCIIString, ASCIIString)) -precompile(resolve_globals, (Symbol, Module, Module, Vector{Any}, Vector{Any})) -precompile(resolve_globals, (SymbolNode, Module, Module, Vector{Any}, Vector{Any})) -precompile(BitArray, (Int,)) -precompile(getindex, (BitArray{1}, Int,)) -precompile(setindex!, (BitArray{1}, Bool, Int,)) -precompile(fill!, (BitArray{1}, Bool)) -precompile(pop!, (Array{Any,1},)) -precompile(unshift!, (Array{Any,1}, Task)) -precompile(nnz, (BitArray{1},)) -precompile(get_chunks_id, (Int,)) -precompile(occurs_more, (Uint8, Function, Int)) -precompile(abstract_eval_arg, (Uint8, ObjectIdDict, StaticVarInfo)) -precompile(occurs_outside_tupleref, (Function, Symbol, StaticVarInfo, Int)) -precompile(search, (ASCIIString, Regex, Int)) -precompile(setindex!, (Vector{Any}, Uint8, Int)) -precompile(setindex!, (Vector{Any}, Vector{Any}, Int)) -precompile(first, (Range1{Int},)) -precompile(last, (Range1{Int},)) -precompile(isempty, (ASCIIString,)) -precompile(normpath, (ASCIIString,)) -precompile(print, (ASCIIString,)) -precompile(println, (TTY,)) -precompile(print, (TTY,Char)) -precompile(==, (Bool,Bool)) -precompile(try_include, (ASCIIString,)) -precompile(isfile, (ASCIIString,)) -precompile(include_from_node1, (ASCIIString,)) -precompile(source_path, (Nothing,)) -precompile(task_local_storage, ()) -precompile(atexit, (Function,)) -precompile(print, (TTY, ASCIIString)) -precompile(close, (TTY,)) -precompile(read_buffer, (TTY,Int)) -precompile(put, (RemoteRef, Any)) -precompile(getpid, ()) -precompile(print, (IOStream, Int32)) -precompile(show, (IOStream, Int32)) -precompile(open, (ASCIIString, ASCIIString)) -precompile(readline, (ASCIIString,)) -precompile(endof, (Array{Any,1},)) -precompile(sym_replace, (Uint8, Array{Any,1}, Array{Any,1}, Array{Any,1}, Array{Any,1})) -precompile(isslotempty, (Dict{Any,Any}, Int)) -precompile(setindex!, (Array{Uint8,1}, Uint8, Int)) -precompile(get, (Dict{Any,Any}, Symbol, ASCIIString)) -precompile(*, (ASCIIString, ASCIIString, ASCIIString)) -precompile(chop, (ASCIIString,)) -precompile(ismatch, (Regex, ASCIIString)) -precompile(!=, (Bool, Bool)) -precompile(nextind, (ASCIIString, Int)) -precompile(delete_var!, (Expr, Symbol)) -precompile(close, (IOStream,)) -precompile(haskey, (ObjectIdDict, Symbol)) +include("precompile.jl") # invoke type inference, running the existing inference code on the new # inference code to cache an optimized version of it. @@ -396,4 +235,5 @@ let JL_PRIVATE_LIBDIR = get(ENV, "JL_PRIVATE_LIBDIR", "lib/julia") # create system image file ccall(:jl_save_system_image, Void, (Ptr{Uint8},), "$JULIA_HOME/../$JL_PRIVATE_LIBDIR/sys.ji") +ccall(:jl_dump_bitcode, Void, (Ptr{Uint8},), "$JULIA_HOME/../$JL_PRIVATE_LIBDIR/sys.bc") end diff --git a/src/alloc.c b/src/alloc.c index e54c46595cc46..73c706e06fa9f 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -219,7 +219,7 @@ DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type) return jv; } -jl_tuple_t *jl_tuple(size_t n, ...) +DLLEXPORT jl_tuple_t *jl_tuple(size_t n, ...) { va_list args; if (n == 0) return jl_null; diff --git a/src/builtins.c b/src/builtins.c index bbd96a34078ba..3653d98b75a25 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -29,7 +29,7 @@ // exceptions ----------------------------------------------------------------- -void jl_error(const char *str) +DLLEXPORT void jl_error(const char *str) { if (jl_errorexception_type == NULL) { JL_PRINTF(JL_STDERR, "%s", str); diff --git a/src/ccall.cpp b/src/ccall.cpp index f7047171606fb..48fd4a47d78d5 100644 --- a/src/ccall.cpp +++ b/src/ccall.cpp @@ -131,12 +131,12 @@ static uint32_t arg_block_n = 0; static Function *save_arg_area_loc_func; static Function *restore_arg_area_loc_func; -static uint64_t save_arg_area_loc() +DLLEXPORT extern "C" uint64_t save_arg_area_loc() { return (((uint64_t)arg_block_n)<<32) | ((uint64_t)arg_area_loc); } -static void restore_arg_area_loc(uint64_t l) +DLLEXPORT extern "C" void restore_arg_area_loc(uint64_t l) { arg_area_loc = l&0xffffffff; uint32_t ab = l>>32; @@ -175,7 +175,7 @@ static void *alloc_temp_arg_copy(void *obj, uint32_t sz) // this is a run-time function // warning: cannot allocate memory except using alloc_temp_arg_space -extern "C" void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, +DLLEXPORT extern "C" void *jl_value_to_pointer(jl_value_t *jt, jl_value_t *v, int argn, int addressof) { jl_value_t *jvt = (jl_value_t*)jl_typeof(v); @@ -448,6 +448,7 @@ static Value *emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) } else if (sym.fptr != NULL) { res = literal_pointer_val(sym.fptr, lrt); + JL_PRINTF(JL_STDERR,"warning: generated literal_pointer_val for cglobal\n"); } else { void *symaddr; @@ -689,6 +690,7 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) else if (fptr != NULL) { Type *funcptype = PointerType::get(functype,0); llvmf = literal_pointer_val(fptr, funcptype); + JL_PRINTF(JL_STDERR,"warning: generated literal_pointer_val for %s\n", f_name); } else { void *symaddr; @@ -740,10 +742,10 @@ static Value *emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx) msg << f_lib; } msg << "\n"; - builder.CreateCall2(jlputs_func, - builder.CreateGEP(stringConst(msg.str()), - ArrayRef(zeros)), - literal_pointer_val(JL_STDERR)); +// builder.CreateCall2(jlputs_func, +// builder.CreateGEP(stringConst(msg.str()), +// ArrayRef(zeros)), +// literal_pointer_val(JL_STDERR,T_pint8)); } // emit arguments diff --git a/src/cgutils.cpp b/src/cgutils.cpp index a268a504fadae..8ecd1e8d9deb2 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -48,14 +48,99 @@ static Value *literal_pointer_val(void *p, Type *t) #endif } -static Value *literal_pointer_val(jl_value_t *p) +static std::map jl_value_to_llvm; + +extern "C" const char *jl_get_llvm_gv(jl_value_t *p) +{ + std::map::iterator it; + it = jl_value_to_llvm.find(p); + if (it == jl_value_to_llvm.end()) + return NULL; + return it->second->getName().data(); +} + +static Value *julia_to_gv(const char *cname, jl_value_t *addr) +{ + std::map::iterator it; + it = jl_value_to_llvm.find(addr); + if (it != jl_value_to_llvm.end()) + return builder.CreateLoad(it->second); + GlobalValue *gv = new GlobalVariable(*jl_Module, jl_pvalue_llvmt, + false, GlobalVariable::ExternalLinkage, + ConstantPointerNull::get((PointerType*)jl_pvalue_llvmt), cname); + jl_value_t **p = (jl_value_t**)jl_ExecutionEngine->getPointerToGlobal(gv); + *p = addr; + jl_value_to_llvm[addr] = gv; + return builder.CreateLoad(gv); +} + +static Value *julia_to_gv(jl_value_t *addr) { - return literal_pointer_val(p, jl_pvalue_llvmt); + return julia_to_gv("jl_global#", addr); } -static Value *literal_pointer_val(void *p) +static Value *julia_to_gv(const char *prefix, jl_sym_t *name, jl_module_t *mod, jl_value_t *addr) { + size_t len = strlen(name->name)+strlen(prefix)+1; + jl_module_t *parent = mod, *prev = NULL; + while (parent != NULL && parent != prev) { + len += strlen(parent->name->name)+1; + prev = parent; + parent = parent->parent; + } + char *fullname = (char*)alloca(len); + strcpy(fullname, prefix); + len -= strlen(name->name)+1; + strcpy(fullname+len,name->name); + parent = mod; + prev = NULL; + while (parent != NULL && parent != prev) { + size_t part = strlen(parent->name->name)+1; + strcpy(fullname+len-part,parent->name->name); + fullname[len-1] = '.'; + len -= part; + prev = parent; + parent = parent->parent; + } + return julia_to_gv(fullname, addr); +} +static Value *julia_to_gv(jl_datatype_t *addr) { + return julia_to_gv("+", addr->name->name, addr->name->module, (jl_value_t*)addr); +} +static Value *julia_to_gv(jl_lambda_info_t *linfo, jl_value_t *addr) { + if (linfo != NULL) + return julia_to_gv("-", linfo->name, linfo->module, addr); + return julia_to_gv("jl_method#", addr); +} +static Value *julia_to_gv(jl_function_t *addr) { + return julia_to_gv(addr->linfo, (jl_value_t*)addr); +} +static Value *julia_to_gv(jl_sym_t *addr) { + return julia_to_gv("jl_sym#", addr, NULL, (jl_value_t*)addr); +} + +static Value *literal_pointer_val(jl_value_t *p) { - return literal_pointer_val(p, T_pint8); + if (p == NULL) + return literal_pointer_val((void*)NULL, jl_pvalue_llvmt); + if (jl_is_datatype(p)) + return julia_to_gv((jl_datatype_t*)p); + if (jl_is_func(p)) + return julia_to_gv((jl_function_t*)p); + if (jl_is_lambda_info(p)) + return julia_to_gv((jl_lambda_info_t*)p, p); + if (jl_is_symbol(p)) + return julia_to_gv((jl_sym_t*)p); + return julia_to_gv(p); +} + +static Value *julia_to_gv(jl_binding_t *b) { + return builder.CreateGEP( + builder.CreateBitCast( + julia_to_gv("*", b->name, b->owner, (jl_value_t*)b), + jl_ppvalue_llvmt), + ConstantInt::get( + T_size, + offsetof(jl_binding_t,value)/sizeof(size_t))); } // --- mapping between julia and llvm types --- diff --git a/src/codegen.cpp b/src/codegen.cpp index 4f60f140c948f..34e73a912c0dc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -26,6 +26,7 @@ #include "llvm/PassManager.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Analysis/Passes.h" +#include "llvm/Bitcode/ReaderWriter.h" #if defined(LLVM_VERSION_MAJOR) && LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 4 #define LLVM34 1 #endif @@ -84,7 +85,7 @@ extern "C" { #include "julia.h" #include "builtin_proto.h" -void *__stack_chk_guard = NULL; +void * __stack_chk_guard = NULL; #if defined(_OS_WINDOWS_) && !defined(_COMPILER_MINGW_) void __stack_chk_fail() @@ -113,6 +114,9 @@ static DIBuilder *dbuilder; static std::map argNumberStrings; static FunctionPassManager *FPM; +// for image reloading +static bool imaging_mode = false; + // types static Type *jl_value_llvmt; static Type *jl_pvalue_llvmt; @@ -283,9 +287,11 @@ extern "C" void jl_generate_fptr(jl_function_t *f) if (li->cFunctionObject != NULL) (void)jl_ExecutionEngine->getPointerToFunction((Function*)li->cFunctionObject); JL_SIGATOMIC_END(); - llvmf->deleteBody(); - if (li->cFunctionObject != NULL) - ((Function*)li->cFunctionObject)->deleteBody(); + if (!imaging_mode) { + llvmf->deleteBody(); + if (li->cFunctionObject != NULL) + ((Function*)li->cFunctionObject)->deleteBody(); + } } f->fptr = li->fptr; } @@ -430,6 +436,21 @@ struct jl_varinfo_t { } }; +// --- helpers for reloading IR image +extern "C" DLLEXPORT +void jl_set_imaging_mode(uint8_t stat) +{ + imaging_mode = (stat == 1); +} + +extern "C" DLLEXPORT +void jl_dump_bitcode(char* fname) +{ + std::string err; + raw_fd_ostream OS(fname, err); + WriteBitcodeToFile(jl_Module, OS); +} + // aggregate of array metadata typedef struct { Value *dataptr; @@ -483,6 +504,15 @@ static Value *emit_condition(jl_value_t *cond, const std::string &msg, jl_codect #include "cgutils.cpp" +extern "C" DLLEXPORT +const char* jl_get_llvmname(void *llvmFunc) +{ + Function *f = (Function*)llvmFunc; + (void)jl_ExecutionEngine->getPointerToFunction(f); //force compile + const char *llname = f->getName().data(); + return llname; +} + // --- code gen for intrinsic functions --- #include "intrinsics.cpp" @@ -1400,8 +1430,8 @@ static Value *emit_known_call(jl_value_t *ff, jl_value_t **args, size_t nargs, #else builder.CreateStore(literal_pointer_val((jl_value_t*)jl_tuple_type), emit_nthptr_addr(tup, (size_t)0)); - builder.CreateStore(literal_pointer_val((jl_value_t*)nargs), - emit_nthptr_addr(tup, (size_t)1)); + builder.CreateStore(ConstantInt::get(T_size, nargs), + builder.CreateBitCast(emit_nthptr_addr(tup, (size_t)1), T_psize)); #endif #ifdef OVERLAP_TUPLE_LEN size_t offs = 1; @@ -1760,7 +1790,7 @@ static Value *global_binding_pointer(jl_module_t *m, jl_sym_t *s, if (assign || b==NULL) b = jl_get_binding_wr(m, s); if (pbnd) *pbnd = b; - return literal_pointer_val(&b->value, jl_ppvalue_llvmt); + return julia_to_gv(b); } // yields a jl_value_t** giving the binding location of a variable @@ -1880,7 +1910,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) if (bnd) { rval = boxed(emit_expr(r, ctx, true)); builder.CreateCall2(jlcheckassign_func, - literal_pointer_val((void*)bnd), + literal_pointer_val((jl_value_t*)bnd), rval); } else { @@ -2009,7 +2039,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, jl_binding_t *b = jl_get_binding(mod, var); if (b == NULL) b = jl_get_binding_wr(mod, var); - Value *bp = literal_pointer_val(&b->value, jl_ppvalue_llvmt); + Value *bp = julia_to_gv(b); if ((b->constp && b->value!=NULL) || (etype!=(jl_value_t*)jl_any_type && !jl_subtype((jl_value_t*)jl_undef_type, etype, 0))) { @@ -2115,7 +2145,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, else { if (is_global((jl_sym_t*)mn, ctx)) { bnd = jl_get_binding_for_method_def(ctx->module, (jl_sym_t*)mn); - bp = literal_pointer_val(&bnd->value, jl_ppvalue_llvmt); + bp = julia_to_gv(bnd); } else { bp = var_binding_pointer((jl_sym_t*)mn, &bnd, false, ctx); @@ -2125,7 +2155,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, make_gcroot(a1, ctx); Value *a2 = boxed(emit_expr(args[2], ctx)); make_gcroot(a2, ctx); - Value *mdargs[5] = { name, bp, literal_pointer_val((void*)bnd), a1, a2 }; + Value *mdargs[5] = { name, bp, literal_pointer_val((jl_value_t*)bnd), a1, a2 }; ctx->argDepth = last_depth; return builder.CreateCall(jlmethod_func, ArrayRef(&mdargs[0], 5)); } @@ -2135,7 +2165,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, (void)var_binding_pointer(sym, &bnd, true, ctx); if (bnd) { builder.CreateCall(jldeclareconst_func, - literal_pointer_val((void*)bnd)); + literal_pointer_val((jl_value_t*)bnd)); } } @@ -2307,9 +2337,9 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, // elide call to jl_copy_ast when possible return emit_expr(arg, ctx); } - } + } return builder.CreateCall(jlcopyast_func, emit_expr(arg, ctx)); - } + } else { if (!strcmp(head->name, "$")) jl_error("syntax: prefix $ in non-quoted expression"); @@ -2332,11 +2362,11 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, jl_errorf("macro definition not allowed inside a local scope"); } else { - jl_errorf("unsupported or misplaced expression %s in function %s", - head->name, ctx->linfo->name->name); - } + jl_errorf("unsupported or misplaced expression %s in function %s", + head->name, ctx->linfo->name->name); } } + } return NULL; } @@ -2577,9 +2607,13 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) } std::string funcName = lam->name->name; + // sanitize macro names, otherwise julia_@name means versioned symbol + size_t atpos = funcName.find("@"); + if (atpos != std::string::npos) + funcName.replace(atpos, 1, "#"); // try to avoid conflicts in the global symbol table funcName = "julia_" + funcName; - + if (specsig) { std::vector fsig(0); for(size_t i=0; i < jl_tuple_len(lam->specTypes); i++) { @@ -3116,7 +3150,32 @@ static Function *jlfunc_to_llvm(const std::string &cname, void *addr) return f; } -extern "C" jl_value_t *jl_new_box(jl_value_t *v) +extern "C" void jlfptr_to_llvm(const char *cname, void *fptr, jl_lambda_info_t *lam, int specsig) { + if (specsig) { + jl_value_t *jlrettype = jl_ast_rettype(lam, (jl_value_t*)lam->ast); + std::vector fsig(0); + for(size_t i=0; i < jl_tuple_len(lam->specTypes); i++) { + fsig.push_back(julia_type_to_llvm(jl_tupleref(lam->specTypes,i))); + } + Type *rt = (jlrettype == (jl_value_t*)jl_nothing->type ? T_void : julia_type_to_llvm(jlrettype)); + Function *f = + Function::Create(FunctionType::get(rt, fsig, false), Function::ExternalLinkage, + cname, jl_Module); + if (lam->cFunctionObject == NULL) { + lam->cFunctionObject = (void*)f; + } + jl_ExecutionEngine->addGlobalMapping(f, (void*)fptr); + } else { + Function *f = jlfunc_to_llvm(cname, fptr); + if (lam->functionObject == NULL) { + lam->functionObject = (void*)f; + assert(lam->fptr == &jl_trampoline); + lam->fptr = (jl_fptr_t)fptr; + } + } +} + +DLLEXPORT extern "C" jl_value_t *jl_new_box(jl_value_t *v) { jl_value_t *box = (jl_value_t*)alloc_2w(); #ifdef OVERLAP_TUPLE_LEN @@ -3274,7 +3333,7 @@ static void init_julia_llvm_env(Module *m) (void*)&jl_type_error_rt); std::vector args_2ptrs(0); - args_2ptrs.push_back(T_pint8); + args_2ptrs.push_back(jl_pvalue_llvmt); args_2ptrs.push_back(jl_pvalue_llvmt); jlcheckassign_func = Function::Create(FunctionType::get(T_void, args_2ptrs, false), @@ -3284,7 +3343,7 @@ static void init_julia_llvm_env(Module *m) (void*)&jl_checked_assignment); std::vector args_1ptr(0); - args_1ptr.push_back(T_pint8); + args_1ptr.push_back(jl_pvalue_llvmt); jldeclareconst_func = Function::Create(FunctionType::get(T_void, args_1ptr, false), Function::ExternalLinkage, @@ -3339,7 +3398,7 @@ static void init_julia_llvm_env(Module *m) std::vector mdargs(0); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_ppvalue_llvmt); - mdargs.push_back(T_pint8); + mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); mdargs.push_back(jl_pvalue_llvmt); jlmethod_func = @@ -3506,6 +3565,7 @@ extern "C" void jl_init_codegen(void) .setMAttrs(attrvec) .create(); #endif // LLVM VERSION + jl_ExecutionEngine->DisableLazyCompilation(); dbuilder = new DIBuilder(*jl_Module); diff --git a/src/dlload.c b/src/dlload.c index 8ea4c28d9e6a4..2eb4e4b0f72cf 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -102,7 +102,7 @@ static uv_lib_t *jl_load_dynamic_library_(char *modname, unsigned flags, int thr error = jl_uv_dlopen(modname,handle,flags); if (!error) goto done; } - else { + else if (jl_base_module != NULL) { jl_array_t* DL_LOAD_PATH = (jl_array_t*)jl_get_global(jl_base_module, jl_symbol("DL_LOAD_PATH")); if (DL_LOAD_PATH != NULL) { size_t j; diff --git a/src/dump.c b/src/dump.c index 586de50eff1f6..56c1c6c009384 100644 --- a/src/dump.c +++ b/src/dump.c @@ -135,9 +135,32 @@ static void jl_serialize_datatype(ios_t *s, jl_datatype_t *dt) jl_serialize_fptr(s, dt->fptr); } +static void jl_serialize_gv(ios_t *s, jl_value_t *v) +{ + const char *gvname = jl_get_llvm_gv(v); + if (gvname != NULL) { + int32_t gvname_len = strlen(gvname); + write_int32(s, gvname_len); + ios_write(s, gvname, gvname_len); + } + else { + write_int32(s, 0); + } +} +static void jl_serialize_gv_syms(ios_t *s, jl_sym_t *v) +{ + void *bp = ptrhash_bp(&backref_table, v); + if (bp != HT_NOTFOUND) { + if (jl_get_llvm_gv((jl_value_t*)v) != NULL) + jl_serialize_value(s, v); + } + if (v->left) jl_serialize_gv_syms(s, v->left); + if (v->right) jl_serialize_gv_syms(s, v->right); +} + static void jl_serialize_module(ios_t *s, jl_module_t *m) { - // set on every startup; don't save + // set on every startup; don't save value jl_sym_t *jhsym = jl_symbol("JULIA_HOME"); writetag(s, jl_module_type); jl_serialize_value(s, m->name); @@ -145,15 +168,19 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m) size_t i; void **table = m->bindings.table; for(i=1; i < m->bindings.size; i+=2) { - if (table[i] != HT_NOTFOUND && - !(table[i-1] == jhsym && m == jl_core_module)) { + if (table[i] != HT_NOTFOUND) { jl_binding_t *b = (jl_binding_t*)table[i]; - if (!(b->owner != m && m == jl_main_module)) { + if (b->owner == m || m != jl_main_module) { jl_serialize_value(s, b->name); - jl_serialize_value(s, b->value); + if (table[i-1] == jhsym && m == jl_core_module) { + jl_serialize_value(s, NULL); + } else { + jl_serialize_value(s, b->value); + } jl_serialize_value(s, b->type); jl_serialize_value(s, b->owner); write_int8(s, (b->constp<<2) | (b->exportp<<1) | (b->imported)); + jl_serialize_gv(s, (jl_value_t*)b); } } } @@ -345,6 +372,26 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_serialize_value(s, (jl_value_t*)li->roots); jl_serialize_value(s, (jl_value_t*)li->def); jl_serialize_value(s, (jl_value_t*)li->capt); + // save functionObject name + // as mangled by llvm + if (li->functionObject) { + const char *llname = jl_get_llvmname(li->functionObject); + int32_t llname_size = strlen(llname); + write_int32(s, llname_size); + ios_write(s, (char*)llname, llname_size); + } + else { + write_int32(s, 0); + } + if (li->cFunctionObject) { + const char *llname = jl_get_llvmname(li->cFunctionObject); + int32_t llname_size = strlen(llname); + write_int32(s, llname_size); + ios_write(s, (char*)llname, llname_size); + } + else { + write_int32(s, 0); + } } else if (jl_typeis(v, jl_module_type)) { jl_serialize_module(s, (jl_module_t*)v); @@ -359,49 +406,50 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) *(int64_t*)data >= S32_MIN && *(int64_t*)data <= S32_MAX) { writetag(s, (jl_value_t*)SmallInt64_tag); write_int32(s, (int32_t)*(int64_t*)data); - return; } - if (t == jl_int32_type) { + else if (t == jl_int32_type) { writetag(s, (jl_value_t*)Int32_tag); write_int32(s, (int32_t)*(int32_t*)data); - return; } - if ((jl_value_t*)t == jl_idtable_type) - writetag(s, (jl_value_t*)IdTable_tag); - else - writetag(s, (jl_value_t*)jl_datatype_type); - jl_serialize_value(s, t); - size_t nf = jl_tuple_len(t->names); - if (nf == 0 && jl_datatype_size(t)>0) { - if (t->name == jl_pointer_type->name) { - write_int32(s, 0); + else { + if ((jl_value_t*)t == jl_idtable_type) + writetag(s, (jl_value_t*)IdTable_tag); + else + writetag(s, (jl_value_t*)jl_datatype_type); + jl_serialize_value(s, t); + size_t nf = jl_tuple_len(t->names); + if (nf == 0 && jl_datatype_size(t)>0) { + if (t->name == jl_pointer_type->name) { + write_int32(s, 0); #ifdef _P64 - write_int32(s, 0); + write_int32(s, 0); #endif + } + else { + ios_write(s, data, jl_datatype_size(t)); + } } else { - ios_write(s, data, jl_datatype_size(t)); - } - } - else { - if ((jl_value_t*)t == jl_idtable_type) { - jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); - jl_value_t **d = (jl_value_t**)data->data; - for(size_t i=0; i < jl_array_len(data); i+=2) { - if (d[i+1] != NULL) { - jl_serialize_value(s, d[i+1]); - jl_serialize_value(s, d[i]); + if ((jl_value_t*)t == jl_idtable_type) { + jl_array_t *data = (jl_array_t*)jl_get_nth_field(v, 0); + jl_value_t **d = (jl_value_t**)data->data; + for(size_t i=0; i < jl_array_len(data); i+=2) { + if (d[i+1] != NULL) { + jl_serialize_value(s, d[i+1]); + jl_serialize_value(s, d[i]); + } } + jl_serialize_value(s, NULL); } - jl_serialize_value(s, NULL); - } - else { - for(size_t i=0; i < nf; i++) { - jl_serialize_value(s, jl_get_nth_field(v, i)); + else { + for(size_t i=0; i < nf; i++) { + jl_serialize_value(s, jl_get_nth_field(v, i)); + } } } } } + jl_serialize_gv(s, v); } // --- deserialize --- @@ -475,11 +523,88 @@ static jl_value_t *jl_deserialize_datatype(ios_t *s, int pos) // parametric types here. jl_cell_1d_push(datatype_list, (jl_value_t*)dt); } + return (jl_value_t*)dt; } +static uv_lib_t *sysimg_handle = NULL; +static void jl_load_sysimg_so() +{ + sysimg_handle = jl_load_dynamic_library("sysimg0", JL_RTLD_DEFAULT); //TODO: use absolute path +} + +static void* *delayed_fptrs = NULL; +static size_t delayed_fptrs_n = 0; +static size_t delayed_fptrs_max = 0; + +static void jl_delayed_fptrs(jl_lambda_info_t *li, char *func, char *cfunc) +{ + if (cfunc || func) { + if (delayed_fptrs_max < delayed_fptrs_n + 3) { + if (delayed_fptrs_max == 0) + delayed_fptrs_max = 512; + else + delayed_fptrs_max *= 2; + delayed_fptrs = realloc(delayed_fptrs, delayed_fptrs_max*sizeof(delayed_fptrs[0])); + } + delayed_fptrs[delayed_fptrs_n++] = li; + if (func) + delayed_fptrs[delayed_fptrs_n++] = strdup(func); + else + delayed_fptrs[delayed_fptrs_n++] = 0; + if (cfunc) + delayed_fptrs[delayed_fptrs_n++] = strdup(cfunc); + else + delayed_fptrs[delayed_fptrs_n++] = 0; + } +} +static void jl_update_all_fptrs() +{ + uv_lib_t *sysimg = (uv_lib_t*)sysimg_handle; + sysimg_handle = NULL; // jlfptr_to_llvm needs to decompress some ast's + size_t i = 0; + while (i < delayed_fptrs_n) { + jl_lambda_info_t *li = (jl_lambda_info_t*)delayed_fptrs[i++]; + char *func = delayed_fptrs[i++]; + if (func) { + jlfptr_to_llvm(func, + (jl_fptr_t)jl_dlsym(sysimg, func), + li, 0); + free(func); + } + char *cfunc = delayed_fptrs[i++]; + if (cfunc){ + assert(cfunc != 0); + jlfptr_to_llvm(cfunc, + (jl_fptr_t)jl_dlsym(sysimg, cfunc), + li, 1); + free(cfunc); + } + } + delayed_fptrs_n = 0; + delayed_fptrs_max = 0; + free(delayed_fptrs); + delayed_fptrs = NULL; +} + jl_array_t *jl_eqtable_put(jl_array_t *h, void *key, void *val); +static jl_value_t *jl_deserialize_value_(ios_t *s, int pos, jl_value_t *vtag); + +static jl_value_t *jl_deserialize_gv(ios_t *s, jl_value_t *v) +{ + int32_t gvname_len = read_int32(s); + if (gvname_len > 0) { + char *gvname = alloca(gvname_len+1); + memset(gvname, 0, gvname_len+1); + ios_read(s, gvname, gvname_len); + gvname[gvname_len] = 0; + if (sysimg_handle != NULL) { + *((jl_value_t**)jl_dlsym((uv_lib_t*)sysimg_handle, gvname)) = v; + } + } + return v; +} static jl_value_t *jl_deserialize_value(ios_t *s) { int pos = ios_pos(s); @@ -504,7 +629,12 @@ static jl_value_t *jl_deserialize_value(ios_t *s) if (tag >= VALUE_TAGS) { return vtag; } - + else if (vtag == (jl_value_t*)LiteralVal_tag) { + return jl_cellref(tree_literal_values, read_uint16(s)); + } + return jl_deserialize_gv(s, jl_deserialize_value_(s, pos, vtag)); +} +static jl_value_t *jl_deserialize_value_(ios_t *s, int pos, jl_value_t *vtag) { int usetable = (tree_literal_values == NULL); size_t i; @@ -587,9 +717,6 @@ static jl_value_t *jl_deserialize_value(ios_t *s) } return (jl_value_t*)e; } - else if (vtag == (jl_value_t*)LiteralVal_tag) { - return jl_cellref(tree_literal_values, read_uint16(s)); - } else if (vtag == (jl_value_t*)jl_tvar_type) { jl_tvar_t *tv = (jl_tvar_t*)newobj((jl_value_t*)jl_tvar_type, 4); if (usetable) @@ -629,13 +756,29 @@ static jl_value_t *jl_deserialize_value(ios_t *s) li->roots = (jl_array_t*)jl_deserialize_value(s); li->def = (jl_lambda_info_t*)jl_deserialize_value(s); li->capt = jl_deserialize_value(s); - li->fptr = &jl_trampoline; li->functionObject = NULL; li->cFunctionObject = NULL; li->inInference = 0; li->inCompile = 0; li->unspecialized = NULL; + int32_t llname_size; + char *cfunc_llvm = NULL, *func_llvm = NULL; + llname_size = read_int32(s); + if (llname_size > 0) { + func_llvm = alloca(llname_size+1); + memset(func_llvm, 0, llname_size+1); + ios_read(s, func_llvm, llname_size); + func_llvm[llname_size] = 0; + } + llname_size = read_int32(s); + if (llname_size > 0) { + cfunc_llvm = alloca(llname_size+1); + memset(cfunc_llvm, 0, llname_size+1); + ios_read(s, cfunc_llvm, llname_size); + cfunc_llvm[llname_size] = 0; + } + jl_delayed_fptrs(li, func_llvm, cfunc_llvm); return (jl_value_t*)li; } else if (vtag == (jl_value_t*)jl_module_type) { @@ -645,10 +788,10 @@ static jl_value_t *jl_deserialize_value(ios_t *s) ptrhash_put(&backref_table, (void*)(ptrint_t)pos, m); m->parent = (jl_module_t*)jl_deserialize_value(s); while (1) { - jl_value_t *name = jl_deserialize_value(s); + jl_sym_t *name = (jl_sym_t*)jl_deserialize_value(s); if (name == NULL) break; - jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name); + jl_binding_t *b = jl_get_binding_wr(m, name); b->value = jl_deserialize_value(s); b->type = (jl_value_t*)jl_deserialize_value(s); b->owner = (jl_module_t*)jl_deserialize_value(s); @@ -656,6 +799,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) b->constp = (flags>>2) & 1; b->exportp = (flags>>1) & 1; b->imported = (flags) & 1; + jl_deserialize_gv(s, (jl_value_t*)b); } size_t ni = read_int32(s); for(size_t i=0; i < ni; i++) { @@ -772,6 +916,16 @@ void jl_save_system_image(char *fname) jl_serialize_value(&f, jl_main_module); + ptrint_t i=2; + void *v = ptrhash_get(&deser_tag, (void*)i); + while (v != HT_NOTFOUND) { + jl_serialize_gv(&f, (jl_value_t*)v); + v = ptrhash_get(&deser_tag, (void*)i); + i += 1; + } + jl_serialize_gv_syms(&f, jl_get_root_symbol()); + jl_serialize_value(&f, NULL); + write_int32(&f, jl_get_t_uid_ctr()); write_int32(&f, jl_get_gs_ctr()); htable_reset(&backref_table, 0); @@ -795,6 +949,7 @@ void jl_restore_system_image(char *fname) JL_PRINTF(JL_STDERR, "System image file \"%s\" not found\n", fname); exit(1); } + jl_load_sysimg_so(); #ifdef JL_GC_MARKSWEEP int en = jl_gc_is_enabled(); jl_gc_disable(); @@ -811,6 +966,17 @@ void jl_restore_system_image(char *fname) jl_symbol("Base")); jl_current_module = jl_base_module; // run start_image in Base + ptrint_t i=2; + void *v = ptrhash_get(&deser_tag, (void*)i); + while (v != HT_NOTFOUND) { + jl_deserialize_gv(&f, (jl_value_t*)v); + v = ptrhash_get(&deser_tag, (void*)i); + i += 1; + } + do { + v = jl_deserialize_value(&f); // deserializing symbols for the side-effects + } while (v != NULL); + // cache builtin parametric types for(int i=0; i < jl_array_len(datatype_list); i++) { jl_value_t *v = jl_cellref(datatype_list, i); @@ -818,7 +984,7 @@ void jl_restore_system_image(char *fname) jl_cache_type_((jl_datatype_t*)v); ((jl_datatype_t*)v)->uid = uid; } - + jl_get_builtin_hooks(); jl_get_system_hooks(); jl_get_uv_hooks(); @@ -837,6 +1003,9 @@ void jl_restore_system_image(char *fname) #ifdef JL_GC_MARKSWEEP if (en) jl_gc_enable(); #endif + jl_get_binding_wr(jl_core_module, jl_symbol("JULIA_HOME"))->value = + jl_cstr_to_string(julia_home); + jl_update_all_fptrs(); } DLLEXPORT diff --git a/src/gc.c b/src/gc.c index ba6554914b0a2..a7d7dd079cea3 100644 --- a/src/gc.c +++ b/src/gc.c @@ -981,7 +981,7 @@ void *allocb(size_t sz) return (void*)((void**)b + 1); } -void *allocobj(size_t sz) +DLLEXPORT void *allocobj(size_t sz) { #ifdef MEMDEBUG return alloc_big(sz); @@ -991,7 +991,7 @@ void *allocobj(size_t sz) return pool_alloc(&pools[szclass(sz)]); } -void *alloc_2w(void) +DLLEXPORT void *alloc_2w(void) { #ifdef MEMDEBUG return alloc_big(2*sizeof(void*)); @@ -1003,7 +1003,7 @@ void *alloc_2w(void) #endif } -void *alloc_3w(void) +DLLEXPORT void *alloc_3w(void) { #ifdef MEMDEBUG return alloc_big(3*sizeof(void*)); @@ -1015,7 +1015,7 @@ void *alloc_3w(void) #endif } -void *alloc_4w(void) +DLLEXPORT void *alloc_4w(void) { #ifdef MEMDEBUG return alloc_big(4*sizeof(void*)); diff --git a/src/init.c b/src/init.c index a1f27e310284b..d5908c42d734d 100644 --- a/src/init.c +++ b/src/init.c @@ -638,12 +638,13 @@ void julia_init(char *imageFile) jl_init_frontend(); jl_init_types(); jl_init_tasks(jl_stack_lo, jl_stack_hi-jl_stack_lo); - jl_init_codegen(); + jl_init_codegen(imageFile); jl_an_empty_cell = (jl_value_t*)jl_alloc_cell_1d(0); jl_init_serializer(); if (!imageFile) { + jl_set_imaging_mode(1); jl_main_module = jl_new_module(jl_symbol("Main")); jl_main_module->parent = jl_main_module; jl_core_module = jl_new_module(jl_symbol("Core")); @@ -658,6 +659,9 @@ void julia_init(char *imageFile) jl_get_builtin_hooks(); jl_boot_file_loaded = 1; jl_init_box_caches(); + jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), + jl_cstr_to_string(julia_home)); + jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); } if (imageFile) { diff --git a/src/jlapi.c b/src/jlapi.c index f5925e76328ce..947df923e8c0b 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -16,9 +16,8 @@ char * __cdecl basename(char *); #include #endif #include "julia.h" -extern char *julia_home; -DLLEXPORT char *jl_locate_sysimg(char *jlhome) +DLLEXPORT char *jl_locate_sysimg(char *jlhome, char* imgpath) { if (jlhome == NULL) { char *julia_path = (char*)malloc(512); @@ -32,7 +31,7 @@ DLLEXPORT char *jl_locate_sysimg(char *jlhome) } char path[512]; snprintf(path, sizeof(path), "%s%s%s", - julia_home, PATHSEPSTRING, JL_SYSTEM_IMAGE_PATH); + julia_home, PATHSEPSTRING, imgpath); return strdup(path); } @@ -44,7 +43,7 @@ DLLEXPORT void *jl_eval_string(char *str); DLLEXPORT void jl_init(char *julia_home_dir) { libsupport_init(); - char *image_file = jl_locate_sysimg(julia_home_dir); + char *image_file = jl_locate_sysimg(julia_home_dir, JL_SYSTEM_IMAGE_PATH); julia_init(image_file); jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), jl_cstr_to_string(julia_home)); diff --git a/src/julia.expmap b/src/julia.expmap index e1352c991ff17..e3815dd306545 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -1,5 +1,7 @@ { global: + alloc_*w; + allocobj; asprintf; bitvector_any1; bitvector_count; @@ -52,6 +54,7 @@ jl_alloc_cell_1d; jl_cell_1d_push; jl_cell_1d_push2; + jl_checked_assignment; jl_apply_generic; jl_array_del_beg; jl_array_del_end; @@ -69,9 +72,9 @@ jl_base_module; jl_boundp; jl_breakpoint; + jl_declare_constant; jl_defines_or_exports_p; - jl_box_int32; - jl_box_int64; + jl_box_*; jl_unbox_int32; jl_unbox_int64; jl_unbox_float32; @@ -98,6 +101,7 @@ jl_dlsym; jl_dlsym_e; jl_dump_function; + jl_f_*; jl_function_ptr; jl_enable_color; jl_enable_inference; @@ -109,6 +113,7 @@ jl_eqtable_put; jl_eqtable_pop; jl_errno; + jl_error; jl_errorexception_type; jl_exception_in_transit; jl_exit; @@ -165,6 +170,9 @@ jl_getutf8; jl_global_event_loop; jl_hrtime; + jl_idle_init; + jl_idle_start; + jl_idle_stop; jl_init_frontend; jl_init_pipe; jl_install_sigint_handler; @@ -195,8 +203,10 @@ jl_make_async; jl_make_pipe; jl_make_tcp; + jl_make_timer; jl_matching_methods; jl_match_method; + jl_method_def; jl_mmap; jl_module_export; jl_module_names; @@ -206,6 +216,7 @@ jl_module_usings; jl_native_alignment; jl_next_from_addrinfo; + jl_new_box; jl_is_char_signed; jl_nb_available; jl_new_array; @@ -226,6 +237,7 @@ jl_pchar_to_string; jl_pgcstack; jl_prepare_ast; + jl_ast_rettype; jl_print_int64; jl_print_symbol; jl_printf; @@ -292,6 +304,8 @@ jl_tcp6_connect; jl_spawn; jl_stackovf_exception; + jl_start_io_thread; + jl_start_reading; jl_stat; jl_stat_blksize; jl_stat_blocks; @@ -352,6 +366,7 @@ jl_write; jl_write_no_copy; jl_value_ptr; + jl_value_to_pointer; jl_zero_subnormals; julia_free; julia_home; @@ -367,8 +382,10 @@ open_any_tcp_port; repl_callback_enable; jl_init_repl; + restore_arg_area_loc_func; restore_signals; rl_clear_input; + save_arg_area_loc_func; jl_SC_CLK_TCK; jl_getpagesize; u8_isvalid; @@ -379,6 +396,19 @@ uv_*; add_library_mapping; + jl_dump_bitcode; + jl_set_imaging_mode; + + jl_stackovf_exception; + jl_memory_exception; + jl_diverror_exception; + jl_domain_exception; + jl_overflow_exception; + jl_inexact_exception; + jl_undefref_exception; + jl_interrupt_exception; + jl_bounds_exception; + /* freebsd */ environ; __progname; diff --git a/src/julia.h b/src/julia.h index c6216cd7fc84c..400e1457a6638 100644 --- a/src/julia.h +++ b/src/julia.h @@ -365,17 +365,17 @@ extern DLLEXPORT jl_datatype_t *jl_ascii_string_type; extern DLLEXPORT jl_datatype_t *jl_utf8_string_type; extern DLLEXPORT jl_datatype_t *jl_errorexception_type; extern DLLEXPORT jl_datatype_t *jl_loaderror_type; -extern jl_datatype_t *jl_typeerror_type; -extern jl_datatype_t *jl_methoderror_type; -extern jl_value_t *jl_stackovf_exception; -extern jl_value_t *jl_memory_exception; -extern jl_value_t *jl_diverror_exception; -extern jl_value_t *jl_domain_exception; -extern jl_value_t *jl_overflow_exception; -extern jl_value_t *jl_inexact_exception; -extern jl_value_t *jl_undefref_exception; -extern jl_value_t *jl_interrupt_exception; -extern jl_value_t *jl_bounds_exception; +extern DLLEXPORT jl_datatype_t *jl_typeerror_type; +extern DLLEXPORT jl_datatype_t *jl_methoderror_type; +extern DLLEXPORT jl_value_t *jl_stackovf_exception; +extern DLLEXPORT jl_value_t *jl_memory_exception; +extern DLLEXPORT jl_value_t *jl_diverror_exception; +extern DLLEXPORT jl_value_t *jl_domain_exception; +extern DLLEXPORT jl_value_t *jl_overflow_exception; +extern DLLEXPORT jl_value_t *jl_inexact_exception; +extern DLLEXPORT jl_value_t *jl_undefref_exception; +extern DLLEXPORT jl_value_t *jl_interrupt_exception; +extern DLLEXPORT jl_value_t *jl_bounds_exception; extern jl_value_t *jl_an_empty_cell; extern jl_datatype_t *jl_box_type; @@ -700,7 +700,7 @@ DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type); DLLEXPORT jl_function_t *jl_new_closure(jl_fptr_t proc, jl_value_t *env, jl_lambda_info_t *li); DLLEXPORT jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_tuple_t *sparams); -jl_tuple_t *jl_tuple(size_t n, ...); +DLLEXPORT jl_tuple_t *jl_tuple(size_t n, ...); jl_tuple_t *jl_tuple1(void *a); jl_tuple_t *jl_tuple2(void *a, void *b); jl_tuple_t *jl_alloc_tuple(size_t n); @@ -720,23 +720,23 @@ void jl_add_method(jl_function_t *gf, jl_tuple_t *types, jl_function_t *meth, jl_tuple_t *tvars); jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, jl_tuple_t *argtypes, jl_function_t *f); -jl_value_t *jl_box_bool(int8_t x); -jl_value_t *jl_box_int8(int32_t x); -jl_value_t *jl_box_uint8(uint32_t x); -jl_value_t *jl_box_int16(int16_t x); -jl_value_t *jl_box_uint16(uint16_t x); +DLLEXPORT jl_value_t *jl_box_bool(int8_t x); +DLLEXPORT jl_value_t *jl_box_int8(int32_t x); +DLLEXPORT jl_value_t *jl_box_uint8(uint32_t x); +DLLEXPORT jl_value_t *jl_box_int16(int16_t x); +DLLEXPORT jl_value_t *jl_box_uint16(uint16_t x); DLLEXPORT jl_value_t *jl_box_int32(int32_t x); -jl_value_t *jl_box_uint32(uint32_t x); -jl_value_t *jl_box_char(uint32_t x); +DLLEXPORT jl_value_t *jl_box_uint32(uint32_t x); +DLLEXPORT jl_value_t *jl_box_char(uint32_t x); DLLEXPORT jl_value_t *jl_box_int64(int64_t x); -jl_value_t *jl_box_uint64(uint64_t x); -jl_value_t *jl_box_float32(float x); -jl_value_t *jl_box_float64(double x); -jl_value_t *jl_box_voidpointer(void *x); -jl_value_t *jl_box8 (jl_datatype_t *t, int8_t x); -jl_value_t *jl_box16(jl_datatype_t *t, int16_t x); -jl_value_t *jl_box32(jl_datatype_t *t, int32_t x); -jl_value_t *jl_box64(jl_datatype_t *t, int64_t x); +DLLEXPORT jl_value_t *jl_box_uint64(uint64_t x); +DLLEXPORT jl_value_t *jl_box_float32(float x); +DLLEXPORT jl_value_t *jl_box_float64(double x); +DLLEXPORT jl_value_t *jl_box_voidpointer(void *x); +DLLEXPORT jl_value_t *jl_box8 (jl_datatype_t *t, int8_t x); +DLLEXPORT jl_value_t *jl_box16(jl_datatype_t *t, int16_t x); +DLLEXPORT jl_value_t *jl_box32(jl_datatype_t *t, int32_t x); +DLLEXPORT jl_value_t *jl_box64(jl_datatype_t *t, int64_t x); DLLEXPORT int8_t jl_unbox_bool(jl_value_t *v); DLLEXPORT int8_t jl_unbox_int8(jl_value_t *v); DLLEXPORT uint8_t jl_unbox_uint8(jl_value_t *v); @@ -862,7 +862,7 @@ DLLEXPORT struct tm* localtime_r(const time_t *t, struct tm *tm); #endif // exceptions -void NORETURN jl_error(const char *str); +DLLEXPORT void NORETURN jl_error(const char *str); void NORETURN jl_errorf(const char *fmt, ...); void jl_too_few_args(const char *fname, int min); void jl_too_many_args(const char *fname, int max); @@ -879,13 +879,17 @@ void jl_init_types(void); void jl_init_box_caches(void); DLLEXPORT void jl_init_frontend(void); void jl_init_primitives(void); -void jl_init_codegen(void); +void jl_init_codegen(); void jl_init_intrinsic_functions(void); void jl_init_tasks(void *stack, size_t ssize); void jl_init_serializer(void); DLLEXPORT void jl_save_system_image(char *fname); DLLEXPORT void jl_restore_system_image(char *fname); +DLLEXPORT void jl_dump_bitcode(char *fname); +const char *jl_get_llvmname(void *func); +DLLEXPORT void jl_set_imaging_mode(uint8_t stat); +const char *jl_get_llvm_gv(jl_value_t *p); // front end interface DLLEXPORT jl_value_t *jl_parse_input_line(const char *str); @@ -925,8 +929,8 @@ DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var); DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var); DLLEXPORT void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val); DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val); -void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs); -void jl_declare_constant(jl_binding_t *b); +DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs); +DLLEXPORT void jl_declare_constant(jl_binding_t *b); void jl_module_using(jl_module_t *to, jl_module_t *from); void jl_module_use(jl_module_t *to, jl_module_t *from, jl_sym_t *s); void jl_module_import(jl_module_t *to, jl_module_t *from, jl_sym_t *s); @@ -987,6 +991,7 @@ jl_function_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tuple_t *types, jl_function_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache); jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types, jl_value_t **args, size_t nargs); +void jlfptr_to_llvm(const char *cname, void *fptr, jl_lambda_info_t *lam, int specsig); // AST access jl_array_t *jl_lam_args(jl_expr_t *l); @@ -1027,7 +1032,7 @@ static inline int jl_vinfo_sa(jl_array_t *vi) // for writing julia functions in C #define JL_CALLABLE(name) \ - jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs) + DLLEXPORT jl_value_t *name(jl_value_t *F, jl_value_t **args, uint32_t nargs) static inline jl_value_t *jl_apply(jl_function_t *f, jl_value_t **args, uint32_t nargs) @@ -1265,6 +1270,8 @@ DLLEXPORT JL_STREAM *jl_stdout_stream(); DLLEXPORT JL_STREAM *jl_stdin_stream(); DLLEXPORT JL_STREAM *jl_stderr_stream(); +extern char *julia_home; + static inline void jl_eh_restore_state(jl_handler_t *eh) { JL_SIGATOMIC_BEGIN(); diff --git a/src/module.c b/src/module.c index ace9a6ad1c6bd..8b5855090f2b4 100644 --- a/src/module.c +++ b/src/module.c @@ -345,7 +345,7 @@ DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) return b && b->constp; } -void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs) +DLLEXPORT void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs) { if (b->constp && b->value != NULL) { if (!jl_egal(rhs, b->value) && @@ -358,7 +358,7 @@ void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs) b->value = rhs; } -void jl_declare_constant(jl_binding_t *b) +DLLEXPORT void jl_declare_constant(jl_binding_t *b) { if (b->value != NULL && !b->constp) { jl_errorf("cannot declare %s constant; it already has a value", diff --git a/src/toplevel.c b/src/toplevel.c index 6c6e62796a45f..81a1ec27dc1da 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -550,7 +550,7 @@ static int type_contains(jl_value_t *ty, jl_value_t *x) void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li); -jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, +DLLEXPORT jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, jl_tuple_t *argtypes, jl_function_t *f) { // argtypes is a tuple ((types...), (typevars...)) diff --git a/ui/repl.c b/ui/repl.c index cfae3cb2e1910..ffdda86435629 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -230,10 +230,7 @@ int true_main(int argc, char *argv[]) jl_arrayset(args, (jl_value_t*)jl_cstr_to_string(argv[i]), i); } } - jl_set_const(jl_core_module, jl_symbol("JULIA_HOME"), - jl_cstr_to_string(julia_home)); - jl_module_export(jl_core_module, jl_symbol("JULIA_HOME")); - + // run program if specified, otherwise enter REPL if (program) { int ret = exec_program();