<commit_before>/******************************************************************************
 *  Copyright (c) 2008 - 2010 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *    <NAME>, IBM Research - Initial Implementation
 *    <NAME>, IBM Research - Initial Implementation
 *    <NAME>, <NAME> - Port to x86 Multi-Core Systems
 ******************************************************************************/


inline void Object::set_object_address_and_backpointer(Oop x  COMMA_DCL_ESB) {
  Safepoint_for_moving_objects::assert_held();
  The_Memory_System()->object_table->set_object_for(x, (Object_p)this  COMMA_USE_ESB);
  set_backpointer(x);
}




inline void Object::set_class_oop(Oop x) {
  The_Memory_System()->store_enforcing_coherence(&class_and_type_word(),
                                              Header_Type::extract_from(class_and_type_word())
                                              |  Header_Type::without_type(x.bits()),
                                              (Object_p)this);
}

inline void Object::set_class_oop_no_barrier(Oop x) {
  class_and_type_word() = Header_Type::extract_from(class_and_type_word())
                       |  Header_Type::without_type(x.bits());
}

inline void Object::  mark_without_store_barrier() { baseHeader |=  MarkBit; }
inline void Object::unmark_without_store_barrier() { baseHeader &= ~MarkBit; }



inline void Object::set_backpointer_word(oop_int_t w) {
  oop_int_t* dst = backpointer_word();
  The_Memory_System()->store_enforcing_coherence(dst, w, (Object_p)this);
}

inline void Object::set_extra_preheader_word(oop_int_t w) {
  assert_always(w); // bug hunt qqq
  oop_int_t* dst = extra_preheader_word();
  The_Memory_System()->store_enforcing_coherence(dst, w, (Object_p)this);
}

inline bool Object::hasSender(Oop aContext) {
  // rcvr must be a context
  Object_p aco = aContext.as_object();
  if (this == &(*aco))  return false;
  Oop nilOop = The_Squeak_Interpreter()->roots.nilObj;
  for (Oop s = fetchPointer(Object_Indices::SenderIndex);
       s != nilOop;
       s = s.as_object()->fetchPointer(Object_Indices::SenderIndex))
    if (s == aContext)  return true;
  return false;
}



inline oop_int_t Object::fetchInteger(oop_int_t fieldIndex) {
  Oop x = fetchPointer(fieldIndex);
  return x.checkedIntegerValue();
}

inline oop_int_t Object::fetchStackPointer() { // rcvr is a ContextObject
  Oop sp = fetchPointer(Object_Indices::StackPointerIndex);
  return sp.is_int() ? sp.integerValue() : 0;
}


inline u_oop_int_t Object::fixedFieldsOfArray() {
  /* "NOTE: This code supports the backward-compatible extension to 8 bits of instSize.
   When we revise the image format, it should become...
   ^ (classFormat >> 2 bitAnd: 16rFF) - 1 */

  oop_int_t fmt = format();
  return
  Format::has_only_indexable_fields(fmt)
  ?  0 :
  Format::has_only_fixed_fields(fmt)
  ? lengthOf()  :  // "fixed fields only (zero or more)"
  // "fmt = 3 or 4: mixture of fixed and indexable fields, so must look at class format word"
  ClassFormat::fixedFields(fetchClass().as_object()->formatOfClass());
}


inline u_oop_int_t Object::lengthOf() {
  // Return the number of indexable bytes or words in the given object. Assume the given oop is not an integer. For a CompiledMethod, the size of the method header (in bytes) should be subtracted from the result of this method."
  u_oop_int_t sz = sizeBits();
  if (Size4Bit) sz -= baseHeader & Size4Bit;
  sz -= BaseHeaderSize;
  oop_int_t fmt = format();
  return  fmt <= Format::both_fixed_and_indexable_weak_fields
  ?  sz >> ShiftForWord // words
  :  fmt <= Format::indexable_long_fields_only
  ?  sz >> 2 // 32-bit longs
  :  sz - (fmt & Format::byte_size_bits); // bytes
}


inline Oop Object::fetchClass() {
  oop_int_t ccIndex = compact_class_index();
  return ccIndex == 0  ?  get_class_oop()
  :  The_Squeak_Interpreter()->splObj(Special_Indices::CompactClasses).as_object()->fetchPointer(ccIndex - 1);
}


