Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix compile=all, move code related to static compilation to precompile.c #20820

Merged
merged 2 commits into from
Apr 6, 2017

Conversation

JeffBezanson
Copy link
Member

@JeffBezanson JeffBezanson commented Feb 27, 2017

More moving stuff around. I think it will be useful to have a dedicated file for static-compilation-related stuff.

fix #21141

Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

compileout doesn't seem like the best name choice

src/compileout.c Outdated
return jl_options.outputo || jl_options.outputbc || jl_options.outputji;
}

void jl_precompile(int all);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be in a header file

src/compileout.c Outdated
JL_GC_POP();
}

int jl_is_rettype_inferred(jl_method_instance_t *li);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be in a header also

src/compileout.c Outdated
return 1;
}

#if 0 // TODO restore this for jb/subtype
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably should be restored, in order to make sure this code movement isn't breaking anything here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll do that as part of this PR.

@JeffBezanson
Copy link
Member Author

Suggest a name?

@vtjnash
Copy link
Member

vtjnash commented Feb 27, 2017

This seems pretty tightly coupled to the rest of gf.c to me. I'm not sure this code movement is worthwhile.

@JeffBezanson
Copy link
Member Author

This code does something pretty specific: traversing modules to find everything that needs to be compiled for compile=all. In theory, if you were never going to use compile=all you could exclude this code from the build. Sure it uses Method and MethodInstance a fair amount, but so do several other files. gf.c is also coupled to typemap.c, but they can quite sensibly be separate files since typemap.c implements a data structure and gf.c mostly implements caching algorithms on top of it.

@vtjnash
Copy link
Member

vtjnash commented Feb 27, 2017

TypeMap is a fairly general concept though, and can get reused elsewhere. The compile-all code is pretty tightly coupled with the precompile and caching logic. Sure, doesn't mean this can't move, it just means I don't have a clear idea of what categorization this should have. Maybe precompile.c would be a better name?

@JeffBezanson
Copy link
Member Author

precompile.c is fine with me. It would be nice if we could move some of the module precompile code there eventually, to make a single integrated binary-artifact-generator, but that code really is quite coupled with dump.c.

I would say this code is anti-reusable: it's not used by anything else in the system, and is actually an application of various reusable mechanisms that exist elsewhere, such as looking up specializations and traversing typemaps. I'm looking toward the idea of a juliac program separable from the julia runtime, where we want the runtime to consist of the minimal stuff needed to run any julia code.

@JeffBezanson JeffBezanson changed the title reorg: move code related to static compilation to compileout.c reorg: move code related to static compilation to compileout.c, fix compile=all Feb 28, 2017
@JeffBezanson
Copy link
Member Author

Ok, I think I have compile=all working.

@tkelman
Copy link
Contributor

tkelman commented Feb 28, 2017

CI will be broken until the S3 outage is resolved.

src/jltypes.c Outdated
return jl_count_union_components(u->a) + jl_count_union_components(u->b);
}

static jl_value_t *nth_union_component(jl_value_t *v, int *pi)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs comments

src/precompile.c Outdated
m->unspecialized = linfo;
jl_gc_wb(m, linfo);
if (linfo->jlcall_api == 2)
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't uncomment this - this is completely invalid right now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that?

Should I set src = m->source instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the unspecialized field is not world-aware, so it can't store world-specialized data. Yes, use src = m->source.

src/precompile.c Outdated
// keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the template function)
// this is necessary because many intrinsics try to call static_eval and thus are not compilable unspecialized
int complete = _compile_all_union((jl_value_t*)ml->sig);
if (complete) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can delete this branch test now (the comment about intrinsics calling static_eval is incorrect)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you're right about static_eval, but isn't it still true that we don't need to compile an unspecialized method if the signature is a leaf type or union of leaf types?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's going to depend on how we want to define the behavior of the compile=all output. Branching on isleaftype is also valid. I guess the main point is just that this is now just an optimization (while before it was a crutch that was needed for handling intrinsics).

src/precompile.c Outdated
else {
jl_compile_linfo(&linfo, src, jl_world_counter, &jl_default_cgparams);
assert(linfo->functionObjectsDecls.functionObject != NULL);
m->unspecialized = linfo;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this'll corrupt the system. don't store an inferred object here.

src/precompile.c Outdated
jl_printf(JL_STDERR, "\n");
}

static void foreach_def_in_module(jl_module_t *m, int (*visit)(jl_typemap_entry_t *, void*), jl_array_t *out)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

visit should be a jl_typemap_visitor_fptr type

@JeffBezanson
Copy link
Member Author

Comments addressed. However, this doesn't seem to quite do what we want. If I try building a system image with this, I still get lots of code missing warnings with compile=no. What am I doing wrong?

@JeffBezanson JeffBezanson changed the title reorg: move code related to static compilation to compileout.c, fix compile=all fix compile=all, move code related to static compilation to precompile.c Mar 6, 2017
@vtjnash vtjnash mentioned this pull request Mar 7, 2017
53 tasks
@JeffBezanson JeffBezanson added this to the 0.6.0 milestone Mar 17, 2017
@JeffBezanson
Copy link
Member Author

