Main Page   Class Hierarchy   Compound List   File List   Header Files   Compound Members   File Members  

interpreter.h

This is the verbatim text of the interpreter.h include file.
/* Sun-$Revision: 23.11 $ */

/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
   See the LICENSE file for license information. */

# pragma interface

extern oop sneaky_method_argument_to_interpret;


extern "C" {
  oop interpret( oop rcv,
                 oop sel,
                 oop del,
                 oop meth,
                 oop _mh,
                 oop* _args,
                 int32 _nargs );
  oop interpret_from_compiled_sender();
}


enum ReturnPatchReason { not_patched, patched_for_profiling, patched };

class interpreter: public abstract_interpreter {
  friend class interpreted_vframe; // needs mi.literals, etc
  friend class InterpreterIterator;

 public:
  // WARNING all oops here must appear in ITERATOR below
  oop receiver;
  // next 2 are not redundant because of performs:
  oop selector;
  oop delegatee;
  oop method_object; 
  
 protected:
  oop _methodHolder;
  
 public:
  oop* args;
  int32 length_args;

  oop* locals;
  int32 _length_locals;
  int32 minOffset;
  bool hasParentLocalSlot;
  oop* cloned_blocks; // NULL or cloned block
  oop* stack;
  int32 sp;
  oop self;

  // put next two in here instead of locals so that
  //  they will get scavenged; they have to survive a send
  //  when a prim fails
        oop rcvToSend;
  oop       selToSend; // could be anything if a perform
  int32     arg_count; // for the send, not for me
  
  // unlilke compiled frames, cannot patch the return address
  //  because that would lose the call used to verify that this is
  //  an interpreted frame. Instead, save the address that WOULD
  //  be installed here, and check it upon return.

  ReturnPatchReason  return_patch_reason;
  bool               restartSend;
  
  interpreter* parentI; // interp of lexical parent or NULL
  
 protected:
   frame* _block_scope_or_NLR_target;
   
   inline frame* block_scope_or_NLR_target();

 public:
  interpreter( oop rcv,
               oop sel,
               oop del,
               oop meth,
               oop _mh,
               oop* _args,
               int32 _nargs);

  oop top() { return stack[sp-1]; }
  
  inline int32 length_cloned_blocks();
  inline void     set_cloned_blocks(void* p);

  inline int32    length_stack() { return mi.length_codes; }
  inline void     set_stack(void* p);

  inline int32 length_locals() { return _length_locals; }
  inline void  set_locals(void* p);

               
  PrimDesc* current_primDesc; // for stack walking
  
  PrimDesc* getPrimDesc() { return current_primDesc; } 

  void set_restartSend(bool b) {restartSend = b;}
  
  void interpret_method();
  
  oop methodHolder() {
    assert( ! _methodHolder->is_map(), "interp mh always object");
    return _methodHolder;
  }
  
  void set_methodHolder(oop mh) { _methodHolder= mh; }

  // frame oop iterators need this one (via INTERPRETER_ITERATOR below):

  oop* methodHolder_addr() { return &_methodHolder; }
  
  abstract_vframe* parentVF();
  
 protected: 
 
  void do_SELF_CODE();
  void do_POP_CODE();
  void do_NONLOCAL_RETURN_CODE();
  void do_literal_code(oop lit);
  void do_read_write_local_code(bool isWrite);
  void do_send_code(bool isSelfImplicit, stringOop selector);
  
  void do_branch_code( int32 target_PC, oop target_oop = badOop );
  void do_BRANCH_INDEXED_CODE();

  
  
 public:
  void send( LookupType, oop delegatee );
  oop lookup_and_send( LookupType,
                       oop mh,
                       oop delegatee);
                      
  oop send_prim( );
  
 public:
  oop try_perform_prim( bool hasFailBlock,
                        bool& is_perform );

  oop  get_slot(slotDesc* sd);
  void set_slot(slotDesc* sd, oop x);

  
 protected:
 
