// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*============================================================
**
** Class: Object
**
**
** Object is the root class for all CLR objects. This class
** defines only the basics.
**
** Date: January 29, 1998
**
===========================================================*/
namespace System {
using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using CultureInfo = System.Globalization.CultureInfo;
using System.Threading;
using Microsoft.Bartok.Runtime;
// The Object is the root class for all object in the CLR System. Object
// is the super class for all other CLR objects and provide a set of methods and low level
// services to subclasses. These services include object synchronization and support for clone
// operations.
//
//|
[NoCCtor]
public class Object
{
internal PreHeader preHeader;
[AccessedByRuntime("Accessed from halexn.cpp")]
internal PostHeader postHeader;
// Allow us to pretend that the vtable field lives directly in Object.
internal VTable vtable {
[NoHeapAllocation]
[Inline]
get { return this.postHeader.vtableObject; }
[NoHeapAllocation]
[Inline]
set { this.postHeader.vtableObject = value; }
}
internal unsafe UIntPtr* VTableFieldAddr {
[NoHeapAllocation]
get { return Magic.toPointer(ref this.postHeader.vtableObject); }
}
#if REFERENCE_COUNTING_GC
internal uint REF_STATE {
[Inline]
[ManualRefCounts]
[NoHeapAllocation]
get {
return this.postHeader.refState;
}
[Inline]
[ManualRefCounts]
[NoHeapAllocation]
set {
this.postHeader.refState = value;
}
}
#else // REFERENCE_COUNTING_GC
internal uint REF_STATE {
[NoHeapAllocation]
[Inline]
get {
return 1;
}
[NoHeapAllocation]
[Inline]
set {
}
}
#endif
// Creates a new instance of an Object.
//|
[Inline]
public Object()
{
}
// Returns a String which represents the object instance. The default
// for an object is to return the fully qualified name of the class.
//
//|
public virtual String ToString()
{
return GetType().FullName;
}
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
//|
[RequiredByBartok]
public virtual bool Equals(Object obj)
{
// This method is overridden for value types
return (this == obj);
}
//|
public static bool Equals(Object objA, Object objB) {
if (objA==objB) {
return true;
}
if (objA==null || objB==null) {
return false;
}
return objA.Equals(objB);
}
//|
public static bool ReferenceEquals (Object objA, Object objB) {
return objA == objB;
}
// GetHashCode is intended to serve as a hash function for this object.
// Based on the contents of the object, the hash function will return a suitable
// value with a relatively random distribution over the various inputs.
//
// The default implementation returns the sync block index for this instance.
// Calling it on the same object multiple times will return the same value, so
// it will technically meet the needs of a hash function, but it's pretty lame.
// Objects (& especially value classes) should override this method.
//
//|
public virtual int GetHashCode()
{
return MultiUseWord.GetHashCode(this);
}
///
/// Test and set the state of the GC mark bit to be the same
/// as the passed flag. Note that this operation is not
/// synchronized so it is possible for multiple marking threads
/// to 'mark' the same object.
///
[NoHeapAllocation]
internal unsafe bool GcMark(UIntPtr flag) {
UIntPtr *loc = this.VTableFieldAddr;
UIntPtr val = *loc;
VTable.Deny(val == UIntPtr.Zero);
if ((val & (UIntPtr)3) != flag) {
*loc = (val & ~(UIntPtr)3) + flag;
return true;
}
return false;
}
///
/// Return the current state of the GC mark bit.
///
[NoHeapAllocation]
internal unsafe UIntPtr GcMark() {
UIntPtr *loc = this.VTableFieldAddr;
UIntPtr val = *loc;
return (val & 3);
}
internal unsafe VTable GcUnmarkedVTable {
[Inline]
[NoHeapAllocation]
get {
UIntPtr *loc = this.VTableFieldAddr;
return Magic.toVTable(Magic.fromAddress(~(UIntPtr)3 & *loc));
}
}
// Returns a Type object which represent this object instance.
//
//|
[NoHeapAllocation]
public Type GetType()
{
return vtable.vtableType;
}
[NoHeapAllocation]
public virtual TypeCode GetTypeCode()
{
return TypeCode.Object;
}
// Allow an object to free resources before the object is reclaimed by the GC.
// Note: This defines a protected method called Finalize.
//|
[RequiredByBartok]
~Object()
{
}
// Returns a new object instance that is a memberwise copy of this
// object. This is always a shallow copy of the instance. The method is protected
// so that other object may only call this method on themselves. It is intended to
// support the ICloneable interface.
//
//|
// BUGBUG: maybe we can try harder to mess up the GC?
protected Object MemberwiseClone()
{
if(this is String) {
return this;
// REVIEW: ok, but what in the world is the CLR doing?
}
Thread thread = Thread.CurrentThread;
if(this is Array) {
Array srcArray = (Array) this;
Array cloneArray;
int srcLength = srcArray.Length;
if (srcArray.IsVector) {
cloneArray = GC.AllocateVector(srcArray.vtable, srcLength);
CloneVectorContents(srcArray, cloneArray);
} else {
int rank = srcArray.Rank;
cloneArray =
GC.AllocateArray(srcArray.vtable, rank, srcLength);
CloneArrayContents(srcArray, cloneArray);
}
return cloneArray;
} else {
Object clone = GC.AllocateObject(this.vtable);
CloneObjectContents(this, clone);
return clone;
}
}
#if !REFERENCE_COUNTING_GC && !DEFERRED_REFERENCE_COUNTING_GC
private unsafe static void CloneObjectContents(Object src, Object dst)
{
System.GCs.WriteBarrier.Clone(src, dst);
}
private unsafe static void CloneVectorContents(Array srcArray,
Array dstArray)
{
System.GCs.WriteBarrier.Clone(srcArray, dstArray);
}
private unsafe static void CloneArrayContents(Array srcArray,
Array dstArray)
{
System.GCs.WriteBarrier.Clone(srcArray, dstArray);
}
#else
private unsafe static void CloneObjectContents(Object src, Object dst)
{
byte * dstNOTFIXED = (byte *)(Magic.addressOf(dst) + PostHeader.Size);
byte * srcNOTFIXED = (byte *)(Magic.addressOf(src) + PostHeader.Size);
int size = unchecked((int) src.vtable.baseLength);
// We don't copy the header fields, the vtable or the RS field!
size -= (PreHeader.Size + PostHeader.Size);
#if REFERENCE_COUNTING_GC
GCs.ReferenceCountingCollector.
IncrementReferentRefCounts(Magic.addressOf(src), src.vtable);
GCs.ReferenceCountingCollector.
DecrementReferentRefCounts(Magic.addressOf(dst), dst.vtable);
#elif DEFERRED_REFERENCE_COUNTING_GC
GCs.DeferredReferenceCountingCollector.
IncrementReferentRefCounts(Magic.addressOf(src), src.vtable);
GCs.DeferredReferenceCountingCollector.
DecrementReferentRefCounts(Magic.addressOf(dst), dst.vtable);
#endif // REFERENCE_COUNTING_GC
Buffer.MoveMemory(dstNOTFIXED,srcNOTFIXED,size);
}
private unsafe static void CloneVectorContents(Array srcArray,
Array dstArray)
{
int srcLength = srcArray.Length;
fixed (int *srcFieldPtr = &srcArray.field1) {
fixed (int *dstFieldPtr = &dstArray.field1) {
byte *srcDataPtr = (byte *)
srcArray.GetFirstElementAddress(srcFieldPtr);
byte *dstDataPtr = (byte *)
dstArray.GetFirstElementAddress(dstFieldPtr);
int size = srcArray.vtable.arrayElementSize * srcLength;
Buffer.MoveMemory(dstDataPtr, srcDataPtr, size);
}
}
}
private unsafe static void CloneArrayContents(Array srcArray,
Array dstArray)
{
int srcLength = srcArray.Length;
fixed (int *srcFieldPtr = &srcArray.field1) {
fixed (int *dstFieldPtr = &dstArray.field1) {
byte *srcDataPtr = (byte *)
srcArray.GetFirstElementAddress(srcFieldPtr);
byte *dstDataPtr = (byte *)
dstArray.GetFirstElementAddress(dstFieldPtr);
byte *srcDimPtr = (byte *)
srcArray.GetFirstDimInfoRectangleArray();
int dimInfoSize = (int) (srcDataPtr - srcDimPtr);
int size = srcArray.vtable.arrayElementSize * srcLength;
Buffer.MoveMemory(dstDataPtr - dimInfoSize,
srcDataPtr - dimInfoSize,
size + dimInfoSize);
}
}
}
#endif
}
}