Introduce new macros to replace overriding global new and delete which we don't do anymore unless AVMFEATURE_OVERRIDE_GLOBAL_NEW is on (r=edwsmith)
authorTommy Reilly <treilly@adobe.com>
Thu, 20 Aug 2009 12:35:48 -0400
changeset 2384 97f74a6fb9b3b794770d0f6dd9e81b92483d4e48
parent 2383 e8f13d20cb96179fa40c4a6b71306b20d6328d16
child 2385 cb453f61fe737fd75bd11eb6caf3667396e1f7cc
push id1140
push usertreilly@adobe.com
push dateThu, 20 Aug 2009 16:36:04 +0000
reviewersedwsmith
Introduce new macros to replace overriding global new and delete which we don't do anymore unless AVMFEATURE_OVERRIDE_GLOBAL_NEW is on (r=edwsmith)
MMgc/AllocationMacros.h
MMgc/FixedMalloc.h
MMgc/GCGlobalNew.cpp
MMgc/GCGlobalNew.h
MMgc/GCHeap.h
MMgc/GCStack.cpp
MMgc/MMgc.h
MMgc/MMgc2008.vcproj
MMgc/manifest.mk
build/avmfeatures.py
core/MethodInfo.cpp
core/avmfeatures.as
core/avmfeatures.cpp
core/avmfeatures.h
eval/eval.h
platform/mac/mac-platform.h
platform/unix/unix-platform.h
platform/win32/win32-platform.h
shell/avmshell-features.h
new file mode 100644
--- /dev/null
+++ b/MMgc/AllocationMacros.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine.].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2004-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+ 
+#ifndef __ALLOCATIONMACROS__
+#define __ALLOCATIONMACROS__
+
+// The allocation macros. mmfx_? ones will have an alternative implementation of mapping to original new/delete implementations
+// the others are always on.
+
+namespace MMgc 
+{
+	enum NewDummyOperand { kUseFixedMalloc };
+}
+
+#ifndef MMGC_OVERRIDE_GLOBAL_NEW
+
+// Used for allocating/deallocating memory with MMgc's fixed allocator.
+// The memory allocated using these macros will be released when the MMgc aborts due to 
+// an unrecoverable out of memory situation.
+#define mmfx_new(new_data)					new (MMgc::kUseFixedMalloc) new_data
+#define mmfx_new0(new_data)					new (MMgc::kUseFixedMalloc, MMgc::kZero) new_data
+
+#define mmfx_new_array(type, n)				::MMgcNewArrayCall((type*)NULL, n, MMgc::kNone)
+
+#define mmfx_new_opt(new_data, opts)		new (MMgc::kUseFixedMalloc, opts) new_data
+#define mmfx_new_array_opt(type, n, opts)	::MMgcNewArrayCall((type*)NULL, n, opts)
+
+#define mmfx_delete(p)						::MMgcDestructorCall(p)
+#define mmfx_delete_array(p)				::MMgcDestructorArrayCall(p)
+
+#define mmfx_alloc(_siz) MMgc::AllocCall(_siz)
+#define mmfx_alloc_opt(_siz, opts)          MMgc::AllocCall(_siz, opts)
+#define mmfx_free(_ptr) MMgc::DeleteCall(_ptr)
+
+#else
+
+#define mmfx_new(new_data)					new new_data
+#define mmfx_new0(new_data)					new (MMgc::kZero) new_data
+
+#define mmfx_new_array(type, n)				new type[n]
+
+#define mmfx_new_opt(new_data, opts)		new (opts) new_data
+#define mmfx_new_array_opt(type, n, opts)	new (opts) type[n]
+
+#define mmfx_delete(p)						delete p
+#define mmfx_delete_array(p)				delete[] p
+
+#define mmfx_alloc(_siz)                    new char[_siz]
+#define mmfx_alloc_opt(_siz, opts)          new (opts) char[_siz]
+#define mmfx_free(_ptr)                     delete [] (char*)_ptr
+
+#endif // MMGC_OVERRIDE_GLOBAL_NEW
+
+// Used to allocate memory from the system default operator new. The lifetime of these
+// allocations may exceed the lifetime of MMgc.
+#define system_new(new_data)				new new_data
+#define system_new_array(type, n)			new type[n]
+#define system_delete(p)					delete p
+#define system_delete_array(p)				delete[] p
+
+#endif // __ALLOCATIONMACROS__
--- a/MMgc/FixedMalloc.h
+++ b/MMgc/FixedMalloc.h
@@ -112,25 +112,25 @@ namespace MMgc
 				size = FixedAlloc::Size(item);
 			}
 #ifdef MMGC_MEMORY_INFO
 			size -= DebugSize();
 #endif
 			return size;
 		}
 