  fint return_pc()  { return mi.length_codes - 1; }
  fint restart_pc() { return mi.length_codes;     }
  void local_slot_desc(interpreter*& interp, abstract_vframe*& vf, slotDesc*& sd);
  void block_scope_and_desc_of_home( frame*& block_scope_frame, int32& block_desc);


  
 public:
  bool is_return_patched() { return return_patch_reason != not_patched; }
  void patch_return(ReturnPatchReason x) { return_patch_reason = x; }
  ReturnPatchReason get_return_patch_reason() { 
    return return_patch_reason; }
    
  void print();

 public: // should be prot but friend doesn't work
  void setup_for_method( );
  void setup_for_block(  );
 protected:
  void start_NLR(oop res);
  void continue_NLR();
};

extern void InterpreterLookup_cont( simpleLookup *L, int32 arg_count);



// for scavenging, see frame.c
// Don't do:
//    for (p = is->args;  p < &is->args[is->length_args];  p++) { template; }
// because when args are passed from interpreter, they are iterated
// in its stack anyway. This means that non-interp calling interp
// must arrange to scavenge, etc the top-level args.

# define INTERPRETER_ITERATOR(interp, template, zap, reinit) \
  { \
    ABSTRACT_INTERPRETER_ITERATOR(interp, template, zap, reinit) \
    \
    oop* p; \
    \
    p =       &(interp)->receiver;      template; \
    p = (oop*)&(interp)->selector;      template; \
    p = (oop*)&(interp)->delegatee;     template; \
    p = (oop*)&(interp)->method_object; template; \
    p =       &(interp)->self;          template; \
    p = (interp)->methodHolder_addr();  template; \
    \
    for ( p =  (interp)->locals;  \
          p < &(interp)->locals[(interp)->length_locals()]; \
        ++p) { \
      template; \
    } \
    for ( p = (interp)->cloned_blocks;  \
          p < &(interp)->cloned_blocks[(interp)->mi.length_literals]; \
        ++p) { \
      if (*p != NULL) { template; }  \
    } \
    for (p = (interp)->stack;  p < &(interp)->stack[(interp)->sp];  p++) { \
      template; \
    } \
    if (zap) for ( ; p < &(interp)->stack[(interp)->length_stack()]; p++) { \
      *p = badOop; \
    } \
    p =       &(interp)->rcvToSend;  template; \
    p = (oop*)&(interp)->selToSend;  template; \
  } 
  
  
// new style:

class InterpreterIterator: public StackObj {
 private:
  interpreter* interp;
  OopClosure* oop_closure;
  bool zap;
  bool reinit;
  
 public:
  InterpreterIterator(interpreter* i, OopClosure* oc, bool z, bool r) {
    interp = i;  oop_closure = oc;  zap = z;  reinit = r;
    do_all();
  }
 private:
  void do_all() {
    ABSTRACT_INTERPRETER_ITERATOR(interp, oop_closure->do_oop(p), zap, reinit) 
    
    oop* p; 
    
    p =       &(interp)->receiver;             oop_closure->do_oop(p); 
    p = (oop*)&(interp)->selector;             oop_closure->do_oop(p); 
    p = (oop*)&(interp)->delegatee;            oop_closure->do_oop(p); 
    p = (oop*)&(interp)->method_object;        oop_closure->do_oop(p); 
    p =       &(interp)->self;                 oop_closure->do_oop(p); 
    p =        (interp)->methodHolder_addr();  oop_closure->do_oop(p);
    
    for ( p =  (interp)->locals;  
          p < &(interp)->locals[(interp)->length_locals()]; 
        ++p) { 
      oop_closure->do_oop(p); 
    }
    for ( p = (interp)->cloned_blocks;   
          p < &(interp)->cloned_blocks[(interp)->mi.length_literals];
        ++p) { 
      if (*p != NULL) { oop_closure->do_oop(p); } 
    }
    for (p = (interp)->stack;  p < &(interp)->stack[(interp)->sp];  p++) { 
      oop_closure->do_oop(p);
    } 
    if (zap) for ( ; p < &(interp)->stack[(interp)->length_stack()]; p++) { 
      *p = badOop;
    }
    p =       &(interp)->rcvToSend;  oop_closure->do_oop(p);
    p = (oop*)&(interp)->selToSend;  oop_closure->do_oop(p);
  }
};  
    

Generated at Tue Jun 27 12:07:42 2000 for SelfVM by doxygen 1.0.0 written by Dimitri van Heesch, © 1997-1999