Пример #1
0
void stack_trace (MonoMethod *method, void *args[], ArmRegs *regs) {
    LOGD ("stack_trace be call!");
    MonoContext ctx;
    ctx.eip = regs->pc;
    ctx.esp = regs->sp;
    ctx.ebp = regs->r11;
    memcpy (ctx.regs, regs, 4 * 16);
    MemWriter writer;
    /*因为当前被跟踪的函数还没被调用(当前在specific_trampo中), 所以这里手动写入当前函数的跟踪结构*/
    char const *m = get_method_image_name (method);
    m = m ? m : "NO_IMAGE_NAME";
    char const *n = mono_method_full_name (method, 1);
    if (n) {
        writer.sprintf ("[%s]%s[%08X]\n", m, n, mono_method_get_token (method));
        g_free (n);
    } else {
        writer.sprintf ("[%s]%s[%08X]\n", m, "NO_METHOD_NAME", mono_method_get_token (method));
    }
    mono_walk_stack (mono_domain_get (), 0, &ctx, walk_stack, &writer);

    xmono::StackTraceRsp rsp;
    rsp.set_err (true);
    rsp.set_stack (std::string ((char*)writer.getBuffPtr (), writer.getBuffSize ()));
    std::string out;
    rsp.SerializeToString (&out);
    ecmd_send (XMONO_ID_STACK_TRACE_RSP, (uint8_t const*)out.c_str (), out.size ());
}
Пример #2
0
static void
mop_jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
{
	static int n = 0;
	char* name = mono_method_full_name (method, TRUE);

	char* start = mono_jit_info_get_code_start (jinfo);
	int len = mono_jit_info_get_code_size (jinfo);
	int i;
	
	JitRange * jr;
	jr = mop_get_jit_range (start);
	
	for (i = 0; name [i]; ++i) {
		if (!isalnum (name [i]))
			name [i] = '_';
	}
	
	fprintf (assm, ".section vm%d\n", jr->rangenum);
	fprintf (assm, ".org %p\n", (char*)start - (char*)jr->start);
	fprintf (assm, "%s%d:\n", name, ++n);

	for (i = 0; i < len; i ++) {
		fprintf (assm, ".byte %d; ", start [i]);
	}
	fprintf (assm, "\n\n\n");

	g_free (name);
}
Пример #3
0
static void
mono_draw_code_cfg (MonoCompile *cfg, FILE *fp)
{
	MonoBasicBlock *bb;
		
	fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
	fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
	fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));

	fprintf (fp, "BB0 [shape=doublecircle];\n");
	fprintf (fp, "BB1 [color=red];\n");

	for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
		MonoInst *inst;
		const char *color;

		if (bb == cfg->bb_exit)
			continue;

		if ((cfg->comp_done & MONO_COMP_REACHABILITY) && (bb->flags & BB_REACHABLE))
			color = "color=red,";
		else
			color = "";

		fprintf (fp, "BB%d [%sshape=record,labeljust=l,label=\"{BB%d|", bb->block_num, color, bb->block_num);
			
		MONO_BB_FOR_EACH_INS (bb, inst) {
			//mono_print_label (fp, inst);
			fprintf (fp, "\\n");			
		}

		fprintf (fp, "}\"];\n");			
	}
