/* Sun-$Revision: 23.20 $ */
/* Copyright 1992-9 Sun Microsystems, Inc. and Stanford University.
   See the LICENSE file for license information. */
# pragma interface
class codeSlotsMap: public slotsMap {
  // abstract class for objects with code  
 public:
  bool is_method_like()         { return true; }
  oop mirror_names(oop ignored);
  oop  mirror_reflectee(oop r)  {
    Unused(r); return ErrorCodes::vmString_prim_error(REFLECTTYPEERROR); }
  fint arg_count();
};
class oldMapList;
class methodMap: public codeSlotsMap {
  friend slotsOop create_outerMethod(slotList* slots, ByteCode* b,
                                     char* annotation = "",
                                     IntBList* stack_deltas = NULL);
 protected:
  // instance variables
  byteVectorOop    _codes;
  stringOop        _file;
  smiOop           _line;
  stringOop      _source;
  objVectorOop _literals;
 public:
  byteVectorOop   codes() { return    _codes; }
  stringOop        file() { return     _file; }
  smiOop           line() { return     _line; }
  objVectorOop literals() { return _literals; }
  stringOop      source() { return   _source; }
  void setFile(stringOop f) { Memory->store((oop*)&_file, oop(f)); }
  void setLine(smiOop l)    { Memory->store((oop*)&_line, l); }
  virtual methodMap* get_lexical_link_map() = 0;
 protected:
  void setLiterals(objVectorOop lit) {
    Memory->store((oop*)&_literals, lit); }
  void setCodes(byteVectorOop c) {
    Memory->store((oop*)&_codes, c); }
  void setSource(stringOop s)   {
    Memory->store((oop*)&_source, s); }
   
  // functions to implement local access bytecodes
   
  void fix_local_bytecodes_and_links(    oldMapList* old_maps,
                                         slotsOop   outerMethod,
                                         IntBList*  stack_deltas = NULL);
  void fix_local_bytecodes_and_links_of_my_blocks( oldMapList* old_maps,
                                                   slotsOop outerMethod);
  void fix_local_bytecodes_and_links_in_myself(    oldMapList* old_maps,
                                                   slotsOop outerMethod,
                                                   IntBList* stack_deltas);
 public:
  void      GenSendOrLocal( ByteCode* bc,  stringOop sel);
  slotDesc* getLocalSlot( fint lexicalLevel, fint index);
 public:
  bool has_code() { return true; }
  bool hasSubBlocks() {
    for (oop *p= start_literals(), *end= p + length_literals();  p < end;  p++)
      if ((*p)->is_block_with_code())
        return true;
    return false; }
 public:
  u_char* start_codes()  { return (u_char*) _codes->bytes(); }
  fint    length_codes() { return _codes->length();          }
  oop* start_literals()  { return literals()->objs();   }
  fint length_literals() { return literals()->length(); }
  oop mirror_codes(oop r);
  oop mirror_literals(oop r);
  oop mirror_source(oop r);
  oop mirror_file(oop r);
  oop mirror_line(oop r);
  // compiler helper functions
  bool containsBranch();
  bool containsLoop();
  bool containsNLR();
  IntList* accessedSlots(blockMethodMap *bmm);
        // Indices of all slots that could be uplevel-accessed by sends
        // in bmm and subblocks thereof.
 public:
  fint     beginningOfStatement(fint bci);
  IntList* expression_stack(fint bci, bool keepArgs, fint startBCI);
  IntList* expression_stack(fint bci, bool keepArgs) {
    // this used to be:
    
    // if (!keepArgs 
    // && bci+1 < length_codes()
    // && start_codes()[bci+1] == BuildCode(NO_OPERAND_CODE, POP_CODE)) {
    //   // last send in a statement has empty expression stack
    //   return EMPTY;
    // } else {
    //   return expression_stack(bci, keepArgs, beginningOfStatement(bci));
    // } 
    
    // but the then-case fails when the bytecodes do not come from source.
    // So I took it out, which broke Mario's concurrentProgrammingTest
    // but am pressing on for now. -- dmu
    return expression_stack(bci, keepArgs, beginningOfStatement(bci));
    }
  IntList* expression_stack_bcis(bool debugMode);
  IntList* all_blocks(OopList** literals = NULL);
  IntList* blocks_upto(fint bci, OopList** literals = NULL);
    
