Skip to content

Commit

Permalink
Merge branch 'sverk/hipe-wrap-bif-disable-gc-fixes/OTP-12231' into maint
Browse files Browse the repository at this point in the history
* sverk/hipe-wrap-bif-disable-gc-fixes/OTP-12231:
  erts: Fix bug when hipe tailcalls trapping BIF that disables GC
  erts: Fix hipe bug when gc-disabling bif traps with gc enabled
  • Loading branch information
sverker committed Oct 24, 2014
2 parents 9f0477e + bc59e9a commit a70f0ce
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
20 changes: 14 additions & 6 deletions erts/emulator/hipe/hipe_mode_switch.c
Expand Up @@ -2,7 +2,7 @@
* %CopyrightBegin%
*
* Copyright Ericsson AB 2001-2013. All Rights Reserved.
* Copyright Ericsson AB 2001-2014. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
Expand Down Expand Up @@ -187,6 +187,9 @@ void hipe_set_call_trap(Uint *bfun, void *nfun, int is_closure)

void hipe_reserve_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
{
if (!hipe_bifcall_from_native_is_recursive(p))
return;

/* ensure that at least 2 words are available on the BEAM stack */
if ((p->stop - 2) < p->htop) {
DPRINTF("calling gc to reserve BEAM stack size");
Expand All @@ -195,38 +198,43 @@ void hipe_reserve_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
}
p->stop -= 2;
p->stop[0] = NIL;
p->stop[1] = NIL;
p->stop[1] = hipe_beam_catch_throw;
}

static __inline__ void
hipe_push_beam_trap_frame(Process *p, Eterm reg[], unsigned arity)
{
if (p->flags & F_DISABLE_GC) {
if (&p->stop[1] < p->hend && p->stop[1] == hipe_beam_catch_throw) {
/* Trap frame already reserved */
ASSERT(p->stop[0] == NIL && p->stop[1] == NIL);
ASSERT(p->stop[0] == NIL);
}
else {
ASSERT(!(p->flags & F_DISABLE_GC));
if ((p->stop - 2) < p->htop) {
DPRINTF("calling gc to increase BEAM stack size");
p->fcalls -= erts_garbage_collect(p, 2, reg, arity);
ASSERT(!((p->stop - 2) < p->htop));
}
p->stop -= 2;
p->stop[1] = hipe_beam_catch_throw;
}
p->stop[1] = hipe_beam_catch_throw;
p->stop[0] = make_cp(p->cp);
++p->catches;
p->cp = hipe_beam_pc_return;
}

void hipe_unreserve_beam_trap_frame(Process *p)
{
ASSERT(p->stop[0] == NIL && p->stop[1] == NIL);
if (!hipe_bifcall_from_native_is_recursive(p))
return;

ASSERT(p->stop[0] == NIL && p->stop[1] == hipe_beam_catch_throw);
p->stop += 2;
}

static __inline__ void hipe_pop_beam_trap_frame(Process *p)
{
ASSERT(p->stop[1] == hipe_beam_catch_throw);
p->cp = cp_val(p->stop[0]);
--p->catches;
p->stop += 2;
Expand Down
8 changes: 8 additions & 0 deletions erts/emulator/hipe/hipe_risc_glue.h
Expand Up @@ -214,6 +214,14 @@ hipe_trap_from_native_is_recursive(Process *p)
return 0;
}

/* Native called BIF. Is it a recursive call?
i.e should we return back to native when BIF is done? */
static __inline__ int
hipe_bifcall_from_native_is_recursive(Process *p)
{
return (p->hipe.nra != (void(*)(void))&nbif_return);
}


/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
Expand Down
8 changes: 8 additions & 0 deletions erts/emulator/hipe/hipe_x86_glue.h
Expand Up @@ -207,6 +207,14 @@ hipe_trap_from_native_is_recursive(Process *p)
return 0;
}

/* Native called BIF. Is it a recursive call?
i.e should we return back to native when BIF is done? */
static __inline__ int
hipe_bifcall_from_native_is_recursive(Process *p)
{
return (*p->hipe.nsp != (Eterm)nbif_return);
}


/* Native makes a call which needs to unload the parameters.
This differs from hipe_call_from_native_is_recursive() in
Expand Down

0 comments on commit a70f0ce

Please sign in to comment.