// RelinkCache.h -- relink cache
// 
// Author: Ian.Piumarta@INRIA.Fr
// 
// Last edited: Sat Jan  1 18:01:47 2000 by piumarta (Ian Piumarta) on pingu


#ifndef _j_RelinkCache_h
#define _j_RelinkCache_h


#include "archdep.h"
#include "Memoizer.h"
#include "NativeMethod.h"


// Size of relink cache.  Must be a power of 2.  Never purged: make it
// as large as you like.

static const size_t RelinkCacheSize=  4096;
static const size_t RelinkCacheMask=  RelinkCacheSize - 1;


class RelinkCache
{
private:
  MemoIndex	 classIndex;
  NativeMethod	*method;
  insn		*entry;
  unsigned 	 cacheArgument;

  static RelinkCache line[];

  static inline size_t hash(const MemoIndex ci, const MemoIndex mi)
    {
      return (ci.hash() ^ mi.hash());
    }

  inline void init(MemoIndex ci, NativeMethod *nm, insn *pc, unsigned arg)
    {
      assert((classIndex != ci) || (entry != pc) || (cacheArgument != arg));
      classIndex= ci;
      method= nm;
      entry= pc;
      cacheArgument= arg;
    }

  inline insn *probe(const MemoIndex ci, const MemoIndex mi,
		     NativeMethod *&nm, unsigned &arg) const
    {
      if ((classIndex == ci) && (method->methodIndex == mi))
	{
	  nm= method;
	  arg= cacheArgument;
	  return entry;
	}
      return 0;
    }

public:

  static void initialise(void);

  inline static insn *lookup(const MemoIndex ci, const MemoIndex mi,
			     NativeMethod *&nm, unsigned &arg)
    {
      return line[hash(ci, mi) & RelinkCacheMask].probe(ci, mi, nm, arg);
    }

  inline static void add(MemoIndex ci, NativeMethod *nm, insn *pc, unsigned arg)
    {
      MemoIndex mi= nm->methodIndex;
      line[hash(ci, mi) & RelinkCacheMask].init(ci, nm, pc, arg);
    }
};


#endif // _j_RelinkCache_h
