Merge: compiler: improve `poset_from_mtypes` used for type coloring.
authorJean Privat <jean@pryen.org>
Sat, 21 Mar 2015 06:13:27 +0000 (13:13 +0700)
committerJean Privat <jean@pryen.org>
Sat, 21 Mar 2015 06:13:27 +0000 (13:13 +0700)
Instead of doing the full matrix mtypes X cast_types, a grouping is done by the base classes of the types so that we compare only types whose base classes are in inheritance.

For nitc/nitc/nitc the result is not that bad:

before:
0m6.584s
17.605 GIr
time passed in poset_from_mtypes: 26.01% (4.579 GIr)

now:
0m5.880s (-10%)
15.088 GIr (-14%)
time passed in poset_from_mtypes: 11.72% (1.768 GIr)

In the best condition, I can now expect to compile in less than 6s.

Note that coloring is still a MAJOR issue in term of compile time since 1/4 of the Ir are used to compute coloration.

 * type_coloring: 17.23%
 * property_coloring: 9.35%

Pull-Request: #1212
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Romain Chanoir <chanoir.romain@courrier.uqam.ca>

contrib/header_keeper/Makefile [new file with mode: 0644]
contrib/header_keeper/src/header_keeper.nit [new file with mode: 0644]
lib/standard/exec_nit.c
lib/standard/exec_nit.h
src/compiler/abstract_compiler.nit
src/compiler/global_compiler.nit
src/compiler/separate_compiler.nit
src/compiler/separate_erasure_compiler.nit

diff --git a/contrib/header_keeper/Makefile b/contrib/header_keeper/Makefile
new file mode 100644 (file)
index 0000000..76d36c6
--- /dev/null
@@ -0,0 +1,7 @@
+bin/header_keeper:
+       mkdir -p bin
+       ../../bin/nitc --dir bin src/header_keeper.nit
+
+tests: bin/header_keeper
+       gcc -E /usr/include/SDL/SDL_image.h | bin/header_keeper SDL_image.h
+       gcc -E /usr/include/GLES2/gl2.h | bin/header_keeper gl2.h
diff --git a/contrib/header_keeper/src/header_keeper.nit b/contrib/header_keeper/src/header_keeper.nit
new file mode 100644 (file)
index 0000000..adf6b77
--- /dev/null
@@ -0,0 +1,57 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Filters preprocessed C-like header files to remove included files
+#
+# This tool is used in the process of parsing header files to extract
+# information on the declared services (the functions and structures).
+# This information is then used to generate bindings for Nit code
+# to access these services.
+#
+# The C preprocessor extends macros, inline files marked with `#include`,
+# and more. This tool acts after the C preprocessor, in a way to keep
+# everything but the included files. It searches for line pragmas
+# to identify the source of each line. The result is printed to stdout.
+#
+# Typical usage on the output of `gcc -E` (it would be the same with `clang`):
+#
+# ~~~sh
+# gcc -E /usr/include/SDL/SDL_image.h | header_keeper SDL_image.h > preprocessed_header.h
+# ~~~
+#
+# This module can also be used as a library.
+# The main service is the method `header_keeper`.
+module header_keeper
+
+# Filters the preprocessed `input` to keep only files from `target` and write to the `output`
+fun header_keeper(input: Reader, output: Writer, target: String)
+do
+       var in_target = false
+       while not input.eof do
+               var line = input.read_line
+               if not line.is_empty and line[0] == '#' then
+                       in_target = line.has(target)
+                       continue
+               end
+
+               if in_target then output.write line + "\n"
+       end
+end
+
+if args.length != 1 then
+       print "Usage: header_keeper header_name.h"
+       exit 1
+end
+
+header_keeper(sys.stdin, sys.stdout, args.first)
index 317e909..5b5ffbb 100644 (file)
@@ -142,3 +142,11 @@ void exec_NativeProcess_NativeProcess_wait_0(void*d) {
                data->running = 0;
        }
 }
