From 671c5a22c9c97ccb339c31c25cb25fd15b95469d Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Sun, 4 Sep 2016 04:32:34 -0400 Subject: [PATCH] Track the module during inlining Compute per-statement `in_user_code` to support user code only logging mode with inlining on. --- base/inference.jl | 14 +++++++++++-- src/codegen.cpp | 50 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index c4e6f475efa9f..e5fe298014b15 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -2741,8 +2741,18 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference else linfo.def.line end - unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, - linfo.def.name, line)) + # Check if we are switching module, which is necessary to catch user + # code inlined into `Base` with `--code-coverage=user`. + # Assume we are inlining directly into `enclosing` instead of another + # function inlined in it + mod = linfo.def.module + if mod === sv.mod + unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, + linfo.def.name, line)) + else + unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, + linfo.def.name, line, mod)) + end push!(stmts, Expr(:meta, :pop_loc)) elseif !isempty(stmts) if all(inlining_ignore, stmts) diff --git a/src/codegen.cpp b/src/codegen.cpp index 671dbd0a17346..84eba2c16ab76 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -4038,12 +4038,8 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func ctx.f = f; // step 5. set up debug info context and create first basic block - bool in_user_code = !jl_is_submodule(ctx.module, jl_base_module) && - !jl_is_submodule(ctx.module, jl_core_module); - bool do_coverage = jl_options.code_coverage == JL_LOG_ALL || - (jl_options.code_coverage == JL_LOG_USER && in_user_code); - bool do_malloc_log = jl_options.malloc_log == JL_LOG_ALL || - (jl_options.malloc_log == JL_LOG_USER && in_user_code); + int coverage_mode = jl_options.code_coverage; + int malloc_log_mode = jl_options.malloc_log; StringRef filename = ""; StringRef dbgFuncName = ctx.name; int toplineno = -1; @@ -4073,8 +4069,8 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func ctx.debug_enabled = true; if (dbgFuncName.empty()) { // special value: if function name is empty, disable debug info - do_coverage = false; - do_malloc_log = false; + coverage_mode = JL_LOG_NONE; + malloc_log_mode = JL_LOG_NONE; //dbgFuncName = filename; // for testing, uncomment this line ctx.debug_enabled = !dbgFuncName.empty(); } @@ -4483,6 +4479,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func DISubprogram *sp; StringRef file; ssize_t line; + bool in_user_code; }; #else struct DbgState { @@ -4499,6 +4496,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func bool is_inbounds; bool loc_changed; bool is_poploc; + bool in_user_code; }; std::vector stmtprops(stmtslen); std::vector DI_stack; @@ -4511,7 +4509,12 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func inbounds |= inbounds_stack[sz - 2]; return inbounds; }; - StmtProp cur_prop{topdebugloc, filename, toplineno, false, true, false}; + StmtProp cur_prop{topdebugloc, filename, toplineno, + false, true, false, false}; + if (coverage_mode != JL_LOG_NONE || malloc_log_mode) { + cur_prop.in_user_code = (!jl_is_submodule(ctx.module, jl_base_module) && + !jl_is_submodule(ctx.module, jl_core_module)); + } for (i = 0; i < stmtslen; i++) { cur_prop.loc_changed = false; cur_prop.is_poploc = false; @@ -4565,7 +4568,8 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func if (ctx.debug_enabled) new_file = dbuilder.createFile(new_filename, "."); DI_stack.push_back({cur_prop.loc, SP, - cur_prop.file, cur_prop.line}); + cur_prop.file, cur_prop.line, + cur_prop.in_user_code}); const char *inl_name = ""; int inlined_func_lineno = 0; if (jl_array_len(expr->args) > 2) { @@ -4577,6 +4581,12 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func inlined_func_lineno = jl_unbox_int32(arg); else if (jl_is_int64(arg)) inlined_func_lineno = jl_unbox_int64(arg); + else if (jl_is_module(arg)) { + jl_module_t *mod = (jl_module_t*)arg; + cur_prop.in_user_code = + (!jl_is_submodule(mod, jl_base_module) && + !jl_is_submodule(mod, jl_core_module)); + } } } else { @@ -4615,6 +4625,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func cur_prop.loc = DI.loc; cur_prop.file = DI.file; cur_prop.line = DI.line; + cur_prop.in_user_code = DI.in_user_code; DI_stack.pop_back(); cur_prop.loc_changed = true; } @@ -4712,10 +4723,19 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func return bb; }; + auto do_coverage = [&] (bool in_user_code) { + return (coverage_mode == JL_LOG_ALL || + (coverage_mode == JL_LOG_USER && in_user_code)); + }; + auto do_malloc_log = [&] (bool in_user_code) { + return (malloc_log_mode == JL_LOG_ALL || + (malloc_log_mode == JL_LOG_USER && in_user_code)); + }; + // If the first expresion changes the line number, we need to visit // the start of the function. This can happen when the first line is // a inlined function call. - if (stmtprops[0].loc_changed && do_coverage) { + if (stmtprops[0].loc_changed && do_coverage(stmtprops[0].in_user_code)) { if (ctx.debug_enabled) builder.SetCurrentDebugLocation(topdebugloc); coverageVisitLine(filename, toplineno); @@ -4727,7 +4747,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func if (ctx.debug_enabled) builder.SetCurrentDebugLocation(props.loc); // Disable coverage for pop_loc, it doesn't start a new expression - if (do_coverage && !props.is_poploc) { + if (do_coverage(props.in_user_code) && !props.is_poploc) { coverageVisitLine(props.file, props.line); } } @@ -4763,7 +4783,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func else { // undef return type retval = NULL; } - if (do_malloc_log && props.line != -1) + if (do_malloc_log(props.in_user_code) && props.line != -1) mallocVisitLine(props.file, props.line); if (type_is_ghost(retty) || ctx.sret) builder.CreateRetVoid(); @@ -4782,7 +4802,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func jl_value_t *cond = args[0]; int lname = jl_unbox_long(args[1]); Value *isfalse = emit_condition(cond, "if", &ctx); - if (do_malloc_log && props.line != -1) + if (do_malloc_log(props.in_user_code) && props.line != -1) mallocVisitLine(props.file, props.line); BasicBlock *ifso = BasicBlock::Create(jl_LLVMContext, "if", f); BasicBlock *ifnot = handle_label(lname, false); @@ -4824,7 +4844,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func } else { emit_stmtpos(stmt, &ctx); - if (do_malloc_log && props.line != -1) { + if (do_malloc_log(props.in_user_code) && props.line != -1) { mallocVisitLine(props.file, props.line); } }