// primExtern.cc -- snapshot and external (named) primitives
// 
// Author: Ian.Piumarta@INRIA.Fr
// 
// Last edited: 2000-11-20 13:32:34 by piumarta on emilia.rd.wdi.disney.com

#define EXT_PRIMITIVES_BUGFIX

#include "debug.h"
#include "archdep.h"
#include "generate.h"
#include "machine.h"
#include "primitive.h"

#include "Frame.h"

#ifndef __macintosh__
#include <unistd.h>
#endif


extern "C" { void primitiveSnapshot(void); }

//  activeContext instructionPointer
extern void j_primitiveSnapshot(NativeMethod *nMeth, Frame *sender)
{
  // nothing to do: snapshot is handled in pre/postSnapshotHook().
  //fatal("unimplemented");
  primitiveSnapshot();
}



extern "C" { void primitiveExternalCall(void); }

//  newMethod
extern void j_primitiveExternalCall(NativeMethod *nMeth, Frame *sender)
{
  // we'll just set ALL of the environment that we know how to set,
  // since external primitives can get at almost anything through
  // their VM proxy...
  newMethod= nMeth->compiledMethod();
  assert(argumentCount == (int)nMeth->argumentCount);
  assert(primitiveIndex == (int)nMeth->primitiveIndex);
  assert(activeFrame == sender);

#ifdef NEW_PRIMITIVES_TRACE
  printf("  -> ");
  ((String *)(nMeth->compiledMethod()->literals(0)->asArray()->at(0)))->print();
  printf("::");
  ((String *)(nMeth->compiledMethod()->literals(0)->asArray()->at(1)))->print();
  printf("\n");
#endif // NEW_PRIMITIVES

  PRINTF(("primitiveExternalCall...\n"));
  PRINTLN(nMeth);

#ifdef EXT_PRIMITIVES_BUGFIX
  static oop *oldSP= 0;
  oldSP= stackPointer;
#endif

  primitiveExternalCall();

#ifdef EXT_PRIMITIVES_BUGFIX
  if (successFlag && (stackPointer != (oldSP - nMeth->argumentCount)))
    {
#    if 0
      int nPopped= oldSP - stackPointer;
      printf("BAD SP IN ");
      nMeth->print();
      printf(" [%d popped, should be %d]\n", nPopped, nMeth->argumentCount);
#    endif
      oop result= *stackPointer;
      stackPointer= oldSP - nMeth->argumentCount;
      *stackPointer= result;
    }
#endif

  PRINTF(("...done\n"));
}


extern "C" { void primitiveObsoleteIndexedPrimitive(void); }

//  newMethod
extern void j_primitiveObsoleteIndexedPrimitive(NativeMethod *nMeth, Frame *sender)
{
  // we'll just set ALL of the environment that we know how to set,
  // since external primitives can get at almost anything through
  // their VM proxy...
  newMethod= nMeth->compiledMethod();
  argumentCount == (int)nMeth->argumentCount;
  primitiveIndex == (int)nMeth->primitiveIndex;
  assert(activeFrame == sender);
  PRINTF(("primitiveObsoleteIndexedPrimitive...\n"));
  PRINTLN(nMeth);
  primitiveObsoleteIndexedPrimitive();
  PRINTF(("...done\n"));
}

