blob: 524971e83be19348875d5054ecbd62e4b1500f6f [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*-
****************************************************************************
*
* File: NABasicObject.cpp (previously under /common)
* Description:
*
* Created: 5/6/98
* Language: C++
*
*
*
****************************************************************************
*/
#include "Platform.h"
#include <iosfwd>
using namespace std;
#include <stdlib.h>
#include "ComASSERT.h"
#include "NAMemory.h"
#include "HeapLog.h"
//#include <cextdecs (DEBUG)>
// -----------------------------------------------------------------------
// Methods for NABasicObject
// -----------------------------------------------------------------------
// Here we cannot initialize the heap pointer because that would overwrite
// the value from the "operator new" below.
// Stack or statically allocated objects will just have random garbage in
// this field but as long as noone tries to "delete" them (as noone should)
// that will not matter (except to the Purify tool which may report UMR errors).
NABasicObject::NABasicObject() {}
// Note that this just ignores the passed object, which is correct:
// we do *not* want to copy its heap pointer!
NABasicObject::NABasicObject(const NABasicObject&) {}
// Note that this just ignores the passed object, which is correct:
// we do *not* want to copy its heap pointer!
// Otherwise, a default operator= on a NABasicObject-derived class would
// overwrite the heap pointer, a very bad thing.
NABasicObject& NABasicObject::operator=(const NABasicObject&) { return *this; }
void* NABasicObject::operator new(size_t t, CollHeap* h, NABoolean failureIsFatal)
{
if (t < sizeof(NABasicObject))
t = sizeof(NABasicObject); // always allocate some size.
void* p;
if (NOT_CHECK_NAHEAP(h))
{
// This is asserted only because the check in 'operator delete' below
// depends on it -- but that check is rather half-baked anyway.
// So this is ComDEBUG (no-op if Release build) rather than ComABORT.
ComDEBUG(h != invalidHeapPtr());
p = h->allocateMemory(t, failureIsFatal);
}
else
{
#ifdef NA_LEAK_DETECTION
get_caller_location();
#endif
p = ::operator new(t);
// HEAPLOG_ADD_ENTRY(p, t, NA_HEAP_BASIC, "NABasic Heap")
}
if (p)
((NABasicObject*)p)->h_ = h;
else
{
if (failureIsFatal)
{
ComABORT(p);
}
}
return p;
}
void* NABasicObject::operator new(size_t t, void* loc, NAMemory* h)
{
if (loc != NULL)
{
((NABasicObject*)loc)->h_ = h;
return loc;
}
return 0;
}
void NABasicObject::operator delete(void* p)
{
if (p) // "delete NULL;" is legal in C++, obviously a no-op
{
CollHeap* h = ((NABasicObject*)p)->h_;
// ComDEBUG(h != invalidHeapPtr());
if (h == invalidHeapPtr())
{
#ifndef NDEBUG
cerr << "**WARNING: " << __FILE__ << ": "
<< "Ignoring attempt to delete pointer twice "
<< "(possible memory leak at " << p << "; need to run Purify)"
<< endl;
#endif
return;
}
((NABasicObject*)p)->h_ = invalidHeapPtr();
if (NOT_CHECK_NAHEAP(h))
h->deallocateMemory(p);
else
{
// HEAPLOG_DELETE_ENTRY(p, NA_HEAP_BASIC)
::operator delete(p);
}
}
}
void NABasicObject::operator delete(void* p, NAMemory*h, NABoolean f)
{
if (p)
{
if (NOT_CHECK_NAHEAP(h))
h->deallocateMemory(p);
else
::operator delete(p);
}
}
void NABasicObject::operator delete(void* p, void*, NAMemory*)
{
// This shouldn't do anything.
}
void* NABasicObject::operator new[](size_t t, CollHeap* h, NABoolean failureIsFatal)
{
if (t < sizeof(NABasicObject))
t = sizeof(NABasicObject); // always allocate some size.
void* p;
if (NOT_CHECK_NAHEAP(h))
{
// This is asserted only because the check in 'operator delete' below
// depends on it -- but that check is rather half-baked anyway.
// So this is ComDEBUG (no-op if Release build) rather than ComABORT.
ComDEBUG(h != invalidHeapPtr());
p = h->allocateMemory(t, failureIsFatal);
}
else
{
#ifdef NA_LEAK_DETECTION
get_caller_location();
#endif
p = ::operator new(t);
// HEAPLOG_ADD_ENTRY(p, t, NA_HEAP_BASIC, "NABasic Heap")
}
if (p)
((NABasicObject*)p)->h_ = h;
else
{
if (failureIsFatal)
{
ComABORT(p);
}
}
return p;
}
void NABasicObject::operator delete[](void* p)
{
#if 0
if (p) // "delete NULL;" is legal in C++, obviously a no-op
{
//NGG CollHeap* h = ((NABasicObject*)p)->h_;
NAHeap* h = (NAHeap *) ((NABasicObject*)p)->h_;
// ComDEBUG(h != invalidHeapPtr());
if (h == invalidHeapPtr())
{
#ifndef NDEBUG
cerr << "**WARNING: " << __FILE__ << ": "
<< "Ignoring attempt to delete pointer twice "
<< "(possible memory leak at " << p << "; need to run Purify)"
<< endl;
#endif
return;
}
((NABasicObject*)p)->h_ = invalidHeapPtr();
if (h)
h->deallocateMemory(p);
else
{
// HEAPLOG_DELETE_ENTRY(p, NA_HEAP_BASIC)
::operator delete(p);
}
}
#endif
::operator delete(p);
}
// This function will be called if the constructor throws an exception.
void NABasicObject::operator delete[](void* p, NAMemory* h, NABoolean)
{
if ( p ) {
if (NOT_CHECK_NAHEAP(h))
h->deallocateMemory(p);
else
::operator delete(p);
}
}
//
//void* operator new[](size_t, NAMemory* h, NABoolean failureIsFatal)
//{
//return NABasicObject::operator new(t, h, failureIsFatal);
//}
//void* NABasicObject::operator delete[](void* p /* , another arg; see C++ ARM*/)
//{
// We need to call multiple destructors here, one for each object in
// the array, and then deallocate ...
// NABasicObject::operator delete(p); /*won't work, no dtors called*/
//}
// Calls to this debugging method have been put into the getPtr methods in the
// optimizer; further bugproofing calls could be placed elsewhere.
//
// To debug, set a breakpoint at the "return -1", run the program, and see where
// you are when the invalid dereference occurs and what object type it is (was).
// You can then set a breakpoint in that object class's destructor to see when
// that particular instance is being destroyed and being marked invalid/free.
// (Although not actually being freed by deallocateMemory() yet -- which is why
// Purify can't find this "FMR" error, and also why your code continues to run
// okay FOR NOW; it may not on a future platform or future deallocation scheme.
// This finds latent bugs.)
#if !defined(NDEBUG)
Int32 NABasicObject::checkInvalidObject(const void* const referencingObject)
{
if (this && maybeInvalidObject())
{
Lng32 stackVar = (char*)this - (char*)&stackVar;
if (stackVar < 0) stackVar = -stackVar;
cerr << "**ERROR: Object " << (void*)this;
if (stackVar <= 8192)
cerr << " may be invalid (may be on stack, currently "
<< (void*)&stackVar << ")";
else
cerr << " is invalid";
if (referencingObject)
cerr << " (pointer from " << (void*)referencingObject << ")";
cerr << ".**" << endl;
return -1;
}
return 0;
}
#endif
// -----------------------------------------------------------------------
// overloaded new operator for CollHeap*
// -----------------------------------------------------------------------
// The following new/delete operator should follow the rule of new
// operator, i.e.
// in the case of out of space, it should
// - call the new_handler if being set previously
// - if still no space, throw the bad_alloc exception.
// Since now the new/delete are used by executor, which can not
// take any global variables, need to make sure set_new_handler does
// not use any globals before using it.
// The compiler does not support exception yet. Should be done when
// the compiler supports exception.
//
void* operator new (size_t t, CollHeap* h)
{
if (NOT_CHECK_NAHEAP(h))
{
return h->allocateMemory(t);
} else {
#ifdef NA_LEAK_DETECTION
get_caller_location();
#endif
return (::new char[t] );
}
}
void* operator new[] (size_t t, CollHeap* h)
{
//return ( (h) ? h->allocateMemory(t) : (::new char[t] ) );
if (NOT_CHECK_NAHEAP(h))
{
return h->allocateMemory(t);
} else {
#ifdef NA_LEAK_DETECTION
get_caller_location();
#endif
return (::new char[t] );
}
}
void* operator new[] (size_t t, CollHeap* h, NABoolean failureIsFatal)
{
if (NOT_CHECK_NAHEAP(h))
{
return h->allocateMemory(t, failureIsFatal);
} else {
#ifdef NA_LEAK_DETECTION
get_caller_location();
#endif
return (::new char[t] );
}
}