From c8510e31dc2af6f97358bb7f3b50ef88355feffc Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Thu, 7 Feb 2019 14:22:09 -0500 Subject: [PATCH] internals: share slotnames table via Method Also store a few other unnecessary properties in CodeInfo, which some users might be interested in having. --- base/compiler/inferencestate.jl | 4 +- base/compiler/optimize.jl | 9 +- base/compiler/ssair/legacy.jl | 7 +- base/compiler/ssair/slot2ssa.jl | 4 +- base/compiler/typeinfer.jl | 24 ++-- base/compiler/utilities.jl | 12 +- base/compiler/validation.jl | 4 +- base/methodshow.jl | 38 +++-- src/array.c | 4 + src/ast.c | 21 ++- src/codegen.cpp | 26 ++-- src/dump.c | 164 ++++++++++++++-------- src/gf.c | 2 +- src/jltypes.c | 59 ++++---- src/julia.h | 29 +++- src/julia_internal.h | 20 +-- src/method.c | 45 +++--- src/precompile.c | 2 +- src/staticdata.c | 2 +- stdlib/Serialization/src/Serialization.jl | 6 +- test/compiler/inference.jl | 2 +- test/compiler/validation.jl | 2 +- 22 files changed, 283 insertions(+), 203 deletions(-) diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 7166d227f738a..2d76a3ee7887e 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -58,7 +58,7 @@ mutable struct InferenceState s_types = Any[ nothing for i = 1:n ] # initial types - nslots = length(src.slotnames) + nslots = length(src.slotflags) argtypes = result.argtypes nargs = length(argtypes) s_argtypes = VarTable(undef, nslots) @@ -122,7 +122,7 @@ end function sptypes_from_meth_instance(linfo::MethodInstance) toplevel = !isa(linfo.def, Method) - if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms) + if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll) # linfo is unspecialized sp = Any[] sig = linfo.def.sig diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 8db4b2ea130e4..dc3541d06112c 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -37,8 +37,11 @@ mutable struct OptimizationState if nssavalues isa Int src.ssavaluetypes = Any[ Any for i = 1:nssavalues ] end - nslots = length(src.slotnames) - slottypes = Any[ Any for i = 1:nslots ] + nslots = length(src.slotflags) + slottypes = src.slottypes + if slottypes === nothing + slottypes = Any[ Any for i = 1:nslots ] + end s_edges = [] # cache some useful state computations toplevel = !isa(linfo.def, Method) @@ -73,7 +76,7 @@ end # This is implied by `SLOT_USEDUNDEF`. # If this is not set, all the uses are (statically) dominated by the defs. # In particular, if a slot has `AssignedOnce && !StaticUndef`, it is an SSA. -const SLOT_STATICUNDEF = 1 +const SLOT_STATICUNDEF = 1 # slot might be used before it is defined (structurally) const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError # const SLOT_CALLED = 64 diff --git a/base/compiler/ssair/legacy.jl b/base/compiler/ssair/legacy.jl index 2adf3b57a1f40..6230cfeeba3e2 100644 --- a/base/compiler/ssair/legacy.jl +++ b/base/compiler/ssair/legacy.jl @@ -1,13 +1,11 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license -inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotnames) ]) - function inflate_ir(ci::CodeInfo, linfo::MethodInstance) sptypes = sptypes_from_meth_instance(linfo) if ci.inferred argtypes, _ = matching_cache_argtypes(linfo, nothing) else - argtypes = Any[ Any for i = 1:length(ci.slotnames) ] + argtypes = Any[ Any for i = 1:length(ci.slotflags) ] end return inflate_ir(ci, sptypes, argtypes) end @@ -92,3 +90,6 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int) end end end + +# used by some tests +inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotflags) ]) diff --git a/base/compiler/ssair/slot2ssa.jl b/base/compiler/ssair/slot2ssa.jl index 4ab67b74ff8bc..1cc8a1509fdc4 100644 --- a/base/compiler/ssair/slot2ssa.jl +++ b/base/compiler/ssair/slot2ssa.jl @@ -45,7 +45,7 @@ end @inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id function scan_slot_def_use(nargs::Int, ci::CodeInfo, code::Vector{Any}) - nslots = length(ci.slotnames) + nslots = length(ci.slotflags) result = SlotInfo[SlotInfo() for i = 1:nslots] # Set defs for arguments for var in result[1:(1+nargs)] @@ -654,7 +654,7 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do undef_token else SSAValue(-1) - end for x in 1:length(ci.slotnames) + end for x in 1:length(ci.slotflags) ] worklist = Tuple{Int, Int, Vector{Any}}[(1, 0, initial_incoming_vals)] visited = BitSet() diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index 9358fe13c7916..aadd31a82ffee 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -56,10 +56,12 @@ function typeinf(frame::InferenceState) end end end + end + for caller in frames + caller.src.min_world = min_valid % Int + caller.src.max_world = max_valid % Int if cached - for caller in results - cache_result(caller, min_valid, max_valid) - end + cache_result(caller.result, min_valid, max_valid) end end # if we aren't cached, we don't need this edge @@ -308,6 +310,8 @@ function type_annotate!(sv::InferenceState) # compute the required type for each slot # to hold all of the items assigned into it record_slot_assign!(sv) + sv.src.slottypes = sv.slottypes + sv.src.rettype = sv.bestguess # annotate variables load types # remove dead code optimization @@ -544,16 +548,20 @@ function typeinf_ext(linfo::MethodInstance, params::Params) if invoke_api(linfo) == 2 tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ()) tree.code = Any[ Expr(:return, quoted(linfo.inferred_const)) ] - tree.method_for_inference_limit_heuristics = nothing - tree.slotnames = Any[ COMPILER_TEMP_SYM for i = 1:method.nargs ] - tree.slotflags = fill(0x00, Int(method.nargs)) - tree.ssavaluetypes = 0 + nargs = Int(method.nargs) + tree.slotnames = ccall(:jl_uncompress_argnames, Any, (Any,), method.slot_syms) + tree.slotflags = fill(0x00, nargs) + tree.ssavaluetypes = 1 tree.codelocs = Int32[1] tree.linetable = [LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)] tree.inferred = true - tree.ssaflags = UInt8[] + tree.ssaflags = UInt8[0] tree.pure = true tree.inlineable = true + tree.parent = linfo + tree.rettype = typeof(linfo.inferred_const) + tree.min_world = li.min_world + tree.max_world = li.max_world i == 2 && ccall(:jl_typeinf_end, Cvoid, ()) return svec(linfo, tree) elseif isa(inf, CodeInfo) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index ff6e89bdbb299..0a678ebb92805 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -96,11 +96,12 @@ end function retrieve_code_info(linfo::MethodInstance) m = linfo.def::Method + c = nothing if isdefined(m, :generator) # user code might throw errors – ignore them - return get_staged(linfo) - else - # TODO: post-inference see if we can swap back to the original arrays? + c = get_staged(linfo) + end + if c === nothing && isdefined(m, :source) src = m.source if isa(src, Array{UInt8,1}) c = ccall(:jl_uncompress_ast, Any, (Any, Any), m, src) @@ -108,7 +109,10 @@ function retrieve_code_info(linfo::MethodInstance) c = copy(src::CodeInfo) end end - return c::CodeInfo + if c isa CodeInfo + c.parent = linfo + return c + end end function code_for_method(method::Method, @nospecialize(atypes), sparams::SimpleVector, world::UInt, preexisting::Bool=false) diff --git a/base/compiler/validation.jl b/base/compiler/validation.jl index 1fcbf624e4256..8701b7ab6552b 100644 --- a/base/compiler/validation.jl +++ b/base/compiler/validation.jl @@ -41,7 +41,7 @@ const INVALID_RVALUE = "invalid RHS value" const INVALID_RETURN = "invalid argument to :return" const INVALID_CALL_ARG = "invalid :call argument" const EMPTY_SLOTNAMES = "slotnames field is empty" -const SLOTFLAGS_MISMATCH = "length(slotnames) != length(slotflags)" +const SLOTFLAGS_MISMATCH = "length(slotnames) < length(slotflags)" const SSAVALUETYPES_MISMATCH = "not all SSAValues in AST have a type in ssavaluetypes" const SSAVALUETYPES_MISMATCH_UNINFERRED = "uninferred CodeInfo ssavaluetypes field does not equal the number of present SSAValues" const NON_TOP_LEVEL_METHOD = "encountered `Expr` head `:method` in non-top-level code (i.e. `nargs` > 0)" @@ -168,7 +168,7 @@ function validate_code!(errors::Vector{>:InvalidCodeError}, c::CodeInfo, is_top_ nslotflags = length(c.slotflags) nssavals = length(c.code) !is_top_level && nslotnames == 0 && push!(errors, InvalidCodeError(EMPTY_SLOTNAMES)) - nslotnames != nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags))) + nslotnames < nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags))) if c.inferred nssavaluetypes = length(c.ssavaluetypes) nssavaluetypes < nssavals && push!(errors, InvalidCodeError(SSAVALUETYPES_MISMATCH, (nssavals, nssavaluetypes))) diff --git a/base/methodshow.jl b/base/methodshow.jl index 236b3fd1665ff..f03a02f1c7d24 100644 --- a/base/methodshow.jl +++ b/base/methodshow.jl @@ -43,12 +43,9 @@ function argtype_decl(env, n, sig::DataType, i::Int, nargs, isva::Bool) # -> (ar end function method_argnames(m::Method) - if !isdefined(m, :source) && isdefined(m, :generator) - return m.generator.argnames - end - argnames = Vector{Any}(undef, m.nargs) - ccall(:jl_fill_argnames, Cvoid, (Any, Any), m.source, argnames) - return argnames + argnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), m.slot_syms) + isempty(argnames) && return argnames + return argnames[1:m.nargs] end function arg_decl_parts(m::Method) @@ -60,8 +57,8 @@ function arg_decl_parts(m::Method) end file = m.file line = m.line - if isdefined(m, :source) || isdefined(m, :generator) - argnames = method_argnames(m) + argnames = method_argnames(m) + if length(argnames) >= m.nargs show_env = ImmutableDict{Symbol, Any}() for t in tv show_env = ImmutableDict(show_env, :unionall_env => t) @@ -74,26 +71,23 @@ function arg_decl_parts(m::Method) return tv, decls, file, line end +const empty_sym = Symbol("") + function kwarg_decl(m::Method, kwtype::DataType) sig = rewrap_unionall(Tuple{kwtype, Any, unwrap_unionall(m.sig).parameters...}, m.sig) kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m)) if kwli !== nothing kwli = kwli::Method - if isdefined(kwli, :source) - src = kwli.source - nslots = ccall(:jl_ast_nslots, Int, (Any,), src) - slotnames = Vector{Any}(undef, nslots) - ccall(:jl_fill_argnames, Cvoid, (Any, Any), src, slotnames) - kws = filter(x -> !('#' in string(x)), slotnames[(kwli.nargs + 1):end]) - # ensure the kwarg... is always printed last. The order of the arguments are not - # necessarily the same as defined in the function - i = findfirst(x -> endswith(string(x), "..."), kws) - if i !== nothing - push!(kws, kws[i]) - deleteat!(kws, i) - end - return kws + slotnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), kwli.slot_syms) + kws = filter(x -> !(x === empty_sym || '#' in string(x)), slotnames[(kwli.nargs + 1):end]) + # ensure the kwarg... is always printed last. The order of the arguments are not + # necessarily the same as defined in the function + i = findfirst(x -> endswith(string(x), "..."), kws) + if i !== nothing + push!(kws, kws[i]) + deleteat!(kws, i) end + return kws end return () end diff --git a/src/array.c b/src/array.c index fb5ef7886a5fc..2744eafeab958 100644 --- a/src/array.c +++ b/src/array.c @@ -470,6 +470,8 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a) JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len) { size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size + if (len == 0) + return jl_an_empty_string; jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining *(size_t*)s = len; memcpy((char*)s + sizeof(size_t), str, len); @@ -480,6 +482,8 @@ JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len) JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len) { size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size + if (len == 0) + return jl_an_empty_string; jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining *(size_t*)s = len; ((char*)s + sizeof(size_t))[len] = 0; diff --git a/src/ast.c b/src/ast.c index 0aeedac33b1b0..ea0717339cc61 100644 --- a/src/ast.c +++ b/src/ast.c @@ -50,17 +50,17 @@ jl_sym_t *dot_sym; jl_sym_t *newvar_sym; jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym; jl_sym_t *copyast_sym; jl_sym_t *cfunction_sym; jl_sym_t *pure_sym; jl_sym_t *simdloop_sym; -jl_sym_t *meta_sym; jl_sym_t *compiler_temp_sym; -jl_sym_t *inert_sym; jl_sym_t *polly_sym; -jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym; -jl_sym_t *inline_sym; jl_sym_t *noinline_sym; -jl_sym_t *generated_sym; jl_sym_t *generated_only_sym; -jl_sym_t *isdefined_sym; jl_sym_t *propagate_inbounds_sym; -jl_sym_t *specialize_sym; jl_sym_t *nospecialize_sym; -jl_sym_t *macrocall_sym; jl_sym_t *colon_sym; -jl_sym_t *hygienicscope_sym; jl_sym_t *escape_sym; -jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym; +jl_sym_t *meta_sym; jl_sym_t *inert_sym; +jl_sym_t *polly_sym; jl_sym_t *unused_sym; +jl_sym_t *static_parameter_sym; jl_sym_t *inline_sym; +jl_sym_t *noinline_sym; jl_sym_t *generated_sym; +jl_sym_t *generated_only_sym; jl_sym_t *isdefined_sym; +jl_sym_t *propagate_inbounds_sym; jl_sym_t *specialize_sym; +jl_sym_t *nospecialize_sym; jl_sym_t *macrocall_sym; +jl_sym_t *colon_sym; jl_sym_t *hygienicscope_sym; jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym; +jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym; +jl_sym_t *escape_sym; static uint8_t flisp_system_image[] = { #include @@ -347,7 +347,6 @@ void jl_init_frontend(void) unused_sym = jl_symbol("#unused#"); slot_sym = jl_symbol("slot"); static_parameter_sym = jl_symbol("static_parameter"); - compiler_temp_sym = jl_symbol("#temp#"); inline_sym = jl_symbol("inline"); noinline_sym = jl_symbol("noinline"); polly_sym = jl_symbol("polly"); diff --git a/src/codegen.cpp b/src/codegen.cpp index 63bfe69062474..9a54db0361615 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3315,8 +3315,12 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i) Value *sp = tbaa_decorate(tbaa_const, ctx.builder.CreateLoad(bp)); Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp), maybe_decay_untracked(literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type))); - jl_sym_t *name = (jl_sym_t*)jl_svecref(ctx.linfo->def.method->sparam_syms, i); - undef_var_error_ifnot(ctx, isnull, name); + jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig; + for (size_t j = 0; j < i; j++) { + sparam = (jl_unionall_t*)sparam->body; + assert(jl_is_unionall(sparam)); + } + undef_var_error_ifnot(ctx, isnull, sparam->var->name); return mark_julia_type(ctx, sp, true, jl_any_type); } @@ -5375,7 +5379,7 @@ static std::unique_ptr emit_function( // step 2. process var-info lists to see what vars need boxing int n_ssavalues = jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_len(src->ssavaluetypes); - size_t vinfoslen = jl_array_dim0(src->slotnames); + size_t vinfoslen = jl_array_dim0(src->slotflags); ctx.slots.resize(vinfoslen); size_t nreq = ctx.nargs; int va = 0; @@ -5397,7 +5401,7 @@ static std::unique_ptr emit_function( bool needsparams = false; if (jl_is_method(lam->def.method)) { - if (jl_svec_len(lam->def.method->sparam_syms) != jl_svec_len(lam->sparam_vals)) + if ((size_t)jl_subtype_env_size(lam->def.method->sig) != jl_svec_len(lam->sparam_vals)) needsparams = true; for (size_t i = 0; i < jl_svec_len(lam->sparam_vals); ++i) { if (jl_is_typevar(jl_svecref(lam->sparam_vals, i))) @@ -5597,7 +5601,7 @@ static std::unique_ptr emit_function( for (i = 0; i < vinfoslen; i++) { jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i); jl_varinfo_t &varinfo = ctx.slots[i]; - if (varinfo.isArgument || s == compiler_temp_sym || s == unused_sym) + if (varinfo.isArgument || s == empty_sym || s == unused_sym) continue; // LLVM 4.0: Assume the variable has default alignment varinfo.dinfo = dbuilder.createAutoVariable( @@ -6027,14 +6031,14 @@ static std::unique_ptr emit_function( return; while (dbg) { new_lineinfo.push_back(dbg); - dbg = linetable[dbg].inlined_at; + dbg = linetable.at(dbg).inlined_at; } current_lineinfo.resize(new_lineinfo.size(), 0); for (dbg = 0; dbg < new_lineinfo.size(); dbg++) { unsigned newdbg = new_lineinfo[new_lineinfo.size() - dbg - 1]; if (newdbg != current_lineinfo[dbg]) { current_lineinfo[dbg] = newdbg; - const auto &info = linetable[newdbg]; + const auto &info = linetable.at(newdbg); if (do_coverage(info.is_user_code)) coverageVisitLine(ctx, info.file, info.line); } @@ -6044,9 +6048,9 @@ static std::unique_ptr emit_function( auto mallocVisitStmt = [&] (unsigned dbg) { if (!do_malloc_log(mod_is_user_mod) || dbg == 0) return; - while (linetable[dbg].inlined_at) - dbg = linetable[dbg].inlined_at; - mallocVisitLine(ctx, ctx.file, linetable[dbg].line); + while (linetable.at(dbg).inlined_at) + dbg = linetable.at(dbg).inlined_at; + mallocVisitLine(ctx, ctx.file, linetable.at(dbg).line); }; come_from_bb[0] = ctx.builder.GetInsertBlock(); @@ -6111,7 +6115,7 @@ static std::unique_ptr emit_function( int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor]; if (debuginfoloc > 0) { if (ctx.debug_enabled) - ctx.builder.SetCurrentDebugLocation(linetable[debuginfoloc].loc); + ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc); coverageVisitStmt(debuginfoloc); } jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor); diff --git a/src/dump.c b/src/dump.c index a7b0151e51e8f..f3dc5e210ee6b 100644 --- a/src/dump.c +++ b/src/dump.c @@ -796,7 +796,7 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li write_int8(s->s, m->isva); write_int8(s->s, m->pure); jl_serialize_value(s, (jl_value_t*)m->module); - jl_serialize_value(s, (jl_value_t*)m->sparam_syms); + jl_serialize_value(s, (jl_value_t*)m->slot_syms); jl_serialize_value(s, (jl_value_t*)m->roots); jl_serialize_value(s, (jl_value_t*)m->source); jl_serialize_value(s, (jl_value_t*)m->unspecialized); @@ -865,9 +865,14 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li jl_error("Task cannot be serialized"); } else if (jl_typeis(v, jl_string_type)) { - write_uint8(s->s, TAG_STRING); - write_int32(s->s, jl_string_len(v)); - ios_write(s->s, jl_string_data(v), jl_string_len(v)); + if (jl_string_len(v) == 0) { + jl_serialize_value(s, jl_an_empty_string); + } + else { + write_uint8(s->s, TAG_STRING); + write_int32(s->s, jl_string_len(v)); + ios_write(s->s, jl_string_data(v), jl_string_len(v)); + } } else if (jl_typeis(v, jl_typemap_entry_type)) { write_uint8(s->s, TAG_TYPEMAP_ENTRY); @@ -1658,8 +1663,8 @@ static jl_value_t *jl_deserialize_value_method(jl_serializer_state *s, jl_value_ m->pure = read_int8(s->s); m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module); jl_gc_wb(m, m->module); - m->sparam_syms = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->sparam_syms); - jl_gc_wb(m, m->sparam_syms); + m->slot_syms = jl_deserialize_value(s, (jl_value_t**)&m->slot_syms); + jl_gc_wb(m, m->slot_syms); m->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&m->roots); if (m->roots) jl_gc_wb(m, m->roots); @@ -2456,32 +2461,34 @@ JL_DLLEXPORT jl_array_t *jl_compress_ast(jl_method_t *m, jl_code_info_t *code) | (code->pure << 0); write_uint8(s.s, flags); - size_t nsyms = jl_array_len(code->slotnames); - assert(nsyms >= m->nargs && nsyms < INT32_MAX); // required by generated functions - write_int32(s.s, nsyms); - assert(nsyms == jl_array_len(code->slotflags)); - ios_write(s.s, (char*)jl_array_data(code->slotflags), nsyms); + size_t nslots = jl_array_len(code->slotflags); + assert(nslots >= m->nargs && nslots < INT32_MAX); // required by generated functions + write_int32(s.s, nslots); + ios_write(s.s, (char*)jl_array_data(code->slotflags), nslots); // N.B.: The layout of everything before this point is explicitly referenced // by the various jl_ast_ accessors. Make sure to adjust those if you change // the data layout. - for (i = 0; i < nsyms; i++) { - jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(code->slotnames, i); - assert(jl_is_symbol(name)); - char *namestr = jl_symbol_name(name); - size_t namelen = strlen(namestr); - ios_write(s.s, namestr, namelen + 1); // include nul-byte - } - - size_t nf = jl_datatype_nfields(jl_code_info_type); - for (i = 0; i < nf - 6; i++) { - if (i == 1) // skip codelocs + for (i = 0; i < 6; i++) { + int copy = 1; + if (i == 1) { // skip codelocs + assert(jl_field_offset(jl_code_info_type, i) == offsetof(jl_code_info_t, codelocs)); continue; - int copy = (i != 2); // don't copy contents of method_for_inference_limit_heuristics field + } + if (i == 4) { // don't copy contents of method_for_inference_limit_heuristics field + assert(jl_field_offset(jl_code_info_type, i) == offsetof(jl_code_info_t, method_for_inference_limit_heuristics)); + copy = 0; + } jl_serialize_value_(&s, jl_get_nth_field((jl_value_t*)code, i), copy); } + if (m->generator) + // can't optimize generated functions + jl_serialize_value_(&s, (jl_value_t*)jl_compress_argnames(code->slotnames), 1); + else + jl_serialize_value(&s, jl_nothing); + size_t nstmt = jl_array_len(code->code); assert(nstmt == jl_array_len(code->codelocs)); if (jl_array_len(code->linetable) < 256) { @@ -2516,7 +2523,6 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) if (jl_is_code_info(data)) return (jl_code_info_t*)data; JL_TIMING(AST_UNCOMPRESS); - jl_ptls_t ptls = jl_get_ptls_states(); JL_LOCK(&m->writelock); // protect the roots array (Might GC) assert(jl_is_method(m)); assert(jl_typeis(data, jl_array_uint8_type)); @@ -2533,9 +2539,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) NULL }; - jl_code_info_t *code = - (jl_code_info_t*)jl_gc_alloc(ptls, sizeof(jl_code_info_t), - jl_code_info_type); + jl_code_info_t *code = jl_new_code_info_uninit(); uint8_t flags = read_uint8(s.s); code->inferred = !!(flags & (1 << 3)); code->inlineable = !!(flags & (1 << 2)); @@ -2546,25 +2550,19 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) code->slotflags = jl_alloc_array_1d(jl_array_uint8_type, nslots); ios_read(s.s, (char*)jl_array_data(code->slotflags), nslots); - jl_array_t *syms = jl_alloc_vec_any(nslots); - code->slotnames = syms; - for (i = 0; i < nslots; i++) { - char *namestr = s.s->buf + s.s->bpos; - size_t namelen = strlen(namestr); - jl_sym_t *name = jl_symbol_n(namestr, namelen); - jl_array_ptr_set(syms, i, name); - ios_skip(s.s, namelen + 1); - } - - size_t nf = jl_datatype_nfields(jl_code_info_type); - for (i = 0; i < nf - 6; i++) { - if (i == 1) + for (i = 0; i < 6; i++) { + if (i == 1) // skip codelocs continue; assert(jl_field_isptr(jl_code_info_type, i)); jl_value_t **fld = (jl_value_t**)((char*)jl_data_ptr(code) + jl_field_offset(jl_code_info_type, i)); *fld = jl_deserialize_value(&s, fld); } + jl_value_t *slotnames = jl_deserialize_value(&s, NULL); + if (!jl_is_string(slotnames)) + slotnames = m->slot_syms; + code->slotnames = jl_uncompress_argnames(m->slot_syms); + size_t nstmt = jl_array_len(code->code); code->codelocs = (jl_value_t*)jl_alloc_array_1d(jl_array_int32_type, nstmt); if (jl_array_len(code->linetable) < 256) { @@ -2617,6 +2615,32 @@ JL_DLLEXPORT uint8_t jl_ast_flag_pure(jl_array_t *data) return !!(flags & (1 << 0)); } +JL_DLLEXPORT jl_value_t *jl_compress_argnames(jl_array_t *syms) +{ + size_t nsyms = jl_array_len(syms); + size_t i, len = 0; + for (i = 0; i < nsyms; i++) { + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(syms, i); + assert(jl_is_symbol(name)); + char *namestr = jl_symbol_name(name); + size_t namelen = strlen(namestr) + 1; + len += namelen; + } + jl_value_t *str = jl_alloc_string(len); + len = 0; + for (i = 0; i < nsyms; i++) { + jl_sym_t *name = (jl_sym_t*)jl_array_ptr_ref(syms, i); + assert(jl_is_symbol(name)); + char *namestr = jl_symbol_name(name); + size_t namelen = strlen(namestr) + 1; // include nul-byte + assert(len + namelen <= jl_string_len(str)); + memcpy(jl_string_data(str) + len, namestr, namelen); + len += namelen; + } + assert(len == jl_string_len(str)); + return str; +} + JL_DLLEXPORT ssize_t jl_ast_nslots(jl_array_t *data) { if (jl_is_code_info(data)) { @@ -2635,36 +2659,54 @@ JL_DLLEXPORT uint8_t jl_ast_slotflag(jl_array_t *data, size_t i) assert(i < jl_ast_nslots(data)); if (jl_is_code_info(data)) return ((uint8_t*)((jl_code_info_t*)data)->slotflags->data)[i]; + assert(jl_typeis(data, jl_array_uint8_type)); return ((uint8_t*)data->data)[1 + sizeof(int32_t) + i]; } -JL_DLLEXPORT void jl_fill_argnames(jl_array_t *data, jl_array_t *names) +JL_DLLEXPORT jl_array_t *jl_uncompress_argnames(jl_value_t *syms) { - size_t i, nargs = jl_array_len(names); - if (jl_is_code_info(data)) { - jl_code_info_t *func = (jl_code_info_t*)data; - assert(jl_array_len(func->slotnames) >= nargs); - for (i = 0; i < nargs; i++) { - jl_value_t *name = jl_array_ptr_ref(func->slotnames, i); - jl_array_ptr_set(names, i, name); - } + assert(jl_is_string(syms)); + char *namestr; + namestr = jl_string_data(syms); + size_t remaining = jl_string_len(syms); + size_t i, len = 0; + while (remaining) { + size_t namelen = strlen(namestr); + len += 1; + namestr += namelen + 1; + remaining -= namelen + 1; } - else { - assert(jl_typeis(data, jl_array_uint8_type)); - char *d = (char*)data->data; - int nslots = jl_load_unaligned_i32(d + 1); - assert(nslots >= nargs); - (void)nslots; - char *namestr = d + 5 + nslots; - for (i = 0; i < nargs; i++) { - size_t namelen = strlen(namestr); + namestr = jl_string_data(syms); + jl_array_t *names = jl_alloc_vec_any(len); + JL_GC_PUSH1(&names); + for (i = 0; i < len; i++) { + size_t namelen = strlen(namestr); + jl_sym_t *name = jl_symbol_n(namestr, namelen); + jl_array_ptr_set(names, i, name); + namestr += namelen + 1; + } + JL_GC_POP(); + return names; +} + +JL_DLLEXPORT jl_value_t *jl_uncompress_argname_n(jl_value_t *syms, size_t i) +{ + assert(jl_is_string(syms)); + char *namestr = jl_string_data(syms); + size_t remaining = jl_string_len(syms); + while (remaining) { + size_t namelen = strlen(namestr); + if (i-- == 0) { jl_sym_t *name = jl_symbol_n(namestr, namelen); - jl_array_ptr_set(names, i, name); - namestr += namelen + 1; + return (jl_value_t*)name; } + namestr += namelen + 1; + remaining -= namelen + 1; } + return jl_nothing; } + JL_DLLEXPORT int jl_save_incremental(const char *fname, jl_array_t *worklist) { JL_TIMING(SAVE_MODULE); @@ -3190,7 +3232,7 @@ void jl_init_serializer(void) void *vals[] = { jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type, call_sym, invoke_sym, goto_ifnot_sym, return_sym, jl_symbol("tuple"), - unreachable_sym, + unreachable_sym, jl_an_empty_string, // empirical list of very common symbols #include "common_symbols1.inc" diff --git a/src/gf.c b/src/gf.c index 7c1fa7294f2ce..6e57cea50b988 100644 --- a/src/gf.c +++ b/src/gf.c @@ -206,7 +206,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr m->isva = 1; m->nargs = 2; m->sig = (jl_value_t*)jl_anytuple_type; - m->sparam_syms = jl_emptysvec; + m->slot_syms = jl_an_empty_string; jl_methtable_t *mt = dt->name->mt; jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, diff --git a/src/jltypes.c b/src/jltypes.c index ef58464b2cf53..531d230b77101 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -33,7 +33,7 @@ jl_datatype_t *jl_typedslot_type; jl_datatype_t *jl_simplevector_type; jl_typename_t *jl_tuple_typename; jl_datatype_t *jl_anytuple_type; -jl_datatype_t *jl_emptytuple_type=NULL; +jl_datatype_t *jl_emptytuple_type; jl_unionall_t *jl_anytuple_type_type; jl_typename_t *jl_vecelement_typename; jl_unionall_t *jl_vararg_type; @@ -67,7 +67,7 @@ jl_datatype_t *jl_floatingpoint_type; jl_datatype_t *jl_number_type; jl_datatype_t *jl_signed_type; -JL_DLLEXPORT jl_value_t *jl_emptytuple=NULL; +JL_DLLEXPORT jl_value_t *jl_emptytuple; jl_svec_t *jl_emptysvec; jl_value_t *jl_nothing; @@ -79,7 +79,7 @@ jl_unionall_t *jl_typetype_type; jl_unionall_t *jl_array_type; jl_typename_t *jl_array_typename; jl_value_t *jl_array_uint8_type; -jl_value_t *jl_array_any_type=NULL; +jl_value_t *jl_array_any_type; jl_value_t *jl_array_symbol_type; jl_value_t *jl_array_int32_type; jl_datatype_t *jl_weakref_type; @@ -101,9 +101,10 @@ jl_datatype_t *jl_methtable_type; jl_datatype_t *jl_typemap_entry_type; jl_datatype_t *jl_typemap_level_type; jl_datatype_t *jl_method_instance_type; +jl_datatype_t *jl_lambda_type; jl_datatype_t *jl_code_info_type; jl_datatype_t *jl_module_type; -jl_datatype_t *jl_errorexception_type=NULL; +jl_datatype_t *jl_errorexception_type; jl_datatype_t *jl_argumenterror_type; jl_datatype_t *jl_typeerror_type; jl_datatype_t *jl_methoderror_type; @@ -118,7 +119,8 @@ jl_datatype_t *jl_void_type; jl_datatype_t *jl_voidpointer_type; jl_typename_t *jl_namedtuple_typename; jl_unionall_t *jl_namedtuple_type; -jl_value_t *jl_an_empty_vec_any=NULL; +jl_value_t *jl_an_empty_vec_any; +jl_value_t *jl_an_empty_string; jl_value_t *jl_stackovf_exception; #ifdef SEGV_EXCEPTION jl_value_t *jl_segv_exception; @@ -1877,6 +1879,14 @@ void jl_init_types(void) JL_GC_DISABLED jl_false = jl_permbox8(jl_bool_type, 0); jl_true = jl_permbox8(jl_bool_type, 1); + jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), core, jl_any_type, jl_emptysvec); + jl_string_type = jl_new_datatype(jl_symbol("String"), core, jl_abstractstring_type, jl_emptysvec, + jl_emptysvec, jl_emptysvec, 0, 1, 0); + jl_string_type->instance = NULL; + jl_compute_field_offsets(jl_string_type); + jl_an_empty_string = jl_pchar_to_string("\0", 1); + *(size_t*)jl_an_empty_string = 0; + jl_typemap_level_type = jl_new_datatype(jl_symbol("TypeMapLevel"), core, jl_any_type, jl_emptysvec, jl_perm_symsvec(7, @@ -2017,36 +2027,43 @@ void jl_init_types(void) JL_GC_DISABLED jl_code_info_type = jl_new_datatype(jl_symbol("CodeInfo"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(12, + jl_perm_symsvec(17, "code", "codelocs", - "method_for_inference_limit_heuristics", "ssavaluetypes", - "linetable", "ssaflags", - "slotflags", + "method_for_inference_limit_heuristics", + "linetable", "slotnames", + "slotflags", + "slottypes", + "rettype", + "parent", + "min_world", + "max_world", "inferred", "inlineable", "propagate_inbounds", "pure"), - jl_svec(12, + jl_svec(17, jl_array_any_type, jl_any_type, jl_any_type, + jl_array_uint8_type, + jl_any_type, jl_any_type, jl_any_type, jl_array_uint8_type, - jl_array_uint8_type, - // Note: The following fields have special serialization. - // If you change them, you'll have to adjust the - // serializer - jl_array_any_type, + jl_any_type, + jl_any_type, + jl_any_type, + jl_long_type, + jl_long_type, jl_bool_type, jl_bool_type, jl_bool_type, jl_bool_type), - 0, 1, 12); + 0, 1, 17); jl_method_type = jl_new_datatype(jl_symbol("Method"), core, @@ -2061,7 +2078,7 @@ void jl_init_types(void) JL_GC_DISABLED "max_world", "ambig", "specializations", - "sparam_syms", + "slot_syms", "source", "unspecialized", "generator", @@ -2082,7 +2099,7 @@ void jl_init_types(void) JL_GC_DISABLED jl_long_type, jl_any_type, // Union{Array, Nothing} jl_any_type, // TypeMap - jl_simplevector_type, + jl_string_type, jl_any_type, jl_any_type, // jl_method_instance_type jl_any_type, @@ -2161,12 +2178,6 @@ void jl_init_types(void) JL_GC_DISABLED (jl_unionall_t*)jl_new_struct(jl_unionall_type, typetype_tvar, jl_apply_type1((jl_value_t*)jl_type_type, (jl_value_t*)typetype_tvar)); - jl_abstractstring_type = jl_new_abstracttype((jl_value_t*)jl_symbol("AbstractString"), core, jl_any_type, jl_emptysvec); - jl_string_type = jl_new_datatype(jl_symbol("String"), core, jl_abstractstring_type, jl_emptysvec, - jl_emptysvec, jl_emptysvec, 0, 1, 0); - jl_string_type->instance = NULL; - jl_compute_field_offsets(jl_string_type); - jl_tvar_t *ntval_var = jl_new_typevar(jl_symbol("T"), (jl_value_t*)jl_bottom_type, (jl_value_t*)jl_anytuple_type); tv = jl_svec2(tvar("names"), ntval_var); diff --git a/src/julia.h b/src/julia.h index 47a2705acd8e0..efa69675535db 100644 --- a/src/julia.h +++ b/src/julia.h @@ -233,21 +233,32 @@ typedef struct _jl_llvm_functions_t { const char *specFunctionObject; // specialized llvm Function name (on sig+rettype) } jl_llvm_functions_t; +typedef struct _jl_method_instance_t jl_method_instance_t; + // This type describes a single function body typedef struct _jl_code_info_t { + // ssavalue-indexed arrays of properties: jl_array_t *code; // Any array of statements jl_value_t *codelocs; // Int32 array of indicies into the line table - jl_value_t *method_for_inference_limit_heuristics; // optional method used during inference - jl_value_t *ssavaluetypes; // types of ssa values (or count of them) - jl_value_t *linetable; // Table of locations + jl_value_t *ssavaluetypes; // types of ssa values (or count of them) jl_array_t *ssaflags; // flags associated with each statement: // 0 = inbounds // 1,2 = inlinehint,always-inline,noinline // 3 = strict-ieee (strictfp) // 4-6 = // 7 = has out-of-band info - jl_array_t *slotflags; // local var bit flags + // miscellaneous data: + jl_value_t *method_for_inference_limit_heuristics; // optional method used during inference + jl_value_t *linetable; // Table of locations [TODO: make this volatile like slotnames] jl_array_t *slotnames; // names of local variables + jl_array_t *slotflags; // local var bit flags + // the following are optional transient properties (not preserved by compression--as they typically get stored elsewhere): + jl_value_t *slottypes; // inferred types of slots + jl_value_t *rettype; + jl_method_instance_t *parent; // context (optionally, if available, otherwise nothing) + size_t min_world; + size_t max_world; + // various boolean properties: uint8_t inferred; uint8_t inlineable; uint8_t propagate_inbounds; @@ -274,7 +285,7 @@ typedef struct _jl_method_t { // table of all argument types for which we've inferred or compiled this code jl_typemap_t *specializations; - jl_svec_t *sparam_syms; // symbols giving static parameter names + jl_value_t *slot_syms; // compacted list of slot names (String) jl_value_t *source; // original code template (jl_code_info_t, but may be compressed), null for builtins struct _jl_method_instance_t *unspecialized; // unspecialized executable method instance, or null jl_value_t *generator; // executable code-generating function if available @@ -307,7 +318,7 @@ typedef struct _jl_method_instance_t { } def; // context for this lambda definition jl_value_t *specTypes; // argument types this was specialized for jl_value_t *rettype; // return type for fptr - jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sparam_syms + jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sig UnionAll tvars jl_array_t *backedges; jl_value_t *inferred; // inferred jl_code_info_t, or jl_nothing, or null jl_value_t *inferred_const; // inferred constant return value, or null @@ -573,6 +584,7 @@ extern JL_DLLEXPORT jl_value_t *jl_undefref_exception JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_interrupt_exception JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_boundserror_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_value_t *jl_an_empty_vec_any JL_GLOBALLY_ROOTED; +extern JL_DLLEXPORT jl_value_t *jl_an_empty_string JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_bool_type JL_GLOBALLY_ROOTED; extern JL_DLLEXPORT jl_datatype_t *jl_char_type JL_GLOBALLY_ROOTED; @@ -1548,8 +1560,11 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ast(jl_method_t *m, jl_array_t *data) JL_DLLEXPORT uint8_t jl_ast_flag_inferred(jl_array_t *data); JL_DLLEXPORT uint8_t jl_ast_flag_inlineable(jl_array_t *data); JL_DLLEXPORT uint8_t jl_ast_flag_pure(jl_array_t *data); +JL_DLLEXPORT ssize_t jl_ast_nslots(jl_array_t *data); JL_DLLEXPORT uint8_t jl_ast_slotflag(jl_array_t *data, size_t i); -JL_DLLEXPORT void jl_fill_argnames(jl_array_t *data, jl_array_t *names); +JL_DLLEXPORT jl_value_t *jl_compress_argnames(jl_array_t *syms); +JL_DLLEXPORT jl_array_t *jl_uncompress_argnames(jl_value_t *syms); +JL_DLLEXPORT jl_value_t *jl_uncompress_argname_n(jl_value_t *syms, size_t i); JL_DLLEXPORT int jl_is_operator(char *sym); JL_DLLEXPORT int jl_is_unary_operator(char *sym); diff --git a/src/julia_internal.h b/src/julia_internal.h index 25b2287b2e60b..f1df8442ff692 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -1001,18 +1001,18 @@ extern jl_sym_t *dot_sym; extern jl_sym_t *newvar_sym; extern jl_sym_t *boundscheck_sym; extern jl_sym_t *inbounds_sym; extern jl_sym_t *copyast_sym; extern jl_sym_t *cfunction_sym; extern jl_sym_t *pure_sym; extern jl_sym_t *simdloop_sym; -extern jl_sym_t *meta_sym; extern jl_sym_t *compiler_temp_sym; -extern jl_sym_t *inert_sym; extern jl_sym_t *polly_sym; -extern jl_sym_t *unused_sym; extern jl_sym_t *static_parameter_sym; -extern jl_sym_t *inline_sym; extern jl_sym_t *noinline_sym; -extern jl_sym_t *generated_sym; extern jl_sym_t *generated_only_sym; -extern jl_sym_t *isdefined_sym; extern jl_sym_t *propagate_inbounds_sym; -extern jl_sym_t *specialize_sym; extern jl_sym_t *nospecialize_sym; -extern jl_sym_t *macrocall_sym; extern jl_sym_t *colon_sym; -extern jl_sym_t *hygienicscope_sym; extern jl_sym_t *escape_sym; -extern jl_sym_t *gc_preserve_begin_sym; extern jl_sym_t *gc_preserve_end_sym; +extern jl_sym_t *meta_sym; extern jl_sym_t *inert_sym; +extern jl_sym_t *polly_sym; extern jl_sym_t *unused_sym; +extern jl_sym_t *static_parameter_sym; extern jl_sym_t *inline_sym; +extern jl_sym_t *noinline_sym; extern jl_sym_t *generated_sym; +extern jl_sym_t *generated_only_sym; extern jl_sym_t *isdefined_sym; +extern jl_sym_t *propagate_inbounds_sym; extern jl_sym_t *specialize_sym; +extern jl_sym_t *nospecialize_sym; extern jl_sym_t *macrocall_sym; +extern jl_sym_t *colon_sym; extern jl_sym_t *hygienicscope_sym; extern jl_sym_t *throw_undef_if_not_sym; extern jl_sym_t *getfield_undefref_sym; +extern jl_sym_t *gc_preserve_begin_sym; extern jl_sym_t *gc_preserve_end_sym; extern jl_sym_t *failed_sym; extern jl_sym_t *done_sym; extern jl_sym_t *runnable_sym; +extern jl_sym_t *escape_sym; struct _jl_sysimg_fptrs_t; diff --git a/src/method.c b/src/method.c index f5d07c2c20231..dcca5a629aa98 100644 --- a/src/method.c +++ b/src/method.c @@ -243,7 +243,6 @@ static void jl_code_info_set_ast(jl_code_info_t *li, jl_expr_t *ast) jl_array_del_end(meta, na - ins); } } - li->method_for_inference_limit_heuristics = jl_nothing; jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ast, 1); jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0); size_t nslots = jl_array_len(vis); @@ -273,7 +272,7 @@ static void jl_code_info_set_ast(jl_code_info_t *li, jl_expr_t *ast) if (nxt) name = jl_symbol(nxt+1); else if (str[1] == 's') // compiler-generated temporaries, #sXXX - name = compiler_temp_sym; + name = empty_sym; } } jl_array_ptr_set(li->slotnames, i, name); @@ -312,17 +311,22 @@ JL_DLLEXPORT jl_code_info_t *jl_new_code_info_uninit(void) (jl_code_info_t*)jl_gc_alloc(ptls, sizeof(jl_code_info_t), jl_code_info_type); src->code = NULL; - src->method_for_inference_limit_heuristics = NULL; - src->slotnames = NULL; - src->slotflags = NULL; - src->ssavaluetypes = NULL; src->codelocs = jl_nothing; - src->linetable = jl_nothing; + src->ssavaluetypes = NULL; src->ssaflags = NULL; + src->method_for_inference_limit_heuristics = jl_nothing; + src->linetable = jl_nothing; + src->slotflags = NULL; + src->slotnames = NULL; + src->slottypes = jl_nothing; + src->parent = (jl_method_instance_t*)jl_nothing; + src->rettype = (jl_value_t*)jl_any_type; + src->min_world = 0; + src->max_world = 0; src->inferred = 0; - src->pure = 0; src->inlineable = 0; src->propagate_inbounds = 0; + src->pure = 0; return src; } @@ -449,7 +453,7 @@ JL_DLLEXPORT jl_code_info_t *jl_copy_code_info(jl_code_info_t *src) // return a new lambda-info that has some extra static parameters merged in jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp) { - assert(jl_svec_len(m->sparam_syms) == jl_svec_len(sp) || sp == jl_emptysvec); + assert((size_t)jl_subtype_env_size(m->sig) == jl_svec_len(sp) || sp == jl_emptysvec); jl_method_instance_t *new_linfo = jl_new_method_instance_uninit(); new_linfo->def.method = m; new_linfo->specTypes = types; @@ -558,6 +562,8 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src) src = jl_copy_code_info(src); src->code = copy; jl_gc_wb(src, copy); + m->slot_syms = jl_compress_argnames(src->slotnames); + jl_gc_wb(m, m->slot_syms); if (gen_only) m->source = NULL; else @@ -573,7 +579,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t *module) (jl_method_t*)jl_gc_alloc(ptls, sizeof(jl_method_t), jl_method_type); m->specializations = jl_nothing; m->sig = NULL; - m->sparam_syms = NULL; + m->slot_syms = NULL; m->ambig = jl_nothing; m->roots = NULL; m->module = module; @@ -602,22 +608,11 @@ static jl_method_t *jl_new_method( jl_module_t *inmodule, jl_tupletype_t *sig, size_t nargs, - int isva, - jl_svec_t *tvars) + int isva) { - size_t i, l = jl_svec_len(tvars); - jl_svec_t *sparam_syms = jl_alloc_svec_uninit(l); - for (i = 0; i < l; i++) { - jl_svecset(sparam_syms, i, ((jl_tvar_t*)jl_svecref(tvars, i))->name); - } - jl_value_t *root = (jl_value_t*)sparam_syms; - jl_method_t *m = NULL; - JL_GC_PUSH1(&root); - - m = jl_new_method_uninit(inmodule); - root = (jl_value_t*)m; + jl_method_t *m = jl_new_method_uninit(inmodule); + JL_GC_PUSH1(&m); m->sig = (jl_value_t*)sig; - m->sparam_syms = sparam_syms; m->name = name; m->isva = isva; m->nargs = nargs; @@ -761,7 +756,7 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, // the result is that the closure variables get interpolated directly into the AST f = jl_new_code_info_from_ast((jl_expr_t*)f); } - m = jl_new_method(f, name, module, (jl_tupletype_t*)argtype, nargs, isva, tvars); + m = jl_new_method(f, name, module, (jl_tupletype_t*)argtype, nargs, isva); if (jl_has_free_typevars(argtype)) { jl_exceptionf(jl_argumenterror_type, diff --git a/src/precompile.c b/src/precompile.c index e419eb2d5dbb7..6209e1f9d8dad 100644 --- a/src/precompile.c +++ b/src/precompile.c @@ -372,7 +372,7 @@ static void jl_compile_specializations(void) JL_GC_PUSH1(&m); jl_foreach_reachable_mtable(precompile_enq_all_specializations_, m); // Ensure stable ordering to make inference problems more reproducible (#29923) - jl_sort_types(jl_array_data(m), jl_array_len(m)); + jl_sort_types((jl_value_t**)jl_array_data(m), jl_array_len(m)); size_t i, l; for (i = 0, l = jl_array_len(m); i < l; i++) { jl_compile_hint((jl_tupletype_t*)jl_array_ptr_ref(m, i)); diff --git a/src/staticdata.c b/src/staticdata.c index 363e0d716c3bb..72ad77b3b1488 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -1632,7 +1632,7 @@ static void jl_init_serializer2(int for_serialize) jl_module_type, jl_tvar_type, jl_method_instance_type, jl_method_type, jl_emptysvec, jl_emptytuple, jl_false, jl_true, jl_nothing, jl_any_type, call_sym, invoke_sym, goto_ifnot_sym, return_sym, jl_symbol("tuple"), - unreachable_sym, + unreachable_sym, jl_an_empty_string, jl_linenumbernode_type, jl_lineinfonode_type, jl_gotonode_type, jl_quotenode_type, jl_pinode_type, jl_phinode_type, jl_phicnode_type, jl_upsilonnode_type, diff --git a/stdlib/Serialization/src/Serialization.jl b/stdlib/Serialization/src/Serialization.jl index f5779b73d2603..9db124f63c150 100644 --- a/stdlib/Serialization/src/Serialization.jl +++ b/stdlib/Serialization/src/Serialization.jl @@ -390,7 +390,7 @@ function serialize(s::AbstractSerializer, meth::Method) serialize(s, meth.file) serialize(s, meth.line) serialize(s, meth.sig) - serialize(s, meth.sparam_syms) + serialize(s, meth.slot_syms) serialize(s, meth.ambig) serialize(s, meth.nargs) serialize(s, meth.isva) @@ -913,7 +913,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) file = deserialize(s)::Symbol line = deserialize(s)::Int32 sig = deserialize(s)::Type - sparam_syms = deserialize(s)::SimpleVector + slot_syms = deserialize(s)::String ambig = deserialize(s)::Union{Array{Any,1}, Nothing} nargs = deserialize(s)::Int32 isva = deserialize(s)::Bool @@ -925,7 +925,7 @@ function deserialize(s::AbstractSerializer, ::Type{Method}) meth.file = file meth.line = line meth.sig = sig - meth.sparam_syms = sparam_syms + meth.slot_syms = slot_syms meth.ambig = ambig meth.nargs = nargs meth.isva = isva diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index aab4cd701cf12..d73c925e8659f 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -1384,7 +1384,7 @@ let linfo = get_linfo(Base.convert, Tuple{Type{Int64}, Int32}), opt = Core.Compiler.OptimizationState(linfo, Core.Compiler.Params(world)) # make sure the state of the properties look reasonable @test opt.src !== linfo.def.source - @test length(opt.src.slotflags) == length(opt.src.slotnames) + @test length(opt.src.slotflags) == linfo.def.nargs <= length(opt.src.slotnames) @test opt.src.ssavaluetypes isa Vector{Any} @test !opt.src.inferred @test opt.mod === Base diff --git a/test/compiler/validation.jl b/test/compiler/validation.jl index 94731d376ee58..1ce85b3259328 100644 --- a/test/compiler/validation.jl +++ b/test/compiler/validation.jl @@ -83,7 +83,7 @@ end @testset "SLOTFLAGS_MISMATCH" begin c = copy(c0) - push!(c.slotnames, :dummy) + push!(c.slotflags, 0x00) errors = Core.Compiler.validate_code(c) @test length(errors) == 1 @test errors[1].kind === Core.Compiler.SLOTFLAGS_MISMATCH