inline oop_int_t Object::lastPointer() {
  /*
   "Return the byte offset of the last pointer field of the given object.
   Works with CompiledMethods, as well as ordinary objects.
   Can be used even when the type bits are not correct."
   */
  int fmt = format();
  // ordered this way for optimization
  if (Format::has_only_oops(fmt)) {
    if (Format::might_be_context(fmt) && hasContextHeader())
      return  (Object_Indices::CtextTempFrameStart + fetchStackPointer()) * bytesPerWord;

    return  sizeBitsSafe() - sizeof(Oop);
  }
  if (Format::has_no_oops(fmt))
    return  0;
  if (Format::isCompiledMethod(fmt))
    return  literalCount() * bytesPerWord  +  BaseHeaderSize;

  fatal("should not be here");  return 0;
}


inline char* Object::first_byte_address() {
  if (isFreeObject()) return NULL;
  int32 fmt = format();
  if (!Format::has_bytes(fmt)) return NULL;
  return  first_byte_address_after_header()
  + (Format::isCompiledMethod(fmt)
     ? (Object_Indices::LiteralStart + literalCount()) * bytesPerWord
     : 0);
}

inline char* Object::first_byte_address_after_header() { return as_char_p() + BaseHeaderSize; }

inline oop_int_t Object::methodHeader() { return fetchPointer(Object_Indices::HeaderIndex).bits(); }

inline void Object::byteSwapIfByteObject() {
  char* b = first_byte_address();
  if (b == NULL) return;
  reverseBytes((int32*)b, (int32*)nextChunk());
  // no store barrier, only for reading snapshots
}

inline oop_int_t Object::total_byte_size() {
  oop_int_t r = bytes_to_next_chunk() + extra_header_bytes();
  if (check_many_assertions) assert(!(r & (sizeof(oop_int_t) - 1)));
  return r;
}

inline oop_int_t Object::total_byte_size_without_preheader() {
  return bytes_to_next_chunk() + extra_header_bytes_without_preheader();
}

inline oop_int_t Object::sizeBits() {
  // "Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."
  // "Note: byte indexable objects need to have low bits subtracted from this size."
  if (check_many_assertions) assert_always(!isFreeObject());
  oop_int_t r =  contains_sizeHeader()
  ?  longSizeBits()
  :  shortSizeBits();
  if (check_many_assertions) assert_always((size_t)r >= sizeof(baseHeader));
  return r;
}
inline oop_int_t Object::sizeBitsSafe() {
  // "Compute the size of the given object from the cc and size fields in its header. This works even if its type bits are not correct."
  oop_int_t header = baseHeader;
  return rightType(header) ==  Header_Type::SizeAndClass
  ?  Header_Type::without_type(sizeHeader())
  :  shortSizeBits();
}

inline oop_int_t Object::stSize() {
  // return number of indexable fields in given object, e.g. ST size
  return Format::might_be_context(format()) && hasContextHeader()
  ? fetchStackPointer()
  : lengthOf() - fixedFieldsOfArray();
}

inline int Object::rightType(oop_int_t headerWord) {
  // "Compute the correct header type for an object based on the size and compact class fields of the given base header word, rather than its type bits. This is used during marking, when the header type bits are used to record the state of tracing."
  if (!(headerWord & SizeMask        ))       return Header_Type::SizeAndClass;
  if (!(headerWord & CompactClassMask))  return Header_Type::Class;
  return Header_Type::Short;
}

inline void* Object::arrayValue() {
  return isWordsOrBytes() ? as_char_p() + BaseHeaderSize : (char*)(The_Squeak_Interpreter()->primitiveFail(), 0);
}


inline oop_int_t Object::formatOfClass() {
  /* "**should be in-lined**"
   "Note that, in Smalltalk, the instSpec will be equal to the inst spec
   part of the base header of an instance (without hdr type) shifted left 1.
   In this way, apart from the smallInt bit, the bits
   are just where you want them for the first header word."
   "Callers expect low 2 bits (header type) to be zero!"*/
  return fetchPointer(Object_Indices::InstanceSpecificationIndex).bits() & ~Int_Tag;
}