Пример #4
0
void
mono_trace_enter_method (MonoMethod *method, char *ebp)
{
	int i, j;
	MonoClass *klass;
	MonoObject *o;
	MonoJitArgumentInfo *arg_info;
	MonoMethodSignature *sig;
	char *fname;
	MonoGenericSharingContext *gsctx = NULL;

	if (!trace_spec.enabled)
		return;

	while (output_lock != 0 || InterlockedCompareExchange (&output_lock, 1, 0) != 0)
		mono_thread_info_yield ();

	fname = mono_method_full_name (method, TRUE);
	indent (1);
	printf ("ENTER: %s(", fname);
	g_free (fname);

	if (!ebp) {
		printf (") ip: %p\n", RETURN_ADDRESS_N (1));
		goto unlock;
	}

	sig = mono_method_signature (method);

	arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));

	if (method->is_inflated) {
		/* FIXME: Might be better to pass the ji itself */
		MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), RETURN_ADDRESS (), NULL);
		if (ji) {
			gsctx = mono_jit_info_get_generic_sharing_context (ji);
			if (gsctx && gsctx->is_gsharedvt) {
				/* Needs a ctx to get precise method */
				printf (") <gsharedvt>\n");
				goto unlock;
			}
		}
	}

	mono_arch_get_argument_info (sig, sig->param_count, arg_info);

	if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) {
		g_assert (!mono_method_signature (method)->ret->byref);

		printf ("VALUERET:%p, ", *((gpointer *)(ebp + 8)));
	}

	if (mono_method_signature (method)->hasthis) {
		gpointer *this = (gpointer *)(ebp + arg_info [0].offset);
		if (method->klass->valuetype) {
			printf ("value:%p, ", *arg_in_stack_slot(this, gpointer *));
		} else {
Пример #5
0
static gboolean
recompute_aliased_variables (MonoCompile *cfg, int *restored_vars)
{
	int i;
	MonoBasicBlock *bb;
	MonoInst *ins;
	int kills = 0;
	int adds = 0;
	*restored_vars = 0;

	for (i = 0; i < cfg->num_varinfo; i++) {
		MonoInst *var = cfg->varinfo [i];
		if (var->flags & MONO_INST_INDIRECT) {
			if (cfg->verbose_level > 2) {
				printf ("Killing :"); mono_print_ins (var);
			}
			++kills;
		}
		var->flags &= ~MONO_INST_INDIRECT;
	}

	if (!kills)
		return FALSE;

	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
		for (ins = bb->code; ins; ins = ins->next) {
			if (ins->opcode == OP_LDADDR) {
				MonoInst *var;

				if (cfg->verbose_level > 2) { printf ("Found op :"); mono_print_ins (ins); }

				var = (MonoInst*)ins->inst_p0;
				if (!(var->flags & MONO_INST_INDIRECT)) {
					if (cfg->verbose_level > 1) { printf ("Restoring :"); mono_print_ins (var); }
					++adds;
				}
				var->flags |= MONO_INST_INDIRECT;
			}
		}
	}
	*restored_vars = adds;

	mono_jit_stats.alias_found += kills;
	mono_jit_stats.alias_removed += kills - adds;
	if (kills > adds) {
		if (cfg->verbose_level > 2) {
			printf ("Method: %s\n", mono_method_full_name (cfg->method, 1));
			printf ("Kills %d Adds %d\n", kills, adds);
		}
		return TRUE;
	}
	return FALSE;
}
Пример #6
0
void
mono_error_set_not_verifiable (MonoError *oerror, MonoMethod *method, const char *msg_format, ...)
{
	MonoErrorInternal *error = (MonoErrorInternal*)oerror;
	mono_error_prepare (error);

	error->error_code = MONO_ERROR_NOT_VERIFIABLE;
	mono_error_set_class (oerror, method->klass);
	if (method)
		mono_error_set_member_name (oerror, mono_method_full_name (method, 1));

	set_error_message ();
}
Пример #7
0
/**
 * mono_debug_print_stack_frame:
 * \param native_offset Native offset within the \p method's machine code.
 * Conventient wrapper around \c mono_debug_lookup_source_location which can be
 * used if you only want to use the location to print a stack frame.
 */
gchar *
mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
{
	MonoDebugSourceLocation *location;
	gchar *fname, *ptr, *res;
	int offset;

	fname = mono_method_full_name (method, TRUE);
	for (ptr = fname; *ptr; ptr++) {
		if (*ptr == ':') *ptr = '.';
	}

	location = mono_debug_lookup_source_location (method, native_offset, domain);

	if (!location) {
		if (mono_debug_initialized) {
			mono_debugger_lock ();
			offset = il_offset_from_address (method, domain, native_offset);
			mono_debugger_unlock ();
		} else {
			offset = -1;
		}

		if (offset < 0 && get_seq_point)
			offset = get_seq_point (domain, method, native_offset);

		if (offset < 0)
			res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
		else {
			char *mvid = mono_guid_to_string_minimal ((uint8_t*)m_class_get_image (method->klass)->heap_guid.data);
			char *aotid = mono_runtime_get_aotid ();
			if (aotid)
				res = g_strdup_printf ("at %s [0x%05x] in <%s#%s>:0" , fname, offset, mvid, aotid);
			else
				res = g_strdup_printf ("at %s [0x%05x] in <%s>:0" , fname, offset, mvid);

			g_free (aotid);
			g_free (mvid);
		}
		g_free (fname);
		return res;
	}

	res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
			       location->source_file, location->row);

	g_free (fname);
	mono_debug_free_source_location (location);
	return res;
}
Пример #8
0
static void
foreach_method (gpointer data, gpointer user_data)
{
	ForeachData *udata = (ForeachData*)user_data;
	MonoMethod *method = (MonoMethod*)data;
	char *name;

	if (!mono_method_get_token (method) || mono_class_get_image (mono_method_get_class (method)) != udata->image)
		return;

	name = mono_method_full_name (method, TRUE);
	fprintf (udata->outfile, "%s\n", name);
	g_free (name);
}
Пример #9
0
static void
mono_draw_cfg (MonoCompile *cfg, FILE *fp)
{
	fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
	fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
	fprintf (fp, "label=\"CFG for %s\";\n", mono_method_full_name (cfg->method, TRUE));

	fprintf (fp, "BB0 [shape=doublecircle];\n");
	fprintf (fp, "BB1 [color=red];\n");

	cfg_emit_one_loop_level (cfg, fp, NULL);

	fprintf (fp, "}\n");
}
Пример #10
0
static int test_callspec (int test_idx,
			  MonoMethod *method,
			  const char *callspec,
			  gboolean expect_match)
{
	int res = 0;
	gboolean initialized = FALSE;
	gboolean match;
	MonoCallSpec spec = {0};
	char *errstr;
	char *method_name = mono_method_full_name (method, TRUE);
	if (!method_name) {
		printf ("FAILED getting method name in callspec test #%d\n",
			test_idx);
		res = 1;
		goto out;
	}

	if (!mono_callspec_parse (callspec, &spec, &errstr)) {
		printf ("FAILED parsing callspec '%s' - %s\n", callspec,
			errstr);
		g_free (errstr);
		res = 1;
		goto out;
	}
	initialized = TRUE;

	match = mono_callspec_eval (method, &spec);

	if (match && !expect_match) {
		printf ("FAILED unexpected match '%s' against '%s'\n",
			method_name, callspec);
		res = 1;
		goto out;
	}
	if (!match && expect_match) {
		printf ("FAILED unexpected mismatch '%s' against '%s'\n",
			method_name, callspec);
		res = 1;
		goto out;
	}

out:
	if (initialized)
		mono_callspec_cleanup(&spec);
	if (method_name)
		g_free (method_name);
	return res;
}
Пример #11
0
static void
mono_draw_dtree (MonoCompile *cfg, FILE *fp)
{
	g_assert ((cfg->comp_done & MONO_COMP_IDOM));

	fprintf (fp, "digraph %s {\n", convert_name (cfg->method->name));
	fprintf (fp, "node [fontsize=12.0]\nedge [len=1,color=red]\n");
	fprintf (fp, "label=\"Dominator tree for %s\";\n", mono_method_full_name (cfg->method, TRUE));

	fprintf (fp, "BB0 [shape=doublecircle];\n");
	fprintf (fp, "BB1 [color=red];\n");

	dtree_emit_one_loop_level (cfg, fp, NULL);

	fprintf (fp, "}\n");
}
Пример #12
0
/*
 * mono_basic_block_split:
 *
 * Return the list of basic blocks of method. Return NULL on failure and set @error.
*/
MonoSimpleBasicBlock*
mono_basic_block_split (MonoMethod *method, MonoError *error)
{
	MonoSimpleBasicBlock *bb, *root;
	const unsigned char *start, *end;
	MonoMethodHeader *header = mono_method_get_header (method);

	mono_error_init (error);

	if (!header) {
		mono_error_set_not_verifiable (error, method, "Could not decode header");
		return NULL;
	}

	start = header->code;
	end = start + header->code_size;

	bb = g_new0 (MonoSimpleBasicBlock, 1);
	bb->start = 0;
	bb->end = end - start;
	bb->colour = BLACK;
	bb->dead = FALSE;

	root = bb;
	bb_formation_il_pass (start, end, bb, &root, method, error);
	if (!mono_error_ok (error))
		goto fail;
	
	bb_formation_eh_pass (header, bb, &root, method, error);
	if (!mono_error_ok (error))
		goto fail;

	bb_liveness (bb);

#if DEBUG_BB
	dump_bb_list (bb, &root, g_strdup_printf("AFTER LIVENESS %s", mono_method_full_name (method, TRUE)));
#endif

	mono_metadata_free_mh (header);
	return bb;

fail:
	mono_metadata_free_mh (header);
	mono_basic_block_free (bb);
	return NULL;
}
Пример #13
0
static int walk_stack (MonoDomain *domain, MonoContext *ctx, MonoJitInfo *jit_info, void *user_data) {
    MemWriter *writer = (MemWriter*)user_data;
    MonoMethod *method =mono_jit_info_get_method (jit_info);
    if (!method) {
        writer->sprintf("%s", "jit_info no method!");
        return 0;
    }
    char const *m = get_method_image_name (method);
    m = m ? m : "NO_IMAGE_NAME";
    char const *n = mono_method_full_name (method, 1);
    if (n) {
        writer->sprintf ("[%s] %s [%08X]\n", m, n, mono_method_get_token (method));
        g_free (n);
    } else {
        writer->sprintf ("[%s] %s [%08X]\n", m, "NO_METHOD_NAME", mono_method_get_token (method));
    }
    return 0; /*一直walk, 直到栈帧尽头*/
}
Пример #14
0
static void send_trace_log (std::map<MonoMethod*, CallInfo> const &dict) {
    MemWriter sbuf(0x100000);
    MemWriter writer(0x100000);
    std::map<MonoMethod*, CallInfo>::const_iterator p;
    for (p = dict.begin (); p != dict.end (); p++) {
        MonoMethod *method = p->first;
        CallInfo call_info = p->second;
        char const *m = get_method_image_name (method);
        char *n = mono_method_full_name (method, 0);
        char str[256];
        sbuf.sprintf ("[%s] %s [%08X]|%d|%d\n", m, n, mono_method_get_token (method), call_info.times, call_info.order);
        g_free (n);
    }
    if (!compress_data (sbuf.getBuffPtr (), sbuf.getBuffSize (), &writer)) {
        LOGD ("compress_data err!");
        return;
    }
    /*Fixme : 这里写在使用protocolbuf之前, 因此非常不河蟹的出现了不使用pb的封包*/
    ecmd_send (XMONO_ID_TRACE_REPORT, writer.getBuffPtr (), writer.getBuffSize ());
    return;
}
Пример #15
0
static void disasm_method (Package *pkg) {
    xmono::DisasmMethodReq req;
    xmono::DisasmMethodRsp rsp;
    std::string str((char*)pkg->body, pkg->all_len - sizeof (Package)); //Fixme : 修复头部all_len是总长的问题
    if (!req.ParseFromString (str)) {
        LOGD ("xmono::DisasmMethodReq ParseFromString err!");
        return;
    }
    std::string err("");
    MonoMethod *method = get_method_with_token (req.image_name ().c_str (), req.method_token ());
    if (!method) err += helper_last_err ();
    MonoImage *image = mono_image_loaded (req.image_name ().c_str ());
    if (!image) err += "  image : " + req.image_name () + " can not be find!";
    if (image && method) {
        MemWriter writer(4096);
        char const *mname = mono_method_full_name (method, 1);
        if (mname) {
            writer.sprintf ("//[%s]%s[%08X]\n", get_method_image_name (method), mname, mono_method_get_token (method));
            g_free (mname);
        }
        MonoMethodHeader *header = mono_method_get_header (method);
        disassemble_cil (image, header, &writer); /*Fixme : disassemble_cil需要在失败时返回更多信息*/
        rsp.set_err (true);
        LOGD ("writer : %s", writer.getBuffPtr ());
        std::string s((char*)writer.getBuffPtr (), writer.getBuffSize ());
        rsp.set_disasm_code (s);
        //这部分只是测试用的
        uint32_t asm_size = 0;
        uint8_t const *p = mono_method_header_get_code (header, &asm_size, 0);
        std::string asm_code ((char const*)p, asm_size);
        rsp.set_asm_code (asm_code);
    } else {
        rsp.set_err (false);
        rsp.set_err_str (err);
    }
    std::string out;
    rsp.SerializeToString (&out);
    ecmd_send (XMONO_ID_DISASM_METHOD_RSP, (uint8_t const*)out.c_str (), out.size ());
    return;
}
Пример #16
0
void
mono_trace_enter_method (MonoMethod *method, char *ebp)
{
	int i, j;
	MonoClass *class;
	MonoObject *o;
	MonoJitArgumentInfo *arg_info;
	MonoMethodSignature *sig;
	char *fname;

	if (!trace_spec.enabled)
		return;

	fname = mono_method_full_name (method, TRUE);
	indent (1);
	printf ("ENTER: %s(", fname);
	g_free (fname);

	if (!ebp) {
		printf (") ip: %p\n", __builtin_return_address (1));
		return;
	}	

	sig = mono_method_signature (method);

	arg_info = alloca (sizeof (MonoJitArgumentInfo) * (sig->param_count + 1));

	mono_arch_get_argument_info (sig, sig->param_count, arg_info);

	if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) {
		g_assert (!mono_method_signature (method)->ret->byref);

		printf ("VALUERET:%p, ", *((gpointer *)(ebp + 8)));
	}

	if (mono_method_signature (method)->hasthis) {
		gpointer *this = (gpointer *)(ebp + arg_info [0].offset);
		if (method->klass->valuetype) {
			printf ("value:%p, ", *arg_in_stack_slot(this, gpointer *));
		} else {
Пример #17
0
/**
 * mono_debug_print_stack_frame:
 * @native_offset: Native offset within the @method's machine code.
 *
 * Conventient wrapper around mono_debug_lookup_source_location() which can be
 * used if you only want to use the location to print a stack frame.
 */
gchar *
mono_debug_print_stack_frame (MonoMethod *method, guint32 native_offset, MonoDomain *domain)
{
	MonoDebugSourceLocation *location;
	gchar *fname, *ptr, *res;
	int offset;

	fname = mono_method_full_name (method, TRUE);
	for (ptr = fname; *ptr; ptr++) {
		if (*ptr == ':') *ptr = '.';
	}

	location = mono_debug_lookup_source_location (method, native_offset, domain);

	if (!location) {
		if (mono_debug_initialized) {
			mono_debugger_lock ();
			offset = il_offset_from_address (method, domain, native_offset);
			mono_debugger_unlock ();
		} else {
			offset = -1;
		}

		if (offset < 0)
			res = g_strdup_printf ("at %s <0x%05x>", fname, native_offset);
		else
			res = g_strdup_printf ("at %s <IL 0x%05x, 0x%05x>", fname, offset, native_offset);
		g_free (fname);
		return res;
	}

	res = g_strdup_printf ("at %s [0x%05x] in %s:%d", fname, location->il_offset,
			       location->source_file, location->row);

	g_free (fname);
	mono_debug_free_source_location (location);
	return res;
}
Пример #18
0
static void
add_types_from_method (MonoMethod *method) {
	const MonoOpcode *opcode;
	MonoMethodHeader *header;
	const unsigned char *ip, *il_code_end;
	gpointer val = NULL, oldkey = NULL;
	int i, n;
	guint32 token;
	MonoClass *klass;
	MonoClassField *field;
	MonoCustomAttrInfo* cattrs;
	MonoType** locals;
	gpointer exc_iter;
	MonoExceptionClause clause;

	if (g_hash_table_lookup_extended (method_table, method, &oldkey, &val))
		return;
	g_hash_table_insert (method_table, method, NULL);

	g_assert (method->klass);

	if (verbose > 1)
		g_print ("#processing method: %s\n", mono_method_full_name (method, TRUE));
	mono_class_init (method->klass);
	cattrs = mono_custom_attrs_from_method (method);
	handle_cattrs (cattrs);
	add_type (method->klass);
	add_types_from_signature (mono_method_signature (method));
	for (i = 0; i < mono_method_signature (method)->param_count + 1; ++i) {
		cattrs = mono_custom_attrs_from_param (method, i);
		handle_cattrs (cattrs);
	}

	if (method->flags & METHOD_ATTRIBUTE_VIRTUAL)
		virtual_methods = g_list_prepend (virtual_methods, method);

	/* if no IL code to parse, return */
	if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME))
		return;
	if (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT))
		return;

	header = mono_method_get_header (method);

	locals = mono_method_header_get_locals (header, &n, NULL);
	for (i = 0; i < n; ++i) {
		klass = mono_class_from_mono_type (locals [i]);
		add_type (klass);
	}
	for (exc_iter = NULL; mono_method_header_get_clauses (header, method, &exc_iter, &clause);) {
		if (clause.flags == MONO_EXCEPTION_CLAUSE_NONE)
			add_type (clause.data.catch_class);
	}

	ip = mono_method_header_get_code (header, &n, NULL);
	il_code_end = ip + n;

	while (ip < il_code_end) {
		if (verbose > 2)
			g_print ("#%s", mono_disasm_code_one (NULL, method, ip, NULL));
		if (*ip == 0xfe) {
			++ip;
			i = *ip + 256;
		} else {
			i = *ip;
		}

		opcode = &mono_opcodes [i];

		switch (opcode->argument) {
		case MonoInlineNone:
			ip++;
			break;
		case MonoInlineType:
			token = read32 (ip + 1);
			add_type (mono_class_get (method->klass->image, token));
			ip += 5;
			break;
		case MonoInlineField: {
			token = read32 (ip + 1);
			field = mono_field_from_token (method->klass->image, token, &klass, NULL);
			add_field (field);
			add_type (klass);
			ip += 5;
			break;
		}
		case MonoInlineTok:
		case MonoInlineSig:
			/* FIXME */
		case MonoInlineString:
		case MonoShortInlineR:
		case MonoInlineBrTarget:
		case MonoInlineI:
			ip += 5;
			break;
		case MonoInlineVar:
			ip += 3;
			break;
		case MonoShortInlineVar:
		case MonoShortInlineI:
		case MonoShortInlineBrTarget:
			ip += 2;
			break;
		case MonoInlineSwitch:
			++ip;
			n = read32 (ip);
			ip += 4;
			ip += 4 * n;
			break;
		case MonoInlineI8:
		case MonoInlineR:
			ip += 9;
			break;
		case MonoInlineMethod:
			{
				MonoMethod *cm = mono_get_method (method->klass->image, read32 (ip + 1), NULL);
				add_type (cm->klass);
				add_types_from_method (cm);
			}
			ip += 5;
			break;
		default:
			g_assert_not_reached ();
		}
	}
}
Пример #19
0
/**
 * mono_perform_abc_removal:
 * @cfg: Control Flow Graph
 *
 * Performs the ABC removal from a cfg in SSA form.
 * It does the following:
 * - Prepare the evaluation area
 * - Allocate memory for the relation graph in the evaluation area
 *   (of course, only for variable definitions) and summarize there all
 *   variable definitions
 * - Allocate memory for the evaluation contexts in the evaluation area
 * - Recursively process all the BBs in the dominator tree (it is enough
 *   to invoke the processing on the entry BB)
 * 
 * cfg: the method code
 */
