From: Jean Privat Date: Sat, 21 Mar 2015 06:13:27 +0000 (+0700) Subject: Merge: compiler: improve `poset_from_mtypes` used for type coloring. X-Git-Tag: v0.7.3~16 X-Git-Url: http://nitlanguage.org?hp=e19268a8c2bd866cd07d31a75f2ca6fe63883a93 Merge: compiler: improve `poset_from_mtypes` used for type coloring. 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 Reviewed-by: Lucas Bajolet Reviewed-by: Romain Chanoir --- diff --git a/contrib/header_keeper/Makefile b/contrib/header_keeper/Makefile new file mode 100644 index 0000000..76d36c6 --- /dev/null +++ b/contrib/header_keeper/Makefile @@ -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 index 0000000..adf6b77 --- /dev/null +++ b/contrib/header_keeper/src/header_keeper.nit @@ -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) diff --git a/lib/standard/exec_nit.c b/lib/standard/exec_nit.c index 317e909..5b5ffbb 100644 --- a/lib/standard/exec_nit.c +++ b/lib/standard/exec_nit.c @@ -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); + } +} diff --git a/lib/standard/exec_nit.h b/lib/standard/exec_nit.h index c6a59d4..fbd040a 100644 --- a/lib/standard/exec_nit.h +++ b/lib/standard/exec_nit.h @@ -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) diff --git a/src/compiler/abstract_compiler.nit b/src/compiler/abstract_compiler.nit index aa57850..1ec7761 100644 --- a/src/compiler/abstract_compiler.nit +++ b/src/compiler/abstract_compiler.nit @@ -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 diff --git a/src/compiler/global_compiler.nit b/src/compiler/global_compiler.nit index 7a0f162..a01e362 100644 --- a/src/compiler/global_compiler.nit +++ b/src/compiler/global_compiler.nit @@ -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) diff --git a/src/compiler/separate_compiler.nit b/src/compiler/separate_compiler.nit index af132f2..99a18d6 100644 --- a/src/compiler/separate_compiler.nit +++ b/src/compiler/separate_compiler.nit @@ -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 diff --git a/src/compiler/separate_erasure_compiler.nit b/src/compiler/separate_erasure_compiler.nit index 6e0d2b6..f4b9824 100644 --- a/src/compiler/separate_erasure_compiler.nit +++ b/src/compiler/separate_erasure_compiler.nit @@ -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}")