inline oop_int_t Object::quickFetchInteger(oop_int_t fieldIndex) { return fetchPointer(fieldIndex).integerValue(); }

inline oop_int_t Object::fetchLong32Length() {
  // Gives size appropriate for fetchLong32
  return (sizeBits() - BaseHeaderSize) >> 2;
}


inline u_char& Object::byte_at(oop_int_t byteIndex) { return as_u_char_p()[BaseHeaderSize + byteIndex]; }
inline u_char  Object::fetchByte(oop_int_t byteIndex) { return byte_at(byteIndex); }
inline void    Object::storeByte( oop_int_t byteIndex, u_char valueByte) {
  The_Memory_System()->store_enforcing_coherence(&byte_at(byteIndex), valueByte, (Object_p)this); // used in interpreter, mostly for new objects
}


inline Oop& Object::pointer_at(oop_int_t fieldIndex) {
  return as_oop_p()[BaseHeaderSize / sizeof(Oop)  +  fieldIndex];
}
inline Oop  Object::fetchPointer(oop_int_t fieldIndex) {
  Oop r;
  MEASURE(fetch_pointer, r.bits(), r = pointer_at(fieldIndex));
  return r;
}


inline void Object::catch_stores_of_method_in_home_ctxs(Oop* addr, int n,  Oop x) {
# if Extra_OTE_Words_for_Debugging_Block_Context_Method_Change_Bug
  if (n != Object_Indices::MethodIndex)  return;
  if (get_count_of_blocks_homed_to_this_method_ctx() <= 0)   return;
  lprintf("caught storePointer of method in Oop 0x%x, changing method 0x%x to 0x%x\n",
          as_oop().bits(), fetchPointer(Object_Indices::MethodIndex).bits(), x.bits());
# endif
}
<commit_msg>Added an assertion fieldIndex to be always >= 0.<commit_after>/******************************************************************************
 *  Copyright (c) 2008 - 2010 IBM Corporation and others.
 *  All rights reserved. This program and the accompanying materials
 *  are made available under the terms of the Eclipse Public License v1.0
 *  which accompanies this distribution, and is available at
 *  http://www.eclipse.org/legal/epl-v10.html
 * 
 *  Contributors:
 *    <NAME>, IBM Research - Initial Implementation
 *    <NAME>, IBM Research - Initial Implementation
 *    <NAME>, <NAME> - Port to x86 Multi-Core Systems
 ******************************************************************************/


inline void Object::set_object_address_and_backpointer(Oop x  COMMA_DCL_ESB) {
  Safepoint_for_moving_objects::assert_held();
  The_Memory_System()->object_table->set_object_for(x, (Object_p)this  COMMA_USE_ESB);
  set_backpointer(x);
}




inline void Object::set_class_oop(Oop x) {
  The_Memory_System()->store_enforcing_coherence(&class_and_type_word(),
                                              Header_Type::extract_from(class_and_type_word())
                                              |  Header_Type::without_type(x.bits()),
                                              (Object_p)this);
}

inline void Object::set_class_oop_no_barrier(Oop x) {
  class_and_type_word() = Header_Type::extract_from(class_and_type_word())
                       |  Header_Type::without_type(x.bits());
}

inline void Object::  mark_without_store_barrier() { baseHeader |=  MarkBit; }
inline void Object::unmark_without_store_barrier() { baseHeader &= ~MarkBit; }



inline void Object::set_backpointer_word(oop_int_t w) {
  oop_int_t* dst = backpointer_word();
  The_Memory_System()->store_enforcing_coherence(dst, w, (Object_p)this);
}

inline void Object::set_extra_preheader_word(oop_int_t w) {
  assert_always(w); // bug hunt qqq
  oop_int_t* dst = extra_preheader_word();
  The_Memory_System()->store_enforcing_coherence(dst, w, (Object_p)this);
}

inline bool Object::hasSender(Oop aContext) {
  // rcvr must be a context
  Object_p aco = aContext.as_object();
  if (this == &(*aco))  return false;
  Oop nilOop = The_Squeak_Interpreter()->roots.nilObj;
  for (Oop s = fetchPointer(Object_Indices::SenderIndex);
       s != nilOop;
       s = s.as_object()->fetchPointer(Object_Indices::SenderIndex))
    if (s == aContext)  return true;
  return false;
}



