Skip to content

Instantly share code, notes, and snippets.

@Praetonus
Created October 12, 2017 18:20
Show Gist options
  • Save Praetonus/e6f9d24d1f88e4d1fbfd97dbdc340fef to your computer and use it in GitHub Desktop.
Save Praetonus/e6f9d24d1f88e4d1fbfd97dbdc340fef to your computer and use it in GitHub Desktop.
diff --git i/src/libponyc/codegen/codegen.c w/src/libponyc/codegen/codegen.c
index 0aa8de7fb..484f3948a 100644
--- i/src/libponyc/codegen/codegen.c
+++ w/src/libponyc/codegen/codegen.c
@@ -336,12 +336,13 @@ static void init_runtime(compile_t* c)
# endif
#endif
- // void pony_sendv(i8*, __object*, $message*, $message*)
+ // void pony_sendv(i8*, __object*, $message*, $message*, i1)
params[0] = c->void_ptr;
params[1] = c->object_ptr;
params[2] = c->msg_ptr;
params[3] = c->msg_ptr;
- type = LLVMFunctionType(c->void_type, params, 4, false);
+ params[4] = c->i1;
+ type = LLVMFunctionType(c->void_type, params, 5, false);
value = LLVMAddFunction(c->module, "pony_sendv", type);
#if PONY_LLVM >= 309
LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
@@ -354,12 +355,13 @@ static void init_runtime(compile_t* c)
# endif
#endif
- // void pony_sendv_single(i8*, __object*, $message*, $message*)
+ // void pony_sendv_single(i8*, __object*, $message*, $message*, i1)
params[0] = c->void_ptr;
params[1] = c->object_ptr;
params[2] = c->msg_ptr;
params[3] = c->msg_ptr;
- type = LLVMFunctionType(c->void_type, params, 4, false);
+ params[4] = c->i1;
+ type = LLVMFunctionType(c->void_type, params, 5, false);
value = LLVMAddFunction(c->module, "pony_sendv_single", type);
#if PONY_LLVM >= 309
LLVMAddAttributeAtIndex(value, LLVMAttributeFunctionIndex, nounwind_attr);
diff --git i/src/libponyc/codegen/gencall.c w/src/libponyc/codegen/gencall.c
index d29fbe384..71047a39a 100644
--- i/src/libponyc/codegen/gencall.c
+++ w/src/libponyc/codegen/gencall.c
@@ -536,7 +536,7 @@ void gen_send_message(compile_t* c, reach_method_t* m, LLVMValueRef args[],
arg_ast = ast_sibling(arg_ast);
}
- LLVMValueRef msg_args[4];
+ LLVMValueRef msg_args[5];
msg_args[0] = LLVMConstInt(c->i32, ponyint_pool_index(msg_size), false);
msg_args[1] = LLVMConstInt(c->i32, m->vtable_index, false);
@@ -595,12 +595,13 @@ void gen_send_message(compile_t* c, reach_method_t* m, LLVMValueRef args[],
msg_args[1] = LLVMBuildBitCast(c->builder, args[0], c->object_ptr, "");
msg_args[2] = msg;
msg_args[3] = msg;
+ msg_args[4] = LLVMConstInt(c->i1, 1, false);
LLVMValueRef send;
if(ast_id(m->r_fun) == TK_NEW)
- send = gencall_runtime(c, "pony_sendv_single", msg_args, 4, "");
+ send = gencall_runtime(c, "pony_sendv_single", msg_args, 5, "");
else
- send = gencall_runtime(c, "pony_sendv", msg_args, 4, "");
+ send = gencall_runtime(c, "pony_sendv", msg_args, 5, "");
LLVMSetMetadataStr(send, "pony.msgsend", md);
diff --git i/src/libponyc/codegen/genexe.c w/src/libponyc/codegen/genexe.c
index 748d4660f..a646280fc 100644
--- i/src/libponyc/codegen/genexe.c
+++ w/src/libponyc/codegen/genexe.c
@@ -47,7 +47,7 @@ LLVMValueRef gen_main(compile_t* c, reach_type_t* t_main, reach_type_t* t_env)
codegen_startfun(c, func, NULL, NULL, false);
- LLVMValueRef args[4];
+ LLVMValueRef args[5];
args[0] = LLVMGetParam(func, 0);
LLVMSetValueName(args[0], "argc");
@@ -121,7 +121,8 @@ LLVMValueRef gen_main(compile_t* c, reach_type_t* t_main, reach_type_t* t_env)
args[1] = main_actor;
args[2] = msg;
args[3] = msg;
- gencall_runtime(c, "pony_sendv_single", args, 4, "");
+ args[4] = LLVMConstInt(c->i1, 1, false);
+ gencall_runtime(c, "pony_sendv_single", args, 5, "");
// Start the runtime.
args[0] = LLVMConstInt(c->i32, 0, false);
diff --git i/src/libponyrt/actor/actor.c w/src/libponyrt/actor/actor.c
index 21905e1a3..0898b5f71 100644
--- i/src/libponyrt/actor/actor.c
+++ w/src/libponyrt/actor/actor.c
@@ -417,7 +417,7 @@ PONY_API pony_msg_t* pony_alloc_msg_size(size_t size, uint32_t id)
}
PONY_API void pony_sendv(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
- pony_msg_t* last)
+ pony_msg_t* last, bool has_app_msg)
{
// The function takes a prebuilt chain instead of varargs because the latter
// is expensive and very hard to optimise.
@@ -437,7 +437,8 @@ PONY_API void pony_sendv(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
DTRACE2(ACTOR_MSG_SEND, (uintptr_t)ctx->scheduler, last->id);
}
- ponyint_maybe_mute(ctx, to, first, last);
+ if(has_app_msg)
+ ponyint_maybe_mute(ctx, to);
if(ponyint_messageq_push(&to->q, first, last))
{
@@ -449,7 +450,7 @@ PONY_API void pony_sendv(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
}
PONY_API void pony_sendv_single(pony_ctx_t* ctx, pony_actor_t* to,
- pony_msg_t* first, pony_msg_t* last)
+ pony_msg_t* first, pony_msg_t* last, bool has_app_msg)
{
// The function takes a prebuilt chain instead of varargs because the latter
// is expensive and very hard to optimise.
@@ -469,7 +470,8 @@ PONY_API void pony_sendv_single(pony_ctx_t* ctx, pony_actor_t* to,
DTRACE2(ACTOR_MSG_SEND, (uintptr_t)ctx->scheduler, last->id);
}
- ponyint_maybe_mute(ctx, to, first, last);
+ if(has_app_msg)
+ ponyint_maybe_mute(ctx, to);
if(ponyint_messageq_push_single(&to->q, first, last))
{
@@ -482,8 +484,7 @@ PONY_API void pony_sendv_single(pony_ctx_t* ctx, pony_actor_t* to,
}
}
-void ponyint_maybe_mute(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
- pony_msg_t* last)
+void ponyint_maybe_mute(pony_ctx_t* ctx, pony_actor_t* to)
{
if(ctx->current != NULL)
{
@@ -497,29 +498,7 @@ void ponyint_maybe_mute(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
(atomic_load_explicit(&to->muted, memory_order_relaxed) > 0)) &&
!has_flag(ctx->current, FLAG_OVERLOADED) &&
ctx->current != to)
- {
- if (first == last)
- {
- if(first->id <= ACTORMSG_APPLICATION_START)
- {
- ponyint_sched_mute(ctx, ctx->current, to);
- return;
- }
- }
-
- pony_msg_t* m = first;
-
- while(m != last)
- {
- if(m->id <= ACTORMSG_APPLICATION_START)
- {
- ponyint_sched_mute(ctx, ctx->current, to);
- return;
- }
-
- m = atomic_load_explicit(&m->next, memory_order_relaxed);
- }
- }
+ ponyint_sched_mute(ctx, ctx->current, to);
}
}
@@ -532,7 +511,7 @@ PONY_API void pony_chain(pony_msg_t* prev, pony_msg_t* next)
PONY_API void pony_send(pony_ctx_t* ctx, pony_actor_t* to, uint32_t id)
{
pony_msg_t* m = pony_alloc_msg(POOL_INDEX(sizeof(pony_msg_t)), id);
- pony_sendv(ctx, to, m, m);
+ pony_sendv(ctx, to, m, m, id <= ACTORMSG_APPLICATION_START);
}
PONY_API void pony_sendp(pony_ctx_t* ctx, pony_actor_t* to, uint32_t id,
@@ -542,7 +521,7 @@ PONY_API void pony_sendp(pony_ctx_t* ctx, pony_actor_t* to, uint32_t id,
POOL_INDEX(sizeof(pony_msgp_t)), id);
m->p = p;
- pony_sendv(ctx, to, &m->msg, &m->msg);
+ pony_sendv(ctx, to, &m->msg, &m->msg, id <= ACTORMSG_APPLICATION_START);
}
PONY_API void pony_sendi(pony_ctx_t* ctx, pony_actor_t* to, uint32_t id,
@@ -552,7 +531,7 @@ PONY_API void pony_sendi(pony_ctx_t* ctx, pony_actor_t* to, uint32_t id,
POOL_INDEX(sizeof(pony_msgi_t)), id);
m->i = i;
- pony_sendv(ctx, to, &m->msg, &m->msg);
+ pony_sendv(ctx, to, &m->msg, &m->msg, id <= ACTORMSG_APPLICATION_START);
}
#ifdef USE_ACTOR_CONTINUATIONS
diff --git i/src/libponyrt/actor/actor.h w/src/libponyrt/actor/actor.h
index 828f1621d..fe3a4aba7 100644
--- i/src/libponyrt/actor/actor.h
+++ w/src/libponyrt/actor/actor.h
@@ -61,8 +61,7 @@ void ponyint_actor_setoverloaded(pony_actor_t* actor);
void ponyint_actor_unsetoverloaded(pony_ctx_t* ctx, pony_actor_t* actor);
-void ponyint_maybe_mute(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
- pony_msg_t* last);
+void ponyint_maybe_mute(pony_ctx_t* ctx, pony_actor_t* to);
PONY_API void ponyint_destroy(pony_actor_t* actor);
diff --git i/src/libponyrt/asio/event.c w/src/libponyrt/asio/event.c
index 280900f87..4c9aba895 100644
--- i/src/libponyrt/asio/event.c
+++ w/src/libponyrt/asio/event.c
@@ -118,5 +118,8 @@ PONY_API void pony_asio_event_send(asio_event_t* ev, uint32_t flags,
pony_register_thread();
#endif
- pony_sendv(pony_ctx(), ev->owner, &m->msg, &m->msg);
+ // ASIO messages technically are application messages, but since they have no
+ // sender they aren't covered by backpressure. We pass false for an early
+ // bailout in the backpressure code.
+ pony_sendv(pony_ctx(), ev->owner, &m->msg, &m->msg, false);
}
diff --git i/src/libponyrt/gc/cycle.c w/src/libponyrt/gc/cycle.c
index e289e1c62..90f12f578 100644
--- i/src/libponyrt/gc/cycle.c
+++ w/src/libponyrt/gc/cycle.c
@@ -922,7 +922,7 @@ void ponyint_cycle_block(pony_ctx_t* ctx, pony_actor_t* actor, gc_t* gc)
m->delta = ponyint_gc_delta(gc);
pony_assert(gc->delta == NULL);
- pony_sendv(ctx, cycle_detector, &m->msg, &m->msg);
+ pony_sendv(ctx, cycle_detector, &m->msg, &m->msg, false);
}
void ponyint_cycle_unblock(pony_ctx_t* ctx, pony_actor_t* actor)
diff --git i/src/libponyrt/pony.h w/src/libponyrt/pony.h
index 2a6aa9e60..81c8dbfd3 100644
--- i/src/libponyrt/pony.h
+++ w/src/libponyrt/pony.h
@@ -175,9 +175,11 @@ PONY_API pony_msg_t* pony_alloc_msg_size(size_t size, uint32_t id);
*
* The first and last messages must either be the same message or the two ends
* of a chain built with calls to pony_chain.
+ *
+ * has_app_msg should be true if there are application messages in the chain.
*/
PONY_API void pony_sendv(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
- pony_msg_t* last);
+ pony_msg_t* last, bool has_app_msg);
/** Single producer version of pony_sendv.
*
@@ -188,9 +190,11 @@ PONY_API void pony_sendv(pony_ctx_t* ctx, pony_actor_t* to, pony_msg_t* first,
*
* The first and last messages must either be the same message or the two ends
* of a chain built with calls to pony_chain.
+ *
+ * has_app_msg should be true if there are application messages in the chain.
*/
PONY_API void pony_sendv_single(pony_ctx_t* ctx, pony_actor_t* to,
- pony_msg_t* first, pony_msg_t* last);
+ pony_msg_t* first, pony_msg_t* last, bool has_app_msg);
/** Chain two messages together.
*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment