/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef __MMgc__
#define __MMgc__

#include "vmbase.h"

// AVMPI.h includes avmfeatures.h, which detects platforms and sets up most MMGC_ names.
#include "AVMPI.h"
#include "atom.h"

#if !defined(GCDEBUG) && (defined(DEBUG) || defined(_DEBUG))
	#define GCDEBUG
#endif

#ifdef MMGC_VALGRIND
    // Valgrind information:
    // The GCHeap, GC and FixedMalloc allocators are instrumented for valgrind's purposes.
    // All memory from the virtual memory API's is unknown to valgrind.   Only when we tell
    // valgrind about the memory using client requests does valgrind track it.
    // See valgrind headers and online manual for client request details.
    #include <valgrind/memcheck.h>
#else
    #define RUNNING_ON_VALGRIND false
    #define VALGRIND_MAKE_MEM_DEFINED(_a,_s)  {}
    #define VALGRIND_MAKE_MEM_UNDEFINED(_a,_s) {}
    #define VALGRIND_MEMPOOL_ALLOC(_p,_a,_s) {}
    #define VALGRIND_MEMPOOL_FREE(_p,_a) {}
    #define VALGRIND_CREATE_MEMPOOL(_a,_rdz,_zer) {}
    #define VALGRIND_DESTROY_MEMPOOL(_p) {}
    #define VALGRIND_MALLOCLIKE_BLOCK(_a,_s,_rdz,_zer) {}
    #define VALGRIND_FREELIKE_BLOCK(_a,rdz) {}
#endif

#ifdef GCDEBUG
    #define MMGC_DELETE_DEBUGGING
    // Valgrind integration is trickier with fresh memory scribbling and free memory
    // poisoning and its pointless since valgrind will uncover the same problems.
    #ifndef MMGC_VALGRIND
        #define MMGC_MEMORY_INFO
    #endif
#endif

#if defined MMGC_MEMORY_INFO && defined MMGC_MEMORY_PROFILER
    #define MMGC_RC_HISTORY
#endif

#if defined DEBUGGER || defined MMGC_MEMORY_PROFILER || defined MMGC_MEMORY_INFO
    #ifndef MMGC_HOOKS
        #define MMGC_HOOKS
    #endif
#endif

// MMGC_MARKSTACK_ALLOWANCE allows host code to limit the size of the mark stack,
// and thus to test the overflow handling.

#ifdef AVMSHELL_BUILD
    #define MMGC_MARKSTACK_ALLOWANCE
#endif

// Policy profiler settings (for MMgc development mostly).
//
// On MacOS X desktop MMGC_POLICY_PROFILING incurs a 5% execution overhead on the
// benchmark test/performance/mmgc/gcbench.as.
//
// Enabling this and MMGC_MEMORY_INFO at the same time is probably not a good idea.
//
// If AVMSHELL_BUILD is enabled then the output can be enabled/disabled with the -gcbehavior
// switch in the shell; the output is directed to whatever channel is used by GCLog.
//
// If AVMSHELL_BUILD is disabled then the output of policy info is unconditional and is
// directed to a file gcbehavior.txt in the working directory.

#ifdef AVMSHELL_BUILD
    #define MMGC_POLICY_PROFILING
#endif

#ifdef MMGC_POLICY_PROFILING
    // Really for the specially interested!  These switches incur measurable overhead,
    // so be careful when benchmarking.

    // Profile the pointer density of scanned memory
    //#define MMGC_POINTINESS_PROFILING

    // Profile reference count traffic.  This feature adds about 8% execution time overhead
    // to the overhead already added by MMGC_POLICY_PROFILING, on the gcbench benchmark,
    // measured on MacOS X desktop.
    //#define MMGC_REFCOUNT_PROFILING

    // Profile mark stack depth
    //#define MMGC_MARKSTACK_DEPTH
#endif

// this might be good to enable in a heightened GCDEBUG build, it triggers bug 561402
//#define MMGC_POISON_MEMORY_FROM_OS

#ifdef MMGC_MEMORY_PROFILER
    // For the following profilers you need source information: VMPI_getFunctionNameFromPC
    // and VMPI_getFileAndLineInfoFromPC must work.

    // Internal: profile uses of the conservative marker
    //
    // When MMGC_CONSERVATIVE_PROFILER is enabled and MMGC_PROFILE=1 is defined in the
    // runtime environment the VM will record all uses of conservative marking and
    // dump the allocation sites that result in conservatively marked storage when
    // the GC is shut down.

    //#define MMGC_CONSERVATIVE_PROFILER

    // Internal: profile uses of explicit deletion
    //
    // When MMGC_DELETION_PROFILER is enabled and MMGC_PROFILE=1 is defined in the
    // runtime environment the VM will record all uses of explicit deletion of managed storage,
    // and dump a profile on GC shutdown.  These profiles are useful because we want to
    // reduce the frequency of those deletions, and tightly control the ones that
    // continue to exist.

    //#define MMGC_DELETION_PROFILER

    // Internal: profile allocations of weak reference allocations
    //
    // When MMGC_WEAKREF_PROFILER is enabled and MMGC_PROFILE=1 is defined in the
    // runtime environment the VM will record all allocations of weak references and dump
    // the allocation sites on GC shutdown.

    //#define MMGC_WEAKREF_PROFILER