+
+int string_NativeString_NativeString_system_0(const char *cmd) {
+       int status = system(cmd);
+       if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) {
+               // cmd exited on SIGINT: in my opinion the user wants the main to be discontinued
+               kill(getpid(), SIGINT);
+       }
+}
index c6a59d4..fbd040a 100644 (file)
@@ -31,7 +31,7 @@ struct se_exec_data {
 
 se_exec_data_t* exec_Process_Process_basic_exec_execute_4(void *, char *, char *, int, int);
 
-#define string_NativeString_NativeString_system_0(self) (system(self))
+int string_NativeString_NativeString_system_0(const char*);
 
 #define exec_NativeProcess_NativeProcess_id_0(self) (((se_exec_data_t*)self)->id)
 #define exec_NativeProcess_NativeProcess_status_0(self) (((se_exec_data_t*)self)->status)
index aa57850..1ec7761 100644 (file)
@@ -603,9 +603,9 @@ abstract class AbstractCompiler
                var gccd_disable = modelbuilder.toolcontext.opt_no_gcc_directive.value
                if gccd_disable.has("noreturn") or gccd_disable.has("all") then
                        # Signal handler function prototype
-                       self.header.add_decl("void show_backtrace(int);")
+                       self.header.add_decl("void fatal_exit(int);")
                else
-                       self.header.add_decl("void show_backtrace(int) __attribute__ ((noreturn));")
+                       self.header.add_decl("void fatal_exit(int) __attribute__ ((noreturn));")
                end
 
                if gccd_disable.has("likely") or gccd_disable.has("all") then
@@ -741,12 +741,7 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                        v.compiler.header.add_decl("extern long count_isset_checks;")
                end
 
-               v.add_decl("void sig_handler(int signo)\{")
-               v.add_decl("PRINT_ERROR(\"Caught signal : %s\\n\", strsignal(signo));")
-               v.add_decl("show_backtrace(signo);")
-               v.add_decl("\}")
-
-               v.add_decl("void show_backtrace (int signo) \{")
+               v.add_decl("static void show_backtrace(void) \{")
                if ost == "nitstack" or ost == "libunwind" then
                        v.add_decl("char* opt = getenv(\"NIT_NO_STACK\");")
                        v.add_decl("unw_cursor_t cursor;")
@@ -776,7 +771,19 @@ extern void nitni_global_ref_decr( struct nitni_ref *ref );
                        v.add_decl("free(procname);")
                        v.add_decl("\}")
                end
-               v.add_decl("exit(signo);")
+               v.add_decl("\}")
+
+               v.add_decl("void sig_handler(int signo)\{")
+               v.add_decl("PRINT_ERROR(\"Caught signal : %s\\n\", strsignal(signo));")
+               v.add_decl("show_backtrace();")
+               # rethrows
+               v.add_decl("signal(signo, SIG_DFL);")
+               v.add_decl("kill(getpid(), signo);")
+               v.add_decl("\}")
+
+               v.add_decl("void fatal_exit(int status) \{")
+               v.add_decl("show_backtrace();")
+               v.add_decl("exit(status);")
                v.add_decl("\}")
 
                if no_main then
@@ -1557,7 +1564,7 @@ abstract class AbstractCompilerVisitor
                else
                        self.add("PRINT_ERROR(\"\\n\");")
                end
-               self.add("show_backtrace(1);")
+               self.add("fatal_exit(1);")
        end
 
        # Add a dynamic cast
index 7a0f162..a01e362 100644 (file)
@@ -312,7 +312,7 @@ class GlobalCompilerVisitor
                        var res = self.new_var(mtype)
                        if not compiler.runtime_type_analysis.live_types.has(valtype) then
                                self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                                return res
                        end
                        self.add("{res} = BOX_{valtype.c_name}({value}); /* autobox from {value.mtype} to {mtype} */")
@@ -323,7 +323,7 @@ class GlobalCompilerVisitor
                        # Bad things will appen!
                        var res = self.new_var(mtype)
                        self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
-                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); fatal_exit(1);")
                        return res
                end
        end
@@ -349,7 +349,7 @@ class GlobalCompilerVisitor
                var res = self.new_var(mtype)
                if not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
                        self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
-                       self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                        return res
                end
                self.add("{res} = BOX_{valtype.c_name}({value}); /* boxing {value.mtype} */")
@@ -630,7 +630,7 @@ class GlobalCompilerVisitor
        do
                if recv.mtype.ctype != "val*" then return
                self.add("PRINT_ERROR(\"BTD BUG: Dynamic type is %s, static type is %s\\n\", class_names[{recv}->classid], \"{recv.mcasttype}\");")
-               self.add("show_backtrace(1);")
+               self.add("fatal_exit(1);")
        end
 
        redef fun isset_attribute(a, recv)
index af132f2..99a18d6 100644 (file)
@@ -1187,7 +1187,7 @@ class SeparateCompilerVisitor
                        var res = self.new_var(mtype)
                        if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(valtype) then
                                self.add("/*no autobox from {value.mtype} to {mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                                return res
                        end
                        self.require_declaration("BOX_{valtype.c_name}")
@@ -1201,7 +1201,7 @@ class SeparateCompilerVisitor
                        # Bad things will appen!
                        var res = self.new_var(mtype)
                        self.add("/* {res} left unintialized (cannot convert {value.mtype} to {mtype}) */")
-                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"Cast error: Cannot cast %s to %s.\\n\", \"{value.mtype}\", \"{mtype}\"); fatal_exit(1);")
                        return res
                end
        end
@@ -1227,7 +1227,7 @@ class SeparateCompilerVisitor
                        var res = self.new_var(mtype)
                        if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
                                self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                                return res
                        end
                        self.require_declaration("BOX_{valtype.c_name}")
@@ -1787,7 +1787,7 @@ class SeparateCompilerVisitor
                                self.add("count_type_test_resolved_{tag}++;")
                        end
                else
-                       self.add("PRINT_ERROR(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); show_backtrace(1);")
+                       self.add("PRINT_ERROR(\"NOT YET IMPLEMENTED: type_test(%s, {mtype}).\\n\", \"{value.inspect}\"); fatal_exit(1);")
                end
 
                # check color is in table
index 6e0d2b6..f4b9824 100644 (file)
@@ -615,7 +615,7 @@ class SeparateErasureCompilerVisitor
                        var res = self.new_var(mtype)
                        if compiler.runtime_type_analysis != null and not compiler.runtime_type_analysis.live_types.has(value.mtype.as(MClassType)) then
                                self.add("/*no boxing of {value.mtype}: {value.mtype} is not live! */")
-                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); show_backtrace(1);")
+                               self.add("PRINT_ERROR(\"Dead code executed!\\n\"); fatal_exit(1);")
                                return res
                        end
                        self.require_declaration("BOX_{valtype.c_name}")