// DeferredSend.h -- out-of-line message sends
//
// Author: Ian.Piumarta@INRIA.Fr
// 
// Last edited: Sat Dec 25 16:31:52 1999 by piumarta (Ian Piumarta) on aria

#ifndef _j_DeferredSend_h
#define _j_DeferredSend_h



// maximum number of deferred sends per method
#define MAX_DEFERRED	1024


class DeferredSend
{
public:

  insn *entryIP;
  insn *resumeIP;
  insn *sendSiteIP;
  int index;
  Descriptor receiver;
  Descriptor argument;

  DeferredSend(void) {}

  inline void init(int si, const Descriptor &r, const Descriptor &a, insn *entry)
    {
      entryIP= entry;
      resumeIP= 0;
      sendSiteIP= entry;
      index= si;
      receiver= r;
      argument= a;
    }

  inline void resume(int pass)
    {
      printf("#%d: resume %p %p = %p\n", pass, this, resumeIP, asm_pc);
      if (pass == 1) {
	resumeIP= asm_pc;
      } else {
	assert(resumeIP == asm_pc);
      }
    }

  inline insn *enter(void)
    {
      printf("#?: entry %p -> %p\n", this, entryIP);
      return entryIP;
    }

  void generate(int pass)
    {
      printf("#%d: generate %p @ %p\n", pass, this, asm_pc);
      if (pass == 1) {
	entryIP= asm_pc;
      } else {
	assert(entryIP == asm_pc);
      }
      flush(receiver);
      flush(argument);
      emit_lcall_l(sendSiteIP, resumeIP,
		   g_SpecialUnlinked, (DeferredBit | (index << 8) | 1));
      if (pass == 1) {
	sendSiteIP= asm_pc;
      } else {
	assert(sendSiteIP == asm_pc);
      }
    }

  inline char *printString(void)
    {
      static char buf[256];
      sprintf(buf, "DB=%p{%d(%s %s) -> %p -> %p}",
	      this, index, receiver.printString(), argument.printString(),
	      entryIP, resumeIP);
      return buf;
    }

  // class variables and methods

  static DefferedSend[MAX_DEFERRED];
  static size_t deferredSendCount;

  inline static void reset(void)
    {
      deferredSendCount= 0;
    }

  inline static DeferredSend &allocate(int selIndex, int pass)
    {
      assert(deferredSendCount < MAX_DEFERRED);
      DeferredSend &ds= deferredSends[deferredSendCount++];
      if (pass == 1)
	{
	  ds.init(selIndex, stackDescriptor(1), stackDescriptor(0), asm_pc);
	  printf("#%d: allocDB ->%s\n", pass, db.printString());
	}
      else
	{
	  printf("#%d: allocDB -> %s\n", pass, db.printString());
	  assert(db.index == selIndex);
	}
      return ds;
    }
};


static DeferredSend DeferredSend::deferredSends[MAX_DEFERRED];
static size_t DeferredSend::deferredSendCount= 0;



#endif // _j_DeferredSend_h