#endif

#ifdef MMGC_WEAKREF_PROFILER
    // Internal: measure the lookup traffic in GCHashtable, the statistics are dumped along
    // with the statistics for MMGC_WEAKREF_PROFILER.
    #define MMGC_GCHASHTABLE_PROFILER
#endif

#ifdef MMGC_REFCOUNT_PROFILING
    #define REFCOUNT_PROFILING_ONLY(x) x
    #define REFCOUNT_PROFILING_ARG(x) , x
#else
    #define REFCOUNT_PROFILING_ONLY(x)
    #define REFCOUNT_PROFILING_ARG(x)
#endif

#ifdef MMGC_MEMORY_PROFILER
    #define MMGC_MEMORY_PROFILER_ARG(x) , x
#else
    #define MMGC_MEMORY_PROFILER_ARG(x)
#endif

#ifdef MMGC_MEMORY_INFO
    #define MEMORY_INFO_ARG(x) , x
#else
    #define MEMORY_INFO_ARG(x)
#endif


// Bugzilla 754281: MMGC_HAS_TRUSTWORTHY_GET_STACK_ENTER,
// when defined, tells the GC that we can use GC::GetStackEnter()
// (whose state is maintained by the GCAutoEnter ctor/dtor via the
// MMGC_GCENTER macros) as the basis for GC::GetStackTop().  When
// undefined, the GC will unconditionally resort to the more
// conservative (and expensive) AVMPI_getThreadStackBase().
//
// Note: If you are seeing time- or space-regressions injected
// by the more conservative AVMPI_getThreadStackBase(), then
// it may be feasible to turn MMGC_HAS_TRUSTWORTHY_GET_STACK_ENTER
// back on for your target.  However, before committing to that
// approach, you should:
// 1.) Carefully review the notes/discussion on Bugzilla 754281,
// 2.) Verify that your target always lays out stack-allocated objects in the
//     order that they are declared in the code, *and*
// 3.) Discuss the change with the MMgc team.

//#define MMGC_HAS_TRUSTWORTHY_GET_STACK_ENTER


// MMGC_FASTBITS enables a potentially faster representation of the per-block bit table. 
// The representation is fairly well hidden from most of the GC code; only GC::GetGCBits
// and GCAlloc / GCLargeAlloc take it into account.
//
// The new representation uses more space than the old because there are gaps in the
// bit table.
//
// Do not disable this.  The #define will be removed and the feature will always be
// enabled when we're certain that the effects of the feature are positive.

#define MMGC_FASTBITS

#include "GCDebug.h"
#include "GCLog.h"

/*
 * If _GCHeapLock is defined, a spin lock is used for thread safety
 * on all public API's (Alloc, Free)
 *
 * Warning:
 * We may use GCHeap for allocation on other threads, hence the
 * spinlock, but the MMgc garbage collector in general is not
 * thread-safe.
 */

#ifdef MMGC_LOCKING
#define MMGC_LOCK(_x) MMgc::GCAcquireSpinlock _lock(&_x)
#include "GCSpinLock.h"
#else
#define MMGC_LOCK(_x)
#endif

// This reverts back to the original pagemap representation.
// https://bugzilla.mozilla.org/show_bug.cgi?id=581070
//#define MMGC_USE_UNIFORM_PAGEMAP

#ifdef MMGC_HEAP_GRAPH
    #define HEAP_GRAPH_ARG(x) , x
#else
    #define HEAP_GRAPH_ARG(x)
#endif

