MonoInst *
mono_get_got_var (MonoCompile *cfg)
{
- if (!cfg->compile_aot || !cfg->backend->need_got_var)
+ if (!cfg->compile_aot || !cfg->backend->need_got_var || cfg->llvm_only)
return NULL;
if (!cfg->got_var) {
cfg->got_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
return addr;
}
-static MonoBreakPolicy
-always_insert_breakpoint (MonoMethod *method)
-{
- return MONO_BREAK_POLICY_ALWAYS;
-}
-
-static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
-
-/**
- * mono_set_break_policy:
- * \param policy_callback the new callback function
- *
- * Allow embedders to decide wherther to actually obey breakpoint instructions
- * (both break IL instructions and \c Debugger.Break method calls), for example
- * to not allow an app to be aborted by a perfectly valid IL opcode when executing
- * untrusted or semi-trusted code.
- *
- * \p policy_callback will be called every time a break point instruction needs to
- * be inserted with the method argument being the method that calls \c Debugger.Break
- * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
- * if it wants the breakpoint to not be effective in the given method.
- * \c MONO_BREAK_POLICY_ALWAYS is the default.
- */
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
- if (policy_callback)
- break_policy_func = policy_callback;
- else
- break_policy_func = always_insert_breakpoint;
-}
-
-static gboolean
-should_insert_brekpoint (MonoMethod *method) {
- switch (break_policy_func (method)) {
- case MONO_BREAK_POLICY_ALWAYS:
- return TRUE;
- case MONO_BREAK_POLICY_NEVER:
- return FALSE;
- case MONO_BREAK_POLICY_ON_DBG:
- g_warning ("mdb no longer supported");
- return FALSE;
- default:
- g_warning ("Incorrect value returned from break policy callback");
- return FALSE;
- }
-}
-
/* optimize the simple GetGenericValueImpl/SetGenericValueImpl generic icalls */
static MonoInst*
emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
return NULL;
}
+
+static gboolean
+mono_type_is_native_blittable (MonoType *t)
+{
+ if (MONO_TYPE_IS_REFERENCE (t))
+ return FALSE;
+
+ if (MONO_TYPE_IS_PRIMITIVE_SCALAR (t))
+ return TRUE;
+
+ MonoClass *klass = mono_class_from_mono_type (t);
+
+ //MonoClass::blitable depends on mono_class_setup_fields being done.
+ mono_class_setup_fields (klass);
+ if (!klass->blittable)
+ return FALSE;
+
+ // If the native marshal size is different we can't convert PtrToStructure to a type load
+ if (mono_class_native_size (klass, NULL) != mono_class_value_size (klass, NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+
static MonoInst*
mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
(strcmp (cmethod->klass->name_space, "System.Diagnostics") == 0) &&
(strcmp (cmethod->klass->name, "Debugger") == 0)) {
if (!strcmp (cmethod->name, "Break") && fsig->param_count == 0) {
- if (should_insert_brekpoint (cfg->method)) {
+ if (mini_should_insert_breakpoint (cfg->method)) {
ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
} else {
MONO_INST_NEW (cfg, ins, OP_NOP);
MONO_ADD_INS (cfg->cbb, ins);
return ins;
}
+ } else if (cmethod->klass->image == mono_defaults.corlib &&
+ (strcmp (cmethod->klass->name_space, "System.Runtime.InteropServices") == 0) &&
+ (strcmp (cmethod->klass->name, "Marshal") == 0)) {
+ //Convert Marshal.PtrToStructure<T> of blittable T to direct loads
+ if (strcmp (cmethod->name, "PtrToStructure") == 0 &&
+ cmethod->is_inflated &&
+ fsig->param_count == 1 &&
+ !mini_method_check_context_used (cfg, cmethod)) {
+
+ MonoGenericContext *method_context = mono_method_get_context (cmethod);
+ MonoType *arg0 = method_context->method_inst->type_argv [0];
+ if (mono_type_is_native_blittable (arg0))
+ return mini_emit_memory_load (cfg, arg0, args [0], 0, 0);
+ }
}
#ifdef MONO_ARCH_SIMD_INTRINSICS
return method;
}
-MonoClass*
-mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
-{
- MonoError error;
- MonoClass *klass;
-
- if (method->wrapper_type != MONO_WRAPPER_NONE) {
- klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
- if (context) {
- klass = mono_class_inflate_generic_class_checked (klass, context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- }
- } else {
- klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- }
- if (klass)
- mono_class_init (klass);
- return klass;
-}
-
static inline MonoMethodSignature*
mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *context, MonoError *error)
{
if ((cfg->method == method) && cfg->coverage_info) {
guint32 cil_offset = ip - header->code;
+ gpointer counter = &cfg->coverage_info->data [cil_offset].count;
cfg->coverage_info->data [cil_offset].cil_code = ip;
- /* TODO: Use an increment here */
-#if defined(TARGET_X86)
- MONO_INST_NEW (cfg, ins, OP_STORE_MEM_IMM);
- ins->inst_p0 = &(cfg->coverage_info->data [cil_offset].count);
- ins->inst_imm = 1;
- MONO_ADD_INS (cfg->cbb, ins);
-#else
- EMIT_NEW_PCONST (cfg, ins, &(cfg->coverage_info->data [cil_offset].count));
- MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
-#endif
+ if (mono_arch_opcode_supported (OP_ATOMIC_ADD_I4)) {
+ MonoInst *one_ins, *load_ins;
+
+ EMIT_NEW_PCONST (cfg, load_ins, counter);
+ EMIT_NEW_ICONST (cfg, one_ins, 1);
+ MONO_INST_NEW (cfg, ins, OP_ATOMIC_ADD_I4);
+ ins->dreg = mono_alloc_ireg (cfg);
+ ins->inst_basereg = load_ins->dreg;
+ ins->inst_offset = 0;
+ ins->sreg2 = one_ins->dreg;
+ ins->type = STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ EMIT_NEW_PCONST (cfg, ins, counter);
+ MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
+ }
}
if (cfg->verbose_level > 3)
MONO_ADD_INS (cfg->cbb, ins);
break;
case CEE_BREAK:
- if (should_insert_brekpoint (cfg->method)) {
+ if (mini_should_insert_breakpoint (cfg->method)) {
ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
} else {
MONO_INST_NEW (cfg, ins, OP_NOP);
TYPE_LOAD_ERROR (cmethod->klass);
context_used = mini_method_check_context_used (cfg, cmethod);
+
+ if (!dont_verify && !cfg->skip_visibility) {
+ MonoMethod *cil_method = cmethod;
+ MonoMethod *target_method = cil_method;
+
+ if (method->is_inflated) {
+ target_method = mini_get_method_allow_open (method, token, NULL, &(mono_method_get_generic_container (method_definition)->context), &cfg->error);
+ CHECK_CFG_ERROR;
+ }
+
+ if (!mono_method_can_access_method (method_definition, target_method) &&
+ !mono_method_can_access_method (method, cil_method))
+ emit_method_access_failure (cfg, method, cil_method);
+ }
if (mono_security_core_clr_enabled ())
ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
CHECK_STACK (info->sig->param_count);
sp -= info->sig->param_count;
- ins = mono_emit_jit_icall (cfg, info->func, sp);
+ if (cfg->compile_aot && !strcmp (info->name, "mono_threads_attach_coop")) {
+ MonoInst *addr;
+
+ /*
+ * This is called on unattached threads, so it cannot go through the trampoline
+ * infrastructure. Use an indirect call through a got slot initialized at load time
+ * instead.
+ */
+ EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_JIT_ICALL_ADDR_NOCALL, (char*)info->name);
+ ins = mini_emit_calli (cfg, info->sig, sp, addr, NULL, NULL);
+ } else {
+ ins = mono_emit_jit_icall (cfg, info->func, sp);
+ }
+
if (!MONO_TYPE_IS_VOID (info->sig->ret))
*sp++ = ins;
CHECK_STACK_OVF (1);
switch (ip [1]) {
- case CEE_MONO_LDPTR_CARD_TABLE:
- ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
- break;
- case CEE_MONO_LDPTR_NURSERY_START:
- ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
- break;
- case CEE_MONO_LDPTR_NURSERY_BITS:
- ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_BITS, NULL);
- break;
- case CEE_MONO_LDPTR_INT_REQ_FLAG:
- ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
- break;
+ case CEE_MONO_LDPTR_CARD_TABLE:
+ ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
+ break;
+ case CEE_MONO_LDPTR_NURSERY_START:
+ ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
+ break;
+ case CEE_MONO_LDPTR_NURSERY_BITS:
+ ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_GC_NURSERY_BITS, NULL);
+ break;
+ case CEE_MONO_LDPTR_INT_REQ_FLAG:
+ ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
}
*sp++ = ins;
MonoInst *ad_ins, *jit_tls_ins;
MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
- g_assert (!mono_threads_is_coop_enabled ());
+ g_assert (!mono_threads_is_blocking_transition_enabled ());
cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
the values on the stack before emitting the last instruction of the bb.
*/
-#else /* !DISABLE_JIT */
-
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
-}
-
#endif /* !DISABLE_JIT */