-		void *Calloc(size_t num, size_t elsize)
+		void *Calloc(size_t num, size_t elsize, FixedMallocOpts opts=kNone)
 		{
 			uint64_t size = (uint64_t)num * (uint64_t)elsize;
 			if(size > 0xfffffff0) 
 			{
 				GCAssertMsg(false, "Attempted allocation overflows size_t\n");
 				return NULL;
 			}
-			return Alloc(num * elsize);
+			return Alloc(num * elsize, opts);
 		}
 
 		size_t GetTotalSize();
 		void GetUsageInfo(size_t& totalAskSize, size_t& totalAllocated);
 		
 		size_t GetBytesInUse()
 		{
 			size_t totalAskSize, totalAllocated;  
new file mode 100644
--- /dev/null
+++ b/MMgc/GCGlobalNew.cpp
@@ -0,0 +1,257 @@
+/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is [Open Source Virtual Machine.].
+ *
+ * The Initial Developer of the Original Code is
+ * Adobe System Incorporated.
+ * Portions created by the Initial Developer are Copyright (C) 2004-2006
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Adobe AS3 Team
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "MMgc.h"
+
+#define MMGC_SCALAR_GUARD 0xafafafaf
+#define MMGC_NORM_VECTOR_GUARD 0xbfbf0001
+#define MMGC_PRIM_VECTOR_GUARD 0xbfbf0002
+
+namespace MMgc
+{
+	void *AllocCall(size_t s, FixedMallocOpts opts) 
+	{ 
+		return AllocCallInline(s, opts);
+	}
+
+	void DeleteCall( void* p )
+	{
+		DeleteCallInline(p);
+	}
+};
+
+#ifndef MMGC_OVERRIDE_GLOBAL_NEW
+
+void* operator new(size_t size, MMgc::NewDummyOperand /*ignored*/) MMGC_NEW_THROWS_CLAUSE
+{
+	return MMgc::NewCall(size);
+}
+
+void* operator new(size_t size, MMgc::NewDummyOperand /*ignored*/, MMgc::FixedMallocOpts opts) MMGC_NEW_THROWS_CLAUSE
+{
+	return MMgc::NewCall(size, opts);
+}
+
+namespace MMgc
+{
+	REALLY_INLINE void *GuardedFixedAlloc(size_t size, FixedMallocOpts opts, uint32_t guard)
+	{
+#ifdef MMGC_DELETE_DEBUGGING
+		// lets store a guard cookie so that we can see if it is released with a proper delete (scalar/vector)
+		size += sizeof(size_t);
+#else
+		(void)guard; // get rid of warning
+#endif //MMGC_DELETE_DEBUGGING
+
+		size_t* mem = (size_t*)AllocCallInline(size, opts);
+
+#ifdef MMGC_DELETE_DEBUGGING
+		if ( mem )
+		{
+			// add the guard cookie
+			*(mem) = guard; 
+			mem += 1;
+		}
+#endif // MMGC_DELETE_DEBUGGING
+
+		return mem;
+	}
+
+	/*REALLY_INLINE*/
+	void* NewCall(size_t size, FixedMallocOpts opts)
+	{
+		GCAssertMsg(GCHeap::GetGCHeap()->StackEnteredCheck(), "MMGC_ENTER macro must exist on the stack");
+		return GuardedFixedAlloc(size, opts, MMGC_SCALAR_GUARD);
+	}
+
+	REALLY_INLINE size_t CallocSizeCalc(size_t el_size, size_t count, bool& overflow, bool addCookie)
+	{
+		uint64_t size = (uint64_t)count * (uint64_t)el_size;
+
+		if(addCookie)
+			size += sizeof(size_t);
+
+		if(size > 0xfffffff0) 
+		{
+			overflow = true;
+			return 0;
+		}
+		return (size_t)size;
+	}
+
+	void* NewArrayCalloc(size_t el_size, size_t count, FixedMallocOpts opts, bool isPrimitive) 
+	{
+		GCAssertMsg(GCHeap::GetGCHeap()->StackEnteredCheck(), "MMGC_ENTER macro must exist on the stack");
+
+		bool overflow = false;
+		size_t size = CallocSizeCalc(el_size, count, overflow, isPrimitive ? false : true);
+		if(overflow) 
+		{
+			GCAssertMsg(false, "Attempted allocation overflows size_t\n");
+			return NULL;
+		}
+
+		return GuardedFixedAlloc(size, opts, isPrimitive ? MMGC_PRIM_VECTOR_GUARD : MMGC_NORM_VECTOR_GUARD);
+	}
+
+#ifdef MMGC_DELETE_DEBUGGING
+	// Helper functions to check the 
+	bool CheckForAllocationGuard(size_t* mem, size_t guard)
+	{
+		mem--;
+		return (*mem == guard);
+	}
+
+	bool IsScalarAllocation(void* p)
+	{
+		return CheckForAllocationGuard((size_t*)p, MMGC_SCALAR_GUARD);
+	}
+
+	bool IsVectorAllocation(void* p, bool primitive)
+	{
+		// Check if we have vector guard right before the pointer.
+		size_t* w = (size_t*)p;
+		size_t guard = primitive ? MMGC_PRIM_VECTOR_GUARD : MMGC_NORM_VECTOR_GUARD;
+		return CheckForAllocationGuard(w, guard) || // simple vector
+			CheckForAllocationGuard(w-1, guard); // vector with count
+	}
+
+	bool IsGCHeapAllocation(void* p)
+	{
+		return (GCHeap::GetGCHeap() && GCHeap::GetGCHeap()->IsAddressInHeap(p));
+	}
+
+	void VerifyScalarDelete(void* p)
+	{
+		if (!IsScalarAllocation(p))
+		{
+			if (IsVectorAllocation(p, true) || IsVectorAllocation(p, false))
+			{
+				GCAssertMsg(0, "Trying to release array pointer with scalar destructor! Check the allocation and free calls for this object!");
+			}
+			else if (!IsGCHeapAllocation(p))
+			{
+				GCAssertMsg(0, "Trying to release system memory with scalar deletefunc! Check the allocation and free calls for this object!");
+			}
+			else
+			{
+				GCAssertMsg(0, "Trying to release funky memory with scalar deletefunc! Check the allocation and free calls for this object!");
+			}
+		}
+	}
+
+	void VerifyVectorDelete(void* p, bool primitive)
+	{
+		if (!IsVectorAllocation(p, primitive))
+		{
+			if (IsVectorAllocation(p, !primitive))
+			{
+				GCAssertMsg(0, "Trying to release array pointer with different type destructor! Check the allocation and free calls for this object!");
+			}
+			if (IsScalarAllocation(p))
+			{
+				GCAssertMsg(0, "Trying to release scalar pointer with vector destructor! Check the allocation and free calls for this object!");
+			}
+			else if (!IsGCHeapAllocation(p))
+			{
+				GCAssertMsg(0, "Trying to release system pointer with vector deletefunc! Check the allocation and free calls for this object!");
+			}
+			else
+			{
+				GCAssertMsg(0, "Trying to release funky memory with vector deletefunc! Check the allocation and free calls for this object!");
+			}
+		}
+	}
+
+#endif //MMGC_DELETE_DEBUGGING
+
+	// Functions to actually release the memory through FixedMalloc.
+	void DeleteFunc( void* p )
+	{
+#ifdef MMGC_DELETE_DEBUGGING
+		// we need to adjust the pointer to release also the guard.
+		size_t* temp = (size_t*)p;
+		temp--;
+		p = temp;
+#endif //MMGC_DELETE_DEBUGGING
+
+		DeleteCallInline(p);
+	}
+
+
+	void DeleteArrayFunc( void* p )
+	{
+		if( p )
+		{
+#ifdef MMGC_DELETE_DEBUGGING
+			p = ((size_t*)p - 2);
+#else
+			p = ((size_t*)p - 1);
+#endif //MMGC_DELETE_DEBUGGING
+			DeleteCallInline(p);
+		}
+	}
+
+	void SimpleDestructorCall(void* p)
+	{
+		if( p ) 
+		{
+#ifdef MMGC_DELETE_DEBUGGING
+			VerifyScalarDelete( p );
+#endif
+			DeleteFunc( p ); 
+		}	
+	}
+
+	void SimpleDestructorArrayCall(void* p, bool primitive)
+	{
+		if(p) 
+		{
+#ifdef MMGC_DELETE_DEBUGGING
+			VerifyVectorDelete( p, primitive );
+#else
+			(void)primitive; // get rid of warning
+#endif
+			// not using DeleteArrayFunc, that's for non-Simple case with count cookie
+			DeleteFunc( p );
+		}
+	}
+
+} // namespace MMgc
+
+#endif //MMGC_OVERRIDE_GLOBAL_NEW
--- a/MMgc/GCGlobalNew.h
+++ b/MMgc/GCGlobalNew.h
@@ -35,68 +35,344 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __GCGLOBALNEW__
 #define __GCGLOBALNEW__
 
 #ifdef MMGC_ENABLE_CPP_EXCEPTIONS
-#include <new>
-#define NEW_THROWS_CLAUSE throw (std::bad_alloc)
-#define DELETE_THROWS_CLAUSE throw ()
+  #define MMGC_NEW_THROWS_CLAUSE throw (std::bad_alloc)
+  #define MMGC_DELETE_THROWS_CLAUSE throw ()
+#else
+  #define MMGC_NEW_THROWS_CLAUSE 
+  #define MMGC_DELETE_THROWS_CLAUSE 
+#endif
+
+namespace MMgc
+{
+	void *AllocCall(size_t, FixedMallocOpts opts=kNone);
+	void DeleteCall(void *);
+
+	REALLY_INLINE void *AllocCallInline(size_t size, FixedMallocOpts opts=kNone)
+	{
+#ifdef MMGC_USE_SYSTEM_MALLOC
+		void *space = VMPI_alloc(size);
+		GCHeap::TrackSystemAlloc(space, size);
+		if ((opts & kZero) != 0)
+		{
+			VMPI_memset(space, 0, size);
+		}
+		// should we abort if space is NULL and they didn't specify kCanFail?
+		return space;
 #else
-#define NEW_THROWS_CLAUSE 
-#define DELETE_THROWS_CLAUSE 
+		return FixedMalloc::GetFixedMalloc()->OutOfLineAlloc(size, opts);
+#endif
+	}
+
+	REALLY_INLINE void DeleteCallInline(void *p)
+	{
+#ifdef MMGC_USE_SYSTEM_MALLOC
+		GCHeap::TrackSystemFree(p);
+		VMPI_free(p);
+#else
+		FixedMalloc::GetFixedMalloc()->OutOfLineFree(p);
 #endif
+	}
+};
+
+#ifdef MMGC_OVERRIDE_GLOBAL_NEW
+
+// Global operator new and delete implementations to allocate/free from FixedMalloc.
+// Using these may create a problem if compiled with system (OS) headers that also use the default
+// new & delete. This happens for example in ATL of the Windows ActiveX builds. Also, out of memory 
+// handling will release everything allocated with FixedMalloc when abort due to OOM occurs. If
+// things in the system headers/plugin interface/platform globals are allocated with these, it will
+// result most likely in a crash. By using the GCAllocObject you can try to go around some of these
+// issues, but atleast to system headers may pose a problem.
 
 // User-defined operator new.
-REALLY_INLINE void *operator new(size_t size) NEW_THROWS_CLAUSE
+REALLY_INLINE void *operator new(size_t size) MMGC_NEW_THROWS_CLAUSE 
+{ 
+	return MMgc::AllocCallInline(size, MMgc::kNone); 
+}
+
+REALLY_INLINE void *operator new(size_t size, MMgc::FixedMallocOpts opts) MMGC_NEW_THROWS_CLAUSE
 {
-#ifdef MMGC_USE_SYSTEM_MALLOC
-	void *space = VMPI_alloc(size);
-	MMgc::GCHeap::TrackSystemAlloc(space, size);
-	return space;
-#else
-	GCAssertMsg(MMgc::GCHeap::GetGCHeap()->StackEnteredCheck(), "MMGC_ENTER macro must exist on the stack");
-	return MMgc::FixedMalloc::GetFixedMalloc()->OutOfLineAlloc(size);
-#endif
+	return MMgc::AllocCallInline(size, opts); 
 }
-       
-REALLY_INLINE void *operator new[](size_t size) NEW_THROWS_CLAUSE
+
+REALLY_INLINE void *operator new[](size_t size) MMGC_NEW_THROWS_CLAUSE
 {
-#ifdef MMGC_USE_SYSTEM_MALLOC
-	void *space = VMPI_alloc(size);
-	MMgc::GCHeap::TrackSystemAlloc(space, size);
-	return space;
-#else
-	GCAssertMsg(MMgc::GCHeap::GetGCHeap()->StackEnteredCheck(), "MMGC_ENTER macro must exist on the stack");
-	return MMgc::FixedMalloc::GetFixedMalloc()->OutOfLineAlloc(size);
-#endif
+	return MMgc::AllocCallInline(size, MMgc::kNone); 
 }
-       
-// User-defined operator delete.
-REALLY_INLINE void operator delete( void *p) DELETE_THROWS_CLAUSE
+
+REALLY_INLINE void *operator new[](size_t size, MMgc::FixedMallocOpts opts) MMGC_NEW_THROWS_CLAUSE
 {
-#ifdef MMGC_USE_SYSTEM_MALLOC
-	MMgc::GCHeap::TrackSystemFree(p);
-	VMPI_free(p);
-#else
-	MMgc::FixedMalloc::GetFixedMalloc()->OutOfLineFree(p);
-#endif
+	return MMgc::AllocCallInline(size, opts); 
 }
-       
-REALLY_INLINE void operator delete[]( void *p ) DELETE_THROWS_CLAUSE
+
+// User-defined operator delete.
+REALLY_INLINE void operator delete( void *p) MMGC_DELETE_THROWS_CLAUSE
 {
-#ifdef MMGC_USE_SYSTEM_MALLOC
-	MMgc::GCHeap::TrackSystemFree(p);
-	VMPI_free(p);
-#else
-	MMgc::FixedMalloc::GetFixedMalloc()->OutOfLineFree(p);
-#endif
+	MMgc::DeleteCallInline(p);
+}
+
+REALLY_INLINE void operator delete[]( void *p ) MMGC_DELETE_THROWS_CLAUSE
+{
+	MMgc::DeleteCallInline(p);
 }
 
-#ifdef MMGC_ENABLE_CPP_EXCEPTIONS
-#undef NEW_THROWS_CLAUSE
-#undef DELETE_THROWS_CLAUSE
+// map these to nothingness
+#define MMGC_DECLARE_OPERATOR_DELETES_FOR_CLASS 
+#define MMGC_DECLARE_SPECIALIZED_DESTRUCTORCALL_TEMPLATES( TYPE )
+#define MMGC_DECLARE_GLOBAL_DELETE_FNCS_AS_FRIEND( TYPE )
+#define MMGC_USING_DELETE_OPERATOR( TYPE )
+
+#else /* MMGC_OVERRIDE_GLOBAL_NEW */
+
+// Defines allocation and deallocation functions used by allocation and deallocation macros.
+// operator new and new[] have a specialized signature by having an ignored MMgc::kUseFixedMalloc parameter.
+// Specialized operator delete and delete[] are provided to get rid of compiler warnings.
+
+void* operator new(size_t size, MMgc::NewDummyOperand /*ignored*/) MMGC_NEW_THROWS_CLAUSE;
+void *operator new(size_t size, MMgc::NewDummyOperand /*ignored*/, MMgc::FixedMallocOpts opts) MMGC_NEW_THROWS_CLAUSE;
+
+// Empty deletes to get rid of warnings
+void operator delete(void *p, MMgc::NewDummyOperand /* ignored */) MMGC_DELETE_THROWS_CLAUSE;
+
+// b/c we need to use the fancy template routines for new[] these arent used
+//void* operator new[](size_t size, size_t arraySize, MMgc::NewDummyOperand /*ignored*/) MMGC_NEW_THROWS_CLAUSE;
+//void* operator new[](size_t size, size_t arraySize, MMgc::NewDummyOperand /*ignored*/, MMgc::FixedMallocOpts opts) NEW_THROWS_CLAUSE;
+//void operator delete[](void *p, MMgc::NewDummyOperand /* ignored */) MMGC_DELETE_THROWS_CLAUSE;
+
+namespace MMgc
+{
+
+#ifdef MMGC_DELETE_DEBUGGING
+	// Helper functions to check whether we are releasing a pointer with the right delete.
+	void VerifyScalarDelete(void* p);
+	void VerifyVectorDelete(void* p, bool primitive);
+#define mmgc_debug_only(_x) _x
+#else
+#define mmgc_debug_only(_x) 
+#endif //MMGC_DELETE_DEBUGGING
+
+	// The operator new is defined also in a library code and they inline this implementation to be the function body.
+	REALLY_INLINE void* NewCall(size_t size, FixedMallocOpts opts=kNone);
+
+	void* NewArrayCalloc(size_t size, size_t count, FixedMallocOpts opts, bool isPrimitive);
+
+	void DeleteFunc(void *);
+	void DeleteArrayFunc(void *);
+
+	void SimpleDestructorCall(void* p);
+	void SimpleDestructorArrayCall(void* p, bool primitive);
+};
+
+	template <class T>
+	T *MMgcNewArrayCall(T* /*dummy template arg*/, size_t count, MMgc::FixedMallocOpts opts)
+	{
+		size_t *p = (size_t*) MMgc::NewArrayCalloc(sizeof(T), count, opts, false /* !isPrimitive */);
+		*p = count;
+		p++;
+		T *tp = (T*)p;
+		for(size_t i=count; i>0; i--, tp++) {
+			new ((void*)tp) T;
+		}	
+		return (T*)p;
+	}
+
+#define DECLARE_PRIM_ARRAY_NEW(_x)										\
+	template <> REALLY_INLINE _x *MMgcNewArrayCall(_x*, size_t count, MMgc::FixedMallocOpts opts) \
+	{ return (_x*)MMgc::NewArrayCalloc(sizeof(_x), count, opts, true /* isPrimitive */); }
+
+	// Scalar delete mechanism. First calls the destructor and then deletefunc to release the memory.
+	template <typename T> REALLY_INLINE void MMgcDestructorCall( T* mem )
+	{
+		if( mem )
+		{
+			mmgc_debug_only(MMgc::VerifyScalarDelete(mem);)
+			//	Call destructor first and then release memory
+			mem->~T();
+			MMgc::DeleteFunc( mem );
+		}
+	}
+
+	//	Vector delete mechanism
+	template <typename T> REALLY_INLINE void MMgcDestructorArrayCall( T* mem )
+	{
+		if( mem )
+		{
+			mmgc_debug_only(MMgc::VerifyVectorDelete(mem, false);)
+
+			// We need to check whether compiler added its own cookie. If we go back 4 bytes and find our guard there
+			// compiler did not add any cookie. Otherwise it added a cookie. The cookie is the sizeof(size_t).
+			size_t* w = (size_t*)mem;
+
+			w--;
+
+			size_t numObj = *(size_t*)w;
+
+			register T* p = mem;
+			p += numObj;
+
+			while ( p > mem )
+			{
+				p--;
+				p->~T();
+			}
+			MMgc::DeleteArrayFunc( mem );
+		}
+	}
+
+#define DECLARE_PRIM_ARRAY_DELETE(_x)									\
+	template <> REALLY_INLINE void MMgcDestructorArrayCall( _x* mem )		\
+	{ MMgc::SimpleDestructorArrayCall( mem, true ); }							\
+	template <> REALLY_INLINE void MMgcDestructorCall(_x *mem) { MMgc::SimpleDestructorCall(mem); }
+
+
+#define DECLARE_PRIM_ARRAY(_x)					\
+	DECLARE_PRIM_ARRAY_NEW(_x)					\
+	DECLARE_PRIM_ARRAY_DELETE(_x)				\
+
+	//	Specialized function templates, for built-in types so that we
+	//	don't call destructor and add extra overhead
+	DECLARE_PRIM_ARRAY(uint8_t)
+	DECLARE_PRIM_ARRAY(int8_t)
+#ifdef __GNUC__
+	// msvc correctly treats char and uint8_t as the same but gcc doesn't
+	DECLARE_PRIM_ARRAY(char)
+#endif		
+	DECLARE_PRIM_ARRAY(uint16_t)		
+	DECLARE_PRIM_ARRAY(int16_t)		
+	DECLARE_PRIM_ARRAY(uint32_t)		
+	DECLARE_PRIM_ARRAY(int32_t)		
+	DECLARE_PRIM_ARRAY(uint64_t)		
+	DECLARE_PRIM_ARRAY(int64_t)	
+	DECLARE_PRIM_ARRAY(void*)	
+	DECLARE_PRIM_ARRAY(void**)
+
+	template <> REALLY_INLINE void *MMgcNewArrayCall(void*, size_t count, MMgc::FixedMallocOpts opts) \
+	{ return (void*)MMgc::NewArrayCalloc(sizeof(void*), count, opts, true /* isPrimitive */); }
+	DECLARE_PRIM_ARRAY_DELETE(void)
+
+#undef DECLARE_PRIM_ARRAY_NEW
+#undef DECLARE_PRIM_ARRAY_DELETE
+#undef DECLARE_PRIM_ARRAY
+
+#ifdef __GNUC__
+	// G++ pukes on the ::, MSC requires them
+
+// If a class has private destructor adding this macro will allow the delete mechanisms to call that.
+#define MMGC_DECLARE_GLOBAL_DELETE_FNCS_AS_FRIEND( TYPE )	\
+	friend void MMgcDestructorCall<>( TYPE* );			\
+	friend void MMgcDestructorArrayCall<>( TYPE* );
+
+#else
+
+// If a class has private destructor adding this macro will allow the delete mechanisms to call that.
+#define MMGC_DECLARE_GLOBAL_DELETE_FNCS_AS_FRIEND( TYPE )	\
+	friend void ::MMgcDestructorCall<>( TYPE* );			\
+	friend void ::MMgcDestructorArrayCall<>( TYPE* );
+
 #endif
 
+// this is necessary for the friend calls above to resolve properly w GCC
+//using namespace MMgc;
+
+// If a class is a base class for multiple inheritance or virtual inheritance, it may need to define 
+// these macros (MMGC_DECLARE_OPERATOR_DELETES_FOR_CLASS) inside the class definition to create a class specific delete, 
+// and MMGC_DECLARE_SPECIALIZED_DESTRUCTORCALL_TEMPLATES outside the class definition to have specialized function 
+// template for the destructor.
+// This is done in cases where the pointer to be destructed is actually the pointer of a non-first base class. 
+#define MMGC_DECLARE_SPECIALIZED_DESTRUCTORCALL_TEMPLATES( TYPE ) \
+	MMGC_DECLARE_SPECIALIZED_DESTRUCTORCALL_TEMPLATE( TYPE ) \
+	MMGC_DECLARE_SPECIALIZED_DESTRUCTORARRAYCALL_TEMPLATE( TYPE )
+
+#define MMGC_DECLARE_SPECIALIZED_DESTRUCTORCALL_TEMPLATE( TYPE )		\
+	template <> REALLY_INLINE void MMgcDestructorCall( TYPE* mem ) { if(mem) delete mem; } 
+
+#define MMGC_DECLARE_SPECIALIZED_DESTRUCTORARRAYCALL_TEMPLATE( TYPE )	\
+	template <> REALLY_INLINE void MMgcDestructorArrayCall( TYPE* mem ) { if(mem) delete[] mem; }
+
+// These dont need to call destructors as the operator delete will do that automatically for us.
+#define MMGC_DECLARE_OPERATOR_DELETES_FOR_CLASS \
+	MMGC_DECLARE_SCALAR_DELETE_FOR_CLASS \
+	MMGC_DECLARE_VECTOR_DELETE_FOR_CLASS
+
+#define MMGC_DECLARE_SCALAR_DELETE_FOR_CLASS \
+	void operator delete(void* p) { MMgc::SimpleDestructorCall(p); }
+
+#define MMGC_DECLARE_VECTOR_DELETE_FOR_CLASS \
+	void operator delete[](void* p) { MMgc::SimpleDestructorArrayCall(p, false); }
+
+// If a class derives from multiple baseclasses that define delete operator, this can be used to
+// select with one to use. 
+#define MMGC_USING_DELETE_OPERATOR( TYPE ) \
+	using TYPE::operator delete
+
+#ifndef MMGC_OVERRIDE_NEWDELETE_DEBUGGING
+//#define MMGC_OVERRIDE_NEWDELETE_DEBUGGING
+#endif 
+
+#ifdef MMGC_OVERRIDE_NEWDELETE_DEBUGGING
+// These help to track where global operator new/delete/new[]/delete[] are used in compile time in MSVC.
+// If you compile the project with /EHsc /Ob1 /W4 flags and compile. This will generate C4714 warnings 
+// (forceinline failed) for places where these operators are used. So far the try catch seems to be the
+// way to do this, but for loops are supposed to generate that as well. May not be turned on on builds that 
+// are to be executed. 
+REALLY_INLINE void *operator new(size_t size) MMGC_NEW_THROWS_CLAUSE
+{
+	(void)size;	GCAssert(false);
+
+	/*
+	try
+	{
+	}
+	catch (...)
+	{
+	}*/
+	return (void*)-1;
+}
+
+REALLY_INLINE void *operator new[](size_t size) MMGC_NEW_THROWS_CLAUSE
+{
+	(void)size;GCAssert(false);
+	/*
+	try
+	{
+	}
+	catch (...)
+	{
+	}*/
+	return (void*)-1;
+}
+
+// User-defined operator delete.
+REALLY_INLINE void operator delete( void *p) MMGC_DELETE_THROWS_CLAUSE
+{
+	(void)p;
+	GCAssert(false); /*
+					 try
+					 {
+					 }
+					 catch (...)
+					 {
+					 }*/
+}
+
+REALLY_INLINE void operator delete[]( void *p ) MMGC_DELETE_THROWS_CLAUSE
+{
+	(void)p;
+	GCAssert(false);/*
+					try
+					{
+					}
+					catch (...)
+					{
+					}*/
+}
+#endif // MMGC_OVERRIDE_NEWDELETE_DEBUGGING
+
+#endif /* MMGC_OVERRIDE_GLOBAL_NEW */
+
 #endif // __GCGLOBALNEW__
--- a/MMgc/GCHeap.h
+++ b/MMgc/GCHeap.h
@@ -376,16 +376,18 @@ namespace MMgc
 			char *reserveTop;
 			char *commitTop;
 			int blockId;
 		};
 		Region *lastRegion;
 		
 		static bool ShouldNotEnter();
 
