00001
00002
00003
00004
00005
00006
00007 #pragma once
00008
00009 #include "..\ScripterExport.h"
00010 #include "..\..\WindowsDefines.h"
00011 #include "..\..\assert1.h"
00012
00013 enum collectable_state
00014 {
00015 booting,
00016 pre_gc,
00017 in_mutator,
00018 in_mark,
00019 in_sweep,
00020 closing_down,
00021 in_coalesce
00022 };
00023
00024
00025 struct free_mem
00026 {
00027 free_mem* next;
00028 free_mem* prev;
00029 size_t size;
00030 };
00031
00032
00033 enum gc_flags
00034 {
00035 GC_IN_USE = 0x0001,
00036 GC_GARBAGE = 0x0002,
00037 GC_PERMANENT = 0x0004,
00038 GC_IN_HEAP = 0x0008,
00039 GC_NOT_NEW = 0x0010,
00040 GC_STATIC = 0x0020,
00041 GC_ON_STACK = 0x0040,
00042 GC_MIGRATED_TO_HEAP = 0x0080,
00043 };
00044
00045
00046 enum gp_flags2
00047 {
00048 COLLECTABLE_IN_SPRIN1 = 0x0001,
00049 COLLECTABLE_UNUSED2 = 0x0002,
00050 COLLECTABLE_UNUSED3 = 0x0004,
00051 COLLECTABLE_UNUSED4 = 0x0008,
00052 COLLECTABLE_UNUSED5 = 0x0010,
00053 COLLECTABLE_UNUSED6 = 0x0020,
00054 COLLECTABLE_UNUSED7 = 0x0040,
00055 COLLECTABLE_UNUSED8 = 0x0080,
00056 };
00057
00058
00059 enum gp_flags3
00060 {
00061 VALUE_FLAGBIT_0 = 0x0001,
00062 VALUE_FLAGBIT_1 = 0x0002,
00063 VALUE_FLAGBIT_2 = 0x0004,
00064 VALUE_FLAGBIT_3 = 0x0008,
00065 VALUE_FLAGBIT_4 = 0x0010,
00066 VALUE_FLAGBIT_5 = 0x0020,
00067 VALUE_FLAGBIT_6 = 0x0040,
00068 VALUE_FLAGBIT_7 = 0x0080,
00069 VALUE_FLAGBIT_8 = 0x0100,
00070 VALUE_FLAGBIT_9 = 0x0200,
00071 VALUE_FLAGBIT_10 = 0x0400,
00072 VALUE_FLAGBIT_11 = 0x0800,
00073 VALUE_FLAGBIT_12 = 0x1000,
00074 VALUE_FLAGBIT_13 = 0x2000,
00075 VALUE_FLAGBIT_14 = 0x4000,
00076 VALUE_FLAGBIT_15 = 0x8000,
00077 };
00078
00079 class Value;
00080 class ValueMapper;
00081 class ValueMetaClass;
00082
00083 #define ALLOCATOR_STACK_SIZE 2048000 // initial size of allocation stack per thread
00084 #define STACK_LIMIT_BUFFER_SIZE 64000 // amount of stack reserved for handling stack overflow exception
00085
00086 static const int STACK_FRAME_HEADER_SIZE = 9;
00087
00088 extern ScripterExport void push_alloc_frame();
00089 extern ScripterExport void pop_alloc_frame();
00090 extern ScripterExport void pop_alloc_frame(Value*& result);
00091
00092 #define ENABLE_STACK_ALLOCATE(_class) \
00093 ScripterExport void* operator new (size_t sz) { return stack_alloc(sz); } \
00094 ScripterExport void* operator new (size_t sz, char flag) { return Collectable::operator new (sz, flag); }
00095
00096
00097
00098
00099
00100
00101
00102 #define GC_NUM_SUBLISTS 128
00103 #define GC_LOW_SUBLIST 16 // <16, 16, 20, 24, 28, 32, ... 512, >512
00104 #define GC_SUBLIST_INDEX_SHIFT 4 // log2(LOW_SUBLIST)
00105
00106 class Collectable
00107 {
00108 public:
00109 Collectable* next;
00110
00111 Collectable* prev;
00112 static CRITICAL_SECTION heap_update;
00113 byte flags;
00114 byte flags2;
00115 short flags3;
00116
00117 static Collectable* collectable_list;
00118 static Collectable* permanent_list;
00119 static free_mem* free_list[GC_NUM_SUBLISTS];
00120 static size_t heap_allocated;
00121 static size_t heap_size;
00122
00123 ScripterExport static collectable_state state;
00124 ScripterExport static bool fullCollectNextHoldFlush;
00125 static bool gc_light;
00126 static bool in_gc;
00127
00128 static HANDLE hGCCompletedEvent;
00129
00130 ScripterExport Collectable();
00131 ScripterExport virtual ~Collectable();
00132
00133 static ScripterExport void for_all_values(void (*map_fn)(Value* val), ValueMapper* mapper = NULL, ValueMetaClass* c = NULL);
00134
00135 ScripterExport static void* heap_alloc(size_t sz);
00136 ScripterExport static void* stack_alloc(size_t sz);
00137 ScripterExport static void heap_free(void* p);
00138
00139 ScripterExport void* operator new (size_t sz, char flag);
00140 ScripterExport void* operator new (size_t sz) { return heap_alloc(sz); }
00141 ScripterExport void operator delete (void* val);
00142 #pragma warning(push)
00143 #pragma warning(disable:4100)
00144 ScripterExport void operator delete (void* val, char flag) { Collectable::operator delete(val); }
00145 #pragma warning(pop)
00146
00147 static void mark();
00148 static void sweep();
00149 static void setup(size_t);
00150 ScripterExport static void gc();
00151 static void coalesce_free_list();
00152 virtual void collect() = 0;
00153 virtual void gc_trace() { mark_in_use(); }
00154 static void close_down();
00155 static void drop_maxwrapper_refs();
00156
00157 ScripterExport void make_collectable();
00158 void make_permanent();
00159 void make_static();
00160
00161 ScripterExport static void push_alloc_stack_frame();
00162 ScripterExport static void pop_alloc_stack_frame();
00163
00164 int is_marked() { return (flags & GC_IN_USE); }
00165 int is_not_marked()
00166 {
00167 DbgAssert (!is_on_stack());
00168 return !is_marked();
00169 }
00170 int is_garbage() { return is_not_marked(); }
00171 int is_permanent() { return (flags & GC_PERMANENT); }
00172 void mark_in_use() { flags |= GC_IN_USE; }
00173 void unmark_in_use() { flags &= ~GC_IN_USE; }
00174 int has_heap_copy() { return (flags & (GC_IN_HEAP | GC_MIGRATED_TO_HEAP | GC_STATIC)); }
00175 int is_in_heap() { return (flags & GC_IN_HEAP); }
00176 int is_on_stack() { return (flags & GC_ON_STACK); }
00177
00178
00179 ScripterExport static ULONGLONG get_num_values_created();
00180
00181 private:
00182 static void increment_num_values_created();
00183 static volatile LONGLONG& get_num_values_created_counter();
00184 };
00185
00186
00187 class ValueMapper
00188 {
00189 public:
00190 virtual ~ValueMapper() {;}
00191 virtual void map(Value* val)=0;
00192 };
00193
00194 ScripterExport void ms_free(void* p);
00195 ScripterExport void* ms_malloc(size_t sz);
00196 ScripterExport void* ms_realloc(void* p, size_t sz);
00197 inline void ms_make_collectable(Collectable* v)
00198 {
00199 if (v != NULL && Collectable::state != closing_down)
00200 v->make_collectable();
00201 }
00202