Adding to milestone since we need to fix compile=all for the release.

@vtjnash
Copy link
Member

vtjnash commented Mar 23, 2017

this gets it much closer for me:

diff --cc src/gf.c
index 5651e279d1,e07378ca58..0000000000
--- a/src/gf.c
+++ b/src/gf.c
diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl
index 1d569265a3..12663bb923 100644
--- a/base/interactiveutil.jl
+++ b/base/interactiveutil.jl
@@ -61,9 +61,10 @@ function edit(path::AbstractString, line::Integer=0)
     end
 
     if is_windows() && name == "open"
-        systemerror(:edit, ccall((:ShellExecuteW,"shell32"), stdcall, Int,
-                                 (Ptr{Void}, Cwstring, Cwstring, Ptr{Void}, Ptr{Void}, Cint),
-                                 C_NULL, "open", path, C_NULL, C_NULL, 10) ≤ 32)
+        @static is_windows() && # don't emit this ccall on other platforms
+            systemerror(:edit, ccall((:ShellExecuteW, "shell32"), stdcall, Int,
+                                     (Ptr{Void}, Cwstring, Cwstring, Ptr{Void}, Ptr{Void}, Cint),
+                                     C_NULL, "open", path, C_NULL, C_NULL, 10) ≤ 32)
     elseif background
         spawn(pipeline(cmd, stderr=STDERR))
     else
diff --git a/src/dump.c b/src/dump.c
index dc9a97ed79..5d6bc80aa3 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -422,7 +422,15 @@ static void jl_update_all_fptrs(void)
 {
     //jl_printf(JL_STDOUT, "delayed_fptrs_n: %d\n", delayed_fptrs_n);
     void **fvars = sysimg_fvars;
-    if (fvars == 0) return;
+    if (fvars == NULL) {
+        size_t i;
+        for (i = 0; i < delayed_fptrs_n; i++) {
+            jl_method_instance_t *li = delayed_fptrs[i].li;
+            assert(li->jlcall_api && li->jlcall_api != 2);
+            li->jlcall_api = 0;
+        }
+        return;
+    }
     // jl_fptr_to_llvm needs to decompress some ASTs, therefore this needs to be NULL
     // to skip trying to restore GlobalVariable pointers in jl_deserialize_gv
     sysimg_gvars = NULL;
@@ -431,7 +439,7 @@ static void jl_update_all_fptrs(void)
     jl_method_instance_t **linfos = (jl_method_instance_t**)malloc(sizeof(jl_method_instance_t*) * sysimg_fvars_max);
     for (i = 0; i < delayed_fptrs_n; i++) {
         jl_method_instance_t *li = delayed_fptrs[i].li;
-        assert(li->def);
+        assert(li->def && li->jlcall_api && li->jlcall_api != 2);
         int32_t cfunc = delayed_fptrs[i].cfunc - 1;
         if (cfunc >= 0) {
             jl_fptr_to_llvm((jl_fptr_t)fvars[cfunc], li, 1);
diff --git a/src/precompile.c b/src/precompile.c
index 909e180b5d..e34ff9a81b 100644
--- a/src/precompile.c
+++ b/src/precompile.c
@@ -266,14 +266,14 @@ static void _compile_all_deq(jl_array_t *found)
         int complete = _compile_all_union((jl_value_t*)ml->sig);
         // if _compile_all_union returns 1, all possible signatures have been covered, so we don't
         // need to compile an unspecialized version.
-        if (complete) {
+        if (0) {
             if (linfo->fptr == NULL && linfo->functionObjectsDecls.functionObject == NULL)
                 // indicate that this method doesn't need to be compiled, because it was fully covered above
                 // TODO: do this some other way
                 linfo->fptr = (jl_fptr_t)(uintptr_t)-1;
         }
         else {
-            jl_compile_linfo(&linfo, src, jl_world_counter, &jl_default_cgparams);
+            jl_compile_linfo(&linfo, src, linfo->min_world, &jl_default_cgparams);
             assert(linfo->functionObjectsDecls.functionObject != NULL);
         }
     }

@vtjnash
Copy link
Member

vtjnash commented Apr 4, 2017

Should be entirely fixed now.

src/precompile.c Outdated
// continue;

_compile_all_union((jl_value_t*)ml->sig);
// if _compile_all_union returns 1, all possible signatures have been covered, so we don't
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this comment not true any more?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, no. The main culprit is inference, which runs in its own world. But it was also only ever intended as a work-around hack for the duct tape, so it's simpler to just remove this now that intrinsics no longer require this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite get it. I thought the idea of the return value of _compile_all_union was that we didn't need to infer or compile an unspecialized version, since the signature is equivalent to a set of concrete signatures.

jl_typemap_visitor(mt->defs, compile_all_enq__, env);
}

void jl_foreach_mtable_in_module(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this defined?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gf.c

@vtjnash vtjnash merged commit 5cacdd6 into master Apr 6, 2017
@vtjnash vtjnash deleted the jb/reorg3 branch April 6, 2017 15:37
@timholy
Copy link
Member

timholy commented Apr 6, 2017

Thanks folks! (Ref #21141)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

World age failure when running GtkReactive demo
4 participants