void
mono_perform_abc_removal (MonoCompile *cfg)
{
	MonoVariableRelationsEvaluationArea area;
	MonoBasicBlock *bb;
	int i;
	
	verbose_level = cfg->verbose_level;
	
	if (TRACE_ABC_REMOVAL) {
		printf ("\nRemoving array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE));
	}

	area.cfg = cfg;
	area.relations = (MonoSummarizedValueRelation *)
		mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation) * (cfg->next_vreg) * 2);
	area.contexts = (MonoRelationsEvaluationContext *)
		mono_mempool_alloc (cfg->mempool, sizeof (MonoRelationsEvaluationContext) * (cfg->next_vreg));
	area.variable_value_kind = (MonoIntegerValueKind *)
		mono_mempool_alloc (cfg->mempool, sizeof (MonoIntegerValueKind) * (cfg->next_vreg));
	for (i = 0; i < cfg->next_vreg; i++) {
		area.variable_value_kind [i] = MONO_UNKNOWN_INTEGER_VALUE;
		area.relations [i].relation = MONO_EQ_RELATION;
		area.relations [i].relation_is_static_definition = TRUE;
		MAKE_VALUE_ANY (area.relations [i].related_value);
		area.relations [i].next = NULL;
	}

	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
		MonoInst *ins;

		if (TRACE_ABC_REMOVAL)
			printf ("\nABCREM BLOCK %d:\n", bb->block_num);

		for (ins = bb->code; ins; ins = ins->next) {
			const char *spec = INS_INFO (ins->opcode);
			
			if (spec [MONO_INST_DEST] == ' ' || MONO_IS_STORE_MEMBASE (ins))
				continue;

			if (spec [MONO_INST_DEST] == 'i') {
				MonoIntegerValueKind effective_value_kind;
				MonoRelationsEvaluationRange range;
				MonoSummarizedValueRelation *type_relation;
				MonoInst *var;

				if (TRACE_ABC_REMOVAL)
					mono_print_ins (ins);

				var = get_vreg_to_inst (cfg, ins->dreg);
				if (var)
					area.variable_value_kind [ins->dreg] = type_to_value_kind (var->inst_vtype);

				effective_value_kind = get_relation_from_ins (&area, ins, &area.relations [ins->dreg], area.variable_value_kind [ins->dreg]);

				MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range);
				apply_value_kind_to_range (&range, area.variable_value_kind [ins->dreg]);
				apply_value_kind_to_range (&range, effective_value_kind);
					
				if (range.upper < INT_MAX) {
					type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation));
					type_relation->relation = MONO_LE_RELATION;
					type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE;
					type_relation->related_value.value.constant.value = range.upper;
					type_relation->relation_is_static_definition = TRUE;
					type_relation->next = area.relations [ins->dreg].next;
					area.relations [ins->dreg].next = type_relation;
					if (TRACE_ABC_REMOVAL) {
						printf ("[var%d <= %d]", ins->dreg, range.upper);
					}
				}
				if (range.lower > INT_MIN) {
					type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation));
					type_relation->relation = MONO_GE_RELATION;
					type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE;
					type_relation->related_value.value.constant.value = range.lower;
					type_relation->relation_is_static_definition = TRUE;
					type_relation->next = area.relations [ins->dreg].next;
					area.relations [ins->dreg].next = type_relation;
					if (TRACE_ABC_REMOVAL) {
						printf ("[var%d >= %d]", ins->dreg, range.lower);
					}
				}
				if (TRACE_ABC_REMOVAL) {
					printf ("Summarized variable %d: ", ins->dreg);
					print_summarized_value (&(area.relations [ins->dreg].related_value));
					printf ("\n");
				}
			}
		}
	}

	/* Add symmetric relations */
	for (i = 0; i < cfg->next_vreg; i++) {
		if (area.relations [i].related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) {
			int related_index = cfg->next_vreg + i;
			int related_variable = area.relations [i].related_value.value.variable.variable;
			
			area.relations [related_index].relation = MONO_EQ_RELATION;
			area.relations [related_index].relation_is_static_definition = TRUE;
			area.relations [related_index].related_value.type = MONO_VARIABLE_SUMMARIZED_VALUE;
			area.relations [related_index].related_value.value.variable.variable = i;
			area.relations [related_index].related_value.value.variable.delta = - area.relations [i].related_value.value.variable.delta;
			
			area.relations [related_index].next = area.relations [related_variable].next;
			area.relations [related_variable].next = &(area.relations [related_index]);
			
			if (TRACE_ABC_REMOVAL) {
				printf ("Added symmetric summarized value for variable variable %d (to %d): ", i, related_variable);
				print_summarized_value (&(area.relations [related_index].related_value));
				printf ("\n");
			}
		}
	}

	process_block (cfg, cfg->bblocks [0], &area);
}
Пример #20
0
/*
 * 将由lua传入的参数表转化为void *[]参数表
 * L : 含有参数表的lua_State
 * base : 参数表在lua_State中的起始位置(靠近栈底的一边)
 * method : 参数表将要应用到的MonoMethod*
 * 
 * 该调用只针对Static methods, 和 non-Static methods, 不针对generic methods
 */