inline oop_int_t Object::fetchInteger(oop_int_t fieldIndex) {
  Oop x = fetchPointer(fieldIndex);
  return x.checkedIntegerValue();
}

inline oop_int_t Object::fetchStackPointer() { // rcvr is a ContextObject
  Oop sp = fetchPointer(Object_Indices::StackPointerIndex);
  return sp.is_int() ? sp.integerValue() : 0;
}


inline u_oop_int_t Object::fixedFieldsOfArray() {
  /* "NOTE: This code supports the backward-compatible extension to 8 bits of instSize.
   When we revise the image format, it should become...
   ^ (classFormat >> 2 bitAnd: 16rFF) - 1 */

  oop_int_t fmt = format();
  return
  Format::has_only_indexable_fields(fmt)
  ?  0 :
  Format::has_only_fixed_fields(fmt)
  ? lengthOf()  :  // "fixed fields only (zero or more)"
  // "fmt = 3 or 4: mixture of fixed and indexable fields, so must look at class format word"
  ClassFormat::fixedFields(fetchClass().as_object()->formatOfClass());
}


inline u_oop_int_t Object::lengthOf() {
  // Return the number of indexable bytes or words in the given object. Assume the given oop is not an integer. For a CompiledMethod, the size of the method header (in bytes) should be subtracted from the result of this method."
  u_oop_int_t sz = sizeBits();
  if (Size4Bit) sz -= baseHeader & Size4Bit;
  sz -= BaseHeaderSize;
  oop_int_t fmt = format();
  return  fmt <= Format::both_fixed_and_indexable_weak_fields
  ?  sz >> ShiftForWord // words
  :  fmt <= Format::indexable_long_fields_only
  ?  sz >> 2 // 32-bit longs
  :  sz - (fmt & Format::byte_size_bits); // bytes
}


inline Oop Object::fetchClass() {
  oop_int_t ccIndex = compact_class_index();
  return ccIndex == 0  ?  get_class_oop()
  :  The_Squeak_Interpreter()->splObj(Special_Indices::CompactClasses).as_object()->fetchPointer(ccIndex - 1);
}


inline oop_int_t Object::lastPointer() {
  /*
   "Return the byte offset of the last pointer field of the given object.
   Works with CompiledMethods, as well as ordinary objects.
   Can be used even when the type bits are not correct."
   */
  int fmt = format();
  // ordered this way for optimization
  if (Format::has_only_oops(fmt)) {
    if (Format::might_be_context(fmt) && hasContextHeader())
      return  (Object_Indices::CtextTempFrameStart + fetchStackPointer()) * bytesPerWord;

    return  sizeBitsSafe() - sizeof(Oop);
  }
  if (Format::has_no_oops(fmt))
    return  0;
  if (Format::isCompiledMethod(fmt))
    return  literalCount() * bytesPerWord  +  BaseHeaderSize;

  fatal("should not be here");  return 0;
}


inline char* Object::first_byte_address() {
  if (isFreeObject()) return NULL;
  int32 fmt = format();
  if (!Format::has_bytes(fmt)) return NULL;
  return  first_byte_address_after_header()
  + (Format::isCompiledMethod(fmt)
     ? (Object_Indices::LiteralStart + literalCount()) * bytesPerWord
     : 0);
}

inline char* Object::first_byte_address_after_header() { return as_char_p() + BaseHeaderSize; }

inline oop_int_t Object::methodHeader() { return fetchPointer(Object_Indices::HeaderIndex).bits(); }

inline void Object::byteSwapIfByteObject() {
  char* b = first_byte_address();
  if (b == NULL) return;
  reverseBytes((int32*)b, (int32*)nextChunk());
  // no store barrier, only for reading snapshots
}

inline oop_int_t Object::total_byte_size() {
  oop_int_t r = bytes_to_next_chunk() + extra_header_bytes();
  if (check_many_assertions) assert(!(r & (sizeof(oop_int_t) - 1)));
  return r;
}

inline oop_int_t Object::total_byte_size_without_preheader() {
  return bytes_to_next_chunk() + extra_header_bytes_without_preheader();
}