+		bool IsAddressInHeap(void *);
+
 	private:
 
 		GCHeap(const GCHeapConfig &config);
 		~GCHeap();
 
 #ifdef MMGC_MEMORY_PROFILER
 		static void InitProfiler();
 		inline static bool IsProfilerInitialized()
--- a/MMgc/GCStack.cpp
+++ b/MMgc/GCStack.cpp
@@ -36,20 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "MMgc.h"
 
 //#define TESTING_MARKSTACK
 #define MARKSTACK_ALLOWANCE  1
 
-#ifndef MMGC_ENABLE_CPP_EXCEPTIONS
-inline void* operator new(size_t, void* p) { return p; }
-#endif
-
 namespace MMgc
 {
 #ifdef TESTING_MARKSTACK
 	static int markstack_allowance = MARKSTACK_ALLOWANCE;
 #endif
 
 	static inline void* AllocStackSegment(size_t nbytes)
 	{
--- a/MMgc/MMgc.h
+++ b/MMgc/MMgc.h
@@ -38,19 +38,18 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __MMgc__
 #define __MMgc__
 
 // VMPI.h includes avmfeatures.h, which detects platforms and sets up most MMGC_ names.
 #include "VMPI.h"
 
-// Memory profiling settings
-
 #ifdef DEBUG
+    #define MMGC_DELETE_DEBUGGING
     #define MMGC_MEMORY_INFO
 #endif
 
 #if defined AVMPLUS_MAC && !(defined MMGC_PPC && defined MMGC_64BIT)
 	#define MMGC_MEMORY_PROFILER
 #endif
 
 #if defined AVMPLUS_WIN32 && !defined AVMPLUS_ARM // note, does not require DEBUG
@@ -134,30 +133,31 @@ namespace MMgc
 	class Cleaner;
 	class GCAlloc;
 	class GCHeap;
 }
 
 #define CAPACITY(T)  (uint32_t(GCHeap::kBlockSize) / uint32_t(sizeof(T)))
 
 #include "GCTypes.h"
+#include "AllocationMacros.h"
 #include "OOM.h"
-#include "BasicList.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 "BasicList.h"
 #include "GCHeap.h"
+#include "GCGlobalNew.h"
 #include "GCAlloc.h"
 #include "GCLargeAlloc.h"
-#include "GCGlobalNew.h"
 #include "ZCT.h"
 #include "GC.h"
 #include "GCObject.h"
 #include "GCWeakRef.h"
 #include "WriteBarrier.h"
 
 #include "ZCT-inlines.h"
 
--- a/MMgc/MMgc2008.vcproj
+++ b/MMgc/MMgc2008.vcproj
@@ -1460,16 +1460,20 @@
 				RelativePath=".\GCDebug.h"
 				>
 			</File>
 			<File
 				RelativePath=".\GCHashtable.cpp"
 				>
 			</File>
 			<File
+				RelativePath=".\GCGlobalNew.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\GCHashtable.h"
 				>
 			</File>
 			<File
 				RelativePath="GCHeap.cpp"
 				>
 			</File>
 			<File
--- a/MMgc/manifest.mk
+++ b/MMgc/manifest.mk
@@ -56,16 +56,17 @@ MMgc_CXXSRCS := $(MMgc_CXXSRCS) \
   $(curdir)/GCLargeAlloc.cpp \
   $(curdir)/GCLog.cpp \
   $(curdir)/GCMemoryProfiler.cpp \
   $(curdir)/GCObject.cpp \
   $(curdir)/GCStack.cpp \
   $(curdir)/GCTests.cpp \
   $(curdir)/GCThreads.cpp \
   $(curdir)/ZCT.cpp \
+  $(curdir)/GCGlobalNew.cpp \
   $(NULL)
 
 ifeq (arm,$(TARGET_CPU))
 ifeq (windows,$(TARGET_OS))
 MMgc_ASMSRCS := $(avmplus_ASMSRCS) \
   $(curdir)/WinCEUtil.armasm
   $(NULL)
 endif
--- a/build/avmfeatures.py
+++ b/build/avmfeatures.py
@@ -76,9 +76,11 @@ def featureSettings(o):
     if o.getBoolArg("jni"):
         args += "-DAVMFEATURE_JNI=1 "
     if o.getBoolArg("heap-alloca"):
         args += "-DAVMFEATURE_HEAP_ALLOCA=1 "
     if o.getBoolArg("static-function_ptrs"):
         args += "-DAVMFEATURE_STATIC_FUNCTION_PTRS=1 "
     if o.getBoolArg("indirect-native_thunks"):
         args += "-DAVMFEATURE_INDIRECT_NATIVE_THUNKS=1 "
+    if o.getBoolArg("override-global_new"):
+        args += "-DAVMFEATURE_OVERRIDE_GLOBAL_NEW=1 "
     return args
--- a/core/MethodInfo.cpp
+++ b/core/MethodInfo.cpp
@@ -40,23 +40,16 @@
 
 #ifdef FEATURE_NANOJIT
 #include "CodegenLIR.h"
 #endif
 
 //#define DOPROF
 //#include "../vprof/vprof.h"
 
-#ifndef MMGC_ENABLE_CPP_EXCEPTIONS
-// if MMGC_ENABLE_CPP_EXCEPTIONS is defined, we already include <new> and get placement-new from there
-// if MMGC_ENABLE_CPP_EXCEPTIONS is not defined, we don't want to to include <new> so we need our own placement-new
-// (@todo, this should probably be moved to GCGlobalNew.h)
-inline void* operator new(size_t, void* p) { return p; }
-#endif
-
 namespace avmplus
 {
 	using namespace MMgc;
 
 	/**
 	 * MethodInfo wrapper around a system-generated init method.  Used when
 	 * there is no init method defined in the abc; this only occurs for activation
 	 * object traits and catch-block activation traits.
--- a/core/avmfeatures.as
+++ b/core/avmfeatures.as
@@ -511,16 +511,27 @@ var FEATURES =
   
   <feature>
     <desc> Enabling this will recycle native thunks with similar signatures.
 			This decreases code size at the expense of slightly slower thunks
 			and an extra field in NativeMethodInfo. </desc>
 	<name> AVMFEATURE_INDIRECT_NATIVE_THUNKS </name>
 	<defines> AVMPLUS_INDIRECT_NATIVE_THUNKS </defines>
   </feature>
+
+  <feature>
+    <desc> Enabling this will cause the mmfx_* memory macros to use global new/delete.
+		By default we use specialized new/delete operators and avoid global new/delete.  However
+		this requires some tricks to get multiple inheritance and private destructors to work
+		so some codebases may want to use the simpler path of overriding global new/delete.
+		Note that this feature works independently of AVMFEATURE_USE_SYSTEM_MALLOC.
+      </desc>
+	<name> AVMFEATURE_OVERRIDE_GLOBAL_NEW </name>
+	<defines> MMGC_OVERRIDE_GLOBAL_NEW </defines>
+  </feature>
   
 </features>;
 
 /****************************************************************************
  ***** End of feature definition ********************************************
  ****************************************************************************/
 
 import avmplus.*;
--- a/core/avmfeatures.cpp
+++ b/core/avmfeatures.cpp
@@ -144,11 +144,14 @@ const char * const avmfeatures = ""
     "AVMFEATURE_HEAP_ALLOCA;"
   #endif
   #if AVMFEATURE_STATIC_FUNCTION_PTRS
     "AVMFEATURE_STATIC_FUNCTION_PTRS;"
   #endif
   #if AVMFEATURE_INDIRECT_NATIVE_THUNKS
     "AVMFEATURE_INDIRECT_NATIVE_THUNKS;"
   #endif
+  #if AVMFEATURE_OVERRIDE_GLOBAL_NEW
+    "AVMFEATURE_OVERRIDE_GLOBAL_NEW;"
+  #endif
 ;
 
 #endif // AVMSHELL_BUILD
--- a/core/avmfeatures.h
+++ b/core/avmfeatures.h
@@ -101,16 +101,17 @@
 #undef MMGC_LOCKING
 #undef MMGC_USE_SYSTEM_MALLOC
 #undef MMGC_ENABLE_CPP_EXCEPTIONS
 #undef MMGC_INTERIOR_PTRS
 #undef AVMPLUS_WITH_JNI
 #undef AVMPLUS_HEAP_ALLOCA
 #undef AVMPLUS_STATIC_POINTERS
 #undef AVMPLUS_INDIRECT_NATIVE_THUNKS
+#undef MMGC_OVERRIDE_GLOBAL_NEW
 
 
 
 /* AVMSYSTEM_32BIT
  *
  * Selects a 32-bit architecture
  */
 #if !defined AVMSYSTEM_32BIT || AVMSYSTEM_32BIT != 0 && AVMSYSTEM_32BIT != 1
@@ -475,16 +476,29 @@
  * Enabling this will recycle native thunks with similar signatures.
  * This decreases code size at the expense of slightly slower thunks
  * and an extra field in NativeMethodInfo.
  */
 #if !defined AVMFEATURE_INDIRECT_NATIVE_THUNKS || AVMFEATURE_INDIRECT_NATIVE_THUNKS != 0 && AVMFEATURE_INDIRECT_NATIVE_THUNKS != 1
 #  error "AVMFEATURE_INDIRECT_NATIVE_THUNKS must be defined and 0 or 1 (only)."
 #endif
 
+
+/* AVMFEATURE_OVERRIDE_GLOBAL_NEW
+ *
+ * Enabling this will cause the mmfx_* memory macros to use global new/delete.
+ * By default we use specialized new/delete operators and avoid global new/delete.  However
+ * this requires some tricks to get multiple inheritance and private destructors to work
+ * so some codebases may want to use the simpler path of overriding global new/delete.
+ * Note that this feature works independently of AVMFEATURE_USE_SYSTEM_MALLOC.
+ */
+#if !defined AVMFEATURE_OVERRIDE_GLOBAL_NEW || AVMFEATURE_OVERRIDE_GLOBAL_NEW != 0 && AVMFEATURE_OVERRIDE_GLOBAL_NEW != 1
+#  error "AVMFEATURE_OVERRIDE_GLOBAL_NEW must be defined and 0 or 1 (only)."
+#endif
+
 #if AVMSYSTEM_32BIT
 #  if AVMSYSTEM_64BIT
 #    error "AVMSYSTEM_64BIT is precluded for AVMSYSTEM_32BIT"
 #  endif
 #endif
 #if AVMSYSTEM_64BIT
 #  if AVMSYSTEM_32BIT
 #    error "AVMSYSTEM_32BIT is precluded for AVMSYSTEM_64BIT"
@@ -559,16 +573,17 @@
 
 
 
 
 
 
 
 
+
 #if AVMSYSTEM_IA32+AVMSYSTEM_AMD64+AVMSYSTEM_ARM+AVMSYSTEM_PPC+AVMSYSTEM_SPARC > 1
 #  error "At most one of AVMSYSTEM_IA32,AVMSYSTEM_AMD64,AVMSYSTEM_ARM,AVMSYSTEM_PPC,AVMSYSTEM_SPARC must be defined."
 #endif
 
 #if AVMSYSTEM_UNIX+AVMSYSTEM_MAC+AVMSYSTEM_WIN32+AVMSYSTEM_SYMBIAN != 1
 #  error "Exactly one of AVMSYSTEM_UNIX,AVMSYSTEM_MAC,AVMSYSTEM_WIN32,AVMSYSTEM_SYMBIAN must be defined."
 #endif
 #if AVMFEATURE_WORDCODE_INTERP+AVMFEATURE_ABC_INTERP != 1
@@ -762,13 +777,16 @@
 #  define AVMPLUS_HEAP_ALLOCA
 #endif
 #if AVMFEATURE_STATIC_FUNCTION_PTRS
 #  define AVMPLUS_STATIC_POINTERS
 #endif
 #if AVMFEATURE_INDIRECT_NATIVE_THUNKS
 #  define AVMPLUS_INDIRECT_NATIVE_THUNKS
 #endif
+#if AVMFEATURE_OVERRIDE_GLOBAL_NEW
+#  define MMGC_OVERRIDE_GLOBAL_NEW
+#endif
 
 #ifdef AVMSHELL_BUILD
 extern const char * const avmfeatures;
 #endif
 
--- a/eval/eval.h
+++ b/eval/eval.h
@@ -96,18 +96,16 @@
 #endif
 
 #ifdef DEBUG
 #  define DEBUG_ONLY(x) x
 #else
 #  define DEBUG_ONLY(x)
 #endif
 
-inline void* operator new(size_t, void* p) { return p; }
-
 namespace avmplus
 {
 	namespace RTC
 	{
 		using namespace ActionBlockConstants;
 		
 		// Types
 		//
--- a/platform/mac/mac-platform.h
+++ b/platform/mac/mac-platform.h
@@ -97,16 +97,17 @@
 #include <AvailabilityMacros.h>
 
 #include <sys/mman.h>
 #include <errno.h>
 #include <stdlib.h>
 
 #include <unistd.h>
 #include <pthread.h>
+#include <new>
 
 typedef void *maddr_ptr;
 
 #ifdef AVMPLUS_MAC_CARBON
     /**
 	 * On Mac Carbon, if you compile with Altivec support,
 	 * setjmp is redirected to __vec_setjmp and longjmp is redirected
 	 * to __vec_longjmp.  These routines do not gracefully degrade if
--- a/platform/unix/unix-platform.h
+++ b/platform/unix/unix-platform.h
@@ -109,16 +109,18 @@
 #endif
 
 #ifdef SOLARIS
 typedef caddr_t maddr_ptr;
 #else
 typedef void *maddr_ptr;
 #endif
 
+#include <new>
+
 #ifdef SOLARIS
 // "NP" = non-portable.  Origin of code unclear, may be old.  Consider removing it,
 // it's not used by current Solaris builds.
 #ifdef HAVE_PTHREAD_NP_H
 #include <pthread_np.h>
 #define pthread_getattr_np pthread_attr_get_np
 #endif
 #endif // SOLARIS
--- a/platform/win32/win32-platform.h
+++ b/platform/win32/win32-platform.h
@@ -125,16 +125,26 @@
 #include <math.h>
 
 #include <ctype.h>
 #include <limits.h>
 
 #include <windows.h>
 #include <malloc.h>
 
+#if defined(UNDER_CE) 
+// winmo complains if we try to include <new> and it complains if someone else includes new before us so...
+#ifndef __PLACEMENT_NEW_INLINE
+#define __PLACEMENT_NEW_INLINE
+inline void* operator new(size_t, void* p) { return p; }
+#endif
+#else
+// others want the system new
+#include <new>
+#endif
 
 #ifdef _ARM_
 	// Windows Mobile doesn't provide intptr_t or uintptr_t
 	typedef __int32				intptr_t; 
 	typedef unsigned __int32	uintptr_t; 
 #endif
 
 typedef void *maddr_ptr;
--- a/shell/avmshell-features.h
+++ b/shell/avmshell-features.h
@@ -152,9 +152,13 @@
 
 #if !defined(_DEBUG) && !defined(DEBUG)
 	// by default, nanojit enables NJ_VERBOSE mode when AVMPLUS_VERBOSE is on,
 	// which is enabled for Debug *and* Debugger builds. 
 	#define NJ_VERBOSE_DISABLED 1
 	#define NJ_PROFILE_DISABLED 1
 #endif
 
+#ifndef AVMFEATURE_OVERRIDE_GLOBAL_NEW
+  #define AVMFEATURE_OVERRIDE_GLOBAL_NEW 0
+#endif
+
 #endif // __avmshell_features__