static void *call_method (lua_State *L, int base, MonoObject *thiz, MonoMethod *method, MonoObject **ex) {
    MonoMethodSignature *sig = mono_method_signature (method);
    if (!sig)
        luaL_error (L, "can not get the method's signature.");
    int n = mono_signature_get_param_count (sig);
    int cur_n = lua_gettop (L) - base + 1;
    if (cur_n != n) {
        /*Fixme : mono_method_full_name 的返回值需要显示 g_free*/
        luaL_error (L, "%s need %d arguments, but get %d.", 
            mono_method_full_name (method, 1), n, cur_n);
    }
    void **args = 0;
    if (n > 0)
        args = new void*[n];
    void *iter = 0;
    MonoType *param_type;
    for (int i = 0; (param_type = mono_signature_get_params (sig, &iter)) != 0; i++) {
        /*reference 类型的参数 无论是否加ref关键字, 都是传递改类型对象指针的指针*/
        if (mono_type_is_reference (param_type) || mono_type_is_byref (param_type)) {
            void *p = lua_touserdata (L, base + i);
            if (!p)
                luaL_error (L, "%s : %d arg need a reference type.", mono_method_full_name (method, 1), i);
            args[i] = p;
            continue;
        }
        /*剩下的都是value类型*/
        switch (mono_type_get_type (param_type)) {
            case MONO_TYPE_BOOLEAN: {
                int b = lua_toboolean (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_boolean_class (), &b);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_CHAR: {
                /*char 用int来表示*/
                int b = luaL_checkint (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_char_class (), &b);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_I1: {
                int b = luaL_checkint (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_sbyte_class (), &b);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_U1: {
                unsigned long l = luaL_checkunsigned (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_byte_class (), &l);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_I2: {
                int b = luaL_checkint (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int16_class (), &b);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_U2: {
                unsigned long l = luaL_checkunsigned (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint16_class (), &l);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_I4: {
                int b = luaL_checkint (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int32_class (), &b);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_VALUETYPE:
            case MONO_TYPE_U4: {
                unsigned long l = luaL_checkunsigned (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint32_class (), &l);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_I8: {
                void *u = lua_touserdata (L, base + i);
                if (!u)
                    luaL_error (L, "%s : %d arg need Int64.", mono_method_full_name (method, 1), i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_int64_class (), u);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_U8: {
                void *u = lua_touserdata (L, base + i);
                if (!u)
                    luaL_error (L, "%s : %d arg need UInt64.", mono_method_full_name (method, 1), i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uint64_class (), u);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_R4: {
                /*这里的精度损失由使用lua的人负责*/
                float f = (float)lua_tonumber (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_single_class (), &f);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_R8: {
                double d = (double)lua_tonumber (L, base + i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_double_class (), &d);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_I: {
                void *u = lua_touserdata (L, base + i);
                if (!u)
                    luaL_error (L, "%s : %d arg need IntPtr.", mono_method_full_name (method, 1), i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_intptr_class (), u);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_U: {
                void *u = lua_touserdata (L, base + i);
                if (!u)
                    luaL_error (L, "%s : %d arg need UIntPtr.", mono_method_full_name (method, 1), i);
                MonoObject *obj = mono_value_box (mono_domain_get (), mono_get_uintptr_class (), u);
                args[i] = mono_object_unbox (obj);
                break;
            }
            case MONO_TYPE_MVAR:
                luaL_error (L, "generic method dont be supported.");
            case MONO_TYPE_PTR:
                luaL_error (L, "dont support the ptr type.");
            default:
                luaL_error (L, "unknow method args type : 0x%02X", mono_type_get_type (param_type));
        }
    }
    MonoObject *ret = mono_runtime_invoke (method, thiz, args, ex);
    //MonoType *ret_type = mono_signature_get_return_type (sig);
    LOGD ("call_method be called!");
    return ret;
}
Пример #21
0
static inline gchar *build_hint_from_stack (MonoDomain *domain, void **stack, gint stack_entries)
{
	gchar *hint;
	MonoMethod *method, *selectedMethod;
	MonoAssembly *assembly;
	MonoImage *image;
	MonoDebugSourceLocation *location;
	MonoStackBacktraceInfo *info;
	gboolean use_full_trace;
	char *methodName;
	gint i, native_offset, firstAvailable;

	selectedMethod = NULL;
	firstAvailable = -1;
	use_full_trace = FALSE;
	native_offset = -1;
	for (i = 0; i < stack_entries; i++) {
		info = (MonoStackBacktraceInfo*) stack [i];
		method = info ? info->method : NULL;

		if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
			continue;

		if (firstAvailable == -1)
			firstAvailable = i;

		image = method->klass->image;
		assembly = image->assembly;

		if ((assembly && assembly->in_gac) || ignore_frame (method))
			continue;
		selectedMethod = method;
		native_offset = info->native_offset;
		break;
	}

	if (!selectedMethod) {
		/* All the frames were from assemblies installed in GAC. Find first frame that is
		 * not in the ignore list */
		for (i = 0; i < stack_entries; i++) {
			info = (MonoStackBacktraceInfo*) stack [i];
			method = info ? info->method : NULL;

			if (!method || ignore_frame (method))
				continue;
			selectedMethod = method;
			native_offset = info->native_offset;
			break;
		}

		if (!selectedMethod)
			use_full_trace = TRUE;
	}

	hint = NULL;
	if (use_full_trace) {
		GString *trace = g_string_new ("Full trace:\n");
		for (i = firstAvailable; i < stack_entries; i++) {
			info = (MonoStackBacktraceInfo*) stack [i];
			method = info ? info->method : NULL;
			if (!method || method->wrapper_type != MONO_WRAPPER_NONE)
				continue;

			location = mono_debug_lookup_source_location (method, info->native_offset, domain);
			methodName = mono_method_full_name (method, TRUE);

			if (location) {
				append_report (&trace, LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
				mono_debug_free_source_location (location);
			} else
				append_report (&trace, LOCATION_INDENT "%s\n", methodName);
			g_free (methodName);
		}

		if (trace) {
			if (trace->len)
				hint = g_string_free (trace, FALSE);
			else
				g_string_free (trace, TRUE);
		}
	} else {
		location = mono_debug_lookup_source_location (selectedMethod, native_offset, domain);
		methodName = mono_method_full_name (selectedMethod, TRUE);

		if (location) {
			hint = g_strdup_printf (LOCATION_INDENT "%s in %s:%u\n", methodName, location->source_file, location->row);
			mono_debug_free_source_location (location);
		} else
			hint = g_strdup_printf (LOCATION_INDENT "%s\n", methodName);
		g_free (methodName);
	}

	return hint;
}
Пример #22
0
static MonoMethod *
create_method_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
{
	MonoMethodHeader *header;
	MonoMethodWrapper *mw;
	MonoImage *image;
	MonoMethod *method;
	GList *l;
	int i;

	g_assert (mb != NULL);

	image = m_class_get_image (mb->method->klass);

	if (mb->dynamic) {
		method = mb->method;
		mw = (MonoMethodWrapper*)method;

		method->name = mb->name;
		method->dynamic = TRUE;

		mw->header = header = (MonoMethodHeader *) 
			g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));

		header->code = mb->code;

		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
			header->locals [i] = (MonoType*)l->data;
		}
	} else
	{
		/* Realloc the method info into a mempool */

		method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
		memcpy (method, mb->method, sizeof (MonoMethodWrapper));
		mw = (MonoMethodWrapper*) method;

		if (mb->no_dup_name)
			method->name = mb->name;
		else
			method->name = mono_image_strdup (image, mb->name);

		mw->header = header = (MonoMethodHeader *) 
			mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));

		header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
		memcpy ((char*)header->code, mb->code, mb->pos);

		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
			header->locals [i] = (MonoType*)l->data;
		}
	}

	/* Free the locals list so mono_mb_free () doesn't free the types twice */
	g_list_free (mb->locals_list);
	mb->locals_list = NULL;

	method->signature = signature;
	if (!signature->hasthis)
		method->flags |= METHOD_ATTRIBUTE_STATIC;

	if (max_stack < 8)
		max_stack = 8;

	header->max_stack = max_stack;

	header->code_size = mb->pos;
	header->num_locals = mb->locals;
	header->init_locals = mb->init_locals;
	header->volatile_args = mb->volatile_args;
	header->volatile_locals = mb->volatile_locals;
	mb->volatile_args = NULL;
	mb->volatile_locals = NULL;

	header->num_clauses = mb->num_clauses;
	header->clauses = mb->clauses;

	method->skip_visibility = mb->skip_visibility;

	i = g_list_length ((GList *)mw->method_data);
	if (i) {
		GList *tmp;
		void **data;
		l = g_list_reverse ((GList *)mw->method_data);
		if (method_is_dynamic (method))
			data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
		else
			data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
		/* store the size in the first element */
		data [0] = GUINT_TO_POINTER (i);
		i = 1;
		for (tmp = l; tmp; tmp = tmp->next) {
			data [i++] = tmp->data;
		}
		g_list_free (l);

		mw->method_data = data;
	}

	/*{
		static int total_code = 0;
		static int total_alloc = 0;
		total_code += mb->pos;
		total_alloc += mb->code_size;
		g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, total_code, total_alloc);
	}*/

#ifdef DEBUG_RUNTIME_CODE
	printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
	printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, mb->code + mb->pos));
#endif

	if (mb->param_names) {
		char **param_names = (char **)mono_image_alloc0 (image, signature->param_count * sizeof (gpointer));
		for (i = 0; i < signature->param_count; ++i)
			param_names [i] = mono_image_strdup (image, mb->param_names [i]);

		mono_image_lock (image);
		if (!image->wrapper_param_names)
			image->wrapper_param_names = g_hash_table_new (NULL, NULL);
		g_hash_table_insert (image->wrapper_param_names, method, param_names);
		mono_image_unlock (image);
	}

	return method;
}
Пример #23
0
String GDMonoMethod::get_full_name(bool p_signature) const {
	char *res = mono_method_full_name(mono_method, p_signature);
	String full_name(res);
	mono_free(res);
	return full_name;
}
Пример #24
0
void
mono_arch_handle_altstack_exception (void *sigctx, MONO_SIG_HANDLER_INFO_TYPE *siginfo, gpointer fault_addr, gboolean stack_ovf)
{
#ifdef MONO_CROSS_COMPILE
	g_assert_not_reached ();
#else
#ifdef MONO_ARCH_USE_SIGACTION
	os_ucontext *uc = (ucontext_t*)sigctx;
	os_ucontext *uc_copy;
	MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (sigctx), NULL);
	gpointer *sp;
	int frame_size;

	if (stack_ovf) {
		const char *method;
		/* we don't do much now, but we can warn the user with a useful message */
		fprintf (stderr, "Stack overflow: IP: %p, SP: %p\n", mono_arch_ip_from_context (sigctx), (gpointer)UCONTEXT_REG_Rn(uc, 1));
		if (ji && !ji->is_trampoline && jinfo_get_method (ji))
			method = mono_method_full_name (jinfo_get_method (ji), TRUE);
		else
			method = "Unmanaged";
		fprintf (stderr, "At %s\n", method);
		abort ();
	}
	if (!ji)
		mono_handle_native_crash ("SIGSEGV", sigctx, siginfo);
	/* setup a call frame on the real stack so that control is returned there
	 * and exception handling can continue.
	 * The frame looks like:
	 *   ucontext struct
	 *   ...
	 * 224 is the size of the red zone
	 */
	frame_size = sizeof (ucontext_t) + sizeof (gpointer) * 16 + 224;
	frame_size += 15;
	frame_size &= ~15;
	sp = (gpointer)(UCONTEXT_REG_Rn(uc, 1) & ~15);
	sp = (gpointer)((char*)sp - frame_size);
	/* may need to adjust pointers in the new struct copy, depending on the OS */
	uc_copy = (ucontext_t*)(sp + 16);
	memcpy (uc_copy, uc, sizeof (os_ucontext));
#if defined(__linux__) && !defined(__mono_ppc64__)
	uc_copy->uc_mcontext.uc_regs = (gpointer)((char*)uc_copy + ((char*)uc->uc_mcontext.uc_regs - (char*)uc));
#endif
	g_assert (mono_arch_ip_from_context (uc) == mono_arch_ip_from_context (uc_copy));
	/* at the return form the signal handler execution starts in altstack_handle_and_restore() */
	UCONTEXT_REG_LNK(uc) = UCONTEXT_REG_NIP(uc);
#ifdef PPC_USES_FUNCTION_DESCRIPTOR
	{
		MonoPPCFunctionDescriptor *handler_ftnptr = (MonoPPCFunctionDescriptor*)altstack_handle_and_restore;

		UCONTEXT_REG_NIP(uc) = (gulong)handler_ftnptr->code;
		UCONTEXT_REG_Rn(uc, 2) = (gulong)handler_ftnptr->toc;
	}
#else
	UCONTEXT_REG_NIP(uc) = (unsigned long)altstack_handle_and_restore;
#if _CALL_ELF == 2
	/* ELF v2 ABI calling convention requires to put the target address into
	* r12 if we use the global entry point of a function. */
	UCONTEXT_REG_Rn(uc, 12) = (unsigned long) altstack_handle_and_restore;
#endif
#endif
	UCONTEXT_REG_Rn(uc, 1) = (unsigned long)sp;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG) = (unsigned long)(sp + 16);
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 1) = 0;
	UCONTEXT_REG_Rn(uc, PPC_FIRST_ARG_REG + 2) = 0;
#endif

#endif /* !MONO_CROSS_COMPILE */
}
Пример #25
0
/* sometime we get a NULL (not found) caller (e.g. get_reflection_caller) */
static char*
get_method_full_name (MonoMethod * method)
{
	return method ? mono_method_full_name (method, TRUE) : g_strdup ("'no caller found'");
}
Пример #26
0
MonoDebugMethodAddress *
mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain)
{
	MonoMethod *declaring;
	MonoDebugDataTable *table;
	MonoDebugMethodHeader *header;
	MonoDebugMethodAddress *address;
	MonoDebugMethodInfo *minfo;
	MonoDebugHandle *handle;
	guint8 buffer [BUFSIZ];
	guint8 *ptr, *oldptr;
	guint32 i, size, total_size, max_size;
	gboolean is_wrapper = FALSE;

	mono_debugger_lock ();

	table = lookup_data_table (domain);

	handle = _mono_debug_get_image (method->klass->image);
	minfo = _mono_debug_lookup_method (method);

	if (!minfo || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
	    (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
	    (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
	    (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
	    (method->wrapper_type != MONO_WRAPPER_NONE)) {
		is_wrapper = TRUE;
	}

	max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) +
		(25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals);

	if (max_size > BUFSIZ)
		ptr = oldptr = g_malloc (max_size);
	else
		ptr = oldptr = buffer;

	write_leb128 (jit->prologue_end, ptr, &ptr);
	write_leb128 (jit->epilogue_begin, ptr, &ptr);

	write_leb128 (jit->num_line_numbers, ptr, &ptr);
	for (i = 0; i < jit->num_line_numbers; i++) {
		MonoDebugLineNumberEntry *lne = &jit->line_numbers [i];

		write_sleb128 (lne->il_offset, ptr, &ptr);
		write_sleb128 (lne->native_offset, ptr, &ptr);
	}

	*ptr++ = jit->this_var ? 1 : 0;
	if (jit->this_var)
		write_variable (jit->this_var, ptr, &ptr);

	write_leb128 (jit->num_params, ptr, &ptr);
	for (i = 0; i < jit->num_params; i++)
		write_variable (&jit->params [i], ptr, &ptr);

	write_leb128 (jit->num_locals, ptr, &ptr);
	for (i = 0; i < jit->num_locals; i++)
		write_variable (&jit->locals [i], ptr, &ptr);

	size = ptr - oldptr;
	g_assert (size < max_size);
	total_size = size + sizeof (MonoDebugMethodAddress);

	address = (MonoDebugMethodAddress *) allocate_data_item (
		table, MONO_DEBUG_DATA_ITEM_METHOD, total_size);

	address->header.size = total_size;
	address->header.symfile_id = handle ? handle->index : 0;
	address->header.domain_id = mono_domain_get_id (domain);
	address->header.method_id = is_wrapper ? 0 : minfo->index;
	address->header.method = method;

	address->code_start = jit->code_start;
	address->code_size = jit->code_size;

	memcpy (&address->data, oldptr, size);
	if (max_size > BUFSIZ)
		g_free (oldptr);

	declaring = method->is_inflated ? ((MonoMethodInflated *) method)->declaring : method;
	header = g_hash_table_lookup (table->method_hash, declaring);

	if (!header) {
		header = &address->header;
		g_hash_table_insert (table->method_hash, declaring, header);

		if (is_wrapper) {
			MonoDebugWrapperData *wrapper;

			header->wrapper_data = wrapper = g_new0 (MonoDebugWrapperData, 1);

			wrapper->wrapper_type = method->wrapper_type;
			wrapper->method_name = mono_method_full_name (declaring, TRUE);
			wrapper->obsolete_cil_code = "";
		}
	} else {
		address->header.wrapper_data = header->wrapper_data;
		header->address_list = g_slist_prepend (header->address_list, address);
	}

	g_hash_table_insert (table->method_address_hash, method, address);

	write_data_item (table, (guint8 *) address);

	mono_debugger_unlock ();
	return address;
}
Пример #27
0
void
mono_linear_scan2 (MonoCompile *cfg, GList *vars, GList *regs, regmask_t *used_mask)
{
	GList *unhandled, *active, *inactive, *l;
	MonoMethodVar *vmv;
	gint32 free_pos [sizeof (regmask_t) * 8];
	gint32 gains [sizeof (regmask_t) * 8];
	regmask_t used_regs = 0;
	int n_regs, n_regvars, i;

	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;
		LSCAN_DEBUG (printf ("VAR R%d %08x %08x C%d\n", cfg->varinfo [vmv->idx]->dreg, vmv->range.first_use.abs_pos, 
							 vmv->range.last_use.abs_pos, vmv->spill_costs));
	}

	LSCAN_DEBUG (printf ("Linear Scan 2 for %s:\n", mono_method_full_name (cfg->method, TRUE)));

	n_regs = g_list_length (regs);
	memset (gains, 0, n_regs * sizeof (gint32));
	unhandled = g_list_sort (g_list_copy (vars), compare_by_interval_start_pos_func);
	active = NULL;
	inactive = NULL;

	while (unhandled) {
		MonoMethodVar *current = (MonoMethodVar *)unhandled->data;
		int pos, reg, max_free_pos;
		gboolean changed;

		unhandled = g_list_delete_link (unhandled, unhandled);

		LSCAN_DEBUG (printf ("Processing R%d: ", cfg->varinfo [current->idx]->dreg));
		LSCAN_DEBUG (mono_linterval_print (current->interval));
		LSCAN_DEBUG (printf ("\n"));

		if (!current->interval->range)
			continue;
			
		pos = current->interval->range->from;

		/* Check for intervals in active which expired or inactive */
		changed = TRUE;
		/* FIXME: Optimize this */
		while (changed) {
			changed = FALSE;
			for (l = active; l != NULL; l = l->next) {
				MonoMethodVar *v = (MonoMethodVar*)l->data;

				if (v->interval->last_range->to < pos) {
					active = g_list_delete_link (active, l);
					LSCAN_DEBUG (printf ("Interval R%d has expired\n", cfg->varinfo [v->idx]->dreg));
					changed = TRUE;
					break;
				}
				else if (!mono_linterval_covers (v->interval, pos)) {
					inactive = g_list_append (inactive, v);
					active = g_list_delete_link (active, l);
					LSCAN_DEBUG (printf ("Interval R%d became inactive\n", cfg->varinfo [v->idx]->dreg));
					changed = TRUE;
					break;
				}
			}
		}

		/* Check for intervals in inactive which expired or active */
		changed = TRUE;
		/* FIXME: Optimize this */
		while (changed) {
			changed = FALSE;
			for (l = inactive; l != NULL; l = l->next) {
				MonoMethodVar *v = (MonoMethodVar*)l->data;

				if (v->interval->last_range->to < pos) {
					inactive = g_list_delete_link (inactive, l);
					LSCAN_DEBUG (printf ("\tInterval R%d has expired\n", cfg->varinfo [v->idx]->dreg));
					changed = TRUE;
					break;
				}
				else if (mono_linterval_covers (v->interval, pos)) {
					active = g_list_append (active, v);
					inactive = g_list_delete_link (inactive, l);
					LSCAN_DEBUG (printf ("\tInterval R%d became active\n", cfg->varinfo [v->idx]->dreg));
					changed = TRUE;
					break;
				}
			}
		}

		/* Find a register for the current interval */
		for (i = 0; i < n_regs; ++i)
			free_pos [i] = ((gint32)0x7fffffff);

		for (l = active; l != NULL; l = l->next) {
			MonoMethodVar *v = (MonoMethodVar*)l->data;

			if (v->reg >= 0) {
				free_pos [v->reg] = 0;
				LSCAN_DEBUG (printf ("\threg %d is busy (cost %d)\n", v->reg, v->spill_costs));
			}
		}

		for (l = inactive; l != NULL; l = l->next) {
			MonoMethodVar *v = (MonoMethodVar*)l->data;
			gint32 intersect_pos;

			if (v->reg >= 0) {
				intersect_pos = mono_linterval_get_intersect_pos (current->interval, v->interval);
				if (intersect_pos != -1) {
					free_pos [v->reg] = intersect_pos;
					LSCAN_DEBUG (printf ("\threg %d becomes free at %d\n", v->reg, intersect_pos));
				}
			}
		}

		max_free_pos = -1;
		reg = -1;
		for (i = 0; i < n_regs; ++i)
			if (free_pos [i] > max_free_pos) {
				reg = i;
				max_free_pos = free_pos [i];
			}

		g_assert (reg != -1);

		if (free_pos [reg] >= current->interval->last_range->to) {
			/* Register available for whole interval */
			current->reg = reg;
			LSCAN_DEBUG (printf ("\tAssigned hreg %d to R%d\n", reg, cfg->varinfo [current->idx]->dreg));

			active = g_list_append (active, current);
			gains [current->reg] += current->spill_costs;
		}
		else {
			/* 
			 * free_pos [reg] > 0 means there is a register available for parts
			 * of the interval, so splitting it is possible. This is not yet
			 * supported, so we spill in this case too.
			 */

			/* Spill an interval */

			/* FIXME: Optimize the selection of the interval */

			if (active) {
				GList *min_spill_pos;
#if 0
				/* 
				 * This favors registers with big spill costs, thus larger liveness ranges,
				 * thus actually leading to worse code size.
				 */
				guint32 min_spill_value = G_MAXINT32;

				for (l = active; l != NULL; l = l->next) {
					vmv = (MonoMethodVar*)l->data;

					if (vmv->spill_costs < min_spill_value) {
						min_spill_pos = l;
						min_spill_value = vmv->spill_costs;
					}
				}
#else
				/* Spill either the first active or the current interval */
				min_spill_pos = active;
#endif
				vmv = (MonoMethodVar*)min_spill_pos->data;
				if (vmv->spill_costs < current->spill_costs) {
				//				if (vmv->interval->last_range->to < current->interval->last_range->to) {
					gains [vmv->reg] -= vmv->spill_costs;
					vmv->reg = -1;
					LSCAN_DEBUG (printf ("\tSpilled R%d\n", cfg->varinfo [vmv->idx]->dreg));
					active = g_list_delete_link (active, min_spill_pos);
				}
				else
					LSCAN_DEBUG (printf ("\tSpilled current (cost %d)\n", current->spill_costs));
			}
			else
				LSCAN_DEBUG (printf ("\tSpilled current\n"));
		}
	}

	/* Decrease the gains by the cost of saving+restoring the register */
	for (i = 0; i < n_regs; ++i) {
		if (gains [i]) {
			/* FIXME: This is x86 only */
			gains [i] -= cfg->method->save_lmf ? 1 : 2;
			if (gains [i] < 0)
				gains [i] = 0;
		}
	}

	/* Do the actual register assignment */
	n_regvars = 0;
	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;

		if (vmv->reg >= 0) {
			int reg_index = vmv->reg;

			/* During allocation, vmv->reg is an index into the regs list */
			vmv->reg = GPOINTER_TO_INT (g_list_nth_data (regs, vmv->reg));

			if ((gains [reg_index] > regalloc_cost (cfg, vmv)) && (cfg->varinfo [vmv->idx]->opcode != OP_REGVAR)) {
				if (cfg->verbose_level > 2)
					printf ("REGVAR R%d G%d C%d %s\n", cfg->varinfo [vmv->idx]->dreg, gains [reg_index], regalloc_cost (cfg, vmv), mono_arch_regname (vmv->reg));
				cfg->varinfo [vmv->idx]->opcode = OP_REGVAR;
				cfg->varinfo [vmv->idx]->dreg = vmv->reg;
				n_regvars ++;
			}
			else {
				if (cfg->verbose_level > 2)
					printf ("COSTLY: %s R%d G%d C%d %s\n", mono_method_full_name (cfg->method, TRUE), cfg->varinfo [vmv->idx]->dreg, gains [reg_index], regalloc_cost (cfg, vmv), mono_arch_regname (vmv->reg));
				vmv->reg = -1;
			}
		}
	}

	cfg->stat_n_regvars = n_regvars;

	/* Compute used regs */
	used_regs = 0;
	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;
		
		if (vmv->reg >= 0)
			used_regs |= 1LL << vmv->reg;
	}

	*used_mask |= used_regs;

	g_list_free (active);
	g_list_free (inactive);
}
Пример #28
0
/*
 * mono_debug_add_vg_method:
 *
 *  Register symbol information for the method with valgrind
 */
static void 
mono_debug_add_vg_method (MonoMethod *method, MonoDebugMethodJitInfo *jit)
{
#ifdef VALGRIND_ADD_LINE_INFO
	MonoMethodHeader *header;
	MonoDebugMethodInfo *minfo;
	int i;
	char *filename = NULL;
	guint32 address, line_number;
	const char *full_name;
	guint32 *addresses;
	guint32 *lines;

	if (!RUNNING_ON_VALGRIND)
		return;

	header = mono_method_get_header (method);

	full_name = mono_method_full_name (method, TRUE);

	addresses = g_new0 (guint32, header->code_size + 1);
	lines = g_new0 (guint32, header->code_size + 1);

	/* 
	 * Very simple code to convert the addr->offset mappings that mono has
	 * into [addr-addr] ->line number mappings.
	 */

	minfo = mono_debug_lookup_method (method);
	if (minfo) {
		/* Create offset->line number mapping */
		for (i = 0; i < header->code_size; ++i) {
			MonoDebugSourceLocation *location;

			location = mono_debug_symfile_lookup_location (minfo, i);
			if (!location)
				continue;

			lines [i] = location.row;
			if (!filename)
				filename = location.source_file;

			mono_debug_free_source_location (location);
		}
	}

	/* Create address->offset mapping */
	for (i = 0; i < jit->num_line_numbers; ++i) {
		MonoDebugLineNumberEntry *lne = jit->line_numbers [i];

		g_assert (lne->offset <= header->code_size);

		if ((addresses [lne->offset] == 0) || (lne->address < addresses [lne->offset]))
			addresses [lne->offset] = lne->address;
	}
	/* Fill out missing addresses */
	address = 0;
	for (i = 0; i < header->code_size; ++i) {
		if (addresses [i] == 0)
			addresses [i] = address;
		else
			address = addresses [i];
	}
	
	address = 0;
	line_number = 0;
	i = 0;
	while (i < header->code_size) {
		if (lines [i] == line_number)
			i ++;
		else {
			if (line_number > 0) {
				//g_assert (addresses [i] - 1 >= address);
				
				if (addresses [i] - 1 >= address) {
					VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + addresses [i] - 1, filename, line_number);
					//printf ("[%d-%d] -> %d.\n", address, addresses [i] - 1, line_number);
				}
			}
			address = addresses [i];
			line_number = lines [i];
		}
	}

	if (line_number > 0) {
		VALGRIND_ADD_LINE_INFO (jit->code_start + address, jit->code_start + jit->code_size - 1, filename, line_number);
		//printf ("[%d-%d] -> %d.\n", address, jit->code_size - 1, line_number);
	}

	VALGRIND_ADD_SYMBOL (jit->code_start, jit->code_size, full_name);

	g_free (addresses);
	g_free (lines);
	mono_metadata_free_mh (header);
#endif /* VALGRIND_ADD_LINE_INFO */
}
Пример #29
0
void
mono_linear_scan (MonoCompile *cfg, GList *vars, GList *regs, regmask_t *used_mask)
{
	GList *l, *a, *active = NULL;
	MonoMethodVar *vmv, *amv;
	int max_regs, n_regvars;
	int gains [sizeof (regmask_t) * 8];
	regmask_t used_regs = 0;
	gboolean cost_driven;

	if (!cfg->disable_reuse_registers && vars && (((MonoMethodVar*)vars->data)->interval != NULL)) {
 		mono_linear_scan2 (cfg, vars, regs, used_mask);
 		return;
 	}

	cost_driven = TRUE;

#ifdef DEBUG_LSCAN
	printf ("Linears scan for %s\n", mono_method_full_name (cfg->method, TRUE));
#endif

#ifdef DEBUG_LSCAN
	for (l = vars; l; l = l->next) {
		vmv = l->data;
		printf ("VAR %d %08x %08x C%d\n", vmv->idx, vmv->range.first_use.abs_pos, 
			vmv->range.last_use.abs_pos, vmv->spill_costs);
	}
#endif
	max_regs = g_list_length (regs);

	for (l = regs; l; l = l->next) {
		int regnum = GPOINTER_TO_INT (l->data);
		g_assert (regnum < G_N_ELEMENTS (gains));
		gains [regnum] = 0;
	}

	/* linear scan */
	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;

#ifdef DEBUG_LSCAN
		printf ("START  %2d %08x %08x\n",  vmv->idx, vmv->range.first_use.abs_pos, 
			vmv->range.last_use.abs_pos);
#endif
		/* expire old intervals in active */
		if (!cfg->disable_reuse_registers) {
			while (active) {
				amv = (MonoMethodVar *)active->data;

				if (amv->range.last_use.abs_pos > vmv->range.first_use.abs_pos)
					break;

#ifdef DEBUG_LSCAN
				printf ("EXPIR  %2d %08x %08x C%d R%d\n", amv->idx, amv->range.first_use.abs_pos, 
						amv->range.last_use.abs_pos, amv->spill_costs, amv->reg);
#endif
				active = g_list_delete_link (active, active);
				regs = g_list_prepend (regs, GINT_TO_POINTER (amv->reg));
				gains [amv->reg] += amv->spill_costs;
			}
		}

		if (active && g_list_length (active) == max_regs) {
			/* Spill */

			a = g_list_nth (active, max_regs - 1);
			amv = (MonoMethodVar *)a->data;

			if ((cost_driven && amv->spill_costs < vmv->spill_costs) || 			     
			    (!cost_driven && amv->range.last_use.abs_pos > vmv->range.last_use.abs_pos)) {
				vmv->reg = amv->reg;
				amv->reg = -1;
				active = g_list_delete_link (active, a);

				if (cost_driven)
					active = mono_varlist_insert_sorted (cfg, active, vmv, 2);	
				else
					active = mono_varlist_insert_sorted (cfg, active, vmv, 1);	

#ifdef DEBUG_LSCAN
				printf ("SPILL0 %2d %08x %08x C%d\n",  amv->idx, 
					amv->range.first_use.abs_pos, amv->range.last_use.abs_pos,
					amv->spill_costs);
#endif
			} else {
#ifdef DEBUG_LSCAN
				printf ("SPILL1 %2d %08x %08x C%d\n",  vmv->idx, 
					vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos,
					vmv->spill_costs);
#endif
				vmv->reg = -1;
			}
		} else {
			/* assign register */

			g_assert (regs);

			vmv->reg = GPOINTER_TO_INT (regs->data);

			used_regs |= 1LL << vmv->reg;

			regs = g_list_delete_link (regs, regs);

#ifdef DEBUG_LSCAN
			printf ("ADD    %2d %08x %08x C%d R%d\n",  vmv->idx, 
				vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos, 
				vmv->spill_costs, vmv->reg);
#endif
			active = mono_varlist_insert_sorted (cfg, active, vmv, TRUE);		
		}


#ifdef DEBUG_LSCAN
		for (a = active; a; a = a->next) {
			amv = (MonoMethodVar *)a->data;		
			printf ("ACT    %2d %08x %08x C%d R%d\n", amv->idx, amv->range.first_use.abs_pos,  
				amv->range.last_use.abs_pos, amv->spill_costs, amv->reg);
		}
		printf ("NEXT\n");
#endif
	}	

	for (a = active; a; a = a->next) {
		amv = (MonoMethodVar *)a->data;		
		gains [amv->reg] += amv->spill_costs;
	}

	n_regvars = 0;
	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;
		
		if (vmv->reg >= 0)  {
			if ((gains [vmv->reg] > mono_arch_regalloc_cost (cfg, vmv)) && (cfg->varinfo [vmv->idx]->opcode != OP_REGVAR)) {
				if (cfg->verbose_level > 2) {
					printf ("ALLOCATED R%d(%d) TO HREG %d COST %d\n", cfg->varinfo [vmv->idx]->dreg, vmv->idx, vmv->reg, vmv->spill_costs);
				}
				cfg->varinfo [vmv->idx]->opcode = OP_REGVAR;
				cfg->varinfo [vmv->idx]->dreg = vmv->reg;
				n_regvars ++;
			} else {
				if (cfg->verbose_level > 2)
					printf ("COSTLY: R%d C%d C%d %s\n", vmv->idx, vmv->spill_costs, mono_arch_regalloc_cost (cfg, vmv), mono_arch_regname (vmv->reg));
				vmv->reg = -1;
			}
		}

		if (vmv->reg == -1) {
			if (cfg->verbose_level > 2)
				printf ("NOT REGVAR: %d\n", vmv->idx);
		}
	}

	cfg->stat_n_regvars = n_regvars;

	/* Compute used regs */
	used_regs = 0;
	for (l = vars; l; l = l->next) {
		vmv = (MonoMethodVar *)l->data;
		
		if (vmv->reg >= 0)
			used_regs |= 1LL << vmv->reg;
	}

	*used_mask |= used_regs;

#ifdef DEBUG_LSCAN
	if (cfg->verbose_level > 2)
		printf ("EXIT: final used mask: %08x\n", *used_mask);
#endif

	g_list_free (regs);
	g_list_free (active);
	g_list_free (vars);
}