 public:
  void branch_targets( bool& got_one,  
                       BoolBList** branch_targets,
                       BoolBList** backwards_branch_targets = NULL);
  
  int32 debug_size(oop p);
  
  fint get_index_at(fint byteCodeIndex);
  
  stringOop get_selector_at(fint byteCodeIndex);
  virtual slotDesc* slots() { return (slotDesc*) (this + 1); }
  
  // creation operation
  friend slotsOop basic_create_method(slotList* slots, ByteCode* b,
                                      methodMap &m1, char *annotation,
                                      bool isBlock);
 protected:
  virtual void set_lexical_links( slotsOop   enclosingMethod,
                                  slotsOop       outerMethod,
                                  stringOop  src,
                                  fint       srcOffset,
                                  bool       isOKToBashLiteralVector);
  void set_outer_method_link_in_literals( slotsOop outerMethod);
  
 public:
  // programming
  friend  char* check_byteCodes_and_literals( smi& errorIndex,
                                              IntBList*& stack_deltas,
                                              byteVectorOop codes,
                                              objVectorOop literals );
  
  // used by programming prims to set backpointers
  oop fix_up_method( oop obj,
                     oop old_optimized_method = NULL,
                     bool isOKToBashLiteralVector = false,
                     bool mustAllocate= true,
                     IntBList* stack_deltas = NULL);
  // printing support
  void print_string(oop obj, char* buf);
  void print_oop(oop obj);
  void print_code(oop obj);
  virtual void print_source();
  void print_byteCode_at(fint byteCodeIndex);
  bool verify(oop obj);
};
class outerMethodMap: public methodMap {
 public:
  friend slotsOop create_outerMethod(slotList* slots, ByteCode* b,
                                     char* annotation,
                                     IntBList* stack_deltas);
  MethodKind kind()             { return OuterMethodType; }
  mirrorOop mirror_proto()      { return Memory->outerMethodMirrorObj; }
  oop mirror_source_offset(oop r) { Unused(r); return smiOop_zero; }
  oop mirror_source_length(oop r) { Unused(r); return smiOop_zero; }
  bool verify(oop obj);
  methodMap* get_lexical_link_map() { return NULL; }
};
class blockMethodMap: public methodMap {
  friend slotsOop basic_create_method(slotList* slots,
                                      ByteCode* b,
                                      methodMap &m1,
                                      char* annotation,
                                      bool isBlock);
  friend class methodMap;
 public: // needs to be public for MW
  smiOop _sourceOffset, _sourceLen;
 protected:
  void set_lexical_links( slotsOop   enclosingMethod,
                          slotsOop       outerMethod,
                          stringOop  src,
                          fint       srcOffset,
                          bool       isOKToBashLiteralVector);
  slotsOop set_lexical_link( slotsOop block_meth, slotsOop enclosing_meth);
  
 public:
  slotDesc* slots() { return (slotDesc*) (this + 1); }
  oop mirror_source_offset(oop r) { Unused(r);  return _sourceOffset; }
  oop mirror_source_length(oop r) { Unused(r);  return _sourceLen; }
  friend slotsOop create_blockMethod(slotList* slots, ByteCode* b,
                                     char* annotation = "",
                                     IntBList* stack_deltas = NULL);
  friend slotsOop basic_create_method(slotList* slots, ByteCode* b,
                                      methodMap* m1, char* annotation,
                                      bool isBlock);
  MethodKind kind()             { return BlockMethodType; }
  mirrorOop mirror_proto()      { return Memory->blockMethodMirrorObj; }
  oop mirror_parent(oop obj);
  void print_source();
  bool verify(oop obj);
  methodMap* get_lexical_link_map();
  slotsOop   get_lexical_link();
  
  // compiler helper
  // return list of indices of slots in parentMap up-level accessed by me
  IntList* uplevel_accessed_slots(methodMap* parentMap);
};