namespace MMgc
{
    class GC;
    class RCObject;
    class GCWeakRef;
    class GCFinalizedObject;
    class GCObject;
    class Cleaner;
    class GCAlloc;
    class GCHeap;
    class GCTraceableBase;

#define CAPACITY(T)  (uint32_t(GCHeap::kBlockSize) / uint32_t(sizeof(T)))

// *** Set up heap partitioning structure ***
	
#ifndef AVMSHELL_BUILD

// Include host-specific partition definitions for Flash Player.
#include "../../../flash/avmglue/avmhost-partitions.h"

#else

// Define trivial partitioning scheme for avmshell build.

// Define a single heap partition.
const static int kNumHeapPartitions = 1;
	
// Slices of the GC arena.
const static int kNumGCPartitions = 1;
	
#define GC_SLICE_TO_PARTITION_MAP { 0 }
	
// Slices of the FixedMalloc arena.
const static int kNumFixedPartitions = 1;
	
#define FIXMEDMALLOC_SLICE_TO_PARTITION_MAP { 0 }
	
// Assign slices of the GC arena to allocation sites.
// The partition argument is a "slice" of the arena, not the entire heap.  Slices are mapped to partitions via gcPartitionMap.
	
const static int kAVMShellGCPartition = 0;
const static int kAVMShellScriptBufferPartition = 0;
const static int kLeafObjectNewPartition = 0;
const static int kLeafVectorNewPartition = 0;
const static int kGCObjectNewPartition = 0;
const static int kGCTraceableObjectNewPartition = 0;
const static int kGCFinalizedObjectNewPartition = 0;
const static int kRCObjectNewPartition = 0;
const static int kGCWeakRefNewPartition = 0;
const static int kFixedBitSetPartition = 0;
const static int kNativeInitializerPartition = 0;
const static int kDebugStackFramePartition = 0;
const static int kAOTDenseCopyPartition = 0;
const static int kTracedListPartition = 0;
const static int kStringBufferPartition = 0;
const static int kBoxedDoublePartition = 0;
const static int kStringObjectContentPartition = 0;

// Assign slices of the FixedMalloc arena to allocation sites.
// The partition argument is a "slice" of the arena, not the entire heap.  Slices are mapped to partitions via fixedPartitionMap.

const static int kAVMShellFixedPartition = 0;
const static int kLargeObjectTrackerPartition = 0;
const static int kGCRootNewPartition = 0;
const static int kFastAllocatorPartition = 0;
const static int kMMFXNewScalarPartition = 0;
const static int kMMFXNewArrayPartition = 0;
const static int kMMFXNewPrimitivePointerArrayPartition = 0;
const static int kJSONSerializerPartition = 0;
const static int kExternalAllocPartition = 0;
const static int kMMFXAllocPartition = 0;
const static int kMMFXNewPrimitiveNonPointerArrayPartition = 0;
const static int kDataListPartition = 0;
const static int kByteArrayPartition = 0;
	
// Assign block-level allocation sites directly to heap partitions.

const static int kAVMShellHeapPartition = 0;
const static int kGCBitmapPartition = 0;
const static int kPageMapPartition = 0;
const static int kZCTPartition = 0;
const static int kBibopPartition = 0;
	
const static int kStackPartition = 0;
const static int kMMGCMetaDataPartition = 0;
const static int kCodePartition = 0;

#endif // AVMSHELL_BUILD

}; // namepsace MMgc


#include "StaticAssert.h"
#include "GCTypes.h"
#include "AllocationMacros.h"
#include "OOM.h"
#include "GCStack.h"
#include "GCThreads.h"
#include "GCAllocObject.h"
#include "GCHashtable.h"
#include "GCMemoryProfiler.h"
#include "GCThreadLocal.h"
#include "FixedAlloc.h"
#include "FixedMalloc.h"
#include "GCGlobalNew.h"
#include "BasicList.h"
#include "GCHeap.h"
#include "PageMap.h"
#include "GCAlloc.h"
#include "GCLargeAlloc.h"
#include "ZCT.h"
#include "HeapGraph.h"
#include "GCPolicyManager.h"
#include "WriteBarrier.h"
#include "GCRef.h"
#include "GCMemberBase.h"
#include "GC.h"
#include "GCObject.h"
#include "GCWeakRef.h"

#include "Shared-inlines.h"
#include "GCHashtable-inlines.h"
#include "FixedAlloc-inlines.h"
#include "FixedMalloc-inlines.h"
#include "PageMap-inlines.h"
#include "GCHeap-inlines.h"
#include "GCAlloc-inlines.h"
#include "GCLargeAlloc-inlines.h"
#include "ZCT-inlines.h"
#include "GCPolicyManager-inlines.h"
#include "GC-inlines.h"
#include "GCStack-inlines.h"
#include "WriteBarrier-inlines.h"
#include "GCMember-inlines.h"
#include "GCRef-inlines.h"

// remove these when the player stops using them
#define MMGC_DRC
#define WRITE_BARRIERS

// DRC_TRIVIAL_DESTRUCTOR is an #ifdef you can use to mark destructors
// of subclasses of RCObject that /only/ zero out fields, including those
// that store NULL pointers in RC fields.  Those destructors will be 
// removed if and when that type is made not to inherit from RCObject.
#define DRC_TRIVIAL_DESTRUCTOR

#endif /* __MMgc__ */