inline oop_int_t Object::sizeBits() {
  // "Answer the number of bytes in the given object, including its base header, rounded up to an integral number of words."
  // "Note: byte indexable objects need to have low bits subtracted from this size."
  if (check_many_assertions) assert_always(!isFreeObject());
  oop_int_t r =  contains_sizeHeader()
  ?  longSizeBits()
  :  shortSizeBits();
  if (check_many_assertions) assert_always((size_t)r >= sizeof(baseHeader));
  return r;
}
inline oop_int_t Object::sizeBitsSafe() {
  // "Compute the size of the given object from the cc and size fields in its header. This works even if its type bits are not correct."
  oop_int_t header = baseHeader;
  return rightType(header) ==  Header_Type::SizeAndClass
  ?  Header_Type::without_type(sizeHeader())
  :  shortSizeBits();
}

inline oop_int_t Object::stSize() {
  // return number of indexable fields in given object, e.g. ST size
  return Format::might_be_context(format()) && hasContextHeader()
  ? fetchStackPointer()
  : lengthOf() - fixedFieldsOfArray();
}

inline int Object::rightType(oop_int_t headerWord) {
  // "Compute the correct header type for an object based on the size and compact class fields of the given base header word, rather than its type bits. This is used during marking, when the header type bits are used to record the state of tracing."
  if (!(headerWord & SizeMask        ))       return Header_Type::SizeAndClass;
  if (!(headerWord & CompactClassMask))  return Header_Type::Class;
  return Header_Type::Short;
}

inline void* Object::arrayValue() {
  return isWordsOrBytes() ? as_char_p() + BaseHeaderSize : (char*)(The_Squeak_Interpreter()->primitiveFail(), 0);
}


inline oop_int_t Object::formatOfClass() {
  /* "**should be in-lined**"
   "Note that, in Smalltalk, the instSpec will be equal to the inst spec
   part of the base header of an instance (without hdr type) shifted left 1.
   In this way, apart from the smallInt bit, the bits
   are just where you want them for the first header word."
   "Callers expect low 2 bits (header type) to be zero!"*/
  return fetchPointer(Object_Indices::InstanceSpecificationIndex).bits() & ~Int_Tag;
}

inline oop_int_t Object::quickFetchInteger(oop_int_t fieldIndex) { return fetchPointer(fieldIndex).integerValue(); }

inline oop_int_t Object::fetchLong32Length() {
  // Gives size appropriate for fetchLong32
  return (sizeBits() - BaseHeaderSize) >> 2;
}


inline u_char& Object::byte_at(oop_int_t byteIndex) { return as_u_char_p()[BaseHeaderSize + byteIndex]; }
inline u_char  Object::fetchByte(oop_int_t byteIndex) { return byte_at(byteIndex); }
inline void    Object::storeByte( oop_int_t byteIndex, u_char valueByte) {
  The_Memory_System()->store_enforcing_coherence(&byte_at(byteIndex), valueByte, (Object_p)this); // used in interpreter, mostly for new objects
}


inline Oop& Object::pointer_at(oop_int_t fieldIndex) {
  return as_oop_p()[BaseHeaderSize / sizeof(Oop)  +  fieldIndex];
}

inline Oop  Object::fetchPointer(oop_int_t fieldIndex) {
  assert(fieldIndex >= 0); // STEFAN that should always hold, shouldn't it?
  Oop r;
  MEASURE(fetch_pointer, r.bits(), r = pointer_at(fieldIndex));
  return r;
}


inline void Object::catch_stores_of_method_in_home_ctxs(Oop* addr, int n,  Oop x) {
# if Extra_OTE_Words_for_Debugging_Block_Context_Method_Change_Bug
  if (n != Object_Indices::MethodIndex)  return;
  if (get_count_of_blocks_homed_to_this_method_ctx() <= 0)   return;
  lprintf("caught storePointer of method in Oop 0x%x, changing method 0x%x to 0x%x\n",
          as_oop().bits(), fetchPointer(Object_Indices::MethodIndex).bits(), x.bits());
# endif
}

{'fraction_non_alphanumeric': 0.12648283038501562, 'fraction_numerical': 0.005515088449531738, 'mean_word_length': 4.548787528868361, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7564911', 'n_tokens_mistral': 6229, 'n_tokens_neox': 6044, 'n_words': 1634}