Logo Search packages:      
Sourcecode: helium version File versions  Download package

stack.c

/*-----------------------------------------------------------------------
  The Lazy Virtual Machine.

  Daan Leijen.

  Copyright 2001, Daan Leijen. All rights reserved. This file is
  distributed under the terms of the GNU Library General Public License.
-----------------------------------------------------------------------*/

/* $Id: stack.c 127 2002-07-25 22:06:02Z cvs-3 $ */

#include <string.h>
#include "mlvalues.h"
#include "alloc.h"
#include "fail.h"
#include "heap/heap.h"
#include "thread.h"

/*----------------------------------------------------------------------
  lazy black holing
  walk through all the frames on the stack and blackhole all AP nodes.
----------------------------------------------------------------------*/
void lazy_blackhole( value* fp )
{
  while(1)
  {
    switch(Frame_frame(fp)) {
    case frame_update: {
      value upd = Frame_value(fp);
      tag_t tag = Tag_val(upd);
      Assert( Is_block(upd) );
      if (tag == Ap_tag) {
        wsize_t i;
        Tag_val(upd) = Inv_tag;
        for (i = 0; i < Wosize_val(upd); i++) { Store_field_inv( upd, i ); }
      }
      else if (tag == Caf_tag) {
        Tag_val(upd) = Inv_tag;
      }
      else {
        Assert( tag == Inv_tag );
      }
      break;
    }
    case frame_catch:
    case frame_cont:
      break;
    case frame_stop:
      return;
    default:
      raise_internal( "invalid stack frame during black holing" );
    }

    fp = Frame_next(fp);
  }
}


/*----------------------------------------------------------------------
   recover from exceptions
   semisynchronous  == heap_overflow, no suspension and no update
----------------------------------------------------------------------*/
value* recover_semi_synchronous( value* fp )
{
  while(1) {
    switch(Frame_frame(fp)) {
    case frame_update:
    case frame_cont:
      break;
    default:
      return fp;
    }
    fp = Frame_next(fp);
  }
}

value* recover_synchronous( value* fp, value exn )
{
  while(1) {
    switch(Frame_frame(fp)) {
    case frame_update: {
      value upd = Frame_value(fp);
      Assert(Is_heap_val(upd) && Wosize_val(upd) > 0);
      if (Tag_val(upd) != Raise_tag) {
        wsize_t i;
        Tag_val(upd) = Raise_tag;
        Store_field(upd,0,exn);
        for (i = 1; i < Wosize_val(upd); i++) { Store_field_inv(upd,i); }
      }
      break;
    }
    case frame_cont:
      break;
    default:
      return fp;
    }
    fp = Frame_next(fp);
  }
}

static value alloc_suspension( value* sp, wsize_t ssize, long base, long top )
{
  CAMLparam0();
  CAMLlocal1(susp);

  wsize_t size = ssize + Susp_info_wosize;
  wsize_t i;

  /* allocate a new suspension */
  if (size >  Max_young_wosize) susp = alloc_shr(size,Suspend_tag);
                         else   susp = alloc_small(size,Suspend_tag);
  Init_field(susp,Field_susp_base,Val_long(base));
  Init_field(susp,Field_susp_top,Val_long(top));
  if (size >  Max_young_wosize) {
    for( i = 0; i < ssize; i++ ) { Init_field(susp,i+Susp_info_wosize,sp[i]); }
  } else {
    for( i = 0; i < ssize; i++ ) { Field(susp,i+Susp_info_wosize) = sp[i]; }
  }

  CAMLreturn(susp);
}

value* recover_asynchronous( value* fp, value* sp )
{
  CAMLparam0();
  CAMLlocal2(susp,upd);

  while(1) {
    long base;
    long top;

    top   = -1;
    base  = fp - sp;
    Assert( base > 0 );

    /* ignore continuation frames */
    while(Frame_frame(fp) == frame_cont) {
      fp = Frame_next(fp);
    }

    top = fp - sp;

    /* create a suspension if we hit an update frame */
    if(Frame_frame(fp) == frame_update) {
      /* update with a suspension */
      susp = alloc_suspension( sp, fp - sp + Frame_size, base, top );
      upd  = Frame_value(fp);
      indirect(upd,susp);

      /* cut the stack & push the suspension
         this will change the stack but everything is still GC-safe and
         the stack is always cut at the catch or stop frame */
      sp = fp + Frame_size - 1;
      fp = Frame_next(fp);
      sp[0] = susp;
    }
    else {
      CAMLreturn(fp);
    }
  }
}

Generated by  Doxygen 1.6.0   Back to index