Compare commits

..

3 Commits

Author SHA1 Message Date
dkl%redhat.com
b52a1dc48a Various fixes. Added CanSeeProduct functionality back in but also left in old style product groups. Removed references to usebuggroupsentry and usebuggroups since we want it on all the time.
git-svn-id: svn://10.0.0.236/branches/Bugzilla_PgSQL_Groups_Branch@122814 18797224-902f-48f8-a5cc-f745e15eee43
2002-06-06 18:07:41 +00:00
dkl%redhat.com
48b5f960fd Initial creation of Bugzilla_PgSQL_Groups_Branch 2002/05/23
git-svn-id: svn://10.0.0.236/branches/Bugzilla_PgSQL_Groups_Branch@122087 18797224-902f-48f8-a5cc-f745e15eee43
2002-05-23 19:34:21 +00:00
(no author)
73bf11394f This commit was manufactured by cvs2svn to create branch
'Bugzilla_PgSQL_Groups_Branch'.

git-svn-id: svn://10.0.0.236/branches/Bugzilla_PgSQL_Groups_Branch@122018 18797224-902f-48f8-a5cc-f745e15eee43
2002-05-22 09:21:37 +00:00
3422 changed files with 104276 additions and 558837 deletions

View File

@@ -1,217 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "MMgc.h"
#define kBlockHeadSize offsetof(MMgc::FixedAlloc::FixedBlock, items)
namespace MMgc
{
FixedAlloc::FixedAlloc(int itemSize)
{
m_heap = GCHeap::GetGCHeap();
m_firstBlock = NULL;
m_lastBlock = NULL;
m_firstFree = NULL;
m_maxAlloc = 0;
#ifdef MEMORY_INFO
itemSize += DebugSize();
#endif
m_itemSize = itemSize;
// The number of items per block is kBlockSize minus
// the # of pointers at the base of each page.
size_t usableSpace = GCHeap::kBlockSize - kBlockHeadSize;
m_itemsPerBlock = usableSpace / m_itemSize;
}
FixedAlloc::~FixedAlloc()
{
// Free all of the blocks
while (m_firstBlock) {
#ifdef MEMORY_INFO
if(m_firstBlock->numAlloc > 0) {
// go through every memory location, if the fourth 4 bytes cast as
// an integer isn't 0xedededed then its allocated space and the integer is
// an index into the stack trace table, the first 4 bytes will contain
// the freelist pointer for free'd items (which is why the trace index is
// stored in the second 4)
// first 4 bytes - free list pointer
// 2nd 4 bytes - alloc stack trace
// 3rd 4 bytes - free stack trace
// 4th 4 bytes - 0xedededed if freed correctly
unsigned int *mem = (unsigned int*) m_firstBlock->items;
unsigned int itemNum = 0;
while(itemNum++ < m_itemsPerBlock) {
unsigned int fourthInt = *(mem+3);
if(fourthInt != 0xedededed) {
GCDebugMsg(false, "Leaked %d byte item. Addr: 0x%x\n", GetItemSize(), mem+2);
PrintStackTraceByIndex(*(mem+1));
}
mem += (m_itemSize / sizeof(int));
}
GCAssert(false);
}
// go through every item on the free list and make sure it wasn't written to
// after being poisoned.
void *item = m_firstBlock->firstFree;
while(item) {
for(int i=3, n=(m_firstBlock->size>>2)-1; i<n; i++)
{
unsigned int data = ((int*)item)[i];
if(data != 0xedededed)
{
GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:");
PrintStackTrace((int*)item+2);
GCDebugMsg(false, "Deletion trace:");
PrintStackTrace((int*)item+3);
GCDebugMsg(true, "Deleted item write violation!");
}
}
// next free item
item = *((void**)item);
}
#endif
FreeChunk(m_firstBlock);
}
}
size_t FixedAlloc::Allocated()
{
size_t bytes = 0;
FixedBlock *b = m_firstBlock;
while(b)
{
bytes += b->numAlloc * b->size;
b = b->next;
}
return bytes;
}
FixedAlloc::FixedBlock* FixedAlloc::CreateChunk()
{
// Allocate a new block
m_maxAlloc += m_itemsPerBlock;
FixedBlock* b = (FixedBlock*) m_heap->Alloc(1, true, false);
GCAssert(m_itemSize <= 0xffff);
b->numAlloc = 0;
b->size = (uint16)m_itemSize;
b->firstFree = 0;
b->nextItem = b->items;
b->alloc = this;
#ifdef _DEBUG
// deleted and unused memory is 0xed'd, this is important for leak diagnostics
memset(b->items, 0xed, m_itemSize * m_itemsPerBlock);
#endif
// Link the block at the end of the list
b->prev = m_lastBlock;
b->next = 0;
if (m_lastBlock) {
m_lastBlock->next = b;
}
if (!m_firstBlock) {
m_firstBlock = b;
}
m_lastBlock = b;
// Add our new ChunkBlock to the firstFree list (which should be empty)
if (m_firstFree)
{
GCAssert(m_firstFree->prevFree == 0);
m_firstFree->prevFree = b;
}
b->nextFree = m_firstFree;
b->prevFree = 0;
m_firstFree = b;
return b;
}
void FixedAlloc::FreeChunk(FixedBlock* b)
{
m_maxAlloc -= m_itemsPerBlock;
// Unlink the block from the list
if (b == m_firstBlock) {
m_firstBlock = b->next;
} else {
b->prev->next = b->next;
}
if (b == m_lastBlock) {
m_lastBlock = b->prev;
} else {
b->next->prev = b->prev;
}
// If this is the first free block, pick a new one...
if ( m_firstFree == b )
m_firstFree = b->nextFree;
else if (b->prevFree)
b->prevFree->nextFree = b->nextFree;
if (b->nextFree)
b->nextFree->prevFree = b->prevFree;
// Free the memory
m_heap->Free(b);
}
size_t FixedAlloc::GetItemSize() const
{
return m_itemSize - DebugSize();
}
void *FastAllocator::operator new[](size_t size)
{
return FixedMalloc::GetInstance()->Alloc(size);
}
void FastAllocator::operator delete [](void *item)
{
FixedMalloc::GetInstance()->Free(item);
}
}

View File

@@ -1,299 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __FixedAlloc__
#define __FixedAlloc__
namespace MMgc
{
/**
* This is a fast, fixed-size memory allocator for manually freed
* objects.
*
* Memory is allocated from the system in 4096 byte chunks
* via the GCHeap class. Not that this won't work well for
* large objects (>400 bytes). For that, we have the
* FixedAllocLarge allocator which will allocate multiple
* pages at a time to minimize waste.
*/
class FixedAlloc : public GCAllocObject
{
friend class FixedMalloc;
friend class FastAllocator;
friend class GC;
public:
FixedAlloc(int itemSize);
~FixedAlloc();
inline void* Alloc(size_t size)
{
(void)size;
GCAssertMsg(((size_t)m_itemSize >= size), "allocator itemsize too small");
if(!m_firstFree) {
if(CreateChunk() == NULL) {
GCAssertMsg(false, "Out of memory!");
return NULL;
}
}
FixedBlock* b = m_firstFree;
GCAssert(b && !IsFull(b));
b->numAlloc++;
// Consume the free list if available
void *item = NULL;
if (b->firstFree) {
item = b->firstFree;
b->firstFree = *((void**)item);
// assert that the freelist hasn't been tampered with (by writing to the first 4 bytes)
GCAssert(b->firstFree == NULL ||
(b->firstFree >= b->items &&
(((intptr)b->firstFree - (intptr)b->items) % b->size) == 0 &&
(intptr) b->firstFree < ((intptr)b & ~0xfff) + GCHeap::kBlockSize));
#ifdef MEMORY_INFO
// ensure previously used item wasn't written to
// -1 because write back pointer space isn't poisoned.
for(int i=3, n=(b->size>>2)-1; i<n; i++)
{
int data = ((int*)item)[i];
if(data != (int)0xedededed)
{
GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:", (int*)item+2);
PrintStackTrace((int*)item+2);
GCDebugMsg(false, "Deletion trace:");
PrintStackTrace((int*)item+3);
GCDebugMsg(true, "Deleted item write violation!");
}
}
#endif
} else {
// Take next item from end of block
item = b->nextItem;
GCAssert(item != 0);
if(!IsFull(b)) {
// There are more items at the end of the block
b->nextItem = (void *) ((intptr)item+m_itemSize);
#ifdef MEMORY_INFO
// space made in ctor
item = DebugDecorate(item, size + DebugSize(), 6);
memset(item, 0xfa, size);
#endif
return item;
}
b->nextItem = 0;
}
// If we're out of free items, be sure to remove ourselves from the
// list of blocks with free items.
if (IsFull(b)) {
m_firstFree = b->nextFree;
b->nextFree = NULL;
GCAssert(b->prevFree == NULL);
if (m_firstFree)
m_firstFree->prevFree = 0;
else
CreateChunk();
}
#ifdef MEMORY_INFO
// space made in ctor
item = DebugDecorate(item, size + DebugSize(), 6);
memset(item, 0xfa, size);
#endif
GCAssertMsg(item != NULL, "Out of memory");
return item;
}
static inline void Free(void *item)
{
FixedBlock *b = (FixedBlock*) ((uint32)item & ~0xFFF);
#ifdef MEMORY_INFO
item = DebugFree(item, 0xED, 6);
#endif
#ifdef _DEBUG
// ensure that we are freeing a pointer on a item boundary
GCAssert(((intptr)item - (intptr)b->items) % b->alloc->m_itemSize == 0);
#endif
// Add this item to the free list
*((void**)item) = b->firstFree;
b->firstFree = item;
// We were full but now we have a free spot, add us to the free block list.
if (b->numAlloc == b->alloc->m_itemsPerBlock)
{
GCAssert(!b->nextFree && !b->prevFree);
b->nextFree = b->alloc->m_firstFree;
if (b->alloc->m_firstFree)
b->alloc->m_firstFree->prevFree = b;
b->alloc->m_firstFree = b;
}
#ifdef _DEBUG
else // we should already be on the free list
{
GCAssert ((b == b->alloc->m_firstFree) || b->prevFree);
}
#endif
b->numAlloc--;
if(b->numAlloc == 0) {
b->alloc->FreeChunk(b);
}
}
size_t Allocated();
size_t GetItemSize() const;
int GetMaxAlloc() const { return m_maxAlloc; }
static FixedAlloc *GetFixedAlloc(void *item)
{
FixedBlock *b = (FixedBlock*) ((uint32)item & ~0xFFF);
#ifdef _DEBUG
// Attempt to sanity check this ptr: numAllocs * size should be less than kBlockSize
GCAssertMsg(((b->numAlloc * b->size) < GCHeap::kBlockSize), "Size called on ptr not part of FixedBlock");
#endif
return b->alloc;
}
private:
struct FixedBlock
{
void* firstFree; // first item on free list
void* nextItem; // next free item
FixedBlock* next;
FixedBlock* prev;
uint16 numAlloc;
uint16 size;
FixedBlock *prevFree;
FixedBlock *nextFree;
FixedAlloc *alloc;
char items[1];
};
GCHeap *m_heap;
unsigned int m_itemsPerBlock;
size_t m_itemSize;
// The list of chunk blocks
FixedBlock* m_firstBlock;
FixedBlock* m_lastBlock;
// The lowest priority block that has free items
FixedBlock* m_firstFree;
int m_maxAlloc;
bool IsFull(FixedBlock *b) const { return b->numAlloc == m_itemsPerBlock; }
FixedBlock* CreateChunk();
void FreeChunk(FixedBlock* b);
static inline size_t Size(const void *item)
{
FixedBlock *b = (FixedBlock*) ((uint32)item & ~0xFFF);
#ifdef _DEBUG
// Attempt to sanity check this ptr: numAllocs * size should be less than kBlockSize
GCAssertMsg(((b->numAlloc * b->size) < GCHeap::kBlockSize), "Size called on ptr not part of FixedBlock");
#endif
return b->size;
}
};
class FixedAllocSafe : public FixedAlloc
{
public:
FixedAllocSafe(int itemSize) : FixedAlloc(itemSize) {}
void* Alloc(size_t size)
{
#ifdef GCHEAP_LOCK
GCAcquireSpinlock lock(m_spinlock);
#endif
return FixedAlloc::Alloc(size);
}
void Free(void *ptr)
{
#ifdef GCHEAP_LOCK
GCAcquireSpinlock lock(m_spinlock);
#endif
FixedAlloc::Free(ptr);
}
static FixedAllocSafe *GetFixedAllocSafe(void *item)
{
return (FixedAllocSafe*) FixedAlloc::GetFixedAlloc(item);
}
private:
#ifdef GCHEAP_LOCK
GCSpinLock m_spinlock;
#endif
};
/**
* classes that need fast lock free allocation should subclass this and pass
* a FixedAlloc * to the new parameter. One new/delete are lock free, scalar
* allocations use the normal locked general size allocator.
*/
class FastAllocator
{
public:
static void *operator new(size_t size, FixedAlloc *alloc)
{
return alloc->Alloc(size);
}
static void operator delete (void *item)
{
FixedAlloc::Free(item);
}
// allow array allocation as well
static void *operator new[](size_t size);
static void operator delete [](void *item);
};
}
#endif /* __FixedAlloc__ */

View File

@@ -1,141 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
// For memset
#include <string.h>
#include "MMgc.h"
namespace MMgc
{
FixedMalloc *FixedMalloc::instance = NULL;
// Size classes for our Malloc. We start with a 4 byte allocator and then from
// 8 to 128, size classes are spaced evenly 8 bytes apart, then from 128 to 1968 they
int16 FixedMalloc::kSizeClasses[kNumSizeClasses] = {
4, 8, 16, 24, 32, 40, 48, 56, 64, 72, //0-9
80, 88, 96, 104, 112, 120, 128, 144, 160, 176, //10-19
184, 192, 200, 208, 224, 232, 248, 264, 288, 312, //20-29
336, 368, 400, 448, 504, 576, 672, 808, 1016, 1352, //30-39
2032, //40
};
// This is an index which indicates that allocator i should be used
// if kSizeClassIndex[i] items fit into a 4096 byte page.
uint8 FixedMalloc::kSizeClassIndex[32] = {
40, 40, 40, 39, 38, 37, 36, 35, 34, 33, //0-10
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, //10-19
22, 21, 20, 19, 19, 18, 18, 18, 17, 17, //20-29
17, 16 //30-31
};
void FixedMalloc::Init()
{
GCAssert(instance == NULL);
instance = new FixedMalloc();
}
void FixedMalloc::Destroy()
{
GCAssert(instance != NULL);
delete instance;
instance = NULL;
}
FixedMalloc::FixedMalloc()
{
m_heap = GCHeap::GetGCHeap();
// Create all the allocators up front (not lazy)
// so that we don't have to check the pointers for
// NULL on every allocation.
for (int i=0; i<kNumSizeClasses; i++) {
// FIXME: by default FixedAlloc uses 4K chunks, for the
// more common size classes maybe we should use 8/16/32.
// FIXME: we could use FixedAllocLarge for the bigger size
// classes but how to call the right Free would need to be work out
m_allocs[i] = new FixedAllocSafe(kSizeClasses[i]);
}
}
FixedMalloc::~FixedMalloc()
{
for (int i=0; i<kNumSizeClasses; i++) {
FixedAllocSafe *a = m_allocs[i];
delete a;
}
}
size_t FixedMalloc::Allocated()
{
size_t bytes = 0;
for (int i=0; i<kNumSizeClasses; i++) {
FixedAllocSafe *a = m_allocs[i];
bytes += a->Allocated();
}
// FIXME: what about big blocks?
return bytes;
}
FixedAllocSafe *FixedMalloc::FindSizeClass(size_t size) const
{
GCAssertMsg(size > 0, "cannot allocate a 0 sized block\n");
size_t size8 = (size+7)&~7; // round up to multiple of 8
// Buckets up to 128 are spaced evenly at 8 bytes.
if (size <= 128) {
unsigned index = size > 4 ? size8 >> 3 : 0;
FixedAllocSafe *a = m_allocs[index];
// make sure I fit
GCAssert(size <= a->GetItemSize());
// make sure I don't fit
GCAssert(index == 0 || size > m_allocs[index-1]->GetItemSize());
return a;
}
// This is the fast lookup table implementation to
// find the right allocator.
// FIXME: do this w/o division!
unsigned index = kSizeClassIndex[kPageUsableSpace/size8];
// assert that I fit
GCAssert(size <= m_allocs[index]->GetItemSize());
// assert that I don't fit (makes sure we don't waste space
GCAssert(size > m_allocs[index-1]->GetItemSize());
return m_allocs[index];
}
}

View File

@@ -1,154 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __Malloc__
#define __Malloc__
namespace MMgc
{
/**
* A general purpose memory allocator using size classes
*/
class FixedMalloc : public GCAllocObject
{
friend class GC;
public:
static void Init();
static void Destroy();
/**
* return the number of bytes of memory issued
*/
size_t Allocated();
static FixedMalloc *GetInstance() { return instance; }
inline void* Alloc(size_t size)
{
void *item;
GCAssert(size + 3 > size);
// overflow detection
if(size+3 < size)
return NULL;
size = (size+3)&~3;
if (size <= (size_t)kLargestAlloc) {
item = FindSizeClass(size)->Alloc(size);
} else {
item = LargeAlloc(size);
}
return item;
}
inline void Free(void *item)
{
if(item == 0)
return;
// small things are never allocated on the 4K boundary b/c the block
// header structure is stored there, large things always are
if(IsLargeAlloc(item)) {
LargeFree(item);
} else {
FixedAllocSafe::GetFixedAllocSafe(item)->Free(item);
}
}
static size_t Size(const void *item)
{
size_t size;
if(IsLargeAlloc(item)) {
size = LargeSize(item);
} else {
size = FixedAlloc::Size(item);
}
#ifdef MEMORY_INFO
size -= DebugSize();
#endif
return size;
}
// private:
FixedMalloc();
~FixedMalloc();
static FixedMalloc *instance;
const static int kLargestAlloc = 2032;
const static int kNumSizeClasses = 41;
const static int kPageUsableSpace = GCHeap::kBlockSize - offsetof(MMgc::FixedAlloc::FixedBlock, items);
static int16 kSizeClasses[kNumSizeClasses];
static uint8 kSizeClassIndex[32];
GCHeap *m_heap;
FixedAllocSafe *m_allocs[kNumSizeClasses];
FixedAllocSafe *FindSizeClass(size_t size) const;
static bool IsLargeAlloc(const void *item)
{
// space made in ctor
item = GetRealPointer(item);
return ((intptr) item & 0xFFF) == 0;
}
inline void *LargeAlloc(size_t size)
{
size += DebugSize();
size_t blocksNeeded = ((size+0xfff)&~0xfff) >> 12;
void *item = m_heap->Alloc(blocksNeeded, true, false);
if(!item)
{
GCAssertMsg(item != NULL, "Large allocation of %d blocks failed!");
}
else
{
#ifdef MEMORY_INFO
item = DebugDecorate(item, size, 5);
memset(item, 0xfb, size - DebugSize());
#endif
}
return item;
}
inline void LargeFree(void *item)
{
#ifdef MEMORY_INFO
item = DebugFree(item, 0xed, 5);
#endif
m_heap->Free(item);
}
static size_t LargeSize(const void *item)
{
return GCHeap::GetGCHeap()->Size(item) * GCHeap::kBlockSize;
}
};
}
#endif /* __Malloc__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,608 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stddef.h>
#include <string.h>
#include <stdlib.h>
#include "MMgc.h"
namespace MMgc
{
GCAlloc::GCAlloc(GC* gc, int itemSize, bool containsPointers, bool isRC, int sizeClassIndex) :
GCAllocBase(gc),
containsPointers(containsPointers),
containsRCObjects(isRC),
m_sizeClassIndex(sizeClassIndex)
{
// Round itemSize to the nearest boundary of 8
itemSize = (itemSize+7)&~7;
m_firstBlock = NULL;
m_lastBlock = NULL;
m_firstFree = NULL;
m_numAlloc = 0;
m_maxAlloc = 0;
m_itemSize = itemSize;
m_numBlocks = 0;
// The number of items per block is kBlockSize minus
// the # of pointers at the base of each page.
m_itemsPerBlock = (kBlockSize - sizeof(GCBlock)) / m_itemSize;
m_numBitmapBytes = (m_itemsPerBlock>>1) + (m_itemsPerBlock & 1);
// round up to 4 bytes so we can go through the bits 8 items at a time
m_numBitmapBytes = (m_numBitmapBytes+3)&~3;
GCAssert(m_numBitmapBytes<<1 >= m_itemsPerBlock);
int usedSpace = m_itemsPerBlock * m_itemSize + sizeof(GCBlock);
GCAssert(usedSpace <= kBlockSize);
GCAssert(kBlockSize - usedSpace < (int)m_itemSize);
if(kBlockSize - usedSpace >= m_numBitmapBytes) {
m_bitsInPage = true;
} else {
m_bitsInPage = false;
}
// compute values that let us avoid division
GCAssert(m_itemSize <= 0xffff);
ComputeMultiplyShift((uint16)m_itemSize, multiple, shift);
}
GCAlloc::~GCAlloc()
{
// Free all of the blocks
GCAssertMsg(GetNumAlloc() == 0, "You have leaks");
while (m_firstBlock) {
if(((intptr)m_firstBlock->bits & 0xfff) == 0)
m_gc->GetGCHeap()->Free(m_firstBlock->bits);
#ifdef _DEBUG
// go through every item on the free list and make sure it wasn't written to
// after being poisoned.
void *item = m_firstBlock->firstFree;
while(item) {
for(int i=3, n=(m_firstBlock->size>>2)-1; i<n; i++)
{
int data = ((int*)item)[i];
if(data != 0xbabababa && data != 0xcacacaca)
{
GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:");
PrintStackTrace((int*)item+2);
GCDebugMsg(false, "Deletion trace:");
PrintStackTrace((int*)item+3);
GCDebugMsg(true, "Deleted item write violation!");
}
}
// next free item
item = *((void**)item);
}
#endif
GCBlock *b = m_firstBlock;
UnlinkChunk(b);
FreeChunk(b);
}
}
GCAlloc::GCBlock* GCAlloc::CreateChunk()
{
// Get space in the bitmap. Do this before allocating the actual block,
// since we might call GC::AllocBlock for more bitmap space and thus
// cause some incremental marking.
uint32* bits = NULL;
if(!m_bitsInPage)
bits = m_gc->GetBits(m_numBitmapBytes, m_sizeClassIndex);
// Allocate a new block
m_maxAlloc += m_itemsPerBlock;
m_numBlocks++;
int numBlocks = kBlockSize/GCHeap::kBlockSize;
GCBlock* b = (GCBlock*) m_gc->AllocBlock(numBlocks, GC::kGCAllocPage);
b->gc = m_gc;
b->alloc = this;
b->size = m_itemSize;
b->needsSweeping = false;
b->bits = m_bitsInPage ? (uint32*)((char*)b + sizeof(GCBlock)) : bits;
// Link the block at the end of the list
b->prev = m_lastBlock;
b->next = 0;
if (m_lastBlock) {
m_lastBlock->next = b;
}
if (!m_firstBlock) {
m_firstBlock = b;
}
m_lastBlock = b;
// Add our new ChunkBlock to the firstFree list (which should be empty)
if (m_firstFree)
{
GCAssert(m_firstFree->prevFree == 0);
m_firstFree->prevFree = b;
}
b->nextFree = m_firstFree;
b->prevFree = 0;
m_firstFree = b;
// calculate back from end (better alignment, no dead space at end)
b->items = (char*)b+GCHeap::kBlockSize - m_itemsPerBlock * m_itemSize;
b->nextItem = b->items;
b->numItems = 0;
return b;
}
void GCAlloc::UnlinkChunk(GCBlock *b)
{
m_maxAlloc -= m_itemsPerBlock;
m_numBlocks--;
// Unlink the block from the list
if (b == m_firstBlock) {
m_firstBlock = b->next;
} else {
b->prev->next = b->next;
}
if (b == m_lastBlock) {
m_lastBlock = b->prev;
} else {
b->next->prev = b->prev;
}
if(b->nextFree || b->prevFree || b == m_firstFree) {
RemoveFromFreeList(b);
}
#ifdef _DEBUG
b->next = b->prev = NULL;
b->nextFree = b->prevFree = NULL;
#endif
}
void GCAlloc::FreeChunk(GCBlock* b)
{
GCAssert(b->numItems == 0);
if(!m_bitsInPage) {
memset(b->GetBits(), 0, m_numBitmapBytes);
m_gc->FreeBits(b->GetBits(), m_sizeClassIndex);
b->bits = NULL;
}
// Free the memory
m_gc->FreeBlock(b, 1);
}
void* GCAlloc::Alloc(size_t size, int flags)
{
(void)size;
GCAssertMsg(((size_t)m_itemSize >= size), "allocator itemsize too small");
start:
if (m_firstFree == NULL) {
if (CreateChunk() == NULL) {
return NULL;
}
}
GCBlock* b = m_firstFree;
// lazy sweeping
if(b->needsSweeping) {
if(!GC::useNewSweep || !m_gc->collecting) {
if(Sweep(b)) {
if(GC::useNewSweep) {
UnlinkChunk(b);
FreeChunk(b);
}
goto start;
}
} else if(b->IsFull()) {
// we are collecting (possibly a Finalize allocation) so we can't
// sweep the page yet (because objects can examine other objects during
// finalize and Sweep poisons. So if we don't have any items (hence
// the IsFull()) we have to create a use a different chunk creating a new
// one if necessary
b = m_firstFree->nextFree;
if(!b) {
CreateChunk();
b = m_firstFree;
}
}
}
GCAssert(b && !b->IsFull());
void *item;
if(b->firstFree) {
item = b->firstFree;
b->firstFree = *((void**)item);
// clear free list pointer, the rest was zero'd in free
*(int*) item = 0;
#ifdef MEMORY_INFO
// ensure previously used item wasn't written to
// -1 because write back pointer space isn't poisoned.
for(int i=3, n=(b->size>>2)-1; i<n; i++)
{
int data = ((int*)item)[i];
if(data != 0xcacacaca && data != 0xbabababa)
{
GCDebugMsg(false, "Object 0x%x was written to after it was deleted, allocation trace:", item);
PrintStackTrace((int*)item+2);
GCDebugMsg(false, "Deletion trace:");
PrintStackTrace((int*)item+3);
GCDebugMsg(true, "Deleted item write violation!");
}
}
#endif
} else {
item = b->nextItem;
if(((int)((char*)item + b->size) & 0xfff) != 0) {
b->nextItem = (char*)item + b->size;
} else {
b->nextItem = NULL;
}
}
// set up bits, items start out white and whether they need finalization
// is determined by the caller
// make sure we ended up in the right place
GCAssert(((flags&GC::kContainsPointers) != 0) == ContainsPointers());
// this assumes what we assert
GCAssert((unsigned long)GC::kFinalize == (unsigned long)GCAlloc::kFinalize);
int index = GetIndex(b, item);
GCAssert(index >= 0);
ClearBits(b, index, 0xf);
SetBit(b, index, flags & kFinalize);
b->numItems++;
#ifdef MEMORY_INFO
m_numAlloc++;
#endif
// If we're out of free items, be sure to remove ourselves from the
// list of blocks with free items.
if (b->IsFull()) {
m_firstFree = b->nextFree;
b->nextFree = NULL;
GCAssert(b->prevFree == NULL);
if (m_firstFree)
m_firstFree->prevFree = 0;
}
return item;
}
/* static */
void GCAlloc::Free(void *item)
{
GCBlock *b = (GCBlock*) ((intptr) item & ~0xFFF);
GCAlloc *a = b->alloc;
#ifdef _DEBUG
// check that its not already been freed
void *free = b->firstFree;
while(free) {
GCAssert(free != item);
free = *((void**) free);
}
#endif
int index = GetIndex(b, item);
if(GetBit(b, index, kHasWeakRef)) {
b->gc->ClearWeakRef(GetUserPointer(item));
}
if(GC::useNewSweep && b->needsSweeping) {
b->alloc->Sweep(b);
}
if(b->IsFull()) {
a->AddToFreeList(b);
}
b->FreeItem(item, index);
if(b->numItems == 0 && !a->IsLastFreeBlock(b)) {
a->UnlinkChunk(b);
a->FreeChunk(b);
}
}
void GCAlloc::Finalize()
{
// Go through every item of every block. Look for items
// that are in use but not marked as reachable, and delete
// them.
GCBlock *next = NULL;
for (GCBlock* b = m_firstBlock; b != NULL; b = next)
{
// we can unlink block below
next = b->next;
static uint32 kMarkBits = 0x11111111;
static uint32 kFinalizeAndWeakRefBits = 0xcccccccc;
GCAssert(kMark == 0x1 && kFinalize == 0x4 && kHasWeakRef == 0x8);
int numMarkedItems = 0;
// TODO: MMX version for IA32
uint32 *bits = (uint32*) b->GetBits();
uint32 count = b->nextItem ? GetIndex(b, b->nextItem) : m_itemsPerBlock;
// round up to eight
count = (count+7)&~7;
for(int i=0, n=count>>3; i < n; i++)
{
uint32 b8 = bits[i];
uint32 unmarkedFinalizeAndWeakRefMask = ((~b8&kMarkBits) << 2) | ((~b8&kMarkBits) << 3);
uint32 finalizeAndWeakRefBits = b8&kFinalizeAndWeakRefBits;
// check the finalize and weak ref bits of unmarked objects
if((unmarkedFinalizeAndWeakRefMask & finalizeAndWeakRefBits) != 0)
{
uint32 marks = b8;
for(int j=0; j<8;j++,marks>>=4)
{
if(marks & kMark || !(marks & (kFinalize|kHasWeakRef)))
continue;
void* item = (char*)b->items + m_itemSize*((i*8)+j);
if (marks & kFinalize)
{
GCFinalizedObject *obj = (GCFinalizedObject*)GetUserPointer(item);
GCAssert(*(int*)obj != 0);
obj->~GCFinalizedObject();
#if defined(_DEBUG) && defined(MMGC_DRC)
if(b->alloc->IsRCObject()) {
m_gc->RCObjectZeroCheck((RCObject*)obj);
}
#endif
}
if (marks & kHasWeakRef) {
b->gc->ClearWeakRef(GetUserPointer(item));
}
}
}
numMarkedItems += CountBits(b8 & kMarkBits);
}
if(GC::useNewSweep && numMarkedItems == 0 && !IsLastFreeBlock(b)) {
// add to list of block to be returned to the Heap after finalization
// we don't do this during finalization b/c we want finalizers to be able
// to reference the memory of other objects being finalized
next = b->next;
UnlinkChunk(b);
b->gc->AddToSweepList(b);
} else if(numMarkedItems == b->numItems) {
// nothing changed on this page
continue;
} else if(GC::useNewSweep) {
// free'ing some items but not all
b->needsSweeping = true;
if(b->IsFull())
AddToFreeList(b);
}
}
}
bool GCAlloc::Sweep(GCBlock *b)
{
bool wasFull = b->IsFull();
// Mark all the items on the free list so we don't try free them again
// TODO: see if we can avoid this somehow
void *item = b->firstFree;
while (item != NULL) {
SetMark(item);
item = *((void**)item);
}
// TODO: MMX version for IA32
uint32 *bits = (uint32*) b->GetBits();
uint32 count = b->nextItem ? GetIndex(b, b->nextItem) : m_itemsPerBlock;
// round up to eight
int numInts = ((count+7)&~7) >> 3;
for(int i=0, n=numInts; i < n; i++)
{
uint32 b8 = bits[i];
uint32 marks = b8;
int subCount = i==(n-1) ? ((count-1)&7)+1 : 8;
for(int j=0; j<subCount;j++,marks>>=4)
{
if(marks & kMark)
continue;
item = (char*)b->items + m_itemSize*(i*8+j);
#ifdef MEMORY_INFO
DebugFreeReverse(item, 0xba, 4);
#endif
b->FreeItem(item, (i*8+j));
}
}
b->needsSweeping = false;
if((b == m_firstFree || b->prevFree != NULL) && // on freelist
b->numItems == 0 && // empty
!IsLastFreeBlock(b))
{
// take this page out of service
return true;
} else if(!GC::useNewSweep && !b->IsFull() && wasFull) {
AddToFreeList(b);
}
if(!GC::useNewSweep && b->numItems == 0) {
UnlinkChunk(b);
FreeChunk(b);
return true;
}
return false;
}
void GCAlloc::Sweep(bool force)
{
// Go through every item of every block. Look for items
// that are in use but not marked as reachable, and delete
// them.
GCBlock* next;
for (GCBlock* b = m_firstBlock; b != NULL; b = next)
{
next = b->next;
bool wasFull = b->IsFull();
// if we aren't forcing and the block wasn't full (ie its
// still on the free list) then just set a flag, the Sweep
// will happen the next time Alloc is called and b is firstFree
if(!force && !wasFull) {
b->needsSweeping = true;
} else {
Sweep(b);
}
}
}
void GCAlloc::ClearMarks()
{
GCBlock *block = m_firstBlock;
start:
while (block) {
GCBlock *next = block->next;
if(block->needsSweeping) {
if(Sweep(block)) {
if(GC::useNewSweep) {
UnlinkChunk(block);
FreeChunk(block);
}
block = next;
goto start;
}
}
// Clear all the mark bits
// FIXME: can we do this in sweep instead?
uint32 *pbits = (uint32*)block->GetBits();
const static uint32 mq32 = 0x33333333;
GCAssert((kMark|kQueued) == 0x3);
// TODO: MMX version for IA32
for(int i=0, n=m_numBitmapBytes>>2; i < n; i++) {
pbits[i] &= ~mq32;
}
// Advance to next block
block = next;
}
}
/*static*/
int GCAlloc::ConservativeGetMark(const void *item, bool bogusPointerReturnValue)
{
GCBlock *block = (GCBlock*) ((intptr) item & ~0xFFF);
#ifdef MEMORY_INFO
item = GetRealPointer(item);
#endif
// guard against bogus pointers to the block header
if (item < block->items)
return bogusPointerReturnValue;
// floor value to start of item
// FIXME: do this w/o division if we can
int itemNum = GetIndex(block, item);
// skip pointers into dead space at end of block
if (itemNum > block->alloc->m_itemsPerBlock - 1)
return bogusPointerReturnValue;
// skip pointers into objects
if(block->items + itemNum * block->size != item)
return bogusPointerReturnValue;
return GetMark(item);
}
// allows us to avoid division in GetItemIndex, kudos to Tinic
void GCAlloc::ComputeMultiplyShift(uint16 d, uint16 &muli, uint16 &shft)
{
uint32 s = 0;
uint32 n = 0;
uint32 m = 0;
for ( ; n < ( 1 << 13 ) ; s++) {
m = n;
n = ( ( 1 << ( s + 1 ) ) / d ) + 1;
}
shft = (uint16) s - 1;
muli = (uint16) m;
}
void GCAlloc::GCBlock::FreeItem(void *item, int index)
{
GCAssert(alloc->m_numAlloc != 0);
void *oldFree = firstFree;
firstFree = item;
#ifdef MEMORY_INFO
alloc->m_numAlloc--;
#endif
numItems--;
// clear all bits
ClearBits(this, index, 0xf);
#ifndef _DEBUG
// memset rest of item not including free list pointer, in _DEBUG
// we poison the memory (and clear in Alloc)
// FIXME: can we do something faster with MMX here?
if(!alloc->IsRCObject())
memset((char*)item, 0, size);
#endif
// Add this item to the free list
*((void**)item) = oldFree;
}
}

View File

@@ -1,342 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCAlloc__
#define __GCAlloc__
namespace MMgc
{
/**
*
* This is a fast, fixed-size memory allocator for garbage-collected
* objects.
*
* Memory is allocated from the system on 4096-byte aligned boundaries,
* which corresponds to the size of an OS page in Windows XP. Allocation
* of pages is performed via the GCPageAlloc class.
*
* In each 4096-byte block, there is a block header with marked bits,
* finalize bits, the pointer to the next free item and "recycling"
* free item linked list.
*
* The bits of the "marked" bitmap are controlled by the SetMark method.
*
* The bits of the "finalize" bitmap are set when an item is
* allocated. The value for the finalize bit is passed in as a
* parameter to the allocation call.
*
* When the Sweep method is invoked, all objects that are not marked
* with the specified mark flag are disposed of. If the corresponding
* finalize bit is set, the GCObject destructor is invoked on that
* item.
*
* When an allocation is requested and there are no more free
* entries, GCAlloc will request that a garbage collection take
* place. It will allocate new blocks if more than 20% of its
* blocks are used after the collection, targeting a 5:1
* heap size / minimim heap size ratio.
*
*/
class GCAlloc : public GCAllocBase
{
friend class GC;
public:
enum ItemBit { kMark=1, kQueued=2, kFinalize=4, kHasWeakRef=8 };
GCAlloc(GC* gc, int itemSize, bool containsPointers, bool isRC, int sizeClassIndex);
~GCAlloc();
void* Alloc(size_t size, int flags);
static void Free(void *ptr);
void Finalize();
void Sweep(bool force=false);
size_t GetItemSize() { return m_itemSize; }
void ClearMarks();
static int SetMark(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return SetBit(block, GetIndex(block, item), kMark);
}
static int SetQueued(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return SetBit(block, GetIndex(block, item), kQueued);
}
static int SetFinalize(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return SetBit(block, GetIndex(block, item), kFinalize);
}
static int IsWhite(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
// not a real item
if(item < block->items)
return false;
if(FindBeginning(item) != item)
return false;
return IsWhite(block, GetIndex(block, item));
}
static int GetMark(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
// Return the "marked" bit
return GetBit(block, GetIndex(block, item), kMark);
}
static void *FindBeginning(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return block->items + block->size * GetIndex(block, item);
}
static void ClearFinalized(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
ClearBits(block, GetIndex(block, item), kFinalize);
}
static int IsFinalized(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return GetBit(block, GetIndex(block, item), kFinalize);
}
static int HasWeakRef(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return GetBit(block, GetIndex(block, item), kHasWeakRef);
}
static bool ContainsPointers(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return block->alloc->ContainsPointers();
}
static bool IsRCObject(const void *item)
{
// Zero low 12 bits of address to get to the Block header
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
return item >= block->items && block->alloc->IsRCObject();
}
static bool IsUnmarkedPointer(const void *val);
int GetNumAlloc() const { return m_numAlloc; }
int GetMaxAlloc() const { return m_maxAlloc; }
int GetNumBlocks() const { return m_numBlocks; }
bool ContainsPointers() const { return containsPointers; }
bool IsRCObject() const { return containsRCObjects; }
void GetBitsPages(void **pages);
static void SetHasWeakRef(const void *item, bool to)
{
GCBlock *block = (GCBlock*) ((uint32)item & ~0xFFF);
if(to) {
SetBit(block, GetIndex(block, item), kHasWeakRef);
} else {
ClearBits(block, GetIndex(block, item), kHasWeakRef);
}
}
private:
const static int kBlockSize = 4096;
struct GCBlock;
friend struct GCAlloc::GCBlock;
struct GCBlock
{
GC *gc;
uint32 size;
GCAlloc *alloc;
char* nextItem;
void* firstFree; // first item on free list
GCBlock* next;
GCBlock* prev;
GCBlock *prevFree;
GCBlock *nextFree;
uint32* bits;
short numItems;
bool needsSweeping;
char *items;
int GetCount() const
{
if (nextItem) {
return GCAlloc::GetIndex(this, nextItem);
} else {
return alloc->m_itemsPerBlock;
}
}
uint32 *GetBits() const
{
return bits;
}
void FreeItem(void *item, int index);
bool IsFull()
{
bool full = (nextItem == firstFree);
// the only time nextItem and firstFree should be equal is when they
// are both zero which is also when we are full, assert to be sure
GCAssert(!full || nextItem==0);
GCAssert(!full || numItems == alloc->m_itemsPerBlock);
return full;
}
};
// The list of chunk blocks
GCBlock* m_firstBlock;
GCBlock* m_lastBlock;
// The lowest priority block that has free items
GCBlock* m_firstFree;
int m_itemsPerBlock;
size_t m_itemSize;
int m_numBitmapBytes;
int m_sizeClassIndex;
bool m_bitsInPage;
int m_maxAlloc;
int m_numAlloc;
int m_numBlocks;
// fast divide numbers
uint16 multiple;
uint16 shift;
bool containsPointers;
bool containsRCObjects;
GCBlock* CreateChunk();
void UnlinkChunk(GCBlock *b);
void FreeChunk(GCBlock* b);
void AddToFreeList(GCBlock *b)
{
GCAssert(b->nextFree == NULL && b->prevFree == NULL);
b->prevFree = NULL;
b->nextFree = m_firstFree;
if (m_firstFree) {
GCAssert(m_firstFree->prevFree == 0);
m_firstFree->prevFree = b;
}
m_firstFree = b;
}
void RemoveFromFreeList(GCBlock *b)
{
GCAssert(m_firstFree == b || b->prevFree != NULL);
if ( m_firstFree == b )
m_firstFree = b->nextFree;
else
b->prevFree->nextFree = b->nextFree;
if (b->nextFree)
b->nextFree->prevFree = b->prevFree;
}
bool Sweep(GCBlock *b);
bool IsLastFreeBlock(GCBlock *b) { return m_firstFree == NULL || (m_firstFree == b && b->nextFree == NULL); }
static int ConservativeGetMark(const void *item, bool bogusPointerReturnValue);
static int GetIndex(const GCBlock *block, const void *item)
{
int index = (((char*) item - block->items) * block->alloc->multiple) >> block->alloc->shift;
#ifdef _DEBUG
GCAssert(((char*) item - block->items) / block->size == (uint32) index);
#endif
return index;
}
static int IsWhite(GCBlock *block, int index)
{
return (block->GetBits()[index>>3] & ((kMark|kQueued)<<((index&7)<<2))) == 0;
}
static int SetBit(GCBlock *block, int index, int bit)
{
int mask = bit << ((index&7)<<2);
int set = (block->GetBits()[index>>3] & mask);
block->GetBits()[index>>3] |= mask;
return set;
}
static int GetBit(GCBlock *block, int index, int bit)
{
int mask = bit << ((index&7)<<2);
return block->GetBits()[index>>3] & mask;
}
static void ClearBits(GCBlock *block, int index, int bits)
{
int mask = bits << ((index&7)<<2);
block->GetBits()[index>>3] &= ~mask;
}
void ComputeMultiplyShift(uint16 d, uint16 &muli, uint16 &shft);
};
}
#endif /* __GCAlloc__ */

View File

@@ -1,71 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdlib.h>
#include "MMgc.h"
#include "GCDebug.h"
namespace MMgc
{
/* Returns the number of bits set in val.
* For a derivation of this algorithm, see
* "Algorithms and data structures with applications to
* graphics and geometry", by Jurg Nievergelt and Klaus Hinrichs,
* Prentice Hall, 1993.
*/
int GCAllocBase::CountBits(uint32 value)
{
value -= (value & 0xaaaaaaaaL) >> 1;
value = (value & 0x33333333L) + ((value >> 2) & 0x33333333L);
value = (value + (value >> 4)) & 0x0f0f0f0fL;
value += value >> 8;
value += value >> 16;
return (int)value & 0xff;
}
#ifdef MEMORY_INFO
void GCAllocBase::WriteBackPointer(const void *item, const void *container, size_t itemSize)
{
GCAssert(container != NULL);
int *p = (int*) item;
size_t size = *p++;
if(size && size <= itemSize) {
// skip traceIndex + data + endMarker
p += (2 + (size>>2));
GCAssert(sizeof(int) == sizeof(void*));
*p = (int) container;
}
}
#endif
}

View File

@@ -1,105 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCAllocBase__
#define __GCAllocBase__
namespace MMgc
{
class GC;
/**
* This is a base class for the GC allocators.
*/
class GCAllocBase : public GCAllocObject
{
public:
GCAllocBase(GC *gc) { m_gc = gc; }
virtual ~GCAllocBase() {}
#ifdef MMGC_IA32
static inline uint32 FindOneBit(uint32 value)
{
#ifndef __GNUC__
_asm
{
bsr eax,[value];
}
#else
// DBC - This gets rid of a compiler warning and matchs PPC results where value = 0
register int result = ~0;
if (value)
{
asm (
"bsr %1, %0"
: "=r" (result)
: "m"(value)
);
}
return result;
#endif
}
#endif
#ifdef MMGC_PPC
static inline int FindOneBit(uint32 value)
{
register int index;
#ifdef DARWIN
asm ("cntlzw %0,%1" : "=r" (index) : "r" (value));
#else
register uint32 in = value;
asm { cntlzw index, in; }
#endif
return 31-index;
}
#endif
static int CountBits(uint32 value);
#ifdef MEMORY_INFO
// debugging routine that records who marked who, can be used to
// answer the question, how did I get marked? also could be used to
// find false positives by verifying the back pointer chain gets back
// to a GC root
static void WriteBackPointer(const void *item, const void *container, size_t itemSize);
#endif
protected:
GC *m_gc;
};
}
#endif /* __GCAllocBase__ */

View File

@@ -1,59 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCAllocObject__
#define __GCAllocObject__
namespace MMgc
{
/**
* GCAllocObject is a base class for allocated objects. MMgc
* cannot have any dependency on the C runtime library, because
* Flash Player does not. MMgc also cannot rely on global
* operator new and delete, because it may be used to implement
* them! So, GCAllocObject provides a simple operator new and
* delete implementation for classes used internally by MMgc.
*
* The implementation of GCAllocObject is platform-dependent.
*/
class GCAllocObject
{
public:
void* operator new (size_t size);
void* operator new [] (size_t size);
void operator delete (void *ptr);
void operator delete [] (void *ptr);
};
}
#endif /* __GCAllocObject__ */

View File

@@ -1,81 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdlib.h>
#include "MMgc.h"
namespace MMgc
{
#if TARGET_API_MAC_CARBON
void* GCAllocObject::operator new (size_t size)
{
return malloc(size);
}
void* GCAllocObject::operator new[] (size_t size)
{
return malloc(size);
}
void GCAllocObject::operator delete (void *ptr)
{
free(ptr);
}
void GCAllocObject::operator delete[](void *ptr)
{
free(ptr);
}
#else
void* GCAllocObject::operator new (size_t size)
{
return NewPtr(size);
}
void* GCAllocObject::operator new[] (size_t size)
{
return NewPtr(size);
}
void GCAllocObject::operator delete (void *ptr)
{
DisposePtr((char*) ptr);
}
void GCAllocObject::operator delete[](void *ptr)
{
DisposePtr((char*) ptr);
}
#endif
}

View File

@@ -1,59 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdlib.h>
#include "MMgc.h"
namespace MMgc
{
void* GCAllocObject::operator new (size_t size)
{
return malloc(size);
}
void* GCAllocObject::operator new[] (size_t size)
{
return malloc(size);
}
void GCAllocObject::operator delete (void *ptr)
{
free(ptr);
}
void GCAllocObject::operator delete [] (void *ptr)
{
free(ptr);
}
}

View File

@@ -1,59 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <windows.h>
#include "MMgc.h"
namespace MMgc
{
void* GCAllocObject::operator new (size_t size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
void* GCAllocObject::operator new[] (size_t size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
void GCAllocObject::operator delete (void *ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
void GCAllocObject::operator delete [] (void *ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
}

View File

@@ -1,108 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 __GCDebug__
#define __GCDebug__
#include "GCTypes.h"
#ifdef WIN32
#include <windows.h>
#endif
#ifdef _MAC
typedef const unsigned char* ConstStr255Param;
extern "C"
{
#if defined(TARGET_RT_MAC_MACHO) // DBC
//extern pascal void DebugStr(ConstStr255Param aStr);
#else
// extern pascal void DebugStr(ConstStr255Param aStr) = 0xABFF;
extern pascal void SysBreakStr(ConstStr255Param aStr) = {0x303C, 0xFE15, 0xA9C9};
#endif
}
#endif
namespace MMgc
{
void GCDebugMsg(bool debuggerBreak, const char* format, ...);
void GCDebugMsg(const char* msg, bool debuggerBreak);
void GCDebugMsg(const wchar* msg, bool debuggerBreak);
#ifdef _DEBUG
inline void _GCAssertMsg(int32 assertion, const char* msg)
{
if (assertion == 0)
GCDebugMsg(msg, true);
}
#define GCAssertMsg(x,y) do { _GCAssertMsg((x), (y)); } while (0) /* no semi */
#define GCAssert(x) _GCAssert((x), __LINE__,__FILE__)
#define _GCAssert(x, line_, file_) __GCAssert((x), line_, file_)
#define __GCAssert(x, line_, file_) do { _GCAssertMsg((x), "Assertion failed: \"" #x "\" (" #file_ ":" #line_ ")"); } while (0) /* no semi */
#else
#define GCAssertMsg(x,y) do { } while (0) /* no semi */
#define GCAssert(x) do { } while (0) /* no semi */
#endif
/*************************************************************************/
/******************************* Debugging *******************************/
/*************************************************************************/
/* This mess serves to define the DebugMsg function on each platform.
* DebugMsg is only defined when the Debug flag is turned on; it halts
* program execution and drops into the debugger with the given message.
* We define it as in inline so that when you fall into the debugger,
* you're in the function that issued the call and not in a "DebugMsg"
* subroutine.
*/
#ifdef _MAC
// WARNING: this function is NOT THREAD SAFE
/*plugin_export*/ ConstStr255Param MakePascalMsg(const char* theString);
#if SOFT_ASSERTS
inline void DebugMsg_(const char* /*msg*/) { }
#else
#ifdef powerc
inline void DebugMsg_(const char* msg) { DebugStr(MakePascalMsg(msg)); }
#else
inline void DebugMsg_(const char* msg) { SysBreakStr(MakePascalMsg(msg)); }
#endif
#endif // SOFT_ASSERTS
#endif
}
#endif /* __GCDebug__ */

View File

@@ -1,123 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
#ifndef __MWERKS__
#include <CoreServices/CoreServices.h>
#endif
#ifndef __MACH__
#include <windows.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
namespace MMgc
{
void GCDebugMsg(bool debuggerBreak, const char* format, ...)
{
char buf[4096];
va_list args;
va_start(args, format);
#if TARGET_API_MAC_CARBON
vsprintf(buf, format, args);
#else
char *bufptr = buf;
// copied from flashstring
while (*format) {
if (*format == '%') {
switch (*++format) {
case 's':
strcpy(bufptr, va_arg(args, char *));
break;
case 'd':
{
int i = va_arg(args, int);
if (!i) {
*bufptr++ = '0';
} else {
if (i < 0) {
*bufptr++ = '-';
i = -i;
}
int n = 0;
char m_buf[128];
while (i > 0) {
int v = (i % 10);
m_buf[n++] = (v<10) ? (v+'0') : (v-10+'a');
i /= 10;
}
char* c = m_buf+n;
while (n--) {
*bufptr++ = (*--c);
}
}
break;
}
case 'c':
*bufptr++ = va_arg(args, char);
break;
case 0:
return;
}
} else {
*bufptr = *format;
}
format++;
bufptr++;
}
#endif
va_end(args);
GCDebugMsg(buf, debuggerBreak);
}
void GCDebugMsg(const char* p, bool debugBreak)
{
char buf[256];
strcpy(buf, p);
if(debugBreak) {
#if TARGET_API_MAC_CARBON
::CopyCStringToPascal(buf, (StringPtr)buf);
#else
c2pstr(buf);
#endif
DebugStr((StringPtr) buf);
} else {
CFStringRef cfStr = ::CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
::CFShow(cfStr);
}
}
}

View File

@@ -1,54 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
namespace MMgc
{
void GCDebugMsg(bool debuggerBreak, const char* format, ...)
{
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
}
void GCDebugMsg(const char* p, bool debugBreak)
{
fprintf(stderr, "%s\n", p);
}
}

View File

@@ -1,103 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef _DEBUG
#include <malloc.h>
#include <strsafe.h>
#endif
/*************************************************************************/
/******************************* Debugging *******************************/
/*************************************************************************/
#ifndef MB_SERVICE_NOTIFICATION
#define MB_SERVICE_NOTIFICATION 0x00200000L
#endif
namespace MMgc
{
static const bool logToStdErr = true;
void GCDebugMsg(bool debuggerBreak, const char *format, ...)
{
// [ggrossman 09.24.04]
// Changed this to _DEBUG only because we don't link to
// CRT in Release builds, so vsprintf is unavailable!!
#ifdef _DEBUG
va_list argptr;
va_start(argptr, format);
int bufferSize = _vscprintf(format, argptr)+1;
char *buffer = (char*)alloca(bufferSize+2);
if (buffer) {
StringCbVPrintf(buffer, bufferSize+1, format, argptr);
GCDebugMsg(buffer, debuggerBreak);
}
#else
(void)debuggerBreak;
(void)format;
#endif
}
void GCDebugMsg(const char* msg, bool debugBreak)
{
OutputDebugString(msg);
if(logToStdErr) {
fprintf( stderr, "%s\n", msg );
}
if (debugBreak) {
DebugBreak();
}
}
void GCDebugMsg(const wchar* msg, bool debugBreak)
{
OutputDebugStringW((LPCWSTR)msg);
if(logToStdErr) {
fprintf( stderr, "%S\n", msg );
}
if (debugBreak) {
DebugBreak();
}
}
}

View File

@@ -1,174 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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"
namespace MMgc
{
const void *GCHashtable::DELETED = (const void*)1;
GCHashtable::GCHashtable(unsigned int capacity)
{
tableSize = capacity*2;
table = new const void*[tableSize];
memset(table, 0, tableSize * sizeof(void*));
numValues = 0;
numDeleted = 0;
}
GCHashtable::~GCHashtable()
{
delete [] table;
table = 0;
tableSize = 0;
numDeleted = 0;
numValues = 0;
}
void GCHashtable::put(const void *key, const void *value)
{
int i = find(key, table, tableSize);
if (table[i] != key) {
// .75 load factor, note we don't take numDeleted into account
// we want to rehash a table with lots of deleted slots
if(numValues * 8 > tableSize * 3)
{
grow();
// grow rehashes
i = find(key, table, tableSize);
}
table[i] = key;
numValues++;
}
table[i+1] = value;
}
const void *GCHashtable::remove(const void *key)
{
const void *ret = NULL;
int i = find(key, table, tableSize);
if (table[i] == key) {
table[i] = (const void*)DELETED;
ret = table[i+1];
table[i+1] = NULL;
numDeleted++;
}
return ret;
}
const void *GCHashtable::get(const void *key)
{
return table[find(key, table, tableSize)+1];
}
/* static */
int GCHashtable::find(const void *key, const void **table, unsigned int tableSize)
{
GCAssert(key != (const void*)DELETED);
int bitmask = (tableSize - 1) & ~0x1;
// this is a quadratic probe but we only hit even numbered slots since those hold keys.
int n = 7 << 1;
#ifdef _DEBUG
unsigned loopCount = 0;
#endif
// Note: Mask off MSB to avoid negative indices. Mask off bottom
// 2 bits because of alignment. Double it because names, values stored adjacently.
unsigned i = ((0x7FFFFFF8 & (int)key)>>1) & bitmask;
const void *k;
while ((k=table[i]) != key && k != NULL)
{
i = (i + (n += 2)) & bitmask; // quadratic probe
GCAssert(loopCount++ < tableSize); // don't scan forever
}
GCAssert(i <= ((tableSize-1)&~0x1));
return i;
}
void GCHashtable::grow()
{
int newTableSize = tableSize;
unsigned int occupiedSlots = numValues - numDeleted;
GCAssert(numValues >= numDeleted);
// grow or shrink as appropriate:
// if we're greater than %50 full grow
// if we're less than %10 shrink
// else stay the same
if (4*occupiedSlots > tableSize)
newTableSize <<= 1;
else if(20*occupiedSlots < tableSize &&
tableSize > kDefaultSize)
newTableSize >>= 1;
const void **newTable = new const void*[newTableSize];
memset(newTable, 0, newTableSize*sizeof(void*));
numValues = 0;
numDeleted = 0;
for (int i=0, n=tableSize; i < n; i += 2)
{
const void *oldKey;
if ((oldKey=table[i]) != NULL)
{
// inlined & simplified version of put()
if(oldKey != (const void*)DELETED) {
int j = find(oldKey, newTable, newTableSize);
newTable[j] = oldKey;
newTable[j+1] = table[i+1];
numValues++;
}
}
}
delete [] table;
table = newTable;
tableSize = newTableSize;
}
int GCHashtable::nextIndex(int index)
{
unsigned int i = index<<1;
while(i < tableSize)
{
if(table[i] > DELETED)
return (i>>1)+1;
i += 2;
}
return 0;
}
}

View File

@@ -1,114 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCHashtable__
#define __GCHashtable__
namespace MMgc
{
class GCHashtableIterator;
/**
* simplified version of avmplus hashtable, doesn't shrink or handle deletions for instance
*/
class GCHashtable
{
friend class GCHashtableIterator;
public:
const static uint32 kDefaultSize=16;
const static void * DELETED;
GCHashtable(unsigned int capacity=kDefaultSize);
~GCHashtable();
const void *get(const void *key);
const void *get(int key) { return get((const void*)key); }
const void *remove(const void *key);
// updates value if present, adds and grows if necessary if not
void put(const void *key, const void *value);
void add(const void *key, const void *value) { put(key, value); }
void add(int key, const void *value) { put((const void*)key, value); }
int count() { return numValues; }
int nextIndex(int index);
const void *keyAt(int index) { return table[index<<1]; }
const void *valueAt(int index) { return table[((index)<<1)+1]; }
private:
// capacity
unsigned int tableSize;
// size of table array
unsigned int numValues;
// number of delete items
unsigned int numDeleted;
// table elements
const void **table;
static int find(const void *key, const void **table, unsigned int tableSize);
void grow();
};
class GCHashtableIterator
{
public:
GCHashtableIterator(GCHashtable *ht) : ht(ht), index(-2) {}
const void *nextKey()
{
do {
index+=2;
} while(index < (int)ht->tableSize && ht->table[index] <= GCHashtable::DELETED);
if(index < (int)ht->tableSize)
return ht->table[index];
return NULL;
}
const void *value()
{
GCAssert(ht->table[index] != NULL);
return ht->table[index+1];
}
void remove()
{
GCAssert(ht->table[index] != NULL);
ht->table[index] = (const void*)GCHashtable::DELETED;
ht->table[index+1] = NULL;
}
private:
GCHashtable *ht;
int index;
};
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,392 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCHeap__
#define __GCHeap__
namespace MMgc
{
/**
* GCHeap is a heap manager for the Flash Player's garbage collector.
*
* Memory is allocated from the operating system in large chunks
* aligned on page boundaries (4096-byte aligned). All allocation
* requests are specified in numbers of 4096-byte pages. The first
* 4 bytes of each page is reserved for GCHeap's use.
*
* Allocations may fail if there is no free block large enough
* to satisfy the request. When this occurs, the GC class will
* choose to either garbage collect or expand the heap, and then
* call GCHeap again to retry the allocation.
*
* When blocks are freed, they are coalesced with their neighbors
* when possible to reduce fragmentation. A "boundary tag" scheme
* similar to Doug Lea's malloc is used to make coalescing fast.
* To keep things simple, coalescing is always performed immediately
* when a block is freed, and not deferred.
*
* Allocations are performed using multiple free lists. Blocks that
* are <= kUniqueThreshold pages in size get their own free list.
* Blocks above the threshold get mapped to more granular free lists,
* and all blocks above kHugeThreshold get mapped to the last free list.
* This approach is borrowed from Hans Boehm's C/C++ Garbage Collector.
*
* Free lists are doubly-linked lists sorted in size order. The
* sorting is done to ensure best-fit allocation. Each free list
* is itself a list node, and the lists are circular, in a technique
* also borrowed from Doug Lea's malloc. This makes for very simple
* logic to insert/remove nodes.
*
* Only Windows is currently supported, although this should be easy
* to get working on other platforms. Memory is allocated in large
* (64K minimum) chunks using the VirtualAlloc API. Every time the
* heap is expanded, a new heap region is created corresponding to
* the address space returned by VirtualAlloc. Heap regions are
* allocated contiguously if possible to reduce fragmentation.
*/
class GCHeap : public GCAllocObject
{
public:
// -- Constants
/** Size of a block */
const static int kBlockSize = 4096;
/** Initial heap size, in blocks */
static int kInitialHeapSize;
/** Default size of address space reserved per region */
const static int kDefaultReserve = 4096;
/** Sizes up to this many blocks each have their own free list. */
const static int kUniqueThreshold = 16;
/**
* Sizes of at least this many heap blocks are mapped to a
* single free list.
*/
const static int kHugeThreshold = 128;
/** In between sizes map this many distinct sizes to a single bin. */
const static int kFreeListCompression = 8;
/** Calculated number of free lists */
const static int kNumFreeLists = (kHugeThreshold-kUniqueThreshold)/kFreeListCompression+kUniqueThreshold;
/** Minimum heap increment, in blocks */
const static int kMinHeapIncrement = 32;
/** if this much of the heap stays free for kDecommitThresholdMillis decommit some memory */
const static int kDecommitThresholdPercentage = 25;
static const int kDecommitThresholdMillis = 1000;
/** The native VM page size (in bytes) for the current architecture */
static int kNativePageSize;
static bool heapVerbose;
/**
* Init must be called to set up the GCHeap singleton
*/
static void Init(GCMallocFuncPtr malloc = NULL, GCFreeFuncPtr free = NULL);
/**
* Destroy the GCHeap singleton
*/
static void Destroy();
/**
* Get the GCHeap singleton
*/
static GCHeap *GetGCHeap() { GCAssert(instance != NULL); return instance; }
/**
* Allocates a block from the heap.
* @param size the number of pages (kBlockSize bytes apiece)
* to allocate.
* @return pointer to beginning of block, or NULL if failed.
*/
void *Alloc(int size, bool expand=true, bool zero=true);
/**
* Frees a block.
* @param item the block to free. This must be the same
* pointer that was previously returned by
* a call to Alloc.
*/
void Free(void *item);
size_t Size(const void *item);
/**
* Expands the heap by size pages.
*
* Expands the heap by "size" blocks, such that a single contiguous
* allocation of "size" blocks can be performed. This method is
* also called to create the initial heap.
*
* On Windows, this uses the VirtualAlloc API to obtain memory.
* VirtualAlloc can _reserve_ memory, _commit_ memory or both at
* the same time. Reserved memory is just virtual address space.
* It consumes the address space of the process but isn't really
* allocated yet; there are no pages committed to it yet.
* Memory allocation really occurs when reserved pages are
* committed. Our strategy in GCHeap is to reserve a fairly large
* chunk of address space, and then commit pages from it as needed.
* By doing this, we're more likely to get contiguous regions in
* memory for our heap.
*
* By default, we reserve 16MB (4096 pages) per heap region.
* The amount to reserve by default is controlled by kDefaultReserve.
* That shouldn't be a big deal, as the process address space is 2GB.
* As we're usually a plug-in, however, we don't want to make it too
* big because it's not all our memory.
*
* The goal of reserving so much address space is so that subsequent
* expansions of the heap are able to obtain contiguous memory blocks.
* If we can keep the heap contiguous, that reduces fragmentation
* and the possibility of many small "Balkanized" heap regions.
*
* Algorithm: When an allocation is requested,
* 1. If there is enough reserved but uncommitted memory in the
* last-created region to satisfy the request, commit that memory
* and exit with success, also check decommitted list
* 2. Try to reserve a new region contiguous with the last-created
* region. Go for a 16MB reservation or the requested size,
* whichever is bigger.
* 3. If we tried for 16MB reserved space and it didn't work, try
* to reserve again, but for the requested size.
* 4. If we were able to retrieve a contiguous region in Step 2 or 3,
* commit any leftover memory from the last-created region,
* commit the remainer from the newly created region, and exit
* with success.
* 5. OK, the contiguous region didn't work out, so allocate a
* non-contiguous region. Go for 16MB or the requested size
* again, whichever is bigger.
* 6. If we tried for 16MB reserved space and it didn't work, try
* to reserve again, but for the requested size.
* 7. Commit the requested size out of the newly created region
* and exit with success.
*
* If we are able to reserve memory but can't commit it, then, well
* there isn't enough memory. We free the reserved memory and
* exit with failure.
*
* @param size the number of pages to expand the heap by
*/
bool ExpandHeap(int size);
/**
* Returns the used heap size, that is, the total
* space actually used by allocated objects.
* @return the minimum heap size in pages (kBlockSize bytes apiece)
*/
unsigned int GetUsedHeapSize() const { return numAlloc; }
/**
* Returns the "free heap size", that is, the difference in the
* total heap size and the used heap size
* @return the minimum heap size in pages (kBlockSize bytes apiece)
*/
unsigned int GetFreeHeapSize() const { return GetTotalHeapSize()-numAlloc; }
/**
* Returns the total heap size, that is, the total amount
* of space managed by the heap, including all used and
* free space.
* @return the total heap size in pages (kBlockSize bytes apiece)
*/
unsigned int GetTotalHeapSize() const { return blocksLen - numDecommitted; }
/**
* gives memory back to the OS when there hasn't been any memory activity in a while
* and we have lots of free memory
*/
void Decommit();
private:
// -- Implementation
static GCHeap *instance;
GCHeap(GCMallocFuncPtr m, GCFreeFuncPtr f);
~GCHeap();
// Heap regions
class Region : public GCAllocObject
{
public:
Region *prev;
char *baseAddr;
char *reserveTop;
char *commitTop;
int blockId;
};
Region *lastRegion;
// Block struct used for free lists and memory traversal
class HeapBlock : public GCAllocObject
{
public:
char *baseAddr; // base address of block's memory
int size; // size of this block
int sizePrevious; // size of previous block
HeapBlock *prev; // prev entry on free list
HeapBlock *next; // next entry on free list
bool committed; // is block fully committed?
bool dirty; // needs zero'ing, only valid if committed
#ifdef MEMORY_INFO
int allocTrace;
#endif
bool inUse() { return prev == NULL; }
};
bool ExpandHeapPrivate(int size);
// Core data structures
HeapBlock *blocks;
unsigned int blocksLen;
unsigned int numDecommitted;
HeapBlock freelists[kNumFreeLists];
unsigned int numAlloc;
// Core methods
void AddToFreeList(HeapBlock *block);
void AddToFreeList(HeapBlock *block, HeapBlock* pointToInsert);
HeapBlock *AllocBlock(int size, bool& zero);
void FreeBlock(HeapBlock *block);
void FreeAll();
HeapBlock *Split(HeapBlock *block, int size);
#ifdef DECOMMIT_MEMORY
void Commit(HeapBlock *block);
#endif
#ifdef _DEBUG
friend class GC;
#endif
HeapBlock *AddrToBlock(const void *item) const;
Region *AddrToRegion(const void *item) const;
void RemoveRegion(Region *r);
// only used on mac
GCMallocFuncPtr m_malloc;
GCFreeFuncPtr m_free;
// debug only freelist consistency checks
void CheckFreelist();
bool BlocksAreContiguous(void *item1, void *item2);
// Remove a block from a free list (inlined for speed)
inline void RemoveFromList(HeapBlock *block)
{
GCAssert(!block->inUse());
block->prev->next = block->next;
block->next->prev = block->prev;
block->next = block->prev = 0;
}
// Map a number of blocks to the appropriate large block free list index
// (inlined for speed)
inline int GetFreeListIndex(int size)
{
if (size <= kUniqueThreshold) {
return size-1;
} else if (size >= kHugeThreshold) {
return kNumFreeLists-1;
} else {
return (size-kUniqueThreshold)/kFreeListCompression+kUniqueThreshold-1;
}
}
// used for decommit smoothing
// millis to wait before decommitting anything
uint64 decommitTicks;
uint64 decommitThresholdTicks;
#ifdef GCHEAP_LOCK
GCSpinLock m_spinlock;
#endif /* GCHEAP_LOCK */
#ifdef MMGC_AVMPLUS
// OS abstraction to determine native page size
int vmPageSize();
size_t committedCodeMemory;
#ifdef WIN32
bool useGuardPages;
#endif
public:
// support for jit buffers
void* ReserveCodeMemory(void* address, size_t size);
void* CommitCodeMemory(void* address, size_t size=0); // size=0 => 1 page
void* DecommitCodeMemory(void* address, size_t size=0); // size=0 => 1 page
void ReleaseCodeMemory(void* address, size_t size);
bool SetGuardPage(void *address);
#ifdef AVMPLUS_JIT_READONLY
void SetExecuteBit(void *address, size_t size, bool executeFlag);
#endif /* AVMPLUS_JIT_READONLY */
size_t GetCodeMemorySize() const { return committedCodeMemory; }
#endif
#ifdef USE_MMAP
public:
char *ReserveMemory(char *address, size_t size);
bool CommitMemory(char *address, size_t size);
bool DecommitMemory(char *address, size_t size);
void ReleaseMemory(char *address, size_t size);
bool CommitMemoryThatMaySpanRegions(char *address, size_t size);
bool DecommitMemoryThatMaySpanRegions(char *address, size_t size);
#else
char *AllocateMemory(size_t size);
void ReleaseMemory(char *address);
#endif
private:
#ifdef _DEBUG
/* m_megamap is a debugging aid for finding bugs in this
memory allocator. It tracks allocated/free pages in
the crudest way possible ... a 1MB byte array with a
0/1 byte for every page in the 32-bit address space. */
static uint8 m_megamap[1048576];
#endif
};
}
#endif /* __GCHeap__ */

View File

@@ -1,368 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "MMgc.h"
#include "GC.h"
#ifdef USE_MMAP
#include <sys/mman.h>
#endif
#if defined(__MACH__)
#include <mach/mach.h>
#endif
#ifdef _MAC
#define MAP_ANONYMOUS MAP_ANON
#endif
#if defined(MMGC_IA32) && defined(MEMORY_INFO)
#include <dlfcn.h>
#endif
namespace MMgc
{
#ifndef USE_MMAP
void *aligned_malloc(size_t size, size_t align_size, GCMallocFuncPtr m_malloc)
{
char *ptr, *ptr2, *aligned_ptr;
int align_mask = align_size - 1;
int alloc_size = size + align_size + sizeof(int);
ptr=(char *)m_malloc(alloc_size);
if(ptr==NULL) return(NULL);
ptr2 = ptr + sizeof(int);
aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask));
ptr2 = aligned_ptr - sizeof(int);
*((int *)ptr2)=(int)(aligned_ptr - ptr);
return(aligned_ptr);
}
void aligned_free(void *ptr, GCFreeFuncPtr m_free)
{
int *ptr2=(int *)ptr - 1;
char *unaligned_ptr = (char*) ptr - *ptr2;
m_free(unaligned_ptr);
}
#endif /* !USE_MMAP */
#ifdef MMGC_AVMPLUS
#ifdef USE_MMAP
int GCHeap::vmPageSize()
{
long v = sysconf(_SC_PAGESIZE);
if (v == -1) v = 4096; // Mac 10.1 needs this
return v;
}
void* GCHeap::ReserveCodeMemory(void* address,
size_t size)
{
return mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
}
void GCHeap::ReleaseCodeMemory(void* address,
size_t size)
{
if (munmap(address, size) != 0)
GCAssert(false);
}
bool GCHeap::SetGuardPage(void* /*address*/)
{
return false;
}
#ifdef AVMPLUS_JIT_READONLY
/**
* SetExecuteBit changes the page access protections on a block of pages,
* to make JIT-ted code executable or not.
*
* If executableFlag is true, the memory is made executable and read-only.
*
* If executableFlag is false, the memory is made non-executable and
* read-write.
*/
void GCHeap::SetExecuteBit(void *address,
size_t size,
bool executableFlag)
{
// mprotect requires that the addresses be aligned on page boundaries
void *endAddress = (void*) ((char*)address + size);
void *beginPage = (void*) ((size_t)address & ~0xFFF);
void *endPage = (void*) (((size_t)endAddress + 0xFFF) & ~0xFFF);
size_t sizePaged = (size_t)endPage - (size_t)beginPage;
int retval = mprotect(beginPage, sizePaged,
executableFlag ? (PROT_READ|PROT_EXEC) : (PROT_READ|PROT_WRITE));
GCAssert(retval == 0);
(void)retval;
}
#endif /* AVMPLUS_JIT_READONLY */
void* GCHeap::CommitCodeMemory(void* address,
size_t size)
{
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
#ifdef AVMPLUS_JIT_READONLY
void *res = mmap(address,
size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
#else
void *res = mmap(address,
size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
#endif /* AVMPLUS_JIT_READONLY */
if (res == MAP_FAILED)
address = 0;
else
address = (void*)( (int)address + size );
return address;
}
void* GCHeap::DecommitCodeMemory(void* address,
size_t size)
{
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
char *addr = (char*)mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
GCAssert(addr == address);
(void)addr;
return address;
}
#else
int GCHeap::vmPageSize()
{
return 4096;
}
void* GCHeap::ReserveCodeMemory(void* address,
size_t size)
{
return aligned_malloc(size, 4096, m_malloc);
}
void GCHeap::ReleaseCodeMemory(void* address,
size_t size)
{
aligned_free(address, m_free);
}
bool GCHeap::SetGuardPage(void *address)
{
return false;
}
#ifdef AVMPLUS_JIT_READONLY
void GCHeap::SetExecuteBit(void *address,
size_t size,
bool executableFlag)
{
// No-op on Mac CFM
}
#endif /* AVMPLUS_JIT_READONLY */
void* GCHeap::CommitCodeMemory(void* address,
size_t size)
{
return address;
}
void* GCHeap::DecommitCodeMemory(void* address,
size_t size)
{
return address;
}
#endif /* USE_MMAP */
#endif /* MMGC_AVMPLUS */
#ifdef USE_MMAP
char* GCHeap::ReserveMemory(char *address, size_t size)
{
char *addr = (char*)mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
// the man page for mmap documents it returns -1 to signal failure.
if (addr == (char *)-1) return NULL;
if(address && address != addr) {
// behave like windows and fail if we didn't get the right address
ReleaseMemory(addr, size);
return NULL;
}
return addr;
}
bool GCHeap::CommitMemory(char *address, size_t size)
{
char *addr = (char*)mmap(address,
size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-1, 0);
GCAssert(addr == address);
return addr == address;
}
bool GCHeap::DecommitMemory(char *address, size_t size)
{
char *addr = (char*)mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
GCAssert(addr == address);
return addr == address;
}
bool GCHeap::CommitMemoryThatMaySpanRegions(char *address, size_t size)
{
return CommitMemory(address, size);
}
bool GCHeap::DecommitMemoryThatMaySpanRegions(char *address, size_t size)
{
return DecommitMemory(address, size);
}
void GCHeap::ReleaseMemory(char *address, size_t size)
{
int result = munmap(address, size);
GCAssert(result == 0);
(void)result;
}
#else
char* GCHeap::AllocateMemory(size_t size)
{
return (char *) aligned_malloc(size, 4096, m_malloc);
//return (char *) MPAllocateAligned(size, kMPAllocate4096ByteAligned, 0);
}
void GCHeap::ReleaseMemory(char *address)
{
aligned_free(address, m_free);
//MPFree(address);
}
#endif
#ifdef MEMORY_INFO
#ifdef MMGC_PPC
// no idea how to do this with codewarrior
void GetInfoFromPC(int pc, char *buff, int /*buffSize*/)
{
sprintf(buff, "0x%x", pc);
}
void GetStackTrace(int *trace, int len, int skip)
{
register int stackp;
int pc;
asm("mr %0,r1" : "=r" (stackp));
while(skip--) {
stackp = *(int*)stackp;
}
int i=0;
// save space for 0 terminator
len--;
while(i<len && stackp) {
pc = *((int*)stackp+2);
trace[i++]=pc;
stackp = *(int*)stackp;
}
trace[i] = 0;
}
#endif
#ifdef MMGC_IA32
void GetInfoFromPC(int pc, char *buff, int buffSize)
{
Dl_info dlip;
dladdr((void * const)pc, &dlip);
snprintf(buff, buffSize, "0x%08x:%s", pc, dlip.dli_sname);
}
void GetStackTrace(int* trace, int len, int skip)
{
void **ebp;
asm("mov %%ebp, %0" : "=r" (ebp));
while(skip-- && *ebp)
{
ebp = (void**)(*ebp);
}
len--;
int i=0;
while(i<len && *ebp)
{
trace[i++] = *((int*)ebp+1);
ebp = (void**)(*ebp);
}
trace[i] = 0;
}
#endif
#endif
}

View File

@@ -1,320 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef USE_MMAP
#include <sys/mman.h>
#endif
#include <unistd.h>
#include "GCDebug.h"
#include "MMgc.h"
#include "GC.h"
// avmplus standalone uses UNIX
#ifdef _MAC
#define MAP_ANONYMOUS MAP_ANON
#endif
namespace MMgc
{
#ifndef USE_MMAP
void *aligned_malloc(size_t size, size_t align_size, GCMallocFuncPtr m_malloc)
{
char *ptr, *ptr2, *aligned_ptr;
int align_mask = align_size - 1;
int alloc_size = size + align_size + sizeof(int);
ptr=(char *)m_malloc(alloc_size);
if(ptr==NULL) return(NULL);
ptr2 = ptr + sizeof(int);
aligned_ptr = ptr2 + (align_size - ((size_t)ptr2 & align_mask));
ptr2 = aligned_ptr - sizeof(int);
*((int *)ptr2)=(int)(aligned_ptr - ptr);
return(aligned_ptr);
}
void aligned_free(void *ptr, GCFreeFuncPtr m_free)
{
int *ptr2=(int *)ptr - 1;
char *unaligned_ptr = (char*) ptr - *ptr2;
m_free(unaligned_ptr);
}
#endif /* !USE_MMAP */
#ifdef USE_MMAP
int GCHeap::vmPageSize()
{
long v = sysconf(_SC_PAGESIZE);
return v;
}
void* GCHeap::ReserveCodeMemory(void* address,
size_t size)
{
return (char*) mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
}
void GCHeap::ReleaseCodeMemory(void* address,
size_t size)
{
if (munmap(address, size) != 0)
GCAssert(false);
}
bool GCHeap::SetGuardPage(void *address)
{
return false;
}
#ifdef AVMPLUS_JIT_READONLY
/**
* SetExecuteBit changes the page access protections on a block of pages,
* to make JIT-ted code executable or not.
*
* If executableFlag is true, the memory is made executable and read-only.
*
* If executableFlag is false, the memory is made non-executable and
* read-write.
*/
void GCHeap::SetExecuteBit(void *address,
size_t size,
bool executableFlag)
{
// mprotect requires that the addresses be aligned on page boundaries
void *endAddress = (void*) ((char*)address + size);
void *beginPage = (void*) ((size_t)address & ~0xFFF);
void *endPage = (void*) (((size_t)endAddress + 0xFFF) & ~0xFFF);
size_t sizePaged = (size_t)endPage - (size_t)beginPage;
int retval = mprotect(beginPage, sizePaged,
executableFlag ? (PROT_READ|PROT_EXEC) : (PROT_READ|PROT_WRITE));
GCAssert(retval == 0);
}
#endif /* AVMPLUS_JIT_READONLY */
void* GCHeap::CommitCodeMemory(void* address,
size_t size)
{
void* res;
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
#ifdef AVMPLUS_JIT_READONLY
mmap(address,
size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-1, 0);
#else
mmap(address,
size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-1, 0);
#endif /* AVMPLUS_JIT_READONLY */
res = address;
if (res == address)
address = (void*)( (int)address + size );
else
address = 0;
return address;
}
void* GCHeap::DecommitCodeMemory(void* address,
size_t size)
{
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
// release and re-reserve it
ReleaseCodeMemory(address, size);
address = ReserveCodeMemory(address, size);
return address;
}
#else
int GCHeap::vmPageSize()
{
return 4096;
}
void* GCHeap::ReserveCodeMemory(void* address,
size_t size)
{
return aligned_malloc(size, 4096, m_malloc);
}
void GCHeap::ReleaseCodeMemory(void* address,
size_t size)
{
aligned_free(address, m_free);
}
bool GCHeap::SetGuardPage(void *address)
{
return false;
}
void* GCHeap::CommitCodeMemory(void* address,
size_t size)
{
return address;
}
void* GCHeap::DecommitCodeMemory(void* address,
size_t size)
{
return address;
}
#endif /* USE_MMAP */
#ifdef USE_MMAP
char* GCHeap::ReserveMemory(char *address, size_t size)
{
char *addr = (char*)mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if(address && address != addr) {
// behave like windows and fail if we didn't get the right address
ReleaseMemory(addr, size);
return NULL;
}
return addr;
}
bool GCHeap::CommitMemory(char *address, size_t size)
{
char *addr = (char*)mmap(address,
size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
-1, 0);
GCAssert(addr == address);
return addr == address;
}
bool GCHeap::DecommitMemory(char *address, size_t size)
{
ReleaseMemory(address, size);
// re-reserve it
char *addr = (char*)mmap(address,
size,
PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
-1, 0);
GCAssert(addr == address);
return addr == address;
}
bool GCHeap::CommitMemoryThatMaySpanRegions(char *address, size_t size)
{
return CommitMemory(address, size);
}
bool GCHeap::DecommitMemoryThatMaySpanRegions(char *address, size_t size)
{
return DecommitMemory(address, size);
}
void GCHeap::ReleaseMemory(char *address, size_t size)
{
int result = munmap(address, size);
GCAssert(result == 0);
}
#else
char* GCHeap::AllocateMemory(size_t size)
{
return (char *) aligned_malloc(size, 4096, m_malloc);
}
void GCHeap::ReleaseMemory(char *address)
{
aligned_free(address, m_free);
}
#endif
#ifdef MEMORY_INFO
// Bandaid implementations for these functions. Windows has its own version.
void GetInfoFromPC(int pc, char *buff, int buffSize)
{
sprintf(buff, "0x%x", pc);
}
#ifdef MMGC_PPC
void GetStackTrace(int *trace, int len, int skip)
{
register int stackp;
int pc;
asm("mr %0,r1" : "=r" (stackp));
while(skip--) {
stackp = *(int*)stackp;
}
int i=0;
// save space for 0 terminator
len--;
while(i<len && stackp) {
pc = *((int*)stackp+2);
trace[i++]=pc;
stackp = *(int*)stackp;
}
trace[i] = 0;
}
#endif
#ifdef MMGC_IA32
void GetStackTrace(int *trace, int len, int skip) {}
#endif
#ifdef MMGC_ARM
void GetStackTrace(int *trace, int len, int skip) {}
#endif
#endif
}

View File

@@ -1,547 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <windows.h>
#include "MMgc.h"
#ifdef MEMORY_INFO
#include <malloc.h>
#include <strsafe.h>
#include <DbgHelp.h>
#endif
#ifdef MEMORY_INFO
namespace MMgc
{
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// helper snarfed and simplified from main flash player code.
// since we only need it here and only for debug, I didn't bother
// migrating the whole thing.
class DynamicLoadLibraryHelper
{
protected:
DynamicLoadLibraryHelper(const char* p_dllName, bool p_required = true);
virtual ~DynamicLoadLibraryHelper();
FARPROC GetProc(const char* p_funcName, bool p_required = true);
public:
// note that this is only if any of the *required* ones failed;
// some "optional" ones may be missing and still have this return true.
bool AllRequiredItemsPresent() const { return m_allRequiredItemsPresent; }
private:
HMODULE m_lib;
bool m_allRequiredItemsPresent;
};
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
#define GETPROC(n) do { m_##n = (n##ProcPtr)GetProc(#n); } while (0)
#define GETPROC_OPTIONAL(n) do { m_##n = (n##ProcPtr)GetProc(#n, false); } while (0)
// --------------------------------------------------------------------------
DynamicLoadLibraryHelper::DynamicLoadLibraryHelper(const char* p_dllName, bool p_required) :
m_lib(NULL),
m_allRequiredItemsPresent(true) // assume the best
{
m_lib = ::LoadLibraryA(p_dllName);
if (p_required && (m_lib == NULL || m_lib == INVALID_HANDLE_VALUE))
{
// don't assert here... it will trigger a DebugBreak(), which will crash
// systems not running a debugger... and QE insists that they be able
// to run Debug builds on debuggerless Win98 systems... (sigh)
//GCAssertMsg(0, p_dllName);
m_allRequiredItemsPresent = false;
}
}
// --------------------------------------------------------------------------
FARPROC DynamicLoadLibraryHelper::GetProc(const char* p_funcName, bool p_required)
{
FARPROC a_proc = NULL;
if (m_lib != NULL && m_lib != INVALID_HANDLE_VALUE)
{
a_proc = ::GetProcAddress(m_lib, p_funcName);
}
if (p_required && a_proc == NULL)
{
// don't assert here... it will trigger a DebugBreak(), which will crash
// systems not running a debugger... and QE insists that they be able
// to run Debug builds on debuggerless Win98 systems... (sigh)
//GCAssertMsg(0, p_funcName);
m_allRequiredItemsPresent = false;
}
return a_proc;
}
// --------------------------------------------------------------------------
DynamicLoadLibraryHelper::~DynamicLoadLibraryHelper()
{
if (m_lib != NULL && m_lib != INVALID_HANDLE_VALUE)
{
::FreeLibrary(m_lib);
}
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
class DbgHelpDllHelper : public DynamicLoadLibraryHelper
{
public:
DbgHelpDllHelper();
public:
typedef BOOL (__stdcall *StackWalk64ProcPtr)(
DWORD MachineType,
HANDLE hProcess,
HANDLE hThread,
LPSTACKFRAME64 StackFrame,
PVOID ContextRecord,
PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
);
typedef PVOID (__stdcall *SymFunctionTableAccess64ProcPtr)(
HANDLE hProcess,
DWORD64 AddrBase
);
typedef DWORD64 (__stdcall *SymGetModuleBase64ProcPtr)(
HANDLE hProcess,
DWORD64 qwAddr
);
typedef BOOL (__stdcall *SymGetLineFromAddr64ProcPtr)(
HANDLE hProcess,
DWORD64 qwAddr,
PDWORD pdwDisplacement,
PIMAGEHLP_LINE64 Line64
);
typedef BOOL (__stdcall *SymGetSymFromAddr64ProcPtr)(
HANDLE hProcess,
DWORD64 qwAddr,
PDWORD64 pdwDisplacement,
PIMAGEHLP_SYMBOL64 Symbol
);
typedef BOOL (__stdcall *SymInitializeProcPtr)(
HANDLE hProcess,
PSTR UserSearchPath,
BOOL fInvadeProcess
);
public:
StackWalk64ProcPtr m_StackWalk64;
SymFunctionTableAccess64ProcPtr m_SymFunctionTableAccess64;
SymGetModuleBase64ProcPtr m_SymGetModuleBase64;
SymGetLineFromAddr64ProcPtr m_SymGetLineFromAddr64;
SymGetSymFromAddr64ProcPtr m_SymGetSymFromAddr64;
SymInitializeProcPtr m_SymInitialize;
};
// --------------------------------------------------------------------------
DbgHelpDllHelper::DbgHelpDllHelper() :
DynamicLoadLibraryHelper("dbghelp.dll"),
m_StackWalk64(NULL),
m_SymFunctionTableAccess64(NULL),
m_SymGetModuleBase64(NULL),
m_SymGetLineFromAddr64(NULL),
m_SymGetSymFromAddr64(NULL),
m_SymInitialize(NULL)
{
GETPROC(StackWalk64);
GETPROC(SymFunctionTableAccess64);
GETPROC(SymGetModuleBase64);
GETPROC(SymGetLineFromAddr64);
GETPROC(SymGetSymFromAddr64);
GETPROC(SymInitialize);
}
// declaring this statically will dynamically load the dll and procs
// at startup, and never ever release them... if this ever becomes NON-debug
// code, you might want to have a way to toss all this... but for _DEBUG
// only, it should be fine
static DbgHelpDllHelper g_DbgHelpDll;
}
#endif
namespace MMgc
{
#ifdef MMGC_AVMPLUS
int GCHeap::vmPageSize()
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwPageSize;
}
void* GCHeap::ReserveCodeMemory(void* address,
size_t size)
{
return VirtualAlloc(address,
size,
MEM_RESERVE,
PAGE_NOACCESS);
}
void GCHeap::ReleaseCodeMemory(void* address,
size_t /*size*/)
{
VirtualFree(address, 0, MEM_RELEASE);
}
void* GCHeap::CommitCodeMemory(void* address,
size_t size)
{
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
#ifdef AVMPLUS_JIT_READONLY
void* addr = VirtualAlloc(address,
size,
MEM_COMMIT,
PAGE_READWRITE);
#else
void* addr = VirtualAlloc(address,
size,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
#endif /* AVMPLUS_JIT_READONLY */
if (addr == NULL)
address = 0;
else {
address = (void*)( (int)address + size );
committedCodeMemory += size;
}
return address;
}
#ifdef AVMPLUS_JIT_READONLY
/**
* SetExecuteBit changes the page access protections on a block of pages,
* to make JIT-ted code executable or not.
*
* If executableFlag is true, the memory is made executable and read-only.
*
* If executableFlag is false, the memory is made non-executable and
* read-write.
*
* [rickr] bug #182323 The codegen can bail in the middle of generating
* code for any number of reasons. When this occurs we need to ensure
* that any code that was previously on the page still executes, so we
* leave the page as PAGE_EXECUTE_READWRITE rather than PAGE_READWRITE.
* Ideally we'd use PAGE_READWRITE and then on failure revert it back to
* read/execute but this is a little tricker and doesn't add too much
* protection since only a single page is 'exposed' with this technique.
*/
void GCHeap::SetExecuteBit(void *address,
size_t size,
bool executableFlag)
{
DWORD oldProtectFlags = 0;
BOOL retval = VirtualProtect(address,
size,
executableFlag ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE,
&oldProtectFlags);
(void)retval;
GCAssert(retval);
// We should not be clobbering PAGE_GUARD protections
GCAssert((oldProtectFlags & PAGE_GUARD) == 0);
}
#endif /* AVMPLUS_JIT_READONLY */
bool GCHeap::SetGuardPage(void *address)
{
if (!useGuardPages)
{
return false;
}
void *res = VirtualAlloc(address,
GCHeap::kNativePageSize,
MEM_COMMIT,
PAGE_GUARD | PAGE_READWRITE);
return res != 0;
}
void* GCHeap::DecommitCodeMemory(void* address,
size_t size)
{
if (size == 0)
size = GCHeap::kNativePageSize; // default of one page
if (VirtualFree(address, size, MEM_DECOMMIT) == false)
address = 0;
else
committedCodeMemory -= size;
return address;
}
#endif
#ifdef USE_MMAP
char* GCHeap::ReserveMemory(char *address,
size_t size)
{
return (char*) VirtualAlloc(address,
size,
MEM_RESERVE,
PAGE_NOACCESS);
}
bool GCHeap::CommitMemory(char *address,
size_t size)
{
void *addr = VirtualAlloc(address,
size,
MEM_COMMIT,
PAGE_READWRITE);
#ifdef _DEBUG
if(addr == NULL) {
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL );
GCAssertMsg(false, (const char*)lpMsgBuf);
}
#endif
return addr != NULL;
}
bool GCHeap::DecommitMemory(char *address, size_t size)
{
return VirtualFree(address, size, MEM_DECOMMIT) != 0;
}
void GCHeap::ReleaseMemory(char *address,
size_t /*size*/)
{
VirtualFree(address, 0, MEM_RELEASE);
}
bool GCHeap::CommitMemoryThatMaySpanRegions(char *address, size_t size)
{
bool success = false;
MEMORY_BASIC_INFORMATION mbi;
do {
VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
size_t commitSize = size > mbi.RegionSize ? mbi.RegionSize : size;
success = CommitMemory(address, commitSize);
address += commitSize;
size -= commitSize;
} while(size > 0 && success);
return success;
}
bool GCHeap::DecommitMemoryThatMaySpanRegions(char *address, size_t size)
{
bool success = false;
MEMORY_BASIC_INFORMATION mbi;
do {
VirtualQuery(address, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
size_t commitSize = size > mbi.RegionSize ? mbi.RegionSize : size;
success = DecommitMemory(address, commitSize);
address += commitSize;
size -= commitSize;
} while(size > 0 && success);
return success;
}
#else
char* GCHeap::AllocateMemory(size_t size)
{
return (char*)_aligned_malloc(size, kBlockSize);
}
void GCHeap::ReleaseMemory(char *address)
{
_aligned_free(address);
}
#endif
#ifdef MEMORY_INFO
#ifndef MEMORY_INFO
// empty when MEMORY_INFO not defined
void GetInfoFromPC(int pc, char *buff, int buffSize) { }
void GetStackTrace(int *trace, int len, int skip) {}
#else
void GetStackTrace(int *trace, int len, int skip)
{
HANDLE ht = GetCurrentThread();
HANDLE hp = GetCurrentProcess();
CONTEXT c;
memset( &c, '\0', sizeof c );
c.ContextFlags = CONTEXT_FULL;
#if 0
// broken with SP2
if ( !GetThreadContext( ht, &c ) )
return;
#else
__asm
{
call x
x: pop eax
mov c.Eip, eax
mov c.Ebp, ebp
}
#endif
// skip an extra frame
skip++;
STACKFRAME64 frame;
memset(&frame, 0, sizeof frame);
frame.AddrPC.Offset = c.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = c.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
int i=0;
// save space for 0 pc terminator
len--;
while(i < len &&
g_DbgHelpDll.m_StackWalk64 != NULL &&
g_DbgHelpDll.m_SymFunctionTableAccess64 != NULL &&
g_DbgHelpDll.m_SymGetModuleBase64 != NULL &&
(*g_DbgHelpDll.m_StackWalk64)(IMAGE_FILE_MACHINE_I386, hp, ht, &frame,
NULL, NULL, g_DbgHelpDll.m_SymFunctionTableAccess64, g_DbgHelpDll.m_SymGetModuleBase64, NULL)) {
if(skip-- > 0)
continue;
// FIXME: not 64 bit safe
trace[i++] = (int) frame.AddrPC.Offset;
}
trace[i] = 0;
}
static bool inited = false;
static const int MaxNameLength = 256;
void GetInfoFromPC(int pc, char *buff, int buffSize)
{
if(!inited) {
if(!g_DbgHelpDll.m_SymInitialize ||
!(*g_DbgHelpDll.m_SymInitialize)(GetCurrentProcess(), NULL, true)) {
LPVOID lpMsgBuf;
if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL ))
{
GCDebugMsg("See lpMsgBuf", true);
LocalFree(lpMsgBuf);
}
goto nosym;
}
inited = true;
}
// gleaned from IMAGEHLP_SYMBOL64 docs
IMAGEHLP_SYMBOL64 *pSym = (IMAGEHLP_SYMBOL64 *) alloca(sizeof(IMAGEHLP_SYMBOL64) + MaxNameLength);
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
pSym->MaxNameLength = MaxNameLength;
DWORD64 offsetFromSymbol;
if(!g_DbgHelpDll.m_SymGetSymFromAddr64 ||
!(*g_DbgHelpDll.m_SymGetSymFromAddr64)(GetCurrentProcess(), pc, &offsetFromSymbol, pSym)) {
goto nosym;
}
// get line
IMAGEHLP_LINE64 line;
memset(&line, 0, sizeof(IMAGEHLP_LINE64));
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD offsetFromLine;
if(!g_DbgHelpDll.m_SymGetLineFromAddr64 ||
!(*g_DbgHelpDll.m_SymGetLineFromAddr64)(GetCurrentProcess(), pc, &offsetFromLine, &line)) {
goto nosym;
}
/*
this isn't working, I think i need to call SymLoadModule64 or something
IMAGEHLP_MODULE64 module;
memset(&module, 0, sizeof module);
module.SizeOfStruct = sizeof module;
if(!SymGetModuleInfo64(GetCurrentProcess(), pSym->Address, &module))
{
LPVOID lpMsgBuf;
if(FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL ))
{
GCDebugMsg((wchar*)lpMsgBuf, true);
LocalFree(lpMsgBuf);
}
}
*/
// success!
char *fileName = line.FileName + strlen(line.FileName);
// skip everything up to last slash
while(fileName > line.FileName && *fileName != '\\')
fileName--;
fileName++;
StringCchPrintfA(buff, buffSize, "%s:%d", fileName, line.LineNumber);
return;
nosym:
StringCchPrintfA(buff, buffSize, "0x%x", pc);
}
#endif
#endif // MEMORY_INFO
}

View File

@@ -1,179 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "MMgc.h"
namespace MMgc
{
GCLargeAlloc::GCLargeAlloc(GC* gc) : GCAllocBase(gc)
{
m_blocks = NULL;
}
void* GCLargeAlloc::Alloc(size_t size, int flags)
{
int blocks = (size+sizeof(LargeBlock)+GCHeap::kBlockSize-1) / GCHeap::kBlockSize;
LargeBlock *block = (LargeBlock*) m_gc->AllocBlock(blocks, GC::kGCLargeAllocPageFirst, (flags&GC::kZero) != 0);
void *item = NULL;
if (block)
{
block->flags = ((flags&GC::kFinalize) != 0) ? kFinalizeFlag : 0;
block->flags |= ((flags&GC::kContainsPointers) != 0) ? kContainsPointers : 0;
block->flags |= ((flags&GC::kRCObject) != 0) ? kRCObject : 0;
block->gc = this->m_gc;
block->next = m_blocks;
block->usableSize = blocks*GCHeap::kBlockSize - sizeof(LargeBlock);
m_blocks = block;
item = (void*)(block+1);
#ifdef _DEBUG
if (flags & GC::kZero)
{
// AllocBlock should take care of this
for(int i=0, n=size/sizeof(int); i<n; i++) {
if(((int*)item)[i] != 0)
GCAssert(false);
}
}
#endif
}
return item;
}
void GCLargeAlloc::Free(void *item)
{
LargeBlock *b = GetBlockHeader(item);
if(b->flags & kHasWeakRef)
b->gc->ClearWeakRef(GetUserPointer(item));
LargeBlock **prev = &m_blocks;
while(*prev)
{
if(b == *prev)
{
*prev = b->next;
m_gc->FreeBlock(b, b->GetNumBlocks());
return;
}
prev = &(*prev)->next;
}
GCAssertMsg(false, "Bad free!");
}
void GCLargeAlloc::ClearMarks()
{
LargeBlock *block = m_blocks;
while (block) {
block->flags &= ~(kMarkFlag|kQueuedFlag);
block = block->next;
}
}
void GCLargeAlloc::Finalize()
{
LargeBlock *b = m_blocks;
while (b) {
if ((b->flags & kMarkFlag) == 0) {
void *item = b+1;
if (NeedsFinalize(b)) {
GCFinalizedObject *obj = (GCFinalizedObject *) item;
obj = (GCFinalizedObject *) GetUserPointer(obj);
obj->~GCFinalizedObject();
#if defined(_DEBUG) && defined(MMGC_DRC)
if((b->flags & kRCObject) != 0) {
b->gc->RCObjectZeroCheck((RCObject*)obj);
}
#endif
}
if(b->flags & kHasWeakRef) {
b->gc->ClearWeakRef(GetUserPointer(item));
}
}
b = b->next;
}
}
size_t GCLargeAlloc::Sweep()
{
size_t visitedSize=0;
LargeBlock **prev = &m_blocks;
while (*prev) {
LargeBlock *block = *prev;
visitedSize += block->GetNumBlocks();
LargeBlock *next = block->next;
if ((block->flags & kMarkFlag) == 0) {
// Destroy this block
*prev = block->next;
void *item = block+1;
(void)item;
#ifdef ALLOC_LOG
m_gc->LogFree(item);
#endif
#ifdef MEMORY_INFO
DebugFreeReverse(item, 0xba, 3);
#endif
m_gc->FreeBlock(block, block->GetNumBlocks());
} else {
prev = &block->next;
}
block = next;
}
return visitedSize;
}
GCLargeAlloc::~GCLargeAlloc()
{
GCAssert(!m_blocks);
}
/* static */
bool GCLargeAlloc::ConservativeGetMark(const void *item, bool bogusPointerReturnValue)
{
if(((intptr) item & 0xfff) == sizeof(LargeBlock))
{
return GetMark(item);
}
return bogusPointerReturnValue;
}
}

View File

@@ -1,177 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCLargeAlloc__
#define __GCLargeAlloc__
namespace MMgc
{
/**
* This is a garbage collecting allocator for large memory blocks.
*/
class GCLargeAlloc : public GCAllocBase
{
friend class GC;
private:
enum {
kMarkFlag = 0x1,
kQueuedFlag = 0x2,
kFinalizeFlag = 0x4,
kHasWeakRef = 0x8,
kContainsPointers = 0x10,
kRCObject = 0x20
};
public:
GCLargeAlloc(GC* gc);
~GCLargeAlloc();
void* Alloc(size_t size, int flags);
void Free(void *ptr);
void Finalize();
size_t Sweep();
void ClearMarks();
static void SetHasWeakRef(const void *item, bool to)
{
if(to) {
GetBlockHeader(item)->flags |= kHasWeakRef;
} else {
GetBlockHeader(item)->flags &= ~kHasWeakRef;
}
}
static bool HasWeakRef(const void *item)
{
return (GetBlockHeader(item)->flags & kHasWeakRef) != 0;
}
static bool IsLargeBlock(const void *item)
{
// The pointer should be 4K aligned plus 16 bytes
// Mac inserts 16 bytes for new[] so make it more general
return (((uint32)item & 0xFFF) == sizeof(LargeBlock));
}
static bool SetMark(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
bool oldMark = (block->flags & kMarkFlag) != 0;
block->flags |= kMarkFlag;
block->flags &= ~kQueuedFlag;
return oldMark;
}
static void SetQueued(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
block->flags |= kQueuedFlag;
}
static void SetFinalize(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
block->flags |= kFinalizeFlag;
}
static bool GetMark(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
return (block->flags & kMarkFlag) != 0;
}
static bool IsWhite(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
if(!IsLargeBlock(item))
return false;
return (block->flags & (kMarkFlag|kQueuedFlag)) == 0;
}
static void* FindBeginning(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
return (void*) (block+1);
}
static void ClearFinalized(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
block->flags &= ~kFinalizeFlag;
}
static bool ContainsPointers(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
return (block->flags & kContainsPointers) != 0;
}
static bool IsFinalized(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
return (block->flags & kFinalizeFlag) != 0;
}
static bool IsRCObject(const void *item)
{
LargeBlock *block = GetBlockHeader(item);
return (block->flags & kRCObject) != 0;
}
private:
struct LargeBlock
{
GC *gc;
uint32 usableSize;
uint32 flags;
LargeBlock *next;
int GetNumBlocks() const { return (usableSize + sizeof(LargeBlock)) / GCHeap::kBlockSize; }
};
static LargeBlock* GetBlockHeader(const void *addr)
{
return (LargeBlock*) ((uint32)addr & ~0xFFF);
}
static bool NeedsFinalize(LargeBlock *block)
{
return (block->flags & kFinalizeFlag) != 0;
}
// The list of chunk blocks
LargeBlock* m_blocks;
static bool ConservativeGetMark(const void *item, bool bogusPointerReturnValue);
};
}
#endif /* __GCLargeAlloc__ */

View File

@@ -1,546 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
#ifdef MEMORY_INFO
#ifndef __MWERKS__
#include <typeinfo>
#endif
namespace MMgc
{
GCThreadLocal<const char*> memtag;
GCThreadLocal<void*> memtype;
// Turn this to see GC stack traces.
const bool enableTraces = false;
// this is how many stack frames we'll attempt to lookup, we may not get this many and
// we may leave some out
const int kMaxTraceDepth = 7;
// include total and swept memory totals in memory profiling dumps
const bool showTotal = false;
const bool showSwept = false;
// controls size of table which is fixed
const int kNumTracesPow = 20;
const int kNumTraces = (enableTraces ? 1 << kNumTracesPow : 1);
#ifdef GCHEAP_LOCK
GCCriticalSection m_traceTableLock;
#endif
struct StackTrace
{
int ips[kMaxTraceDepth];
int size;
int totalSize;
int sweepSize;
int vtable;
const char *memtag;
int count;
int totalCount;
int sweepCount;
bool lumped;
};
static StackTrace traceTable[kNumTraces];
unsigned int hashTrace(int *trace)
{
unsigned int hash = *trace++;
while(*trace++ != 0) {
hash ^= *trace;
}
return hash;
}
bool tracesEqual(int *trace1, int *trace2)
{
while(*trace1) {
if(*trace1 != *trace2)
return false;
trace1++;
trace2++;
}
return *trace1 == *trace2;
}
unsigned int LookupTrace(int *trace)
{
#ifdef GCHEAP_LOCK
GCEnterCriticalSection lock(m_traceTableLock);
#endif
// this is true when traces are off
if(*trace == 0)
return 0;
static int numTraces = 0;
int modmask = kNumTraces - 1;
unsigned int hash = hashTrace(trace);
unsigned int index = hash & modmask;
unsigned int n = 17; // small number means cluster at start
int c = 1;
while(traceTable[index].ips[0] && !tracesEqual(traceTable[index].ips, trace)) {
// probe
index = (index + (n=n+c)) & modmask;
}
if(traceTable[index].ips[0] == 0) {
memcpy(traceTable[index].ips, trace, kMaxTraceDepth * sizeof(int));
numTraces++;
}
if(numTraces == kNumTraces) {
GCAssertMsg(false, "Increase trace table size!");
}
return index;
}
// increase this to get more
const int kNumTypes = 10;
const int kNumTracesPerType=5;
// data structure to gather allocations by type with the top 5 traces
struct TypeGroup
{
const char *name;
size_t size;
int count;
int traces[kNumTracesPerType ? kNumTracesPerType : 1];
};
const char* GetTypeName(int index, void *obj)
{
// cache
if(index > kNumTraces)
return "unknown";
if(traceTable[index].memtag)
return traceTable[index].memtag;
const char*name="unknown";
#ifdef WIN32
try {
const std::type_info *ti = &typeid(*(MMgc::GCObject*)obj);
if(ti->name())
name = ti->name();
// sometimes name will get set to bogus memory with no exceptions catch that
char c = *name;
(void)c; // silence compiler warning
} catch(...) {
name = "unknown";
}
#else
(void)obj;
#endif
// cache
traceTable[index].memtag = name;
return name;
}
#define PERCENT(all, some) ((((float)some)/(float)all)*100.0)
void DumpFatties()
{
GCHashtable typeTable(128);
#ifdef GCHEAP_LOCK
//GCEnterCriticalSection lock(m_traceTableLock);
#endif
int residentSize=0;
int residentCount=0;
for(int i=0; i < kNumTraces; i++)
{
int size;
if(showSwept) {
size = traceTable[i].sweepSize;
} else if(showTotal) {
size = traceTable[i].totalSize;
} else {
size = traceTable[i].size;
}
if(size == 0)
continue;
residentSize += size;
int count = traceTable[i].lumped ? 0 : traceTable[i].count;
residentCount += traceTable[i].count;
const char *name = "unknown";
#ifndef _MAC
#ifndef AVMPLUS_LINUX // TODO_LINUX
#ifndef MMGC_ARM
name = GetTypeName(i, &traceTable[i].vtable);
#endif //AVMPLUS_LINUX
#endif //MMGC_ARM
#endif
TypeGroup *tg = (TypeGroup*) typeTable.get((void*)name);
if(tg) {
GCAssert(tg->name == name);
tg->size += size;
tg->count += count;
for(int j=0; j<kNumTracesPerType; j++) {
if(traceTable[tg->traces[j]].size < size) {
if(j != kNumTracesPerType-1) {
memmove(&tg->traces[j+1], &tg->traces[j], (kNumTracesPerType-j-1)*sizeof(int));
}
tg->traces[j] = i;
break;
}
}
} else {
tg = new TypeGroup();
tg->size = size;
tg->count = count;
tg->name = name;
tg->traces[0] = i;
if(kNumTracesPerType) {
int num = kNumTracesPerType - 1;
memset(&tg->traces[1], 0, sizeof(int)*num);
}
typeTable.put((void*)name, tg);
}
}
int codeSize = GCHeap::GetGCHeap()->GetCodeMemorySize();
int inUse = GCHeap::GetGCHeap()->GetUsedHeapSize() * GCHeap::kBlockSize;
int committed = GCHeap::GetGCHeap()->GetTotalHeapSize() * GCHeap::kBlockSize + codeSize;
int free = GCHeap::GetGCHeap()->GetFreeHeapSize() * GCHeap::kBlockSize;
int memInfo = residentCount*16;
// executive summary
GCDebugMsg(false, "Code Size %d kb \n", codeSize>>10);
GCDebugMsg(false, "Total in use (used pages, ignoring code) %d kb \n", inUse>>10);
GCDebugMsg(false, "Total resident (individual allocations - code) %d kb \n", (residentSize-codeSize)>>10);
GCDebugMsg(false, "Allocator overhead (used pages - resident, ignoring code and mem_info): %d kb \n", ((inUse-memInfo)-(residentSize-codeSize))>>10);
GCDebugMsg(false, "Heap overhead (unused committed pages, ignoring code): %d kb \n", free>>10);
GCDebugMsg(false, "Total committed (including code) %d kb \n\n", committed>>10);
TypeGroup *residentFatties[kNumTypes];
memset(residentFatties, 0, kNumTypes * sizeof(TypeGroup *));
GCHashtableIterator iter(&typeTable);
const char *name;
while((name = (const char*)iter.nextKey()) != NULL)
{
TypeGroup *tg = (TypeGroup*)iter.value();
for(int j=0; j<kNumTypes; j++) {
if(!residentFatties[j]) {
residentFatties[j] = tg;
break;
}
if(residentFatties[j]->size < tg->size) {
if(j != kNumTypes-1) {
memmove(&residentFatties[j+1], &residentFatties[j], (kNumTypes-j-1) * sizeof(TypeGroup *));
}
residentFatties[j] = tg;
break;
}
}
}
for(int i=0; i < kNumTypes; i++)
{
TypeGroup *tg = residentFatties[i];
if(!tg)
break;
GCDebugMsg(false, "%s - %3.1f%% - %d kb %d items, avg %d b\n", tg->name, PERCENT(residentSize, tg->size), tg->size>>10, tg->count, tg->count ? tg->size/tg->count : 0);
for(int j=0; j < kNumTracesPerType; j++) {
int traceIndex = tg->traces[j];
if(traceIndex) {
int size = traceTable[traceIndex].size;
int count = traceTable[traceIndex].count;
if(showSwept) {
size = traceTable[traceIndex].sweepSize;
count = traceTable[traceIndex].sweepCount;
} else if(showTotal) {
size = traceTable[traceIndex].totalSize;
count = traceTable[traceIndex].totalCount;
}
GCDebugMsg(false, "\t %3.1f%% - %d kb - %d items - ", PERCENT(tg->size, size), size>>10, count);
PrintStackTraceByIndex(traceIndex);
}
}
}
GCHashtableIterator iter2(&typeTable);
while(iter2.nextKey() != NULL)
delete (TypeGroup*)iter2.value();
}
size_t DebugSize()
{
return 4 * sizeof(int);
}
/*
* allocate the memory such that we can detect underwrites, overwrites and remember
* the allocation stack in case of a leak. Memory is laid out like so:
*
* first four bytes == size / 4
* second four bytes == stack trace index
* size data bytes
* last 4 bytes == 0xdeadbeef
*
* Its important that the stack trace index is not stored in the first 4 bytes,
* it enables the leak detection to work see ~FixedAlloc. Underwrite detection isn't
* perfect, an assert will be fired if the stack table index is invalid (greater than
* the table size or to an unused table entry) or it the size gets mangled and the
* end tag isn't at mem+size.
*/
void *DebugDecorate(void *item, size_t size, int skip)
{
if (!item) return NULL;
static void *lastItem = 0;
static int lastTrace = 0;
#ifndef _MAC
if(lastItem)
{
// this guy might be deleted so swallow access violations
try {
traceTable[lastTrace].vtable = *(int*)lastItem;
} catch(...) {}
lastItem = 0;
}
#endif
int traceIndex;
// get index into trace table
{
#ifdef GCHEAP_LOCK
GCEnterCriticalSection lock(m_traceTableLock);
#endif
traceIndex = GetStackTraceIndex(skip);
}
if(GC::enableMemoryProfiling && memtype)
{
// if an allocation is tagged with MMGC_MEM_TYPE its a sub
// allocation of a "master" type and this flag prevents it
// from contributing to the count so averages make more sense
traceTable[traceIndex].lumped = true;
}
// subtract decoration space
size -= DebugSize();
ChangeSize(traceIndex, size);
int *mem = (int*)item;
// set up the memory
*mem++ = size;
*mem++ = traceIndex;
void *ret = mem;
mem += (size>>2);
*mem++ = 0xdeadbeef;
*mem = 0;
// save these off so we can save the vtable (which is assigned after memory is
// allocated)
if(GC::enableMemoryProfiling)
{
if(memtag || memtype) {
if(memtag)
traceTable[traceIndex].memtag = memtag;
else
traceTable[traceIndex].vtable = *(int*)(void*)memtype;
memtag = NULL;
memtype = NULL;
} else {
lastTrace = traceIndex;
lastItem = ret;
}
}
return ret;
}
void DebugFreeHelper(void *item, int poison, int skip)
{
int *ip = (int*) item;
int size = *ip;
int traceIndex = *(ip+1);
int *endMarker = ip + 2 + (size>>2);
// clean up
*ip = 0;
ip += 2;
// this can be called twice on some memory in inc gc
if(size == 0)
return;
if (*endMarker != 0xdeadbeef)
{
// if you get here, you have a buffer overrun. The stack trace about to
// be printed tells you where the block was allocated from. To find the
// overrun, put a memory breakpoint on the location endMarker is pointing to.
GCDebugMsg("Memory overwrite detected\n", false);
PrintStackTraceByIndex(traceIndex);
GCAssert(false);
}
{
#ifdef GCHEAP_LOCK
GCEnterCriticalSection lock(m_traceTableLock);
#endif
ChangeSize(traceIndex, -1 * size);
if(poison == 0xba) {
traceTable[traceIndex].sweepSize += size;
traceTable[traceIndex].sweepCount++;
}
traceIndex = GetStackTraceIndex(skip);
}
// whack the entire thing except the first 8 bytes,
// the free list
if(poison == 0xca || poison == 0xba)
size = GC::Size(ip);
else
size = FixedMalloc::Size(ip);
// size is the non-Debug size, so add 4 to get last 4 bytes, don't
// touch write back pointer space
memset(ip, poison, size+4);
// write stack index to ip (currently 3rd 4 bytes of item)
*ip = traceIndex;
}
void *DebugFree(void *item, int poison, int skip)
{
item = (int*) item - 2;
DebugFreeHelper(item, poison, skip);
return item;
}
void *DebugFreeReverse(void *item, int poison, int skip)
{
DebugFreeHelper(item, poison, skip);
item = (int*) item + 2;
return item;
}
void ChangeSize(int traceIndex, int delta)
{
#ifdef GCHEAP_LOCK
GCEnterCriticalSection lock(m_traceTableLock);
#endif
if(!enableTraces)
return;
traceTable[traceIndex].size += delta;
traceTable[traceIndex].count += (delta > 0) ? 1 : -1;
GCAssert(traceTable[traceIndex].size >= 0);
if(delta > 0) {
traceTable[traceIndex].totalSize += delta;
traceTable[traceIndex].totalCount++;
}
}
unsigned int GetStackTraceIndex(int skip)
{
if(!enableTraces)
return 0;
int trace[kMaxTraceDepth]; // an array of pcs
GetStackTrace(trace, kMaxTraceDepth, skip);
// get index into trace table
return LookupTrace(trace);
}
void DumpStackTraceHelper(int *trace)
{
if(!enableTraces)
return;
char out[2048];
char *tp = out;
for(int i=0; trace[i] != 0; i++) {
char buff[256];
GetInfoFromPC(trace[i], buff, 256);
strcpy(tp, buff);
tp += strlen(buff);
*tp++ = ' ';
}
*tp++ = '\n';
*tp = '\0';
GCDebugMsg(out, false);
}
void DumpStackTrace()
{
if(!enableTraces)
return;
int trace[kMaxTraceDepth];
GetStackTrace(trace, kMaxTraceDepth, 1);
DumpStackTraceHelper(trace);
}
void PrintStackTrace(const void *item)
{
if (item)
PrintStackTraceByIndex(*((int*)item - 1));
}
void PrintStackTraceByIndex(unsigned int i)
{
#ifdef GCHEAP_LOCK
GCEnterCriticalSection lock(m_traceTableLock);
#endif
if(i < kNumTraces)
DumpStackTraceHelper(traceTable[i].ips);
}
void ChangeSizeForObject(void *object, int size)
{
int traceIndex = *(((int*)object)-1);
ChangeSize(traceIndex, size);
}
void SetMemTag(const char *s)
{
if(memtag == NULL)
memtag = s;
}
void SetMemType(void *s)
{
if(memtype == NULL)
memtype = s;
}
}
#endif

View File

@@ -1,216 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCMemoryProfiler__
#define __GCMemoryProfiler__
#ifndef MEMORY_INFO
#define MMGC_MEM_TAG(_x)
#define MMGC_MEM_TYPE(_x)
#define GetRealPointer(_x) _x
#define GetUserPointer(_x) _x
#define DebugSize() 0
#else
#define MMGC_MEM_TAG(_x) MMgc::SetMemTag(_x)
#define MMGC_MEM_TYPE(_x) MMgc::SetMemType(_x)
namespace MMgc
{
#ifdef WIN32
/**
* GCCriticalSection is a simple Critical Section class used by GCMemoryProfiler to
* ensure mutually exclusive access. GCSpinLock doesn't suffice since its not
* re-entrant and we need that
*/
class GCCriticalSection
{
public:
GCCriticalSection()
{
InitializeCriticalSection(&cs);
}
inline void Acquire()
{
EnterCriticalSection(&cs);
}
inline void Release()
{
LeaveCriticalSection(&cs);
}
private:
CRITICAL_SECTION cs;
};
template<typename T>
class GCThreadLocal
{
public:
GCThreadLocal()
{
GCAssert(sizeof(T) == sizeof(LPVOID));
tlsId = TlsAlloc();
}
T operator=(T tNew)
{
TlsSetValue(tlsId, (LPVOID) tNew);
return tNew;
}
operator T() const
{
return (T) TlsGetValue(tlsId);
}
private:
DWORD tlsId;
};
#else
// FIXME: implement
template<typename T>
class GCThreadLocal
{
public:
GCThreadLocal()
{
}
T operator=(T tNew)
{
tlsId = tNew;
return tNew;
}
operator T() const
{
return tlsId;
}
private:
T tlsId;
};
class GCCriticalSection
{
public:
GCCriticalSection()
{
}
inline void Acquire()
{
}
inline void Release()
{
}
};
#endif
class GCEnterCriticalSection
{
public:
GCEnterCriticalSection(GCCriticalSection& cs) : m_cs(cs)
{
m_cs.Acquire();
}
~GCEnterCriticalSection()
{
m_cs.Release();
}
private:
GCCriticalSection& m_cs;
};
void SetMemTag(const char *memtag);
void SetMemType(void *memtype);
/**
* calculate a stack trace skipping skip frames and return index into
* trace table of stored trace
*/
unsigned int GetStackTraceIndex(int skip);
unsigned int LookupTrace(int *trace);
void ChangeSize(int traceIndex, int delta);
void DumpFatties();
/**
* Manually set me, for special memory not new/deleted, like the code memory region
*/
void ChangeSizeForObject(void *object, int size);
/**
* How much extra size does DebugDecorate need?
*/
size_t DebugSize();
/**
* decorate memory with debug information, return pointer to memory to return to caller
*/
void *DebugDecorate(void *item, size_t size, int skip);
/**
* Given a pointer to user memory do debug checks and return pointer to real memory
*/
void *DebugFree(void *item, int poison, int skip);
/**
* Given a pointer to real memory do debug checks and return pointer to user memory
*/
void *DebugFreeReverse(void *item, int poison, int skip);
/**
* Given a user pointer back up to real beginning
*/
inline void *GetRealPointer(const void *item) { return (void*)((intptr) item - 2 * sizeof(int)); }
/**
* Given a user pointer back up to real beginning
*/
inline void *GetUserPointer(const void *item) { return (void*)((intptr) item + 2 * sizeof(int)); }
const char* GetTypeName(int index, void *obj);
void GetInfoFromPC(int pc, char *buff, int buffSize);
void GetStackTrace(int *trace, int len, int skip);
// print stack trace of index into trace table
void PrintStackTraceByIndex(unsigned int index);
void PrintStackTrace(const void *item);
// print stack trace of caller
void DumpStackTrace();
}
#endif //MEMORY_INFO
#endif //!__GCMemoryProfiler__

View File

@@ -1,79 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
namespace MMgc
{
GCWeakRef* GCObject::GetWeakRef() const
{
return GC::GetWeakRef(this);
}
GCWeakRef* GCFinalizedObject::GetWeakRef() const
{
return GC::GetWeakRef(this);
}
void* GCFinalizedObject::operator new(size_t size, GC *gc, size_t extra)
{
return gc->Alloc(size + extra, GC::kFinalize|GC::kContainsPointers|GC::kZero, 4);
}
void GCFinalizedObject::operator delete (void *gcObject)
{
GC::GetGC(gcObject)->Free(gcObject);
}
void* GCFinalizedObjectOptIn::operator new(size_t size, GC *gc, size_t extra)
{
return gc->Alloc(size + extra, GC::kContainsPointers|GC::kZero, 4);
}
void GCFinalizedObjectOptIn::operator delete (void *gcObject)
{
GC::GetGC(gcObject)->Free(gcObject);
}
#if defined(MMGC_DRC) && defined(_DEBUG)
void RCObject::DumpHistory()
{
GCDebugMsg(false, "Ref count modification history for object 0x%x:\n", this);
int *traces = history.GetData();
for(int i=0, n=history.Count(); i<n; i++)
{
PrintStackTraceByIndex(traces[i]);
}
}
#endif
}

View File

@@ -1,390 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCObject__
#define __GCObject__
// VC++ wants these declared
//void *operator new(size_t size);
//void *operator new[] (size_t size);
inline void *operator new(size_t size, MMgc::GC *gc, int flags=MMgc::GC::kContainsPointers|MMgc::GC::kZero)
{
return gc->Alloc(size, flags, 4);
}
namespace MMgc
{
/**
*
*/
class GCCustomSizer
{
public:
virtual ~GCCustomSizer() {} // here since gcc complains otherwise
virtual size_t Size() = 0;
};
/**
* Baseclass for GC managed objects that aren't finalized
*/
class GCObject
{
public:
static void *operator new(size_t size, GC *gc, size_t extra = 0)
#ifdef __GNUC__
// add this to avoid GCC warning: 'operator new' must not return NULL unless it is declared 'throw()' (or -fcheck-new is in effect)
throw()
#endif
{
// TODO throw exception and shutdown player?
if (size + extra < size)
{
GCAssert(0);
return 0;
}
return gc->Alloc(size + extra, GC::kContainsPointers|GC::kZero, 4);
}
static void operator delete (void *gcObject)
{
GC::GetGC(gcObject)->Free(gcObject);
}
GCWeakRef *GetWeakRef() const;
#ifdef MEMORY_INFO
// give everyone a vtable for rtti type info purposes
virtual ~GCObject() {}
#endif
};
/**
* Baseclass for GC managed objects that are finalized
*/
class GCFinalizedObject
//: public GCObject can't do this, get weird compile errors in AVM plus, I think it has to do with
// the most base class (GCObject) not having any virtual methods)
{
public:
virtual ~GCFinalizedObject() {}
GCWeakRef *GetWeakRef() const;
static void *operator new(size_t size, GC *gc, size_t extra = 0);
static void operator delete (void *gcObject);
};
/**
* Baseclass for GC managed objects that are finalized
*/
class GCFinalizedObjectOptIn : public GCFinalizedObject
//: public GCObject can't do this, get weird compile errors in AVM plus, I think it has to do with
// the most base class (GCObject) not having any virtual methods)
{
public:
static void *operator new(size_t size, GC *gc, size_t extra = 0);
static void operator delete (void *gcObject);
};
#ifdef MMGC_DRC
class RCObject : public GCFinalizedObject
{
friend class GC;
public:
RCObject()
#ifdef _DEBUG
: history(0)
#endif
{
// composite == 0 is special, it means a deleted object in Release builds
// b/c RCObjects have a vtable we know composite isn't the first 4 byte and thus
// won't be trampled by the freelist
composite = 1;
GC::GetGC(this)->AddToZCT(this);
}
~RCObject()
{
// for explicit deletion
if (InZCT())
GC::GetGC(this)->RemoveFromZCT(this);
composite = 0;
}
bool IsPinned()
{
return (composite & STACK_PIN) != 0;
}
void Pin()
{
#ifdef _DEBUG
// this is a deleted object but 0xca indicates the InZCT flag so we
// might erroneously get here for a deleted RCObject
if(composite == 0xcacacaca || composite == 0xbabababa)
return;
#endif
// In Release builds, a deleted object is indicated by
// composite == 0. We must not set the STACK_PIN bit
// on a deleted object, because if we do, it transforms
// from a deleted object into a zero-ref count live object,
// causing nasty crashes down the line.
if (composite == 0)
return;
composite |= STACK_PIN;
}
void Unpin()
{
composite &= ~STACK_PIN;
}
int InZCT() const { return composite & ZCTFLAG; }
int RefCount() const { return (composite & RCBITS) - 1; }
int Sticky() const { return composite & STICKYFLAG; }
void Stick() { composite = STICKYFLAG; }
// called by EnqueZCT
void ClearZCTFlag()
{
composite &= ~(ZCTFLAG|ZCT_INDEX);
}
void IncrementRef()
{
if(Sticky() || composite == 0)
return;
#ifdef _DEBUG
GCAssert(GC::GetGC(this)->IsRCObject(this));
GCAssert(this == GC::GetGC(this)->FindBeginning(this));
// don't touch swept objects
if(composite == 0xcacacaca || composite == 0xbabababa)
return;
#endif
composite++;
if((composite&RCBITS) == RCBITS) {
composite |= STICKYFLAG;
} else if(InZCT()) {
GCAssert(RefCount() == 1);
GC::GetGC(this)->RemoveFromZCT(this);
}
#ifdef _DEBUG
if(GC::keepDRCHistory)
history.Push(GetStackTraceIndex(2));
#endif
}
__forceinline void DecrementRef()
{
if(Sticky() || composite == 0)
return;
#ifdef _DEBUG
GCAssert(GC::GetGC(this)->IsRCObject(this));
GCAssert(this == GC::GetGC(this)->FindBeginning(this));
// don't touch swept objects
if(composite == 0xcacacaca || composite == 0xbabababa)
return;
if(GC::GetGC(this)->Destroying())
return;
if(RefCount() == 0) {
DumpHistory();
GCAssert(false);
}
#endif
if (RefCount() == 0)
{
// This is a defensive measure. If DecrementRef is
// ever called on a zero ref-count object, composite--
// will cause an underflow, flipping all kinds of bits
// in bad ways and resulting in a crash later. Often,
// such a DecrementRef bug would be caught by the
// _DEBUG asserts above, but sometimes we have
// release-only crashers like this. Better to fail
// gracefully at the point of failure, rather than
// push the failure to some later point.
return;
}
composite--;
#ifdef _DEBUG
// the delete flag works around the fact that DecrementRef
// may be called after ~RCObject since all dtors are called
// in one pass. For example a FunctionScriptObject may be
// the sole reference to a ScopeChain and dec its ref in
// ~FunctionScriptObject during a sweep, but since ScopeChain's
// are smaller the ScopeChain was already finalized, thus the
// push crashes b/c the history object has been destructed.
if(GC::keepDRCHistory)
history.Push(GetStackTraceIndex(1));
#endif
// composite == 1 is the same as (rc == 1 && !notSticky && !notInZCT)
if(RefCount() == 0) {
GC::GetGC(this)->AddToZCT(this);
}
}
#ifdef _DEBUG
void DumpHistory();
#endif
void setZCTIndex(int index)
{
GCAssert(index >= 0 && index < (ZCT_INDEX>>8));
GCAssert(index < ZCT_INDEX>>8);
composite = (composite&~ZCT_INDEX) | ((index<<8)|ZCTFLAG);
}
int getZCTIndex() const
{
return (composite & ZCT_INDEX) >> 8;
}
static void *operator new(size_t size, GC *gc, size_t extra = 0)
{
return gc->Alloc(size + extra, GC::kContainsPointers|GC::kZero|GC::kRCObject|GC::kFinalize, 4);
}
private:
// 1 bit for inZCT flag (0x80000000)
// 1 bit for sticky flag (0x40000000)
// 20 bits for ZCT index
// 8 bits for RC count (0x000000FF)
static const int ZCTFLAG = 0x80000000;
static const int STICKYFLAG = 0x40000000;
static const int STACK_PIN = 0x20000000;
static const int RCBITS = 0x000000FF;
static const int ZCT_INDEX = 0x0FFFFF00;
#ifdef MMGC_DRC
int32 composite;
#ifdef _DEBUG
// addref/decref stack traces
GCStack<int,4> history;
int padto32bytes;
#endif
#endif
};
class RCFinalizedObject : public RCObject{};
template<class T>
class ZeroPtr
{
public:
ZeroPtr() { t = NULL; }
ZeroPtr(T t) : t(t) { }
~ZeroPtr()
{
t = NULL;
}
operator T() { return t; }
bool operator!=(T other) { return other != t; }
T operator->() const { return t; }
private:
T t;
};
template<class T>
class RCPtr
{
public:
RCPtr() { t = NULL; }
RCPtr(T t) : t(t) { if(t && (int)t != 1) t->IncrementRef(); }
~RCPtr()
{
if(t && t != (T)1)
t->DecrementRef();
// 02may06 grandma : I want to enable
// class DataIOBase { DRC(PlayerToplevel *) const m_toplevel; }
//
// DataIOBase is a virtual base class, so we don't know if the
// subclass is GCObject or not. We need it to be const, or
// a GCObject would require a DWB(), and if it's const, we
// cannot zero it out during ~DataIOBase. The simplest solution
// seemed to be zeroing out the member here.
t = NULL;
}
T operator=(T tNew)
{
if(t && (int)t != 1)
t->DecrementRef();
t = tNew;
if(t && (int)t != 1)
t->IncrementRef();
// this cast is safe b/c other wise compilation would fail
return (T) t;
}
operator T() const
{
return (T) t;
}
operator ZeroPtr<T>() const { return t; }
bool operator!=(T other) { return other != t; }
T operator->() const
{
return (T) t;
}
void Clear() { t = NULL; }
private:
T t;
};
#define DRC(_type) MMgc::RCPtr<_type>
#else // !MMGC_DRC
#define DRC(_type) _type
class RCObject : public GCObject {};
class RCFinalizedObject : public GCFinalizedObject {};
#endif
}
#endif /* __GCObject__ */

View File

@@ -1,101 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCSpinLock__
#define __GCSpinLock__
#include <pthread.h>
namespace MMgc
{
/**
* GCSpinLock is a simple spin lock class used by GCHeap to
* ensure mutually exclusive access. The GCHeap may be accessed
* by multiple threads, so this is necessary to ensure that
* the threads do not step on each other.
*/
class GCSpinLock
{
public:
GCSpinLock()
{
pthread_spin_init( &m1, 0 );
}
~GCSpinLock()
{
pthread_spin_destroy( &m1 );
}
inline void Acquire()
{
pthread_spin_lock( &m1 );
}
inline void Release()
{
pthread_spin_unlock( &m1 );
}
private:
pthread_spinlock_t m1;
};
/**
* GCAcquireSpinlock is a convenience class which acquires
* the specified spinlock at construct time, then releases
* the spinlock at desruct time. The single statement
*
* GCAcquireSpinlock acquire(spinlock);
*
* ... will acquire the spinlock at the top of the function
* and release it at the end. This makes for less error-prone
* code than explicit acquire/release.
*/
class GCAcquireSpinlock
{
public:
GCAcquireSpinlock(GCSpinLock& spinlock) : m_spinlock(spinlock)
{
m_spinlock.Acquire();
}
~GCAcquireSpinlock()
{
m_spinlock.Release();
}
private:
GCSpinLock& m_spinlock;
};
}
#endif /* __GCSpinLock__ */

View File

@@ -1,135 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCSpinLock__
#define __GCSpinLock__
#ifdef __GNUC__
#include <CoreServices/CoreServices.h>
#else // __GNUC__
#include <Multiprocessing.h>
#endif // __GNUC__
#if TARGET_RT_MAC_MACHO
extern "C"
{
extern void _spin_lock(uint32_t *);
extern void _spin_unlock(uint32_t *);
}
#endif
namespace MMgc
{
/**
* GCSpinLock is a simple spin lock class used by GCHeap to
* ensure mutually exclusive access. The GCHeap may be accessed
* by multiple threads, so this is necessary to ensure that
* the threads do not step on each other.
*/
class GCSpinLock
{
public:
GCSpinLock()
{
#if TARGET_RT_MAC_MACHO
m1 = 0;
#else
OSStatus critErr = ::MPCreateCriticalRegion( &mCriticalRegion );
GCAssert( critErr == noErr );
#endif
}
~GCSpinLock()
{
#if !TARGET_RT_MAC_MACHO
OSStatus critErr = ::MPDeleteCriticalRegion( mCriticalRegion );
GCAssert( critErr == noErr );
#endif
}
inline void Acquire()
{
#if TARGET_RT_MAC_MACHO
_spin_lock(&m1);
#else
OSStatus critErr = ::MPEnterCriticalRegion( mCriticalRegion, kDurationForever );
GCAssert( critErr == noErr );
#endif
}
inline void Release()
{
#if TARGET_RT_MAC_MACHO
_spin_unlock(&m1);
#else
OSStatus critErr = ::MPExitCriticalRegion( mCriticalRegion );
GCAssert( critErr == noErr );
#endif
}
private:
#if TARGET_RT_MAC_MACHO
uint32_t m1;
#else
MPCriticalRegionID mCriticalRegion;
#endif
};
/**
* GCAcquireSpinlock is a convenience class which acquires
* the specified spinlock at construct time, then releases
* the spinlock at desruct time. The single statement
*
* GCAcquireSpinlock acquire(spinlock);
*
* ... will acquire the spinlock at the top of the function
* and release it at the end. This makes for less error-prone
* code than explicit acquire/release.
*/
class GCAcquireSpinlock
{
public:
GCAcquireSpinlock(GCSpinLock& spinlock) : m_spinlock(spinlock)
{
m_spinlock.Acquire();
}
~GCAcquireSpinlock()
{
m_spinlock.Release();
}
private:
GCSpinLock& m_spinlock;
};
}
#endif /* __GCSpinLock__ */

View File

@@ -1,99 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCSpinLock__
#define __GCSpinLock__
#include <windows.h>
namespace MMgc
{
/**
* GCSpinLock is a simple spin lock class used by GCHeap to
* ensure mutually exclusive access. The GCHeap may be accessed
* by multiple threads, so this is necessary to ensure that
* the threads do not step on each other.
*/
class GCSpinLock
{
public:
GCSpinLock()
{
sl = 0;
}
inline void Acquire()
{
GCAssert(sl==0 || sl==1 || sl==0); // Poor mans defense against thread timing issues, per Tom R.
while (InterlockedCompareExchange(&sl, 1, 0) != 0) {
Sleep(0);
}
}
inline void Release()
{
InterlockedExchange(&sl, 0);
}
private:
long sl;
};
/**
* GCAcquireSpinlock is a convenience class which acquires
* the specified spinlock at construct time, then releases
* the spinlock at desruct time. The single statement
*
* GCAcquireSpinlock acquire(spinlock);
*
* ... will acquire the spinlock at the top of the function
* and release it at the end. This makes for less error-prone
* code than explicit acquire/release.
*/
class GCAcquireSpinlock
{
public:
GCAcquireSpinlock(GCSpinLock& spinlock) : m_spinlock(spinlock)
{
m_spinlock.Acquire();
}
~GCAcquireSpinlock()
{
m_spinlock.Release();
}
private:
GCSpinLock& m_spinlock;
};
}
#endif /* __GCSpinLock__ */

View File

@@ -1,123 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCStack__
#define __GCStack__
namespace MMgc
{
template<typename T, int defSize=512>
class GCStack
{
enum { kDefSize = defSize };
public:
GCStack(int defaultSize=kDefSize) : m_iCount(0), m_iAllocSize(defaultSize), m_items(NULL)
{
Alloc();
}
~GCStack()
{
if ( m_items )
{
delete [] m_items;
m_items = NULL;
}
m_iCount = m_iAllocSize = 0;
}
void Push(T item)
{
if ( ( m_iCount + 1 ) > m_iAllocSize )
{
// need to allocate a new block first
m_iAllocSize = m_iAllocSize ? m_iAllocSize*2 : kDefSize;
Alloc();
}
m_items[m_iCount++] = item;
}
T Pop()
{
T t = m_items[--m_iCount];
#ifdef _DEBUG
GCAssert(m_iCount>=0);
memset(&m_items[m_iCount], 0, sizeof(T));
#endif
return t;
}
T Peek()
{
#ifdef _DEBUG
GCAssert(m_iCount>=0);
#endif
T t = m_items[m_iCount-1];
return t;
}
unsigned int Count() { return m_iCount; }
void Keep(unsigned int num)
{
GCAssert(num <= m_iCount);
m_iCount = num;
}
T* GetData() { return m_items; }
protected:
// no impl
GCStack(const GCStack& other);
GCStack& operator=(const GCStack& other);
private:
void Alloc()
{
// need to allocate a new block first
if(m_iAllocSize) {
T* items = new T[ m_iAllocSize ];
if ( items )
{
::memcpy(items, m_items, m_iCount * sizeof(T));
}
delete [] m_items;
m_items = items;
}
}
unsigned int m_iCount, m_iAllocSize;
T *m_items;
};
}
#endif /* __GCStack__ */

View File

@@ -1,147 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"
#ifdef _MSC_VER
// "behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized"
#pragma warning(disable:4345) // b/c GCObject doesn't have a ctor
#endif
namespace MMgc
{
GC *gc;
GCWeakRef* createWeakRef(int extra=0)
{
return (new (gc, extra) GCObject())->GetWeakRef();
}
void weakRefSweepSmall()
{
GCWeakRef *ref = createWeakRef();
gc->Collect();
gc->CleanStack(true);
gc->Collect();
(void)ref;
GCAssert(ref->get() == NULL);
}
void weakRefSweepLarge()
{
GCWeakRef *ref = createWeakRef(5000);
gc->Collect();
gc->CleanStack(true);
gc->Collect();
(void)ref;
GCAssert(ref->get() == NULL);
}
void weakRefFreeSmall()
{
GCWeakRef *ref = createWeakRef();
delete ref->get();
GCAssert(ref->get() == NULL);
}
void weakRefFreeLarge()
{
GCWeakRef *ref = createWeakRef(5000);
delete ref->get();
GCAssert(ref->get() == NULL);
}
class RCObjectAddRefInDtor : public RCObject
{
public:
RCObjectAddRefInDtor(RCObject **stackPinners, int length) : rcs(stackPinners), length(length) {}
~RCObjectAddRefInDtor()
{
// whack these, used create freelist
for(int i=0, n=length; i<n;i++)
{
r1 = rcs[i];
}
// add/remove myself (this was the apollo bug)
r1 = this;
r1 = NULL;
rcs = NULL;
length = 0;
}
DRCWB(RCObject*) r1;
// naked pointer so I can kick these pinners out out of the ZCT during reap
RCObject **rcs;
int length;
};
GCWeakRef* createProblem(RCObject **stackPinners)
{
// now create one that causes some removes from the dtor
return (new (gc) RCObjectAddRefInDtor(stackPinners, 3))->GetWeakRef();
}
/* see bug 182420 */
void drcApolloTest()
{
// prime ZCT with some pinners
RCObject *stackPinners[3];
GCWeakRef *wr = createProblem(stackPinners);
stackPinners[0] = new (gc) RCObject();
stackPinners[1] = new (gc) RCObject();
stackPinners[2] = new (gc) RCObject();
// force ZCT
for(int i=0, n=1000;i<n; i++)
{
new (gc) RCObject();
}
// it may still be alive if we had a dirty stack
if(wr->get())
delete wr->get();
}
void RunGCTests(GC *g)
{
gc = g;
weakRefSweepSmall();
weakRefSweepLarge();
weakRefFreeSmall();
weakRefFreeLarge();
drcApolloTest();
}
}

View File

@@ -1,42 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __GCTests__
#define __GCTests__
namespace MMgc
{
void RunGCTests(GC *gc);
}
#endif /* __GCTests__ */

View File

@@ -1,94 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 __GCTypes__
#define __GCTypes__
#ifdef _MAC
#include <stdint.h>
#endif
namespace MMgc
{
#ifdef _MSC_VER
typedef __int64 int64;
typedef __int64 sint64;
typedef unsigned __int64 uint64;
#elif defined(_MAC)
typedef int64_t int64;
typedef int64_t sint64;
typedef uint64_t uint64;
#else
typedef long long int64;
typedef long long sint64;
typedef unsigned long long uint64;
#endif
typedef unsigned long uint32;
typedef signed long int32;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned char uint8;
typedef signed char int8;
// math friendly pointer (64 bits in LP 64 systems)
typedef unsigned long intptr;
/* wchar is our version of wchar_t, since wchar_t is different sizes
on different platforms, but we want to use UTF-16 uniformly. */
typedef unsigned short wchar;
/**
* Conservative collector unit of work
*/
class GCWorkItem
{
public:
GCWorkItem() : ptr(0), size(0) {}
GCWorkItem(const void *p, uint32 s) : ptr(p), size(s) {}
const void *ptr;
uint32 size;
};
typedef void* (*GCMallocFuncPtr)(size_t size);
typedef void (*GCFreeFuncPtr)(void* mem);
#ifndef NULL
#define NULL 0
#endif
}
#endif /* __GCTypes__ */

View File

@@ -1,107 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 ***** */
//
// GCWeakRef.h
// GC weak references (aka safe handles) as template classes
//
#ifndef _GC_WEAK_REF_H_
#define _GC_WEAK_REF_H_
namespace MMgc
{
// new improved weak ref
class GCWeakRef : public GCObject
{
friend class GC;
public:
GCObject *get() { return (GCObject*)m_obj; }
void clear() { m_obj = 0; }
private:
// override new so we can be tell the GC we don't contain pointers
static void *operator new(size_t size, GC *gc)
{
return gc->Alloc(size, 0, 4);
}
// private, only GC can access
GCWeakRef(const void *obj) : m_obj(obj)
{
#ifdef _DEBUG
obj_creation = *((int*)GetRealPointer(obj)+1);
#endif
}
const void *m_obj;
#ifdef _DEBUG
int obj_creation;
#endif
};
#if 0
// something like this would be nice
template<class T> class GCWeakRefPtr
{
public:
GCWeakRefPtr() {}
GCWeakRefPtr(T t) { set(t);}
~GCWeakRefPtr() { t = NULL; }
T operator=(const GCWeakRefPtr<T>& wb)
{
return set(wb.t);
}
T operator=(T tNew)
{
return set(tNew);
}
operator T() const { return (T) t->get(); }
bool operator!=(T other) const { return other != t; }
T operator->() const
{
return (T) t->get();
}
private:
T set(const T tNew)
{
t = tNew->GetWeakRef();
}
GCWeakRef* t;
};
#endif
}
#endif // _GC_WEAK_REF_H_

View File

@@ -1,32 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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"

View File

@@ -1,151 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __MMgc__
#define __MMgc__
// For size_t
#include <stddef.h>
#ifdef WIN32
#include "winbuild.h"
#endif
#ifdef _MAC
#include "macbuild.h"
#endif
#ifdef AVMPLUS_LINUX
#include "linuxbuild.h"
#endif
#ifdef MMGC_ARM
#include "armbuild.h"
#endif
//define this to get an alloc log
//#define ALLOC_LOG
#if defined(ALLOC_LOG) || defined(GC_STATS)
#include <stdio.h>
#endif
#ifdef SCRIPT_DEBUGGER
#ifndef DEBUGGER
#define DEBUGGER
#endif
#endif
#if defined(_DEBUG) || defined(_MAC)
// for memset
#include <string.h>
#endif
#ifndef _MSC_VER
#define __forceinline
#endif
#include "GCDebug.h"
/*
* If _GCHeapLock is defined, a spin lock is used for thread safety
* on all public API's (Alloc, Free, ExpandHeap)
*
* 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 GCHEAP_LOCK
#ifdef WIN32
#include "GCSpinLockWin.h"
#endif
#ifdef _MAC
#include "GCSpinLockMac.h"
#endif
#ifdef AVMPLUS_LINUX
#include "GCSpinLockLinux.h"
#endif
#endif
namespace MMgc
{
class GCAllocBase;
class GC;
class GCTraceObject;
class RCObject;
class GCWeakRef;
class GCObject;
class GCHashtable;
class Cleaner;
class GCAlloc;
}
#ifdef _MSC_VER
#pragma warning(disable:4291) // no matching operator delete found; memory will not be freed if initialization throws an exception
#endif
#include "GCTypes.h"
#include "GCStack.h"
#include "GCAllocObject.h"
#include "GCAllocBase.h"
#include "GCHeap.h"
#include "GCAlloc.h"
#include "GCLargeAlloc.h"
#include "GCMemoryProfiler.h"
#include "FixedAlloc.h"
#include "FixedMalloc.h"
#include "GCHashtable.h"
#include "GC.h"
#include "GCObject.h"
#include "GCWeakRef.h"
#include "WriteBarrier.h"
#ifdef MMGC_AVMPLUS
#include "avmbuild.h"
#include "avmplus.h"
#ifdef AVMPLUS_PROFILE
#define PROFILE(x) avmplus::DynamicProfiler::StackMark mark(x)
#else
#define PROFILE(x)
#endif
#else
#define PROFILE(x)
#endif
#if defined(MMGC_DRC) && !defined(WRITE_BARRIERS)
#error "Need write barriers for DRC"
#endif
#endif /* __MMgc__ */

Binary file not shown.

View File

@@ -1,30 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMgc", "MMgc.vcproj", "{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Release = Release
VTune = VTune
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug.ActiveCfg = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug.Build.0 = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release.ActiveCfg = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release.Build.0 = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune.ActiveCfg = VTune|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune.Build.0 = VTune|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.Debug.ActiveCfg = Debug|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.Debug.Build.0 = Debug|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.Release.ActiveCfg = Release|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.Release.Build.0 = Release|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.VTune.ActiveCfg = VTune|Win32
{FE29422B-B9A1-4C3A-954A-0B37CF0642D5}.VTune.Build.0 = VTune|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -1,375 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="MMgc"
ProjectGUID="{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}"
SccProjectName=""
SccAuxPath=""
SccLocalPath=""
SccProvider=""
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="0">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="TRUE"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc_d.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="0">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
FavorSizeOrSpeed="0"
OptimizeForProcessor="0"
AdditionalIncludeDirectories=".;..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="0"
BufferSecurityCheck="FALSE"
UsePrecompiledHeader="0"
AssemblerOutput="4"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="TRUE"
Detect64BitPortabilityProblems="FALSE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="VTune|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="0">
<Tool
Name="VCCLCompilerTool"
Optimization="3"
FavorSizeOrSpeed="1"
OptimizeForProcessor="2"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="0"
BufferSecurityCheck="FALSE"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="TRUE"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="2"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="lib/MMgc_vtune.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release Debugger|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;DEBUGGER;AVMPLUS_IA32"
StringPooling="TRUE"
ExceptionHandling="FALSE"
RuntimeLibrary="0"
BufferSecurityCheck="FALSE"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="TRUE"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Debug Debugger|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="0">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;DEBUGGER;AVMPLUS_IA32"
MinimalRebuild="TRUE"
ExceptionHandling="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
RuntimeTypeInfo="TRUE"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="TRUE"
Detect64BitPortabilityProblems="FALSE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc_d.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\FixedAlloc.cpp">
</File>
<File
RelativePath=".\FixedMalloc.cpp">
</File>
<File
RelativePath="GC.cpp">
</File>
<File
RelativePath="GCAlloc.cpp">
</File>
<File
RelativePath="GCAllocBase.cpp">
</File>
<File
RelativePath=".\GCAllocObjectWin.cpp">
</File>
<File
RelativePath=".\GCDebugWin.cpp">
</File>
<File
RelativePath=".\GCHashtable.cpp">
</File>
<File
RelativePath="GCHeap.cpp">
</File>
<File
RelativePath="GCHeapWin.cpp">
</File>
<File
RelativePath="GCLargeAlloc.cpp">
</File>
<File
RelativePath=".\GCMemoryProfiler.cpp">
</File>
<File
RelativePath=".\GCObject.cpp">
</File>
<File
RelativePath=".\GCTests.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\FixedAlloc.h">
</File>
<File
RelativePath=".\FixedMalloc.h">
</File>
<File
RelativePath="GC.h">
</File>
<File
RelativePath="GCAlloc.h">
</File>
<File
RelativePath="GCAllocBase.h">
</File>
<File
RelativePath=".\GCAllocObject.h">
</File>
<File
RelativePath=".\GCDebug.h">
</File>
<File
RelativePath=".\GCHashtable.h">
</File>
<File
RelativePath="GCHeap.h">
</File>
<File
RelativePath="GCLargeAlloc.h">
</File>
<File
RelativePath=".\GCMemoryProfiler.h">
</File>
<File
RelativePath=".\GCObject.h">
</File>
<File
RelativePath=".\GCSpinLockWin.h">
</File>
<File
RelativePath=".\GCStack.h">
</File>
<File
RelativePath=".\GCTests.h">
</File>
<File
RelativePath=".\GCTypes.h">
</File>
<File
RelativePath=".\GCWeakRef.h">
</File>
<File
RelativePath=".\MMgc.h">
</File>
<File
RelativePath=".\winbuild.h">
</File>
<File
RelativePath=".\WriteBarrier.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\VTune\MMgc.vpj">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,28 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMgc", "MMgc_8.vcproj", "{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug Debugger|Win32 = Debug Debugger|Win32
Debug|Win32 = Debug|Win32
Release Debugger|Win32 = Release Debugger|Win32
Release|Win32 = Release|Win32
VTune|Win32 = VTune|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug Debugger|Win32.ActiveCfg = Debug Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug Debugger|Win32.Build.0 = Debug Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug|Win32.ActiveCfg = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug|Win32.Build.0 = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release Debugger|Win32.ActiveCfg = Release Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release Debugger|Win32.Build.0 = Release Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release|Win32.ActiveCfg = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release|Win32.Build.0 = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune|Win32.ActiveCfg = VTune|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune|Win32.Build.0 = VTune|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -1,531 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="MMgc"
ProjectGUID="{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
IntermediateDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
ExceptionHandling="1"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc_d.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
IntermediateDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
FavorSizeOrSpeed="0"
AdditionalIncludeDirectories=".;..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32;_CRT_SECURE_NO_DEPRECATE"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
TreatWChar_tAsBuiltInType="false"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
AssemblerOutput="4"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="VTune|Win32"
OutputDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
IntermediateDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
FavorSizeOrSpeed="1"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;AVMPLUS_IA32;_CRT_SECURE_NO_DEPRECATE"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="0"
BufferSecurityCheck="false"
TreatWChar_tAsBuiltInType="false"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="1"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc_vtune.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release Debugger|Win32"
OutputDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
IntermediateDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;DEBUGGER;AVMPLUS_IA32;_CRT_SECURE_NO_DEPRECATE"
ExceptionHandling="0"
TreatWChar_tAsBuiltInType="false"
RuntimeTypeInfo="false"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug Debugger|Win32"
OutputDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
IntermediateDirectory="obj_8/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="4"
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\core;..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;DEBUGGER;AVMPLUS_IA32;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="true"
ExceptionHandling="1"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
TreatWChar_tAsBuiltInType="false"
UsePrecompiledHeader="0"
ProgramDataBaseFileName="$(IntDir)/MMgc.pdb"
BrowseInformation="0"
WarningLevel="4"
WarnAsError="true"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/MMgc_d.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\FixedAlloc.cpp"
>
</File>
<File
RelativePath=".\FixedMalloc.cpp"
>
</File>
<File
RelativePath="GC.cpp"
>
</File>
<File
RelativePath="GCAlloc.cpp"
>
</File>
<File
RelativePath="GCAllocBase.cpp"
>
</File>
<File
RelativePath=".\GCAllocObjectWin.cpp"
>
</File>
<File
RelativePath=".\GCDebugWin.cpp"
>
</File>
<File
RelativePath=".\GCHashtable.cpp"
>
</File>
<File
RelativePath="GCHeap.cpp"
>
</File>
<File
RelativePath="GCHeapWin.cpp"
>
</File>
<File
RelativePath="GCLargeAlloc.cpp"
>
</File>
<File
RelativePath=".\GCMemoryProfiler.cpp"
>
</File>
<File
RelativePath=".\GCObject.cpp"
>
</File>
<File
RelativePath=".\GCTests.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\FixedAlloc.h"
>
</File>
<File
RelativePath=".\FixedMalloc.h"
>
</File>
<File
RelativePath="GC.h"
>
</File>
<File
RelativePath="GCAlloc.h"
>
</File>
<File
RelativePath="GCAllocBase.h"
>
</File>
<File
RelativePath=".\GCAllocObject.h"
>
</File>
<File
RelativePath=".\GCDebug.h"
>
</File>
<File
RelativePath=".\GCHashtable.h"
>
</File>
<File
RelativePath="GCHeap.h"
>
</File>
<File
RelativePath="GCLargeAlloc.h"
>
</File>
<File
RelativePath=".\GCMemoryProfiler.h"
>
</File>
<File
RelativePath=".\GCObject.h"
>
</File>
<File
RelativePath=".\GCSpinLockWin.h"
>
</File>
<File
RelativePath=".\GCStack.h"
>
</File>
<File
RelativePath=".\GCTests.h"
>
</File>
<File
RelativePath=".\GCTypes.h"
>
</File>
<File
RelativePath=".\GCWeakRef.h"
>
</File>
<File
RelativePath=".\MMgc.h"
>
</File>
<File
RelativePath=".\winbuild.h"
>
</File>
<File
RelativePath=".\WriteBarrier.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\VTune\MMgc.vpj"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,108 +0,0 @@
# ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
# DEBUG can be set to YES to include debugging info, or NO otherwise
DEBUG := YES
# DEBUGGER can be set to choose the Content Debugger version of the gc
DEBUGGER := YES
MMGC_ROOT := .
CC := gcc
CXX := g++
AR := ar
UNAME := $(shell uname)
ARCH := ${shell uname -m}
ifeq ($(UNAME),Linux)
MMGC_PLATFORM_DEFS := -DSOFT_ASSERTS -D_DEBUG
endif
ifeq ($(UNAME),Darwin)
MMGC_PLATFORM_DEFS := -DDARWIN -D_MAC -Dpowerc -DSOFT_ASSERTS -DDEBUGGER -DTARGET_RT_MAC_MACHO=1 -D_DEBUG -DDEBUG
ifeq (${ARCH},i386)
MMGC_PLATFORM_DEFS := ${MMGC_PLATFORM_DEFS} -DAVMPLUS_IA32
else
MMGC_PLATFORM_DEFS := ${MMGC_PLATFORM_DEFS} -DAVMPLUS_PPC
endif
endif
ifeq ($(UNAME),CYGWIN_NT-5.1)
MMGC_PLATFORM_DEFS := -DCYGWIN -DAVMPLUS_IA32
endif
include makecommon
#****************************************************************************
# Targets of the build
#****************************************************************************
OUTPUT := libmmgc.a
all: ${OUTPUT}
#****************************************************************************
# Output
#****************************************************************************
OBJS := $(addsuffix .o,$(basename ${MMGC_SRCS}))
${OUTPUT}: ${OBJS}
@echo "=== creating libmmgc.a ==="
${AR} rcs $@ ${OBJS}
@echo "Done"
#****************************************************************************
# Dependencies
#****************************************************************************
# Create a lists of object and .d files to create -
# one for each source file in the directory
DEPS := ${patsubst %${strip .cpp},%.d,${MMGC_SRCS}}
# make any non-existent make files (using the g++ preprocessor)
${DEPS} : %.d : %.cpp
${CXX} ${MMGC_CXXFLAGS} ${MMGC_INCS} -MM $< > $@
# Rules
clean:
-rm -f core* ${OBJS} ${OUTPUT} ${DEPS} log outputdebug.txt
ifneq (${MAKECMDGOALS},clean)
ifneq (${UNAME},Linux)
include ${DEPS} # include the generated make files, which make the object files
endif
endif

View File

@@ -1,172 +0,0 @@
# ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
# Set this to yes if doing ARM skunkworks
ARM_SKUNKWORKS := YES
# Set this to yes for GNUARM
GNUARM := YES
# DEBUG can be set to YES to include debugging info, or NO otherwise
DEBUG := YES
CC := arm-elf-gcc
CXX := arm-elf-g++
AR := arm-elf-ar
RANLIB := arm-elf-ranlib
UNAME := $(shell uname)
ifeq ($(UNAME),Linux)
PLATFORM_DEFS := -DAVMPLUS_LINUX -DSOFT_ASSERTS -DDEBUGGER -DAVMPLUS_IA32 -D_DEBUG -DDEBUG -DCYGWIN -DAVMPLUS_IA32
endif
ifeq ($(UNAME),Darwin)
PLATFORM_DEFS := -DDARWIN -D_MAC -Dpowerc -DSOFT_ASSERTS -DAVMPLUS_PPC -DDEBUGGER -DTARGET_RT_MAC_MACHO=1 -D_DEBUG -DDEBUG
endif
ifeq ($(UNAME),CYGWIN_NT-5.1)
PLATFORM_DEFS := -DCYGWIN -DAVMPLUS_IA32
endif
ifeq (YES, ${ARM_SKUNKWORKS})
ifeq (YES, ${GNUARM})
SOFT_FLOAT :=
USE_MMAP :=
else
SOFT_FLOAT := -msoft-float
USE_MMAP := -DUSE_MMAP
endif
else
SOFT_FLOAT :=
USE_MMAP := -DUSE_MMAP
endif
ifeq (YES, ${ARM_SKUNKWORKS})
PLATFORM_DEFS := -DSOFT_ASSERTS -DMMGC_ARM -DAVMPLUS_ARM -DAVMPLUS_UCLINUX -DDEBUGGER -D_DEBUG -DDEBUG
endif
DEBUG_CFLAGS := -g -MMD
RELEASE_CFLAGS := -O3 -MMD
DEBUG_CXXFLAGS := ${DEBUG_CFLAGS} -fno-rtti -fcheck-new ${SOFT_FLOAT} ${USE_MMAP}
RELEASE_CXXFLAGS := ${RELEASE_CFLAGS} -fno-rtti -fcheck-new ${SOFT_FLOAT} ${USE_MMAP}
ifeq (YES, ${DEBUG})
CFLAGS := ${DEBUG_CFLAGS}
CXXFLAGS := ${DEBUG_CXXFLAGS}
else
CFLAGS := ${RELEASE_CFLAGS}
CXXFLAGS := ${RELEASE_CXXFLAGS}
endif
#****************************************************************************
# Preprocessor directives
#****************************************************************************
DEFS := -DUNIX ${PLATFORM_DEFS} -DENABLE_PROFILER
CFLAGS := ${CFLAGS} ${DEFS}
CXXFLAGS := ${CXXFLAGS} ${DEFS}
#****************************************************************************
# Include paths
#****************************************************************************
INCS := -I. -I../core -I../codegen
#****************************************************************************
# Targets of the build
#****************************************************************************
OUTPUT := libmmgc.a
all: ${OUTPUT}
#****************************************************************************
# Source files
#****************************************************************************
SRCS := GCObject.cpp \
GCMemoryProfiler.cpp \
GCLargeAlloc.cpp \
GCHeapUnix.cpp \
GCHeap.cpp \
GCHashtable.cpp \
GCDebugUnix.cpp \
GCAllocObjectUnix.cpp \
GCAllocBase.cpp \
GCAlloc.cpp \
GC.cpp \
FixedMalloc.cpp \
FixedAlloc.cpp
#****************************************************************************
# Output
#****************************************************************************
OBJS := $(addsuffix .o,$(basename ${SRCS}))
${OUTPUT}: ${OBJS}
${AR} rcs $@ ${OBJS}
${RANLIB} $@
@echo "Done"
#****************************************************************************
# Dependencies
#****************************************************************************
# Create a lists of object and .d files to create -
# one for each source file in the directory
DEPS := $(addsufix .d,$(basename ${SRCS}))
# make any non-existent make files (using the g++ preprocessor)
${DEPS} : %.d : %.cpp
${CXX} ${CXXFLAGS} ${INCS} -MM $< > $@
#****************************************************************************
# Rules
#****************************************************************************
# Rules for compiling source files to object files
%.o : %.cpp
@echo "=== compiling:" $@ ${OPT}
@${CXX} -c ${OPT} ${CXXFLAGS} ${INCS} $< -o $@
clean:
-rm -f core* ${OBJS} ${OUTPUT} ${DEPS} log outputdebug.txt
ifneq (${MAKECMDGOALS},clean)
ifneq (${UNAME},Linux)
include ${DEPS} # include the generated make files, which make the object files
endif
endif

View File

@@ -1,189 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 ***** */
//
// GCWriteBarrier
//
#ifndef _WRITE_BARRIER_H_
#define _WRITE_BARRIER_H_
#ifdef WRITE_BARRIERS
// inline write barrier
#define WB(gc, container, addr, value) gc->writeBarrier(container, addr, (const void *) (value))
// fast manual RC write barrier
#define WBRC(gc, container, addr, value) gc->writeBarrierRC(container, addr, (const void *) (value))
// declare write barrier
#define DWB(type) MMgc::WriteBarrier<type>
// declare an optimized RCObject write barrier
#define DRCWB(type) MMgc::WriteBarrierRC<type>
#else
#define WB(gc, container, addr, value) *addr = value
#define WBRC(gc, container, addr, value) *addr = value
// declare write barrier
#define DWB(type) type
#define DVWB(type) type
#endif
namespace MMgc
{
/**
* WB is a smart pointer write barrier meant to be used on any field of a GC object that
* may point to another GC object. A write barrier may only be avoided if if the field is
* const and no allocations occur between the construction of the object holding the field
* and the assignment.
*/
template<class T> class WriteBarrier
{
public:
WriteBarrier() {}
WriteBarrier(T t)
{
set(t);
}
~WriteBarrier()
{
t = 0;
}
T operator=(const WriteBarrier<T>& wb)
{
return set(wb.t);
}
T operator=(T tNew)
{
return set(tNew);
}
// BEHOLD ... The weird power of C++ operator overloading
operator T() const { return t; }
#ifdef MMGC_DRC
operator ZeroPtr<T>() const { return t; }
#endif
bool operator!=(T other) const { return other != t; }
T operator->() const
{
return t;
}
private:
// private to prevent its use and someone adding it, GCC creates
// WriteBarrier's on the stack with it
WriteBarrier(const WriteBarrier<T>& toCopy) { GCAssert(false); }
T set(const T tNew)
{
if(t != tNew || tNew != 0)
GC::WriteBarrier(this, (const void*)tNew);
else
t = tNew;
return tNew;
}
T t;
};
/**
* WriteBarrierRC is a write barrier for naked (not pointer swizzled) RC objects.
* the only thing going in and out of the slot is NULL or a valid RCObject
*/
template<class T> class WriteBarrierRC
{
public:
WriteBarrierRC() {}
WriteBarrierRC(T t)
{
set(t);
}
~WriteBarrierRC()
{
if(t != 0) {
((RCObject*)t)->DecrementRef();
t=0;
}
}
T operator=(const WriteBarrierRC<T>& wb)
{
return set(wb.t);
}
T operator=(T tNew)
{
return set(tNew);
}
operator T() const { return t; }
#ifdef MMGC_DRC
operator ZeroPtr<T>() const { return t; }
#endif
bool operator!=(T other) const { return other != t; }
T operator->() const
{
return t;
}
void Clear() { t = 0; }
private:
// see note for WriteBarrier
WriteBarrierRC(const WriteBarrierRC<T>& toCopy);
T set(const T tNew)
{
GC *gc = GC::GetGC(this);
gc->writeBarrierRC(gc->FindBeginning(this), this, (const void*)tNew);
return tNew;
}
T t;
};
}
#endif // _WRITE_BARRIER_H_

View File

@@ -1,79 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 ***** */
#ifdef DEBUG
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
/**
* Critical section on GCHeap allocations.
*/
//#define GCHEAP_LOCK
/**
* Define this to get stack traces. Helps with memory leaks.
*/
#ifdef DEBUG
#define MEMORY_INFO
#endif
/**
* This turns on incremental collection as well as all of
* the write barriers.
*/
// TODO_LINUX
//#define WRITE_BARRIERS
/**
* Define this if MMgc is being integrated with avmplus.
* Activates dynamic profiling support, etc.
*/
#define MMGC_AVMPLUS
/**
*
*/
#define DECOMMIT_MEMORY
/**
* USE_MMAP not used for ARM skunkworks
*/
//#define USE_MMAP
/**
* Controls whether DRC is in use
*/
//#define MMGC_DRC

View File

@@ -1,87 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
#ifdef DEBUG
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
/**
* Critical section on GCHeap allocations.
*/
#define GCHEAP_LOCK
/**
* IA-32
*/
#define MMGC_IA32
/**
* Define this to get stack traces. Helps with memory leaks.
*/
#ifdef DEBUG
#define MEMORY_INFO
#endif
/**
* This turns on incremental collection as well as all of
* the write barriers.
*/
// TODO_LINUX
#define WRITE_BARRIERS
/**
* Define this if MMgc is being integrated with avmplus.
* Activates dynamic profiling support, etc.
*/
#define MMGC_AVMPLUS
/**
*
*/
#define DECOMMIT_MEMORY
/**
* USE_MMAP only for MACHO builds
*/
#if TARGET_RT_MAC_MACHO
#ifndef USE_MMAP
#define USE_MMAP
#endif
#endif
/**
* Controls whether DRC is in use
*/
#define MMGC_DRC

View File

@@ -1,95 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 ***** */
#ifdef DEBUG
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
/**
* Critical section on GCHeap allocations.
*/
#define GCHEAP_LOCK
/**
* PowerPC (MacOS)
*/
#ifdef __i386__
#define MMGC_IA32
#else
#define MMGC_PPC
#endif
#define MMGC_MAC
/**
* Define this to get stack traces. Helps with memory leaks.
*/
#ifdef DEBUG
#define MEMORY_INFO
#endif
/**
* This turns on incremental collection as well as all of
* the write barriers.
*/
#define WRITE_BARRIERS
/**
* Define this if MMgc is being integrated with avmplus.
* Activates dynamic profiling support, etc.
*/
#define MMGC_AVMPLUS
/**
*
*/
#define DECOMMIT_MEMORY
/**
* USE_MMAP only for MACHO builds
*/
#if TARGET_RT_MAC_MACHO
#ifndef USE_MMAP
#define USE_MMAP
#endif
#endif
#define MMGC_DRC
/**
* This makes JIT code buffers read-only to reduce the probability of
* heap overflow attacks.
*/
#define AVMPLUS_JIT_READONLY

View File

@@ -1,95 +0,0 @@
# ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
MMGC_DEBUG_CFLAGS := -g -MMD
MMGC_RELEASE_CFLAGS := -O3 -MMD
MMGC_DEBUG_CXXFLAGS := ${MMGC_DEBUG_CFLAGS} -fno-rtti -fcheck-new
MMGC_RELEASE_CXXFLAGS := ${MMGC_RELEASE_CFLAGS} -fno-rtti -fcheck-new
ifeq (YES, ${DEBUG})
MMGC_CFLAGS := ${MMGC_DEBUG_CFLAGS}
MMGC_CXXFLAGS := ${MMGC_DEBUG_CXXFLAGS}
else
MMGC_CFLAGS := ${MMGC_RELEASE_CFLAGS}
MMGC_CXXFLAGS := ${MMGC_RELEASE_CXXFLAGS}
endif
#************************************************************************
# DEFS
#************************************************************************
MMGC_DEFS := ${MMGC_DEFS} -DAVMPLUS_LINUX -DSOFT_ASSERTS -DDEBUGGER -DAVMPLUS_IA32 -DDEBUG -DCYGWIN -DUSE_MMAP -DENABLE_PROFILER -DENABLE_COMPILER
#************************************************************************
# Include Paths
#************************************************************************
MMGC_INCS := -I${MMGC_ROOT} -I${MMGC_ROOT}/../core -I${MMGC_ROOT}/../codegen
#****************************************************************************
# Preprocessor directives
#****************************************************************************
MMGC_DEFS := ${MMGC_DEFS} -DUNIX ${MMGC_PLATFORM_DEFS} -DUSE_MMAP -DENABLE_PROFILER
MMGC_CFLAGS := ${MMGC_CFLAGS} ${MMGC_DEFS}
MMGC_CXXFLAGS := ${MMGC_CXXFLAGS} ${MMGC_DEFS}
#************************************************************************
# MMgc common files
#************************************************************************
MMGC_SRCS := ${MMGC_ROOT}/GCObject.cpp \
${MMGC_ROOT}/GCMemoryProfiler.cpp \
${MMGC_ROOT}/GCLargeAlloc.cpp \
${MMGC_ROOT}/GCHeapUnix.cpp \
${MMGC_ROOT}/GCHeap.cpp \
${MMGC_ROOT}/GCHashtable.cpp \
${MMGC_ROOT}/GCDebugUnix.cpp \
${MMGC_ROOT}/GCAllocObjectUnix.cpp \
${MMGC_ROOT}/GCAllocBase.cpp \
${MMGC_ROOT}/GCAlloc.cpp \
${MMGC_ROOT}/GC.cpp \
${MMGC_ROOT}/GCTests.cpp \
${MMGC_ROOT}/FixedMalloc.cpp \
${MMGC_ROOT}/FixedAlloc.cpp
#************************************************************************
# MMgc rules
#************************************************************************
define mmgc-cmd
@echo "=== compiling MMgc: ===" $@ ${OPT}
@${CXX} -c ${OPT} ${MMGC_CXXFLAGS} ${MMGC_INCS} $< -o $@
endef
${MMGC_ROOT}/%.o : ${MMGC_ROOT}/%.cpp
$(mmgc-cmd)

View File

@@ -1,67 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 <stdio.h>
#include "MMgc.h"
using namespace MMgc;
using namespace avmplus;
int main(int argc, char*argv[])
{
GCHeap::Init();
GC *gc = new GC(GCHeap::GetGCHeap());
int buffer[1024];
List<void*> allocations(gc, 1024*16, false);
FILE *file = fopen("alloc.log", "rb");
int read = 0;
while((read = fread(buffer, 4, 1024, file)) > 0)
{
for(int i=0; i < read; i++) {
int allocSize = buffer[i];
// positive # is alloc, negative is index of alloc to free
if(allocSize > 0)
allocations.add(gc->Alloc(allocSize&~7, allocSize&6));
else {
int index = -allocSize;
void *obj = allocations[index];
allocations.set(index, 0);
//gc->Free(obj);
}
}
}
fclose(file);
}

View File

@@ -1,60 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 8.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "run_alloc", "run_alloc.vcproj", "{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}"
ProjectSection(ProjectDependencies) = postProject
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B} = {B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}
{437E43D2-ED2D-406B-88DB-B5940F838AE8} = {437E43D2-ED2D-406B-88DB-B5940F838AE8}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMgc", "..\MMgc.vcproj", "{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "avmplus", "..\..\platform\win32\avmplus.vcproj", "{437E43D2-ED2D-406B-88DB-B5940F838AE8}"
ProjectSection(ProjectDependencies) = postProject
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfiguration) = preSolution
Debug = Debug
Debug Debugger = Debug Debugger
Release = Release
Release Debugger = Release Debugger
VTune = VTune
EndGlobalSection
GlobalSection(ProjectConfiguration) = postSolution
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Debug.ActiveCfg = Debug|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Debug.Build.0 = Debug|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Debug Debugger.ActiveCfg = Debug|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Debug Debugger.Build.0 = Debug|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Release.ActiveCfg = Release|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Release.Build.0 = Release|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Release Debugger.ActiveCfg = Release|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.Release Debugger.Build.0 = Release|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.VTune.ActiveCfg = VTune|Win32
{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}.VTune.Build.0 = VTune|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug.ActiveCfg = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug.Build.0 = Debug|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug Debugger.ActiveCfg = Debug Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Debug Debugger.Build.0 = Debug Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release.ActiveCfg = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release.Build.0 = Release|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release Debugger.ActiveCfg = Release Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.Release Debugger.Build.0 = Release Debugger|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune.ActiveCfg = VTune|Win32
{B004A8CC-B3A9-4600-A1A9-EF1BBCF2434B}.VTune.Build.0 = VTune|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Debug.ActiveCfg = Debug|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Debug.Build.0 = Debug|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Debug Debugger.ActiveCfg = Debug Debugger|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Debug Debugger.Build.0 = Debug Debugger|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Release.ActiveCfg = Release|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Release.Build.0 = Release|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Release Debugger.ActiveCfg = Release Debugger|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.Release Debugger.Build.0 = Release Debugger|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.VTune.ActiveCfg = VTune|Win32
{437E43D2-ED2D-406B-88DB-B5940F838AE8}.VTune.Build.0 = VTune|Win32
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
EndGlobalSection
GlobalSection(ExtensibilityAddIns) = postSolution
EndGlobalSection
EndGlobal

View File

@@ -1,188 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="run_alloc"
ProjectGUID="{AE14C92F-2B7C-4B33-9B2C-425A4152A0A7}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..;..\..\core;..\..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;_DEBUG;_CONSOLE;AVMPLUS_IA32"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="5"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib DbgHelp.lib"
OutputFile="$(OutDir)/run_alloc.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/run_alloc.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..;..\..\core;..\..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_CONSOLE;AVMPLUS_IA32"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="0"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/run_alloc.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="VTune|Win32"
OutputDirectory="$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
FavorSizeOrSpeed="2"
AdditionalIncludeDirectories="..;..\..\core;..\..\codegen"
PreprocessorDefinitions="WIN32_LEAN_AND_MEAN;WIN32;NDEBUG;_CONSOLE;AVMPLUS_IA32"
RuntimeLibrary="4"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib"
OutputFile="$(OutDir)/run_alloc.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\run_alloc.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\vtune\run_alloc.vpj">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,113 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 ***** */
/**
* Critical section on GCHeap allocations.
*/
#define GCHEAP_LOCK
/**
* IA32 (Intel architecture)
*/
#define MMGC_IA32
/**
* Define this to get stack traces. Helps with memory leaks.
*/
#ifdef _DEBUG
#define MEMORY_INFO
#endif
/**
* This turns on incremental collection as well as all of
* the write barriers.
*/
#define WRITE_BARRIERS
/**
* Define this if MMgc is being integrated with avmplus.
* Activates dynamic profiling support, etc.
*/
#define MMGC_AVMPLUS
/**
* Use VirtualAlloc to reserve/commit memory
*/
#define USE_MMAP
/**
* Define this to track GC pause times
*/
// uncommenting requires you to link with C runtime
//#define GC_STATS
/**
* Turn this on to decommit memory
*/
#define DECOMMIT_MEMORY
/**
* Controls whether DRC is in use
*/
#define MMGC_DRC
/**
* This makes JIT code buffers read-only to reduce the probability of
* heap overflow attacks.
*/
#define AVMPLUS_JIT_READONLY
/**
* compiled with the /W4 warning level
* which is quite picky. Disable warnings we don't care about.
*/
#ifdef _MSC_VER
#pragma warning(disable:4512) //assignment operator could not be generated
#pragma warning(disable:4511) //can't generate copy ctor
#pragma warning(disable:4127) //conditional expression is constant
// enable some that are off even in /W4 mode, but are still handy
#pragma warning(error:4265) // 'class' : class has virtual functions, but destructor is not virtual
#pragma warning(error:4905) // wide string literal cast to 'LPSTR'
#pragma warning(error:4906) // string literal cast to 'LPWSTR'
// some that might be useful to turn on someday, but would require too much twiddly code tweaking right now
// #pragma warning(error:4263) // 'function' : member function does not override any base class virtual member function
// #pragma warning(error:4264) // 'virtual_function' : no override available for virtual member function from base 'class'; function is hidden
// #pragma warning(error:4266) // 'function' : no override available for virtual member function from base 'type'; function is hidden
// #pragma warning(error:4242) // 'identifier' : conversion from 'type1' to 'type2', possible loss of data
// #pragma warning(error:4263) // member function does not override any base class virtual member function
// #pragma warning(error:4296) // expression is always true (false) (Generally, an unsigned variable was used in a comparison operation with zero.)
#endif

View File

@@ -1,894 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
//hack
#include <stdio.h>
namespace avmplus
{
#ifdef AVMPLUS_ARM
#ifdef AVMPLUS_VERBOSE
const char* ArmAssembler::conditionCodes[] =
{
"eq",
"ne",
"cs",
"cc",
"mi",
"pl",
"vs",
"vc",
"hi",
"ls",
"ge",
"lt",
"gt",
"le",
"al",
"nv"
};
const char* ArmAssembler::regNames[] =
{
"r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
"r8",
"r9",
"r10",
"fp",
"ip",
"sp",
"lr",
"pc"
};
#endif /* AVMPLUS_VERBOSE */
ArmAssembler::ArmAssembler()
{
mip = 0;
mipStart = 0;
mInstructionCount = 0;
verboseFlag = false;
console = 0;
conditionCode = AL;
}
#define PRINT_LAST_INSTRUCTION()
//#define PRINT_LAST_INSTRUCTION() console->format("%A\n", mip[-1])
void ArmAssembler::MOV(Register dst, Register src)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A mov %R, %R\n", mip, dst, src);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01A00000 | (conditionCode<<28) | (dst<<12) | src;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::LSL(Register dst, Register src, Register rShift)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A lsl %R, %R, %R\n", mip, dst, src, rShift);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01A00010 | (conditionCode<<28) | (dst<<12) | src | (rShift<<7);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::LSR(Register dst, Register src, Register rShift)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A lsr %R, %R, %R\n", mip, dst, src, rShift);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01A00030 | (conditionCode<<28) | (dst<<12) | src | (rShift<<7);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::ASR(Register dst, Register src, Register rShift)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A asr %R, %R, %R\n", mip, dst, src, rShift);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01A00050 | (conditionCode<<28) | (dst<<12) | src | (rShift<<7);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::CMP(Register Rn, Register Rm)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A cmp %R, %R\n", mip, Rn, Rm);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01400000 | (conditionCode<<28) | (Rn<<16) | Rm;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::ADD(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A add %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x00800000 | (conditionCode<<28) | (dst<<12) | (src1<<16) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::AND(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A and %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x00000000 | (conditionCode<<28) | (dst<<12) | (src1<<16) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::OR(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A or %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x01800000 | (conditionCode<<28) | (dst<<12) | (src1<<16) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::XOR(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A xor %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x00200000 | (conditionCode<<28) | (dst<<12) | (src1<<16) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::MUL(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A mul %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x00000090 | (conditionCode<<28) | (dst<<16) | (src1<<8) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::SUB(Register dst, Register src1, Register src2)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A sub %R, %R, %R\n", mip, dst, src1, src2);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x00400000 | (conditionCode<<28) | (dst<<12) | (src1<<16) | src2;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::STMFD_bang(Register dst, int mask)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A stmfd %R!, %A\n", mip, dst, mask);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x09200000 | (conditionCode<<28) | (dst<<16) | mask;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::SUB_imm8(Register dst, Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A sub %R, %R, %d\n", mip, dst, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x02400000 | (conditionCode<<28) | (src<<16) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::RSB_imm8(Register dst, Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A rsb %R, %R, %d\n", mip, dst, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x02600000 | (conditionCode<<28) | (src<<16) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::BL(int offset24)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A bl %A\n", mip, offset24);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x0B000000 | (conditionCode<<28) | ((offset24-8)>>2)&0xFFFFFF;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::B(int offset24)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A b %A\n", mip, offset24);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x0A000000 | (conditionCode<<28) | ((offset24-8)>>2)&0xFFFFFF;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::LDR(Register dst, int offset, Register base)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A ldr %R, %d(%R)\n", mip, dst, offset, base);
#endif /* AVMPLUS_VERBOSE */
if (offset<0) {
*mip++ = 0x05100000 | (conditionCode<<28) | (base<<16) | (dst<<12) | (-offset&0x7FF);
} else {
*mip++ = 0x05900000 | (conditionCode<<28) | (base<<16) | (dst<<12) | (offset&0x7FF);
}
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::BIC_imm8(Register dst, Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A bic %R, %R, %d\n", mip, dst, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x03C00000 | (conditionCode<<28) | (src<<16) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::MOV_imm8(Register dst, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A mov %R, %d\n", mip, dst, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x03A00000 | (conditionCode<<28) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
// Cheesy macro for doing IMM32. Needs work.
void ArmAssembler::MOV_imm32(Register dst, int imm32)
{
// Branch to instruction after constant
B(8);
// Write the constant
*mip++ = imm32;
// Load the constant (-12 due to ARM pipeline's +8 bias)
LDR(dst, -12, PC);
}
void ArmAssembler::CMP_imm8(Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A cmp %R, %d\n", mip, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x03500000 | (conditionCode<<28) | (src<<16) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::STR(Register src, int offset, Register base)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A str %R, %d(%R)\n", mip, src, offset, base);
#endif /* AVMPLUS_VERBOSE */
if (offset<0) {
*mip++ = 0x05000000 | (conditionCode<<28) | (base<<16) | (src<<12) | (-offset&0x7FF);
} else {
*mip++ = 0x05800000 | (conditionCode<<28) | (base<<16) | (src<<12) | (offset&0x7FF);
}
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::ADD_imm8(Register dst, Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A add %R, %R, %d\n", mip, dst, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x02800000 | (conditionCode<<28) | (src<<16) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::AND_imm8(Register dst, Register src, int imm8)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A and %R, %R, %d\n", mip, dst, src, imm8);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x02000000 | (conditionCode<<28) | (src<<16) | (dst<<12) | (imm8&0xFF);
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::LDMFD(Register src, int mask)
{
incInstructionCount();
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format(" %A ldmfd %R, %A\n", mip, src, mask);
#endif /* AVMPLUS_VERBOSE */
*mip++ = 0x08900000 | (conditionCode<<28) | (src<<16) | mask;
PRINT_LAST_INSTRUCTION();
}
void ArmAssembler::SET_CONDITION_CODE(ConditionCode conditionCode)
{
this->conditionCode = conditionCode;
#ifdef AVMPLUS_VERBOSE
if (verboseFlag)
console->format("%s:", conditionCodes[conditionCode]);
#endif /* AVMPLUS_VERBOSE */
}
#ifdef AVMPLUS_MIR
bool CodegenMIR::canImmFold(OP *ins, OP *imm) const
{
bool can = false;
return can;
}
void CodegenMIR::emitNativeThunk(NativeMethod *info)
{
SET_CONDITION_CODE(AL);
// Hack to see what instructions we're generating
//verbose = true;
const Register TEMP = R7;
const Register AP = R6;
const Register ARGC = R5;
#ifdef DEBUGGER
const Register ENV = R4;
const Register SAVE0 = R5;
const Register SAVE1 = R6;
const int NonVolatileMask = R4_mask | R5_mask | R6_mask | R7_mask;
const int NonVolatileCount = 4;
#else
const int NonVolatileMask = R5_mask | R6_mask | R7_mask;
const int NonVolatileCount = 3;
#endif
if (!pool)
core->console << "no pool " << info << "\n";
code = getMDBuffer(pool);
mip = (MDInstruction*)code;
if (!code)
{
overflow = true;
return;
}
#ifdef FEATURE_BUFFER_GUARD
GrowthGuard guard(pool->codeBuffer);
#else
if (!ensureMDBufferCapacity(pool, md_native_thunk_size))
return;
#endif /* FEATURE_BUFFER_GUARD */
int in_arg_offset = 0;
const int kMaxGPRIndex = 3;
#ifdef DEBUGGER
uint32 *sendEnterAddr = mip;
*mip++ = ENVADDR(MethodEnv::sendEnter);
uint32 *sendExitAddr = mip;
*mip++ = ENVADDR(MethodEnv::sendExit);
#endif
union {
int handler_addr;
NativeMethod::Handler handler;
};
handler = info->m_handler;
uint32 *handlerAddr = mip;
*mip++ = handler_addr;
// scan for double optional arguments; these will
// be constants stored up front
uint32 *const_ip = mip;
int first_optional = 1+info->param_count-info->optional_count;
for (int i=first_optional; i <= info->param_count; i++)
{
Traits* type = info->paramTraits(i);
Atom arg = info->getDefaultValue(i-first_optional);
if (type == OBJECT_TYPE || type == VOID_TYPE)
{
*mip++ = arg;
}
else if (type == BOOLEAN_TYPE)
{
*mip++ = (arg>>3);
}
else if (type == NUMBER_TYPE)
{
double d = core->number_d(arg);
int *dp = (int*)&d;
*mip++ = dp[0];
*mip++ = dp[1];
}
else if (type == INT_TYPE)
{
Atom arg = info->getDefaultValue(i-first_optional);
int i = core->integer_i(arg);
*mip++ = i;
}
else if (type == UINT_TYPE)
{
Atom arg = info->getDefaultValue(i-first_optional);
uint32 u = core->integer_u(arg);
*mip++ = u;
}
else
{
// push pointer type
// this case includes kStringType, kObjectType, and kNamespaceType
int p = (arg&7)==kSpecialType ? 0 : arg & ~7;
*mip++ = p;
}
}
mipStart = mip;
// prologue
MOV (IP, SP);
// save callee-saved registers
STMFD_bang (SP, NonVolatileMask | FP_mask | IP_mask | LR_mask | PC_mask);
SUB_imm8 (FP, IP, 4);
// the frame size will be updated later
uint32 *patch_frame_size = mip;
SUB_imm8 (SP, SP, 0);
// set up other registers
MOV (AP, R2);
MOV (ARGC, R1);
#ifdef DEBUGGER
MOV (ENV, R0);
#endif
#ifdef DEBUGGER
//MOV (R0, ENV);
//MOV (R1, ARGC);
//MOV (R2, AP);
LDR (IP, (int)sendEnterAddr-(int)mip-8, PC);
MOV (LR, PC);
MOV (PC, IP);
//thincall(ENVADDR(MethodEnv::sendEnter));
#endif
// Push receiver object as first argument
#ifdef NATIVE_GLOBAL_FUNCTION_HACK
// hack - native toplevel functions get invoked with user defined receiver
// but are expecting the global object. this hack is totally unsound
// because it gives users the power to crash the vm. we need to either
// directly support toplevel native functions, or not use them.
LDR (R0, 0, AP); // this is ap[0]
BIC_imm (R0, R0, 7);
#else
LDR (R0, 0, AP); // this is ap[0]
#endif
in_arg_offset += 4;
int GPRIndex = 1;
bool need_rest = ((info->flags & AbstractFunction::NEED_REST) != 0);
if (info->flags & AbstractFunction::NATIVE_COOKIE)
{
MOV_imm8 (R1, info->m_cookie);
GPRIndex++;
}
// push args left to right
for (int i=1; i <= info->param_count; i++)
{
// param 0 is receiver, real params start at 1
Traits* type = info->paramTraits(i);
if (i >= first_optional) {
// emit code to check whether argument
// was specified
CMP_imm8 (ARGC, i);
SET_CONDITION_CODE(LT);
// emit code to push the default value
Atom arg = info->getDefaultValue(i-first_optional);
// the arguments have already been coerced to the right type
// by the caller. We do not do type conversions here.
if (type == NUMBER_TYPE)
{
int offset = (int)const_ip - (int)mip;
// Do first word of double
if (GPRIndex < kMaxGPRIndex) {
LDR ((Register)(R0+GPRIndex), offset, PC);
} else {
LDR (TEMP, offset, PC);
STR (TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
// Do second word of double
if ((GPRIndex+1) < kMaxGPRIndex) {
LDR ((Register)(R0+GPRIndex+1), offset, PC);
} else {
LDR (TEMP, offset+4, PC);
STR (TEMP, (GPRIndex+1-kMaxGPRIndex)*4, SP);
}
const_ip += 2;
}
else
{
int offset = (int)const_ip - (int)mip;
if (GPRIndex < kMaxGPRIndex) {
LDR ((Register)(R0+GPRIndex), offset, PC);
} else {
LDR (TEMP, offset, PC);
STR (TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
const_ip++;
}
SET_CONDITION_CODE(GE);
}
// Generate the code for the non-optional case.
// these args will already be converted to native form by the caller
if (type == NUMBER_TYPE)
{
// Copy first word of double
if (GPRIndex < kMaxGPRIndex) {
LDR((Register)(R0+GPRIndex), in_arg_offset, AP);
} else {
LDR(TEMP, in_arg_offset, AP);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
GPRIndex++;
in_arg_offset += 4;
// Copy second word of double
if (GPRIndex < kMaxGPRIndex) {
LDR((Register)(R0+GPRIndex), in_arg_offset, AP);
} else {
LDR(TEMP, in_arg_offset, AP);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
GPRIndex++;
in_arg_offset += 4;
}
else
{
// push general type
// this case includes everything except Number/double
if (GPRIndex < kMaxGPRIndex) {
LDR((Register)(R0+GPRIndex), in_arg_offset, AP);
} else {
LDR(TEMP, in_arg_offset, AP);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
in_arg_offset += 4;
GPRIndex++;
}
SET_CONDITION_CODE(AL);
}
if (need_rest) {
// If the method signature ends with "...",
// deliver any arguments after the explicitly
// specified ones as (Atom *argv, int argc)
// rest_count = argc-param_count
CMP_imm8 (ARGC, info->param_count);
SET_CONDITION_CODE (LT);
// rest_count<0, push argc=0, argv=NULL
// push argc
if (GPRIndex < kMaxGPRIndex) {
MOV_imm8((Register)(R0+GPRIndex), 0);
} else {
MOV_imm8(TEMP, 0);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
// push argv
if ((GPRIndex+1) < kMaxGPRIndex) {
MOV_imm8((Register)(R0+GPRIndex+1), 0);
} else {
MOV_imm8(TEMP, 0);
STR(TEMP, (GPRIndex+1-kMaxGPRIndex)*4, SP);
}
SET_CONDITION_CODE(GE);
// rest_count>=0
// push rest_count
// push rest_argv = argv+param_count
// push argv
if (GPRIndex < kMaxGPRIndex) {
ADD_imm8((Register)(R0+GPRIndex), AP, info->restOffset);
} else {
ADD_imm8(TEMP, AP, info->restOffset);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
GPRIndex++;
// push argc
if (GPRIndex < kMaxGPRIndex) {
SUB_imm8((Register)(R0+GPRIndex), ARGC, info->param_count);
} else {
SUB_imm8(TEMP, ARGC, info->param_count);
STR(TEMP, (GPRIndex-kMaxGPRIndex)*4, SP);
}
GPRIndex++;
SET_CONDITION_CODE(AL);
}
// all args have been pushed, now call function using thiscall calling conventions
Traits* type = info->returnTraits();
LDR (IP, (int)handlerAddr-(int)mip-8, PC);
MOV (LR, PC);
MOV (PC, IP);
//thincall(handler_addr);
#ifdef DEBUGGER
if (type == NUMBER_TYPE)
{
// result is in R0, R1. Store in nonvolatile while
// we call sendExit.
MOV (SAVE0, R0);
MOV (SAVE1, R1);
}
else
{
// result is in R0. Store in nonvolatile while we
// call sendExit.
MOV (SAVE0, R0);
}
MOV (R0, ENV);
LDR (IP, (int)sendExitAddr-(int)mip-8, PC);
MOV (LR, PC);
MOV (PC, IP);
//thincall(ENVADDR(MethodEnv::sendExit));
if (type == NUMBER_TYPE)
{
MOV (R0, SAVE0);
MOV (R1, SAVE1);
}
else
{
MOV (R0, SAVE0);
}
#endif
if (type != NUMBER_TYPE)
{
// result in R3
if (type == BOOLEAN_TYPE)
{
// return value already in R3
// bool is just a byte, so mask it off
AND_imm8 (R0, R0, 255);
}
else if (type == VOID_TYPE)
{
MOV_imm8 (R0, undefinedAtom);
}
}
// else, result in FPU register F1
// epilogue
SUB_imm8 (SP, FP, 12 + NonVolatileCount * 4);
LDMFD (SP, NonVolatileMask | FP_mask | SP_mask | PC_mask);
// Patch up the frame size.
// For each arg, we need 4 bytes in the called parameter
// area. We also leave a little cushion in the called
// parameter area, since there are a few other function
// calls the thunk makes (intToAtom, doubleToAtom)
if (GPRIndex > kMaxGPRIndex)
{
int frameSize = (GPRIndex-kMaxGPRIndex)*4;
*patch_frame_size |= (frameSize & 0xFF);
}
bindMethod(info);
}
void* CodegenMIR::emitImtThunk(ImtBuilder::ImtEntry *e)
{
SET_CONDITION_CODE(AL);
mip = mipStart = (MDInstruction*)getMDBuffer(pool);
#ifdef FEATURE_BUFFER_GUARD
GrowthGuard guard(pool->codeBuffer);
#else
if (!ensureMDBufferCapacity(pool, md_native_thunk_size))
return NULL;
#endif /* FEATURE_BUFFER_GUARD */
// the generated thunk does not call any helper methods, so we are
// free to use eax, ecx, edx as scratch regs without touchning the
// stack.
// in: R3 = iid
// R0 = MethodEnv
// R1 = argc
// R2 = ap
// 0(ap) = ScriptObject (concrete instance of class)
// local register allocation:
// R4 = iid parameter
// R5 = vtable of receiver obj
// R6 = temp
#ifdef AVMPLUS_VERBOSE
if (pool->verbose)
{
core->console << "imt thunk\n";
}
#endif
LDR (IP, 0, R2); // obj
LDR (IP, offsetof(ScriptObject, vtable), IP); // vtable
AvmAssert(e->next != NULL); // must have 2 or more entries
while (e->next)
{
ImtBuilder::ImtEntry *next = e->next;
#ifdef AVMPLUS_VERBOSE
if (pool->verbose)
{
core->console << " disp_id="<< e->disp_id << " " << e->virt << "\n";
}
#endif
int iid = e->virt->iid();
CMP_imm8 (R3, iid);
#if 0
// todo
if (isUIMM(iid))
{
CMP (R3, iid);
}
else
{
//LI32(R0, iid);
//CMP (R3, R0);
}
#endif
SET_CONDITION_CODE(EQ);
LDR (IP, offsetof(VTable,methods)+4*e->disp_id, IP); // load concrete env
LDR (IP, offsetof(MethodEnv, impl32), IP); // invoke real method indirectly
MOV (PC, IP);
SET_CONDITION_CODE(AL);
pool->core->gc->Free(e);
e = next;
}
// last one is unconditional
#ifdef AVMPLUS_VERBOSE
if (pool->verbose)
{
core->console << " disp_id="<< e->disp_id << " " << e->virt << "\n";
}
#endif
LDR (IP, offsetof(VTable,methods)+4*e->disp_id, IP); // load concrete env
LDR (IP, offsetof(MethodEnv, impl32), IP); // invoke real method indirectly
MOV (PC, IP);
MDInstruction *retval;
retval = mipStart;
// lock in the next available location in the buffer (16B aligned)
pool->codeBuffer->setPos((byte*) ( (size_t)mip+15 & ~15 ));
return retval;
}
#endif /* AVMPLUS_MIR */
#endif /* AVMPLUS_ARM */
}

View File

@@ -1,207 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_ArmAssembler__
#define __avmplus_ArmAssembler__
namespace avmplus
{
class ArmAssembler
{
public:
/* ARM registers */
typedef enum
{
R0 = 0,
R1 = 1,
R2 = 2,
R3 = 3,
R4 = 4,
R5 = 5,
R6 = 6,
R7 = 7,
R8 = 8,
R9 = 9,
R10 = 10,
FP = 11,
IP = 12,
SP = 13,
LR = 14,
PC = 15,
// Pseudo-register for floating point
F0 = 0,
Unknown = -1
}
Register;
/* ARM registers */
typedef enum
{
R0_mask = (1<<0),
R1_mask = (1<<1),
R2_mask = (1<<2),
R3_mask = (1<<3),
R4_mask = (1<<4),
R5_mask = (1<<5),
R6_mask = (1<<6),
R7_mask = (1<<7),
R8_mask = (1<<8),
R9_mask = (1<<9),
R10_mask = (1<<10),
FP_mask = (1<<11),
IP_mask = (1<<12),
SP_mask = (1<<13),
LR_mask = (1<<14),
PC_mask = (1<<15)
}
RegisterMask;
/* ARM condition codes */
typedef enum
{
EQ = 0x0, // Equal
NE = 0x1, // Not Equal
CS = 0x2, // Carry Set (or HS)
CC = 0x3, // Carry Clear (or LO)
MI = 0x4, // MInus
PL = 0x5, // PLus
VS = 0x6, // oVerflow Set
VC = 0x7, // oVerflow Clear
HI = 0x8, // HIgher
LS = 0x9, // Lower or Same
GE = 0xA, // Greater or Equal
LT = 0xB, // Less Than
GT = 0xC, // Greater Than
LE = 0xD, // Less or Equal
AL = 0xE, // ALways
NV = 0xF // NeVer
}
ConditionCode;
/* --- Data Processing Instructions --- */
/* Values for operator "a" */
typedef enum
{
AND_op = 0x0, // Boolean And Rd = Rn AND Op2
EOR_op = 0x1, // Boolean Eor Rd = Rn EOR Op2
SUB_op = 0x2, // Subtract Rd = Rn - Op2
RSB_op = 0x3, // Reverse Subtract Rd = Op2 - Rn
ADD_op = 0x4, // Addition Rd = Rn + Op2
ADC_op = 0x5, // Add with Carry Rd = Rn + Op2 + C
SBC_op = 0x6, // Subtract with Carry Rd = Rn - Op2 - (1-C)
RSC_op = 0x7, // Reverse Subtract with Carry Rd - Op2 - Rn - (1-C)
TST_op = 0x8, // Test bit Rn AND Op2
TEQ_op = 0x9, // Test equality Rn EOR Op2
CMP_op = 0xA, // Compare Rn - Op2
CMN_op = 0xB, // Compare Negative Rn + Op2
ORR_op = 0xC, // Boolean Or Rd = Rn OR Op2
MOV_op = 0xD, // Move value Rd = Op2
BIC_op = 0xE, // Bit Clear Rd = Rn AND NOT Op2
MVN_op = 0xF // Move Not Rd = NOT Op2
}
Operator;
/* Values for operand "t" */
typedef enum
{
LSL_imm = 0, // LSL #c - Logical Shift Left
LSL_reg = 1, // LSL Rc - Logical Shift Left
LSR_imm = 2, // LSR #c - Logical Shift Right
LSR_reg = 3, // LSR Rc - Logical Shift Right
ASR_imm = 4, // ASR #c - Arithmetic Shift Right
ASR_reg = 5, // ASR Rc - Arithmetic Shift Right
ROR_imm = 6, // Rotate Right (c != 0)
RRX = 6, // Rotate Right one bit with extend (c == 0)
ROR_reg = 7 // Rotate Right
}
ShiftOperator;
typedef uint32 MDInstruction;
/* Instruction pointer */
MDInstruction *mip;
MDInstruction *mipStart;
int mInstructionCount; // number of machine instructions
#define incInstructionCount() mInstructionCount++
/* Current condition code */
ConditionCode conditionCode;
ArmAssembler();
void SET_CONDITION_CODE(ConditionCode conditionCode);
void MOV(Register dst, Register src);
void STMFD_bang(Register dst, int mask);
void SUB_imm8(Register dst, Register src, int imm8);
void RSB_imm8(Register dst, Register src, int imm8);
void B(int offset24);
void BL(int offset24);
void LDR(Register dst, int offset, Register base);
void BIC_imm8(Register dst, Register src, int imm8);
void MOV_imm8(Register dst, int imm8);
void CMP_imm8(Register src, int imm8);
void ADD(Register dst, Register src1, Register src2);
void SUB(Register dst, Register src1, Register src2);
void AND(Register dst, Register src1, Register src2);
void OR(Register dst, Register src1, Register src2);
void XOR(Register dst, Register src1, Register src2);
void MUL(Register dst, Register src1, Register src2);
void CMP(Register Rn, Register Rm);
void LSL(Register dst, Register src, Register rShift);
void LSR(Register dst, Register src, Register rShift);
void ASR(Register dst, Register src, Register rShift);
void STR(Register src, int offset, Register base);
void ADD_imm8(Register dst, Register src, int imm8);
void AND_imm8(Register dst, Register src, int imm8);
void LDMFD(Register src, int mask);
// Cheeseball way of doing imm32.
void MOV_imm32(Register dst, int imm32);
// Set if verbose output desired
#ifdef AVMPLUS_VERBOSE
bool verboseFlag;
#endif
PrintWriter *console;
static const char* regNames[];
#define gpregNames regNames
static const char* conditionCodes[];
};
}
#endif /* __avmplus_ArmAssembler__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
namespace NativeID {
#include "builtin.cpp"
}
}

View File

@@ -1,58 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
ScriptEnv* AbcEnv::getScriptEnv(Stringp name, Namespacep ns)
{
if(ns->isPrivate())
{
return (ScriptEnv*)privateScriptEnvs.get(name, ns);
}
else
{
return (ScriptEnv*)domainEnv->getScriptInit(ns, name);
}
}
ScriptEnv* AbcEnv::getScriptEnv(Multiname *multiname)
{
ScriptEnv *se = (ScriptEnv*)domainEnv->getScriptInit(multiname);
if(!se)
{
// check privates
se = (ScriptEnv*)privateScriptEnvs.getMulti(multiname);
}
return se;
}
}

View File

@@ -1,78 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AbcEnv__
#define __avmplus_AbcEnv__
namespace avmplus
{
// runtime info associated with a pool
class AbcEnv : public MMgc::GCObject
{
public:
PoolObject* const pool;
DomainEnv* const domainEnv;
CodeContext* const codeContext;
MultinameHashtable privateScriptEnvs;
MethodEnv* methods[1]; // actual size will hold pool->methodCount methods
AbcEnv(PoolObject* pool,
DomainEnv* domainEnv,
CodeContext *codeContext)
: pool(pool),
domainEnv(domainEnv),
codeContext(codeContext)
{
}
void setMethod(int i, MethodEnv* env)
{
WB(pool->core->gc, this, &methods[i], env);
}
static size_t calcExtra(PoolObject* pool)
{
if (pool->methodCount <= 1)
return 0;
else
return sizeof(MethodEnv*)*(pool->methodCount-1);
}
ScriptEnv* getScriptEnv(Stringp name, Namespacep ns);
ScriptEnv* getScriptEnv(Multiname *m);
};
}
#endif // __avmplus_AbcEnv__

View File

@@ -1,84 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
void AbcGen::writeInt(unsigned int v)
{
if( v < 128 )
{
bytes.add((byte)v);
}
else if ( v < 16384 )
{
byte first = (byte)((v & 0x7F) | 0x80);
byte second = (byte)(v>>7);
bytes.add(first);
bytes.add(second);
}
else if ( v < 2097152 )
{
byte first = (byte)((v & 0x7F) | 0x80);
byte second = (byte)(v>>7 | 0x80);
byte third = (byte)(v>>14);
bytes.add(first);
bytes.add(second);
bytes.add(third);
}
else if ( v < 268435456 )
{
byte first = (byte)((v & 0x7F) | 0x80);
byte second = (byte)(v>>7 | 0x80);
byte third = (byte)(v>>14 | 0x80);
byte fourth = (byte) ( v >>21 );
bytes.add(first);
bytes.add(second);
bytes.add(third);
bytes.add(fourth);
}
else
{
byte first = (byte)((v & 0x7F) | 0x80);
byte second = (byte)(v>>7 | 0x80);
byte third = (byte)(v>>14 | 0x80);
byte fourth = (byte) (v >>21 | 0x80);
byte fifth = (byte) (v >> 28);
bytes.add(first);
bytes.add(second);
bytes.add(third);
bytes.add(fourth);
bytes.add(fifth);
}
}
}

View File

@@ -1,74 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AbcGen__
#define __avmplus_AbcGen__
namespace avmplus
{
class AbcGen
{
public:
/**
* construct an abc code gen buffer with the given initial capacity
*/
AbcGen(MMgc::GC *gc, int initCapacity=128) : bytes(gc, initCapacity) {}
List<byte,LIST_NonGCObjects>& getBytes() { return bytes; }
void construct_super() { bytes.add(OP_constructsuper); }
void pushnan() { bytes.add(OP_pushnan); }
void pushundefined() { bytes.add(OP_pushundefined); }
void pushnull() { bytes.add(OP_pushnull); }
void pushtrue() { bytes.add(OP_pushtrue); }
void pushconstant(CPoolKind kind, int index)
{
// AbcParser should already ensure kind is legal value.
AvmAssert(kind >=0 && kind <= CONSTANT_StaticProtectedNs && kindToPushOp[kind] != 0);
int op = kindToPushOp[kind];
bytes.add((byte)op);
if(opOperandCount[op] > 0)
writeInt(index);
}
void getlocalN(int N) { bytes.add((byte)(OP_getlocal0+N)); }
void setslot(int slot) { bytes.add(OP_setslot); writeInt(slot+1); }
void abs_jump(const byte *pc, int code_length) { bytes.add(OP_abs_jump); writeInt((unsigned int)pc); writeInt(code_length); }
void returnvoid() { bytes.add(OP_returnvoid); }
void writeBytes(List<byte,LIST_NonGCObjects>& b) { bytes.add(b); }
void writeInt(unsigned int n);
size_t size() { return bytes.size(); }
private:
List<byte, LIST_NonGCObjects> bytes;
};
}
#endif // __avmplus_MethodEnv__

File diff suppressed because it is too large Load Diff

View File

@@ -1,219 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AbcParser__
#define __avmplus_AbcParser__
namespace avmplus
{
/**
* Parser for reading .abc (Actionscript Byte Code) files.
*/
class AbcParser
{
public:
AbcParser(AvmCore* core, ScriptBuffer code,
Toplevel* toplevel,
Domain* domain,
AbstractFunction *nativeMethods[],
NativeClassInfo *nativeClasses[],
NativeScriptInfo *nativeScripts[]);
~AbcParser();
/**
* parse an .abc file
* @param code
* @return
*/
static PoolObject* decodeAbc(AvmCore* core, ScriptBuffer code,
Toplevel* toplevel,
Domain* domain,
AbstractFunction *nativeMethods[],
NativeClassInfo *nativeClasses[],
NativeScriptInfo *nativeScripts[]);
protected:
PoolObject* parse();
AbstractFunction* resolveMethodInfo(uint32 index) const;
#ifdef AVMPLUS_VERBOSE
void parseTypeName(const byte* &p, Multiname& m) const;
#endif
Namespace* parseNsRef(const byte* &pc) const;
Stringp resolveUtf8(uint32 index) const;
Stringp parseName(const byte* &pc) const;
Atom resolveQName(const byte* &pc, Multiname &m) const;
int computeInstanceSize(int class_id, Traits* base) const;
void parseMethodInfos();
void parseMetadataInfos();
bool parseInstanceInfos();
void parseClassInfos();
bool parseScriptInfos();
void parseMethodBodies();
void parseCpool();
Traits* parseTraits(Traits* base, Namespace* ns, Stringp name, AbstractFunction* script, int interfaceDelta, Namespace* protectedNamespace = NULL);
/**
* add script to VM-wide table
*/
void addNamedScript(Namespace* ns, Stringp name, AbstractFunction* script);
/**
* Adds traits to the VM-wide traits table, for types
* that can be accessed from multiple abc's.
* @param name The name of the class
* @param ns The namespace of the class
* @param itraits The instance traits of the class
*/
void addNamedTraits(Namespace* ns, Stringp name, Traits* itraits);
sint64 readS64(const byte* &p) const
{
#ifdef SAFE_PARSE
// check to see if we are trying to read past the file end.
if (p < abcStart || p+7 >= abcEnd )
toplevel->verifyErrorClass()->throwError(kCorruptABCError);
#endif //SAFE_PARSE
unsigned first = p[0] | p[1]<<8 | p[2]<<16 | p[3]<<24;
unsigned second = p[4] | p[5]<<8 | p[6]<<16 | p[7]<<24;
p += 8;
return first | ((sint64)second)<<32;
}
/**
* Reads in 2 bytes and turns them into a 16 bit number. Always reads in 2 bytes. Currently
* only used for version number of the ABC file and for version 11 support.
*/
int readU16(const byte* p) const
{
#ifdef SAFE_PARSE
if (p < abcStart || p+1 >= abcEnd)
toplevel->verifyErrorClass()->throwError(kCorruptABCError);
#endif //SAFE_PARSE
return p[0] | p[1]<<8;
}
/**
* Read in a 32 bit number that is encoded with a variable number of bytes. The value can
* take up 1-5 bytes depending on its value. 0-127 takes 1 byte, 128-16383 takes 2 bytes, etc.
* The scheme is that if the current byte has the high bit set, then the following byte is also
* part of the value.
*
* Returns the value, and the 2nd argument is set to the number of bytes that were read to get that
* value.
*/
int readS32(const byte *&p) const
{
#ifdef SAFE_PARSE
// We have added kBufferPadding bytes to the end of the main swf buffer.
// Why? Here we can read from 1 to 5 bytes. If we were to
// put the required safety checks at each byte read, we would slow
// parsing of the file down. With this buffer, only one check at the
// top of this function is necessary. (we will read on into our own memory)
if ( p < abcStart || p >= abcEnd )
toplevel->verifyErrorClass()->throwError(kCorruptABCError);
#endif //SAFE_PARSE
int result = p[0];
if (!(result & 0x00000080))
{
p++;
return result;
}
result = (result & 0x0000007f) | p[1]<<7;
if (!(result & 0x00004000))
{
p += 2;
return result;
}
result = (result & 0x00003fff) | p[2]<<14;
if (!(result & 0x00200000))
{
p += 3;
return result;
}
result = (result & 0x001fffff) | p[3]<<21;
if (!(result & 0x10000000))
{
p += 4;
return result;
}
result = (result & 0x0fffffff) | p[4]<<28;
p += 5;
return result;
}
unsigned int readU30(const byte *&p) const
{
#ifdef SAFE_PARSE
// We have added kBufferPadding bytes to the end of the main swf buffer.
// Why? Here we can read from 1 to 5 bytes. If we were to
// put the required safety checks at each byte read, we would slow
// parsing of the file down. With this buffer, only one check at the
// top of this function is necessary. (we will read on into our own memory)
if ( p < abcStart || p >= abcEnd )
toplevel->verifyErrorClass()->throwError(kCorruptABCError);
#endif //SAFE_PARSE
return toplevel->readU30(p);
}
private:
Toplevel* const toplevel;
Domain* const domain;
AvmCore* core;
ScriptBuffer code;
int version;
PoolObject* pool;
const byte* pos;
AbstractFunction **nativeMethods;
NativeClassInfo **nativeClasses;
NativeScriptInfo **nativeScripts;
int classCount;
List<Traits*, LIST_GCObjects> instances;
byte* abcStart;
byte* abcEnd; // one past the end, actually
Stringp* metaNames;
Stringp kNeedsDxns;
#ifdef AVMPLUS_VERBOSE
Stringp kVerboseVerify;
#endif
#ifdef FEATURE_BUFFER_GUARD // no Carbon
BufferGuard *guard;
#endif
};
}
#endif // __avmplus_AbcParser__

View File

@@ -1,433 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
using namespace MMgc;
AbstractFunction::AbstractFunction()
{
this->flags = 0;
this->method_id = -1;
}
void AbstractFunction::initParamTypes(int count)
{
MMGC_MEM_TYPE(this);
m_types = (Traits**)core()->gc->Calloc(count, sizeof(Traits*), GC::kContainsPointers|GC::kZero);
}
void AbstractFunction::initDefaultValues(int count)
{
MMGC_MEM_TYPE(this);
m_values = (Atom*)core()->gc->Calloc(count, sizeof(Atom), GC::kContainsPointers|GC::kZero);
}
void AbstractFunction::setParamType(int index, Traits* t)
{
AvmAssert(index >= 0 && index <= param_count);
WB(core()->gc, m_types, &m_types[index], t);
}
void AbstractFunction::setDefaultValue(int index, Atom value)
{
AvmAssert(index > (param_count-optional_count) && index <= param_count);
int i = index-(param_count-optional_count)-1;
AvmAssert(i >= 0 && i < optional_count);
WBATOM(core()->gc, m_values, &m_values[i], value);
}
#ifdef AVMPLUS_VERBOSE
Stringp AbstractFunction::format(AvmCore* core) const
{
return core->concatStrings(name ? (Stringp)name : core->newString("?"),
core->newString("()"));
}
#endif //AVMPLUS_VERBOSE
bool AbstractFunction::makeMethodOf(Traits* traits)
{
if (!m_types[0])
{
declaringTraits = traits;
setParamType(0, traits);
flags |= NEED_CLOSURE;
if (traits->final)
{
// all methods of a final class are final
flags |= FINAL;
}
return true;
}
else
{
#ifdef AVMPLUS_VERBOSE
if (pool->verbose)
core()->console << "WARNING: method " << this << " was already bound to " << declaringTraits << "\n";
#endif
return false;
}
}
void AbstractFunction::makeIntoPrototypeFunction(const Toplevel* toplevel)
{
if (declaringTraits == NULL)
{
// make sure param & return types are fully resolved.
// this does not set the verified flag, so real verification will
// still happen before the function runs the first time.
resolveSignature(toplevel);
// ftraits = new traits, extends function
// this->declaringTraits = ftraits
// ftraits->call = this
// ftraits->construct = create object, call this(), return obj or result
AvmCore* core = this->core();
int functionSlotCount = core->traits.function_itraits->slotCount;
int functionMethodCount = core->traits.function_itraits->methodCount;
// type of F is synthetic subclass of Function, with a unique
// [[call]] property and a unique scope
Traits* ftraits = core->newTraits(core->traits.function_itraits, 1, 1,
sizeof(ClassClosure));
ftraits->slotCount = functionSlotCount;
ftraits->methodCount = functionMethodCount;
ftraits->pool = pool;
ftraits->final = true;
ftraits->needsHashtable = true;
ftraits->itraits = core->traits.object_itraits;
this->declaringTraits = ftraits;
ftraits->ns = core->publicNamespace;
#ifdef AVMPLUS_VERBOSE
ftraits->name = core->internString(
core->concatStrings(core->newString("Function-"), core->intToString(method_id))
);
#endif
ftraits->hashTableOffset = ftraits->sizeofInstance;
ftraits->setTotalSize(ftraits->hashTableOffset + sizeof(Hashtable));
ftraits->initTables();
AvmAssert(core->traits.function_itraits->linked);
ftraits->linked = true;
#ifdef AVMPLUS_UNCHECKED_HACK
// HACK - compiler should do this, and only to toplevel functions
// that meet the E4 criteria for being an "unchecked function"
// the tests below are too loose
// if all params and return types are Object then make all params optional=undefined
if (param_count == 0)
flags |= IGNORE_REST;
if (!(flags & HAS_OPTIONAL) && param_count > 0)
{
if (m_returnType == NULL)
{
for (int i=1; i <= param_count; i++)
{
if (m_types[i] != NULL)
return;
}
// make this an unchecked function
flags |= HAS_OPTIONAL | IGNORE_REST;
optional_count = param_count;
initDefaultValues(optional_count);
for (int i=1; i <= optional_count; i++)
{
// since the type is object the default value is undefined.
setDefaultValue(i, undefinedAtom);
}
}
}
#endif
}
}
/**
* convert native args to atoms. argc is the number of
* args, not counting the instance which is arg[0]. the
* layout is [instance][arg1..argN]
*/
void AbstractFunction::boxArgs(int argc, va_list ap, Atom* out)
{
// box the typed args, up to param_count
AvmCore* core = this->core();
for (int i=0; i <= argc; i++)
{
if (i <= param_count)
{
Traits* t = paramTraits(i);
AvmAssert(t != VOID_TYPE);
if (t == NUMBER_TYPE)
{
out[i] = core->doubleToAtom(va_arg(ap, double));
}
else if (t == INT_TYPE)
{
out[i] = core->intToAtom(va_arg(ap, int));
}
else if (t == UINT_TYPE)
{
out[i] = core->uintToAtom(va_arg(ap, uint32));
}
else if (t == BOOLEAN_TYPE)
{
out[i] = va_arg(ap, int) ? trueAtom : falseAtom;
}
else if (!t || t == OBJECT_TYPE)
{
out[i] = va_arg(ap, Atom);
}
else
{
// it's a pointer type, possibly null
void* p = va_arg(ap, void*); // unknown pointer
if (t == STRING_TYPE)
{
out[i] = ((Stringp)p)->atom();
}
else if (t == NAMESPACE_TYPE)
{
out[i] = ((Namespace*)p)->atom();
}
else
{
out[i] = ((ScriptObject*)p)->atom();
}
}
}
else
{
out[i] = va_arg(ap, Atom);
}
}
}
void AbstractFunction::resolveSignature(const Toplevel* toplevel)
{
if (!(flags & LINKED))
{
AvmCore* core = this->core();
AvmAssert(info_pos != NULL);
const byte* pos = info_pos;
Traits* t = pool->resolveTypeName(pos, toplevel, /*allowVoid=*/true);
m_returnType = t;
// use va_arg macro to compute the size of the typed argument list.
// va_arg adds padding according to platform calling conventions.
va_list apstart = 0;
va_list ap = apstart;
// param 0 is contextual
t = m_types[0];
if (!t)
{
setParamType(0, OBJECT_TYPE);
va_arg(ap, Atom);
}
else
{
if (t == NUMBER_TYPE)
va_arg(ap, double);
else
va_arg(ap, int);
if (t->isInterface)
flags |= ABSTRACT_METHOD;
}
// param types 1..N come from abc stream
for (int i=1, n=param_count; i <= n; i++)
{
t = pool->resolveTypeName(pos, toplevel);
setParamType(i, t);
if (t == NUMBER_TYPE)
va_arg(ap, double);
else
va_arg(ap, int);
}
restOffset = ((int)ap)-((int)apstart);
AvmCore::readU30(pos); // name_index;
pos++; // skip flags
if (flags & HAS_OPTIONAL)
{
AvmCore::readU30(pos); // optional_count
initDefaultValues(optional_count);
for (int j=0,n=optional_count; j < n; j++)
{
int param = param_count-optional_count+1+j;
int index = AvmCore::readU30(pos);
CPoolKind kind = (CPoolKind)*(pos++);
// check that the default value is legal for the param type
Traits* t = this->paramTraits(param);
AvmAssert(t != VOID_TYPE);
Atom value;
if (t == NULL)
{
value = !index ? undefinedAtom : pool->getDefaultValue(toplevel, index, kind, t);
}
else if (t == OBJECT_TYPE)
{
value = !index ? nullObjectAtom : pool->getDefaultValue(toplevel, index, kind, t);
if (value == undefinedAtom)
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == NUMBER_TYPE)
{
value = !index ? core->kNaN : pool->getDefaultValue(toplevel, index, kind, t);
if (!(AvmCore::isInteger(value)||AvmCore::isDouble(value)))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == BOOLEAN_TYPE)
{
value = !index ? falseAtom : pool->getDefaultValue(toplevel, index, kind, t);
if (!AvmCore::isBoolean(value))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == UINT_TYPE)
{
value = !index ? 0|kIntegerType : pool->getDefaultValue(toplevel, index, kind, t);
if (!AvmCore::isInteger(value) && !AvmCore::isDouble(value))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
double d = AvmCore::number_d(value);
if (d != (uint32)d)
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == INT_TYPE)
{
value = !index ? 0|kIntegerType : pool->getDefaultValue(toplevel, index, kind, t);
if (!AvmCore::isInteger(value) && !AvmCore::isDouble(value))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
double d = AvmCore::number_d(value);
if (d != (int)d)
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == STRING_TYPE)
{
value = !index ? nullStringAtom : pool->getDefaultValue(toplevel, index, kind, t);
if (!(AvmCore::isNull(value) || AvmCore::isString(value)))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else if (t == NAMESPACE_TYPE)
{
value = !index ? nullNsAtom : pool->getDefaultValue(toplevel, index, kind, t);
if (!(AvmCore::isNull(value) || AvmCore::isNamespace(value)))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
else
{
// any other type: only allow null default value
value = !index ? nullObjectAtom : pool->getDefaultValue(toplevel, index, kind, t);
if (!AvmCore::isNull(value))
{
Multiname qname(t->ns, t->name);
toplevel->verifyErrorClass()->throwError(kIllegalDefaultValue, core->toErrorString(&qname));
}
}
setDefaultValue(param, value);
}
}
/*
// Don't need this for anything yet, so no point in wasting time parsing it. Here just so we don't
// forget about it if we add any sections after this one, and need to skip past it.
if( flags & AbstractFunction::HAS_PARAM_NAMES)
{
// AVMPlus doesn't care about the param names, just skip past them
for( int j = 0; j < param_count; ++j )
{
readU30(pos);
}
}
*/
flags |= LINKED;
}
}
#ifdef DEBUGGER
uint32 AbstractFunction::size() const
{
uint32 size = sizeof(AbstractFunction);
size += param_count * 2 * sizeof(Atom);
return size;
}
#endif
}

View File

@@ -1,297 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AbstractFunction__
#define __avmplus_AbstractFunction__
#ifdef verify
#undef verify
#endif
namespace avmplus
{
/**
* AbstractFunction is the base class for all functions that
* can be executed by the VM: Actionscript functions,
* native functions, etc.
*/
class AbstractFunction : public MMgc::GCObject
{
public:
/** @name flags from .abc - limited to a BYTE */
/*@{*/
/** need arguments[0..argc] */
static const int NEED_ARGUMENTS = 0x00000001;
/** need activation object */
static const int NEED_ACTIVATION = 0x00000002;
/** need arguments[param_count+1..argc] */
static const int NEED_REST = 0x00000004;
/** has optional parameters */
static const int HAS_OPTIONAL = 0x00000008;
/** allow extra args, but dont capture them */
static const int IGNORE_REST = 0x00000010;
/** method is native */
static const int NATIVE = 0x00000020;
/** method sets default namespace */
static const int SETS_DXNS = 0x00000040;
/** method has table for parameter names */
static const int HAS_PARAM_NAMES = 0x00000080;
/*@}*/
/** @name internal flags - upper 3 BYTES available */
/*@{*/
static const int OVERRIDE = 0x00010000;
static const int NON_INTERRUPTABLE = 0x00020000;
static const int UNBOX_THIS = 0x00040000;
static const int NEEDS_CODECONTEXT = 0x00080000;
static const int HAS_EXCEPTIONS = 0x00100000;
#ifdef AVMPLUS_VERBOSE
static const int VERBOSE_VERIFY = 0x00200000;
#endif
static const int NEEDS_DXNS = 0x00400000;
static const int VERIFIED = 0x00800000;
#ifdef AVMPLUS_VERIFYALL
static const int VERIFY_PENDING = 0x01000000;
#endif
/** indicates method is final, no overrides allowed */
static const int FINAL = 0x02000000;
/** indicates the function is a method, that pushes the
receiver object onto the scope chain at method entry */
static const int NEED_CLOSURE = 0x04000000;
/** set to indicate that a function has no bytecode body. */
static const int ABSTRACT_METHOD = 0x08000000;
#ifdef AVMPLUS_INTERP
/**
* set to indicate that a function has been compiled
* to native code. In release mode we always compile
* so we don't need the flag.
*/
static const int TURBO = 0x80000000;
/**
* set to indictate that a function has been
* recommended to be interpreted.
*/
static const int SUGGEST_INTERP = 0x40000000;
#endif /* AVMPLUS_INTERP */
/**
* set once the signature types have been resolved and
* override signatures have been checked.
*/
static const int LINKED = 0x20000000;
/*@}*/
/**
* @name NativeMethod flags
* These are used in the NativeMethod subclass
*/
/*@{*/
/** cookie int passed into C++ code */
static const int NATIVE_COOKIE = 0x10000000;
/*@}*/
DWB(Traits*) declaringTraits;
DWB(Traits*) activationTraits;
DWB(PoolObject*) pool;
AvmCore* core() const
{
return pool->core;
}
int iid() const
{
return ((unsigned)this)>>3;
}
bool usesCallerContext() const
{
return pool->isBuiltin && (!(flags & NATIVE) || (flags & NEEDS_CODECONTEXT));
}
// Builtin + non-native functions always need the dxns code emitted
// Builtin + native functions have flags to specify if they need the dxns code
bool usesDefaultXmlNamespace() const
{
return pool->isBuiltin && (!(flags & NATIVE) || (flags & NEEDS_DXNS));
}
/** number of declared parameters including optionals */
int param_count;
/** last optional_count params are optional */
int optional_count;
// offset to first rest arg in native va_list,
// including the instance parameter.
// this is sum(sizeof(paramType(0..N)))
int restOffset;
/** see bitmask defs above */
int flags;
int method_id;
/** pointer to abc MethodInfo record */
const byte* info_pos;
void initParamTypes(int count);
void initDefaultValues(int count);
void resolveSignature(const Toplevel* toplevel);
bool argcOk(int argc)
{
return argc >= param_count-optional_count &&
(argc <= param_count || allowExtraArgs());
}
/**
* invoke this method. args are already coerced. argc
* is the number of arguments AFTER the instance, which
* is arg 0. ap will always have at least the instance.
*/
union {
int (*impl32)(MethodEnv*, int, va_list);
double (*implN)(MethodEnv*, int, va_list);
};
protected:
AbstractFunction();
public:
void setParamType(int index, Traits* t);
void setDefaultValue(int index, Atom defaultValue);
void makeIntoPrototypeFunction(const Toplevel* toplevel);
Traits* paramTraits(int index) const {
AvmAssert(index >= 0 && index <= param_count);
return m_types[index];
}
const Atom* getDefaultValues() const {
return m_values;
}
Atom getDefaultValue(int i) const {
return m_values[i];
}
void setReturnType(Traits* t) {
m_returnType = t;
}
Traits* returnTraits() const {
return m_returnType;
}
int requiredParamCount() const {
return param_count-optional_count;
}
int allowExtraArgs() const {
return isFlagSet(NEED_REST|NEED_ARGUMENTS|IGNORE_REST);
}
int hasMethodBody() const {
return !isFlagSet(ABSTRACT_METHOD);
}
int isFlagSet(int f) const {
return (flags & f);
}
int hasExceptions() const {
return flags & HAS_EXCEPTIONS;
}
int setsDxns() const {
return flags & SETS_DXNS;
}
bool makeMethodOf(Traits* type);
#ifdef AVMPLUS_VERIFYALL
int isVerified() const {
return flags & VERIFIED;
}
virtual void verify(Toplevel* toplevel) = 0;
#endif
void boxArgs(int argc, va_list ap, Atom* out);
protected:
DWB(Traits*) m_returnType;
DWB(Traits**) m_types; // actual length will be 1+param_count
DWB(Atom*) m_values; // default values for any optional params. size = optional_count
#ifdef AVMPLUS_VERBOSE
/** Dummy destructor to avoid warnings */
virtual ~AbstractFunction() {}
public:
virtual Stringp format(AvmCore* core) const;
#endif
#if defined(AVMPLUS_VERBOSE) || defined(DEBUGGER)
public:
DRCWB(Stringp) name;
#endif
#ifdef DEBUGGER
virtual uint32 size() const;
#endif
};
}
#endif /* __avmplus_AbstractFunction__ */

View File

@@ -1,37 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
}

View File

@@ -1,52 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
namespace avmplus
{
/**
* immutable wrapper for a Binding, used for specifying the
* bindings for a property or method.
* Since it's immutable, we can copy by reference.
*/
class Accessor : public MMgc::GCObject
{
public:
Binding get;
Binding set;
Accessor()
{
AvmAssert(get == BIND_NONE && set == BIND_NONE); // make sure memory was cleared
}
};
}

View File

@@ -1,116 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
namespace ActionBlockConstants
{
const unsigned char kindToPushOp[] = {
0,
OP_pushstring, // CONSTANT_Utf8=1
0,
OP_pushint, // CONSTANT_Int=3
OP_pushint, // CONSTANT_UInt=4
OP_pushnamespace, // CONSTANT_PrivateNs=5
OP_pushdouble, // CONSTANT_Double=6
0,
OP_pushnamespace, // CONSTANT_Namespace=8
0,
OP_pushfalse, // CONSTANT_False=10
OP_pushtrue, // CONSTANT_True=11
OP_pushnull, // CONSTANT_Null=12
0,
0,
0,
0,
0,
0,
0,
0,
0,
OP_pushnamespace, //CONSTANT_PackageNamespace=22
OP_pushnamespace, //CONSTANT_PackageInternalNs=23
OP_pushnamespace, //CONSTANT_ProtectedNamespace=24
OP_pushnamespace, //CONSTANT_ExplicitNamespace=25
OP_pushnamespace, //CONSTANT_StaticProtectedNs=26
};
#ifdef AVMPLUS_VERBOSE
const char *constantNames[] = {
"const-0",
"utf8",//const int CONSTANT_Utf8 = 0x01;
"const-2",
"int",//const int CONSTANT_Int = 0x03;
"uint",//const int CONSTANT_UInt = 0x04;
"private",//const int CONSTANT_PrivateNS = 0x05;
"double",//const int CONSTANT_Double = 0x06;
"qname",//const int CONSTANT_Qname = 0x07;
"namespace",//const int CONSTANT_Namespace = 0x08;
"multiname",//const int CONSTANT_Multiname = 0x09;
"false",//const inst CONSTANT_False = 0x0A;
"true",//const int CONSTANT_True = 0x0B;
"null",//const int CONSTANT_Null = 0x0C;
"@qname",//const int CONSTANT_QnameAttr = 0x0D;
"@multiname",//const int CONSTANT_MultinameAttr= 0x0E;
"rtqname",//const int CONSTANT_RTQname = 0x0F; // ns::name, var qname, const name
"@rtqname",//const int CONSTANT_RTQnameA = 0x10; // @ns::name, var qname, const name
"rtqnamelate",//const int CONSTANT_RTQnameL = 0x11; // ns::[], var qname
"@rtqnamelate",//const int CONSTANT_RTQnameLA = 0x12; // @ns::[], var qname
"", //const int CONSTANT_NameL = 0x13, // o.[], ns=public implied, rt name
"", //CONSTANT_NameLA = 0x14, // o.@[], ns=public implied, rt attr-name
"namespaceset", //CONSTANT_NamespaceSet = 0x15
"namespace", //PackageNamespace and Namespace are the same as far as the VM is concerned
"internal",//const int CONSTANT_PackageInternalNS = 0x17
"protected",//const int CONSTANT_ProtectedNamespace = 0x18
"explicit",//const int CONSTANT_ExplicitNamespace = 0x19
"staticprotected",//const int CONSTANT_StaticProtectedNs = 0x1A,
"multinamelate", //const int CONSTANT_MultinameL = 0x1B, // o.[], ns, rt name
"@multinamelate" //CONSTANT_MultinameLA = 0x1C, // o.@[], ns, rt attr-name
};
const char *traitNames[] = {
"slot",//const int TRAIT_Slot = 0x00;
"method",//const int TRAIT_Method = 0x01;
"getter",//const int TRAIT_Getter = 0x02;
"setter",//const int TRAIT_Setter = 0x03;
"class",//const int TRAIT_Class = 0x04;
"function",//const int TRAIT_Function = 0x05;
"const",//const int TRAIT_Const = 0x06;
};
#endif // AVMPLUS_VERBOSE
#include "opcodes.cpp"
}
}

View File

@@ -1,131 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_ActionBlockConstants__
#define __avmplus_ActionBlockConstants__
namespace avmplus
{
/**
* Constants for all of the opcodes in the AVM+ instruction set.
*/
namespace ActionBlockConstants
{
/** @name cpool tags */
/*@{*/
enum CPoolKind {
CONSTANT_Utf8 = 0x01,
CONSTANT_Int = 0x03,
CONSTANT_UInt = 0x04,
CONSTANT_PrivateNs = 0x05, // non-shared namespace
CONSTANT_Double = 0x06,
CONSTANT_Qname = 0x07, // o.ns::name, ct ns, ct name
CONSTANT_Namespace = 0x08,
CONSTANT_Multiname = 0x09, // o.name, ct nsset, ct name
CONSTANT_False = 0x0A,
CONSTANT_True = 0x0B,
CONSTANT_Null = 0x0C,
CONSTANT_QnameA = 0x0D, // o.@ns::name, ct ns, ct attr-name
CONSTANT_MultinameA = 0x0E, // o.@name, ct attr-name
CONSTANT_RTQname = 0x0F, // o.ns::name, rt ns, ct name
CONSTANT_RTQnameA = 0x10, // o.@ns::name, rt ns, ct attr-name
CONSTANT_RTQnameL = 0x11, // o.ns::[name], rt ns, rt name
CONSTANT_RTQnameLA = 0x12, // o.@ns::[name], rt ns, rt attr-name
CONSTANT_NamespaceSet = 0x15,
CONSTANT_PackageNamespace = 0x16,
CONSTANT_PackageInternalNs = 0x17,
CONSTANT_ProtectedNamespace = 0x18,
CONSTANT_ExplicitNamespace = 0x19,
CONSTANT_StaticProtectedNs = 0x1A,
CONSTANT_MultinameL = 0x1B,
CONSTANT_MultinameLA = 0x1C,
};
/*@}*/
/** @name traits kinds */
/*@{*/
enum TraitKind {
TRAIT_Slot = 0x00,
TRAIT_Method = 0x01,
TRAIT_Getter = 0x02,
TRAIT_Setter = 0x03,
TRAIT_Class = 0x04,
TRAIT_Function = 0x05,
TRAIT_Const = 0x06,
};
/*@}*/
/** @name attributes */
/*@{*/
const int ATTR_final = 0x10; // 1=final, 0=virtual
const int ATTR_override = 0x20; // 1=override, 0=new
const int ATTR_metadata = 0x40; // 1=has metadata, 0=no metadata
/*@}*/
/** @name opcodes */
/*@{*/
#include "opcodes.h"
/*@}*/
/**
* The opOperandCount array specifies the number of operands in
* each opcode. It is used by the VM to advance through
* bytecode streams. -1 means invalid opcode.
*/
extern signed char opOperandCount[];
/**
* The opCanThrow array specifies whether an opcode can throw
* exceptions or not.
*/
extern unsigned char opCanThrow[];
#if defined(AVMPLUS_PROFILE) || defined(AVMPLUS_VERBOSE) || defined(DEBUGGER)
extern const char *opNames[];
#endif
extern const unsigned char kindToPushOp[];
#ifdef AVMPLUS_VERBOSE
/** @name debugger string names */
/*@{*/
extern const char *constantNames[];
extern const char *traitNames[];
/*@}*/
#endif
}
}
#endif /* __avmplus_ActionBlockConstants__ */

View File

@@ -1,427 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
package
{
public dynamic class Array extends Object
{
// option flags for sort and sortOn
public static const CASEINSENSITIVE:uint = 1;
public static const DESCENDING:uint = 2;
public static const UNIQUESORT:uint = 4;
public static const RETURNINDEXEDARRAY:uint = 8;
public static const NUMERIC:uint = 16;
// E262 {DontEnum, DontDelete}
public native function get length():uint
public native function set length(newLength:uint)
// Array.length = 1 per ES3
public static const length:int = 1
// ECMA 15.4.2.2
public function Array(...args)
{
var n:uint = args.length
if (n == 1 && (args[0] is Number))
{
var dlen:Number = args[0];
var ulen:uint = dlen
if (ulen != dlen)
Error.throwError( RangeError, 1005 /*kArrayIndexNotIntegerError*/, dlen );
length = ulen;
}
else
{
length = n
for (var i:uint=0; i < n; i++)
this[i] = args[i]
}
}
/**
15.4.4.5 Array.prototype.join (separator)
The elements of the array are converted to strings, and these strings are then concatenated, separated by
occurrences of the separator. If no separator is provided, a single comma is used as the separator.
The join method takes one argument, separator, and performs the following steps:
1. Call the [[Get]] method of this object with argument "length".
2. Call ToUint32(Result(1)).
3. If separator is undefined, let separator be the single-character string ",".
4. Call ToString(separator).
5. If Result(2) is zero, return the empty string.
6. Call the [[Get]] method of this object with argument "0".
7. If Result(6) is undefined or null, use the empty string; otherwise, call ToString(Result(6)).
8. Let R be Result(7).
9. Let k be 1.
10. If k equals Result(2), return R.
11. Let S be a string value produced by concatenating R and Result(4).
12. Call the [[Get]] method of this object with argument ToString(k).
13. If Result(12) is undefined or null, use the empty string; otherwise, call ToString(Result(12)).
14. Let R be a string value produced by concatenating S and Result(13).
15. Increase k by 1.
16. Go to step 10.
*/
private static function _join(o, sep):String
{
var s:String = (sep === undefined) ? "," : String(sep)
var out:String = ""
for (var i:uint = 0, n:uint=uint(o.length); i < n; i++)
{
var x = o[i]
if (x != null)
out += x
if (i+1 < n)
out += s
}
return out
}
AS3 function join(sep=void 0):String
{
return _join(this, sep)
}
prototype.join = function(sep=void 0):String
{
return _join(this, sep)
}
private static native function _pop(o)
AS3 native function pop()
prototype.pop = function()
{
return _pop(this)
}
/**
15.4.4.2 Array.prototype.toString ( )
The result of calling this function is the same as if the built-in join method were invoked for this object with no
argument.
The toString function is not generic; it throws a TypeError exception if its this value is not an Array object.
Therefore, it cannot be transferred to other kinds of objects for use as a method.
*/
prototype.toString = function():String
{
var a:Array = this // TypeError if not compatible
return _join(a, ",");
}
/**
15.4.4.3 Array.prototype.toLocaleString ( )
The elements of the array are converted to strings using their toLocaleString methods, and these strings are
then concatenated, separated by occurrences of a separator string that has been derived in an implementationdefined
locale-specific way. The result of calling this function is intended to be analogous to the result of
toString, except that the result of this function is intended to be locale-specific.
The result is calculated as follows:
1. Call the [[Get]] method of this object with argument "length".
2. Call ToUint32(Result(1)).
3. Let separator be the list-separator string appropriate for the host environments current locale (this is derived in
an implementation-defined way).
4. Call ToString(separator).
5. If Result(2) is zero, return the empty string.
6. Call the [[Get]] method of this object with argument "0".
7. If Result(6) is undefined or null, use the empty string; otherwise, call ToObject(Result(6)).toLocaleString().
8. Let R be Result(7).
9. Let k be 1.
10. If k equals Result(2), return R.
11. Let S be a string value produced by concatenating R and Result(4).
12. Call the [[Get]] method of this object with argument ToString(k).
13. If Result(12) is undefined or null, use the empty string; otherwise, call ToObject(Result(12)).toLocaleString().
14. Let R be a string value produced by concatenating S and Result(13).
15. Increase k by 1.
16. Go to step 10.
The toLocaleString function is not generic; it throws a TypeError exception if its this value is not an Array
object. Therefore, it cannot be transferred to other kinds of objects for use as a method.
*/
prototype.toLocaleString = function():String
{
var a:Array = this // TypeError if not compatible
var out:String = ""
for (var i:uint = 0, n:uint=a.length; i < n; i++)
{
var x = a[i]
if (x != null)
out += x.toLocaleString()
if (i+1 < n)
out += ","
}
return out
}
/**
When the push method is called with zero or more arguments item1, item2, etc., the following steps are taken:
1. Call the [[Get]] method of this object with argument "length".
2. Let n be the result of calling ToUint32(Result(1)).
3. Get the next argument in the argument list; if there are no more arguments, go to step 7.
4. Call the [[Put]] method of this object with arguments ToString(n) and Result(3).
5. Increase n by 1.
6. Go to step 3.
7. Call the [[Put]] method of this object with arguments "length" and n.
8. Return n.
The length property of the push method is 1.
NOTE The push function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be
transferred to other kinds of objects for use as a method. Whether the push function can be applied successfully to a host object
is implementation-dependent.
*/
AS3 native function push(...args):uint
prototype.push = function(...args):uint
{
var n:uint = uint(this.length)
for (var i:uint=0, argc:uint=args.length; i < argc; i++)
this[n++] = args[i]
this.length = n
return n
}
private static native function _reverse(o)
AS3 function reverse():Array
{
return _reverse(this) // return will cast to Array
}
prototype.reverse = function()
{
return _reverse(this)
}
private static native function _concat(o, args:Array):Array
AS3 function concat(...args):Array
{
return _concat(this, args)
}
prototype.concat = function(...args):Array
{
return _concat(this, args)
}
private static native function _shift(o)
AS3 function shift()
{
return _shift(this)
}
prototype.shift = function()
{
return _shift(this)
}
private static native function _slice(o, A:Number, B:Number):Array
AS3 function slice(A=0, B=0xffffffff):Array
{
return _slice(this, Number(A), Number(B))
}
prototype.slice = function(A=0, B=0xffffffff):Array
{
return _slice(this, Number(A), Number(B))
}
/**
15.4.4.13 Array.prototype.unshift ( [ item1 [ , item2 [ , … ] ] ] )
The arguments are prepended to the start of the array, such that their order within the array is the same as the
order in which they appear in the argument list.
When the unshift method is called with zero or more arguments item1, item2, etc., the following steps are taken:
1. Call the [[Get]] method of this object with argument "length".
2. Call ToUint32(Result(1)).
3. Compute the number of arguments.
4. Let k be Result(2).
5. If k is zero, go to step 15.
6. Call ToString(k1).
7. Call ToString(k+Result(3)1).
8. If this object has a property named by Result(6), go to step 9; but if this object has no property named by
Result(6), then go to step 12.
9. Call the [[Get]] method of this object with argument Result(6).
10. Call the [[Put]] method of this object with arguments Result(7) and Result(9).
11. Go to step 13.
12. Call the [[Delete]] method of this object with argument Result(7).
13. Decrease k by 1.
14. Go to step 5.
15. Let k be 0.
16. Get the next argument in the part of the argument list that starts with item1; if there are no more arguments, go
to step 21.
17. Call ToString(k).
18. Call the [[Put]] method of this object with arguments Result(17) and Result(16).
19. Increase k by 1.
20. Go to step 16.
21. Call the [[Put]] method of this object with arguments "length" and (Result(2)+Result(3)).
22. Return (Result(2)+Result(3)).
The length property of the unshift method is 1.
NOTE The unshift function is intentionally generic; it does not require that its this value be an Array object. Therefore it can
be transferred to other kinds of objects for use as a method. Whether the unshift function can be applied successfully to a
host object is implementation-dependent.
*/
native AS3 function unshift(...args):uint
prototype.unshift = function(...args):uint
{
var len:uint = uint(this.length)
var argc:uint = args.length
var k:uint
for (k=len; k > 0; )
{
k--
var d:uint = k+argc
if (k in this)
this[d] = this[k]
else
delete this[d]
}
for (var i:uint = 0; i < argc; i++)
this[k++] = args[i]
len += argc
this.length = len
return len
}
private static native function _splice(o, args:Array):Array
// splice with zero args returns undefined. All other cases return Array.
AS3 function splice(...args)
{
if (!args.length)
return undefined;
return _splice(this, args)
}
prototype.splice = function(...args)
{
if (!args.length)
return undefined;
return _splice(this, args)
}
// sort can return an Array or a Number (unique sort option)
private static native function _sort(o, args:Array)
AS3 function sort(...args)
{
return _sort (this, args);
}
prototype.sort = function(...args)
{
return _sort (this, args);
}
private static native function _sortOn(o, names, options)
AS3 function sortOn(names, options=0, ...ignored)
{
// this is our own addition so we don't have to make names be optional
return _sortOn(this, names, options);
}
prototype.sortOn = function(names, options=0, ...ignored)
{
return _sortOn(this, names, options)
}
// Array extensions that are in Mozilla...
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array
//
// These all work on generic objects (array like objects) as well as arrays
private static native function _indexOf (o, searchElement, fromIndex:int):int;
AS3 function indexOf(searchElement, fromIndex=0):int
{
return _indexOf (this, searchElement, int(fromIndex));
}
prototype.indexOf = function(searchElement, fromIndex=0):int
{
return _indexOf (this, searchElement, int(fromIndex));
}
private static native function _lastIndexOf (o, searchElement, fromIndex:int=0):int;
AS3 function lastIndexOf(searchElement, fromIndex=0x7fffffff):int
{
return _lastIndexOf (this, searchElement, int(fromIndex));
}
prototype.lastIndexOf = function(searchElement, fromIndex=0x7fffffff):int
{
return _lastIndexOf (this, searchElement, int(fromIndex));
}
// Returns true if every element in this array satisfies the provided testing function.
private static native function _every(o, callback:Function, thisObject):Boolean;
AS3 function every(callback:Function, thisObject=null):Boolean
{
return _every (this, callback, thisObject);
}
prototype.every = function(callback:Function, thisObject=null):Boolean
{
return _every (this, callback, thisObject);
}
// Creates a new array with all elements that pass the test implemented by the provided function.
private static native function _filter(o, callback:Function, thisObject):Array;
AS3 function filter(callback:Function, thisObject=null):Array
{
return _filter (this, callback, thisObject);
}
prototype.filter = function(callback:Function, thisObject=null):Array
{
return _filter (this, callback, thisObject);
}
// Calls a function for each element in the array.
private static native function _forEach(o, callback:Function, thisObject):void;
AS3 function forEach(callback:Function, thisObject=null):void
{
_forEach (this, callback, thisObject);
}
prototype.forEach = function(callback:Function, thisObject=null):void
{
_forEach (this, callback, thisObject);
}
// Creates a new array with the results of calling a provided function on every element in this array.
private native static function _map(o, callback:Function, thisObject):Array;
AS3 function map(callback:Function, thisObject=null):Array
{
return _map (this, callback, thisObject);
}
prototype.map = function(callback:Function, thisObject=null):Array
{
return _map (this, callback, thisObject);
}
// Returns true if at least one element in this array satisfies the provided testing function.
private static native function _some(o, callback:Function, thisObject):Boolean;
AS3 function some(callback:Function, thisObject=null):Boolean
{
return _some (this, callback, thisObject);
}
prototype.some = function(callback:Function, thisObject=null):Boolean
{
return _some (this, callback, thisObject);
}
_dontEnumPrototype(prototype);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,98 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_ArrayClass__
#define __avmplus_ArrayClass__
namespace avmplus
{
/**
* class Array
*/
class ArrayClass : public ClassClosure
{
public:
ArrayClass(VTable* cvtable);
// this = argv[0]
// arg1 = argv[1]
// argN = argv[argc]
Atom call(int argc, Atom* argv)
{
return construct(argc, argv);
}
// create a new array, even when argc=1
ArrayObject* newarray(Atom* argv, int argc);
ArrayObject* newArray(uint32 capacity=0);
// override ScriptObject::createInstance
ArrayObject* createInstance(VTable *ivtable, ScriptObject* prototype);
ArrayObject* concat(Atom thisAtom, ArrayObject* args);
Atom pop(Atom thisAtom);
Atom reverse(Atom thisAtom);
Atom shift(Atom thisAtom);
ArrayObject* slice(Atom thisAtom, double A, double B);
Atom sort(Atom thisAtom, ArrayObject *args);
Atom sortOn(Atom thisAtom, Atom namesAtom, Atom optionsAtom);
ArrayObject* splice(Atom thisAtom, ArrayObject* args);
int indexOf (Atom thisAtom, Atom searchElement, int startIndex);
int lastIndexOf (Atom thisAtom, Atom searchElement, int startIndex);
bool every (Atom thisAtom, ScriptObject *callback, Atom thisObject);
ArrayObject *filter (Atom thisAtom, ScriptObject *callback, Atom thisObject);
void forEach (Atom thisAtom, ScriptObject *callback, Atom thisObject);
bool some (Atom thisAtom, ScriptObject *callback, Atom thisObject);
ArrayObject *map (Atom thisAtom, ScriptObject *callback, Atom thisObject);
DECLARE_NATIVE_MAP(ArrayClass)
uint32 getLengthHelper (ScriptObject *d);
private:
void setLengthHelper (ScriptObject *d, uint32 newLen);
ArrayObject* isArray(Atom instance)
{
if (core()->istype(instance, ivtable()->traits))
return (ArrayObject*)AvmCore::atomToScriptObject(instance);
return NULL;
}
const DRCWB(Stringp) kComma;
};
}
#endif /* __avmplus_ArrayClass__ */

View File

@@ -1,504 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
ArrayObject::ArrayObject(VTable *vtable, ScriptObject* proto, uint32 capacity)
: ScriptObject(vtable, proto, 0),
m_denseArr(capacity)
{
AvmAssert(traits()->sizeofInstance >= sizeof(ArrayObject));
m_length = 0;
m_lowHTentry = NO_LOW_HTENTRY;
}
#if 0 // Test code to determine if our array is a pure dense array
bool ArrayObject::getDense()
{
// If are dense part equals are length and we have no
// atoms in our HT, we are a pure dense array. We can't
// call getTable()->GetSize() since we might have deleted
// atoms in our HT and size would be non-zero.
return (isSimpleDense() && !ScriptObject::nextNameIndex(0));
}
#endif
// This routine checks to see if our dense portion is directly next
// to any entries in our HT. If so, the HT entries are deleted and added
// to the dense portion. If the HT is completely emptied, it is cleared.
void ArrayObject::checkForSparseToDenseConversion()
{
// check for lowHTentry being consumed
if (m_lowHTentry == NO_LOW_HTENTRY)
return;
if (getDenseLength() != m_lowHTentry)
return;
AvmCore *core = this->core();
while (getDenseLength() == m_lowHTentry)
{
AvmAssert (ScriptObject::hasUintProperty (m_lowHTentry));
// Move prop from HT to dense Array. No need to update m_length
Atom lowHT = ScriptObject::getUintProperty (m_lowHTentry);
this->m_denseArr.push (lowHT);
// Delete prop from HT
ScriptObject::delUintProperty (m_lowHTentry);
// If our low entry happened to match our length, we're out of HT entries
// and we can just quit.
if ((m_lowHTentry + 1) == m_length)
{
m_lowHTentry = NO_LOW_HTENTRY;
}
else
{
// Find the next integer HT prop and update m_lowHTentry
// This is tricky. Our HT section could be huge but very sparse
// Do we want to linearly walk from index+1 to m_length or do
// we want to walk the entire HT looking for a low integer value?
if (ScriptObject::hasUintProperty (m_lowHTentry + 1))
{
m_lowHTentry++;
}
else
{
// assume we don't find an entry
m_lowHTentry = NO_LOW_HTENTRY;
int index = ScriptObject::nextNameIndex(0);
while (index)
{
Atom name = ScriptObject::nextName (index);
uint32 nameIndex;
if (core->getIndexFromAtom (name, &nameIndex))
{
if ((m_lowHTentry == NO_LOW_HTENTRY) || (nameIndex < m_lowHTentry))
{
m_lowHTentry = nameIndex;
}
}
index = ScriptObject::nextNameIndex(index);
}
}
}
}
// We're done moving our sparse entries over to our dense part of our array.
// This may have left a large HT that is now completely empty. If ScriptObject::nextNameIndex(0)
// returns 0, we know we have no atoms in our HT and we can clear it.
if (ScriptObject::nextNameIndex (0) == 0)
getTable()->reset();
}
void ArrayObject::setProperty(Atom name, Atom value)
{
if (traits()->needsHashtable)
{
AvmCore *core = this->core();
// Update the array length.
uint32 index;
if (core->getIndexFromAtom (name, &index))
{
return setUintProperty (index, value);
}
if (name == core->klength->atom())
return setLength(core->toUInt32(value));
}
ScriptObject::setProperty(name, value);
}
void ArrayObject::setUintProperty(uint32 index, Atom value)
{
if (traits()->needsHashtable)
{
if (hasDense())
{
if (index == getDenseLength())
{
this->m_denseArr.push (value);
if (m_length < getDenseLength())
m_length = getDenseLength();
checkForSparseToDenseConversion ();
return;
}
else if (index < getDenseLength())
{
this->m_denseArr.setAt (index, value);
return;
}
else
{
// fall through and put the new property into our HT
}
}
// If we're NOT dense yet and setting first element, we can create a dense array
else if (index == 0)
{
m_denseArr.push (value);
if (!m_length)
m_length = 1;
else
checkForSparseToDenseConversion ();
return;
}
if (m_length <= index) {
m_length = index+1;
}
if ((m_lowHTentry == NO_LOW_HTENTRY) || (index < m_lowHTentry))
m_lowHTentry = index;
}
// end if (dynamic)
// If our index value is going to overflow our int atom storage and be
// converted to a string, do that here instead of calling the
// SciptObject::setUintProperty which will call ArrayObject::setProperty
// which will call back into this routine in an infinite loop.
if (index & ScriptObject::MAX_INTEGER_MASK)
ScriptObject::setProperty (core()->internUint32(index)->atom(), value);
else
ScriptObject::setUintProperty(index, value);
}
Atom ArrayObject::getProperty(Atom name) const
{
if (traits()->needsHashtable)
{
AvmCore *core = this->core();
if (hasDense())
{
uint32 index;
if (core->getIndexFromAtom (name, &index))
{
// if we get here, we have a valid integer index.
if ((index < getDenseLength()))
return m_denseArr.getAtFast(index);
}
}
if (name == core->klength->atom())
return core->intToAtom (getLength());
}
return ScriptObject::getProperty (name);
}
Atom ArrayObject::getUintProperty(uint32 index) const
{
if (traits()->needsHashtable)
{
if (hasDense())
{
if ((index < getDenseLength()))
return m_denseArr.getAtFast(index);
}
}
return ScriptObject::getUintProperty (index);
}
Atom ArrayObject::getIntProperty(int index) const
{
if (index >= 0)
return getUintProperty(index);
else // integer is negative - we must intern it
return getProperty(core()->internInt(index));
}
void ArrayObject::setIntProperty(int index, Atom value)
{
if (index >= 0)
setUintProperty(index, value);
else // integer is negative - we must intern it
setProperty(core()->internInt(index), value);
}
// This does NOT affect the length of the array
bool ArrayObject::deleteProperty(Atom name)
{
if (traits()->needsHashtable)
{
if (hasDense())
{
uint32 index;
if (core()->getIndexFromAtom (name, &index))
{
return delUintProperty(index);
}
}
}
return ScriptObject::deleteProperty (name);
}
bool ArrayObject::delUintProperty(uint32 index)
{
// if we get here, we have a valid integer index.
if (traits()->needsHashtable)
{
if ((index < getDenseLength()))
{
if (index == (getDenseLength() - 1))
{
m_denseArr.pop();
}
// We're deleting an element in the middle of our array. The lower
// part can be left in the dense array but the upper part needs to
// get moved to the HT.
else
{
for (uint32 i = index + 1; i < getDenseLength(); i++)
{
ScriptObject::setUintProperty (i, m_denseArr.getAtFast(i));
}
m_denseArr.splice (index, 0, (getDenseLength() - index), 0);
}
return true;
}
}
return ScriptObject::delUintProperty(index);
}
bool ArrayObject::propertyIsEnumerable(Atom name) const
{
if (traits()->needsHashtable)
{
if (hasDense())
{
uint32 index;
if (core()->getIndexFromAtom(name, &index))
{
// {DontEnum} is not supported on the dense portion
// of an array. Those properties are always enumerable.
if (index < getDenseLength())
return true;
}
}
}
return ScriptObject::propertyIsEnumerable(name);
}
bool ArrayObject::hasProperty(Atom name) const
{
if (traits()->needsHashtable)
{
if (hasDense())
{
uint32 index;
if (core()->getIndexFromAtom (name, &index))
{
if (index < getDenseLength())
return true;
}
}
}
return ScriptObject::hasProperty (name);
}
bool ArrayObject::hasUintProperty(uint32 index) const
{
if (traits()->needsHashtable)
{
if (hasDense())
{
if (index < getDenseLength())
return true;
}
}
return ScriptObject::hasUintProperty (index);
}
// Iterator support - for in, for each
Atom ArrayObject::nextName(int index)
{
AvmAssert(index > 0);
int denseLength = (int)getDenseLength();
if (index <= denseLength)
{
AvmCore *core = this->core();
return core->intToAtom(index-1);
}
else
{
return ScriptObject::nextName (index - denseLength);
}
}
Atom ArrayObject::nextValue(int index)
{
AvmAssert(index > 0);
int denseLength = (int) getDenseLength();
if (index <= denseLength)
{
return m_denseArr.getAtFast (index-1);
}
else
{
return ScriptObject::nextValue (index - denseLength);
}
}
int ArrayObject::nextNameIndex(int index)
{
int denseLength = (int) getDenseLength();
if (index < denseLength)
{
return index + 1;
}
else
{
index = ScriptObject::nextNameIndex (index - denseLength);
if (!index)
return index;
return denseLength + index;
}
}
#ifdef AVMPLUS_VERBOSE
Stringp ArrayObject::format(AvmCore* core) const
{
Stringp prefix = core->newString("[]@");
return core->concatStrings(prefix, core->formatAtomPtr(atom()));
}
#endif
void ArrayObject::setLength(uint32 newLength)
{
if (traits()->needsHashtable)
{
// Delete all items between size and newLength
uint32 oldLength = getLength();
if (newLength < oldLength)
{
uint32 deleteStart = newLength;
uint32 denseLength = getDenseLength();
if (newLength < denseLength)
{
this->m_denseArr.splice (deleteStart, 0, (denseLength - deleteStart), 0);
deleteStart = denseLength;
}
for (uint32 i = deleteStart; i < oldLength; i++) {
delUintProperty(i);
}
}
m_length = newLength;
}
// else, if !dynamic ignore set.
}
// public native function pop(...rest):Object
Atom ArrayObject::pop()
{
if (isSimpleDense())
{
if (!m_length)
return undefinedAtom;
m_length--;
return m_denseArr.pop ();
}
if (getLength() != 0)
{
Atom outAtom = getUintProperty(getLength()-1);
setLength(getLength()-1);
return outAtom;
}
else
{
return undefinedAtom;
}
}
uint32 ArrayObject::push(Atom* argv, int argc)
{
if (isSimpleDense())
{
m_denseArr.push (argv, argc);
m_length += argc;
}
else
{
for (int i=0; i < argc; i++) {
setUintProperty(getLength(), argv[i]);
}
}
return m_length;
}
uint32 ArrayObject::unshift(Atom* argv, int argc)
{
if (argc != 0)
{
if (isSimpleDense())
{
m_denseArr.unshift (argv, argc);
m_length += argc;
}
else
{
uint32 i;
// First, move all the elements up
uint32 len = getLength();
for (i=len; i > 0; ) { // note: i is unsigned, can't check if --i >=0.
i--;
setUintProperty(i+argc, getUintProperty(i));
}
for (i=0; i < ((uint32)argc); i++) {
setUintProperty(i, argv[i]);
}
setLength(len+argc);
}
}
return getLength();
}
}

View File

@@ -1,137 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_ArrayObject__
#define __avmplus_ArrayObject__
namespace avmplus
{
/**
* an instance of class Array. constructed with "new Array" or
* an array literal [...]. We need this class to support Array's
* special "get" and "put" semantics and to maintain the virtual
* "length" property.
*/
class ArrayObject : public ScriptObject
{
private:
friend class ArrayClass;
AtomArray m_denseArr;
// We can NOT use 0xFFFFFFFF for this since x[0xFFFFFFFE] is a valid prop
// which would make our length 0xFFFFFFFF
static const uint32 NO_LOW_HTENTRY = 0;
uint32 m_lowHTentry; // lowest numeric entry in our hash table
uint32 m_length;
public:
ArrayObject(VTable* ivtable, ScriptObject *delegate, uint32 capacity);
~ArrayObject()
{
m_lowHTentry = 0;
m_length = 0;
}
bool hasDense() const { return (m_denseArr.getLength() != 0); };
bool isSimpleDense() const { return (m_denseArr.getLength() == m_length); };
uint32 getDenseLength() const { return m_denseArr.getLength(); }
uint32 getLength() const { return (m_length); }
void setLength(uint32 newLength);
Atom getProperty(Stringp name) const { return getProperty(name->atom()); }
void setProperty(Stringp name, Atom value) { setProperty(name->atom(), value); }
bool deleteProperty(Stringp name) { return deleteProperty(name->atom()); }
bool hasProperty(Stringp name) const { return hasProperty(name->atom()); }
Atom getProperty(Atom name) const;
void setProperty(Atom name, Atom value);
bool deleteProperty(Atom name);
bool hasProperty(Atom name) const;
// Faster versions that takes direct indices
Atom getUintProperty(uint32 index) const;
void setUintProperty(uint32 index, Atom value);
bool delUintProperty(uint32 index);
bool hasUintProperty(uint32 i) const;
Atom getIntProperty(int index) const;
void setIntProperty(int index, Atom value);
bool propertyIsEnumerable(Atom name) const;
#ifdef AVMPLUS_MAC
// Hack for Mac; can't take addr of virtual function
Atom _getUintProperty(uint32 index) const
{
return getUintProperty(index);
}
void _setUintProperty(uint32 index, Atom value)
{
setUintProperty(index, value);
}
Atom _getIntProperty(int index) const
{
return getIntProperty(index);
}
void _setIntProperty(int index, Atom value)
{
setIntProperty(index, value);
}
#endif
// Iterator support - for in, for each
Atom nextName(int index);
Atom nextValue(int index);
int nextNameIndex(int index);
// native methods
Atom pop(); // pop(...rest)
uint32 push(Atom *args, int argc); // push(...args):uint
uint32 unshift(Atom *args, int argc); // unshift(...args):
void checkForSparseToDenseConversion();
#ifdef DEBUGGER
uint32 size() const;
#endif
#ifdef AVMPLUS_VERBOSE
public:
Stringp format(AvmCore* core) const;
#endif
};
}
#endif /* __avmplus_ArrayObject__ */

View File

@@ -1,304 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
/////////////////////////////////////////////////////////
// AtomArray object
/////////////////////////////////////////////////////////
#include "avmplus.h"
namespace avmplus
{
using namespace MMgc;
AtomArray::AtomArray (int initialCapacity)
{
m_length = 0;
if (!initialCapacity)
{
m_atoms = 0;
}
else
{
if (initialCapacity < kMinCapacity)
initialCapacity = kMinCapacity;
GC *gc = GC::GetGC(this);
setAtoms(gc, (Atom*) gc->Calloc(initialCapacity, sizeof(Atom), GC::kContainsPointers|GC::kZero));
}
}
AtomArray::~AtomArray()
{
clear();
}
/////////////////////////////////////////////////////
// Array AS API
/////////////////////////////////////////////////////
// Pop last element off the end of the array and shrink length
Atom AtomArray::pop()
{
if (!m_length)
return undefinedAtom;
Atom retAtom = m_atoms[m_length - 1];
setAtInternal(m_length - 1, 0); // so GC collects this item
m_length--;
return retAtom;
}
using namespace MMgc;
// n arguments are pushed on the array
uint32 AtomArray::push(Atom *args, int argc)
{
checkCapacity (m_length + argc);
// slow path to trigger write barrier
for(int i=0; i < argc; i++) {
push(args[i]);
}
return argc;
}
// Reverse array elements
void AtomArray::reverse()
{
if (m_length > 1)
{
for (uint32 k = 0; k < (m_length >> 1); k++)
{
Atom temp = m_atoms[k];
m_atoms[k] = m_atoms[m_length - k - 1];
m_atoms[m_length - k - 1] = temp;
}
}
}
// return 0th element, shift rest down
Atom AtomArray::shift()
{
if (!m_length)
return undefinedAtom;
Atom *arr = m_atoms;
Atom retAtom = arr[0];
setAtInternal(0, 0);
memmove (arr, arr + 1, (m_length - 1) * sizeof(Atom));
arr[m_length - 1] = 0; // clear item so GC can collect it.
m_length--;
return retAtom;
}
// insertPoint arg - place to insert
// insertCount arg - number to insert
// deleteCount - number to delete
// args - #insertCount args to insert
void AtomArray::splice(uint32 insertPoint, uint32 insertCount, uint32 deleteCount, AtomArray *args, int offset)
{
long l_shiftAmount = (long)insertCount - (long) deleteCount; // long because result could be negative
// Must be BEFORE arr = m_atoms since m_atoms might change
checkCapacity (m_length + l_shiftAmount);
Atom *arr = m_atoms;
Atom *argsArr = args ? args->m_atoms : 0;
if (l_shiftAmount < 0)
{
int numberBeingDeleted = -l_shiftAmount;
// whack deleted items so they're ref count goes down
AvmCore::decrementAtomRegion(arr + insertPoint + insertCount, numberBeingDeleted);
// shift elements down
int toMove = m_length - insertPoint - deleteCount;
memmove (arr + insertPoint + insertCount, arr + insertPoint + deleteCount, toMove * sizeof(Atom));
// clear top part for RC purposes
memset (arr + m_length - numberBeingDeleted, 0, numberBeingDeleted * sizeof(Atom));
}
else if (l_shiftAmount > 0)
{
memmove (arr + insertPoint + l_shiftAmount, arr + insertPoint, (m_length - insertPoint) * sizeof(Atom));
// clear for RC purposes
memset (arr + insertPoint, 0, l_shiftAmount * sizeof(Atom));
}
// Add the items to insert
if (insertCount)
{
AvmAssert(args != 0);
for (uint32 i=0; i<insertCount; i++)
{
setAtInternal(insertPoint+i, argsArr[i+offset]);
}
}
m_length += l_shiftAmount;
return;
}
// insert array of arguments at front of array
Atom AtomArray::unshift(Atom *args, int argc)
{
// shift elements up by argc
// inserts args into initial spots
checkCapacity (m_length + argc);
Atom *arr = m_atoms;
memmove (arr + argc, arr, m_length * sizeof(Atom));
// clear moved element for RC purposes
memset (arr, 0, argc * sizeof(Atom));
for(int i=0; i<argc; i++) {
setAtInternal(i, args[i]);
}
m_length += argc;
return nullObjectAtom;
}
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
/////////////////////////////////////////////////////
void AtomArray::checkCapacity (int newLength)
{
AvmAssert(newLength >= 0);
// !!@ handle case where capacity shrinks by 50% (resize buffer smaller)
if (!m_atoms || newLength > int(capacity()))
{
// We oversize our buffer by 50% (is that the best algorithm?)
int capacity = newLength + (newLength >> 2);
if (capacity < kMinCapacity) capacity = kMinCapacity;
GC* gc = GC::GetGC(this);
Atom* newAtoms = (Atom*) gc->Calloc(capacity, sizeof(Atom), GC::kContainsPointers|GC::kZero);
Atom* oldAtoms = m_atoms;
setAtoms(gc, newAtoms);
if(oldAtoms) {
// use a memcpy to skip ref counting
memcpy(m_atoms, oldAtoms, m_length*sizeof(Atom));
memset(oldAtoms, 0, m_length*sizeof(Atom));
gc->Free(oldAtoms);
}
}
}
void AtomArray::push (Atom a)
{
checkCapacity (m_length + 1);
setAtInternal(m_length++, a);
}
void AtomArray::push (const AtomArray *a)
{
if (!a)
return;
push (a->m_atoms, a->getLength());
}
void AtomArray::removeAt (uint32 index)
{
AvmAssert (m_length > 0);
AvmAssert (index >= 0);
AvmAssert (index < uint32(m_length));
if (!m_length)
return;
checkCapacity (m_length - 1);
m_length--;
// use setAt instead of direct access for proper ref count maintenance
setAtInternal(index, 0);
Atom *arr = m_atoms;
if (m_length)
{
// shift down entries
memmove (arr + index, arr + index + 1, (this->m_length - index) * sizeof(Atom));
}
arr[m_length] = 0; // clear our entry so GC can collect it
}
void AtomArray::insert (uint32 index, Atom a)
{
AvmAssert(index <= m_length);
checkCapacity (m_length + 1);
m_length++;
Atom *arr = m_atoms;
// shift entries up by one to make room
memmove (arr + index + 1, arr + index, (m_length - index - 1) * sizeof(Atom));
// this element is still in the array so don't let setAtInternal decrement its count
m_atoms[index] = 0;
setAtInternal(index, a);
}
void AtomArray::setAt (uint32 index, Atom a)
{
if (index > m_length)
{
AvmAssert(0);
return;
}
setAtInternal(index, a);
}
Atom AtomArray::getAt (uint32 index) const
{
if (index > m_length)
{
AvmAssert(0);
return nullObjectAtom;
}
return m_atoms[index];
}
void AtomArray::clear()
{
#ifdef MMGC_DRC
AvmCore::decrementAtomRegion(m_atoms, m_length);
#endif
m_length = 0;
if(m_atoms) {
GC::GetGC(m_atoms)->Free(m_atoms);
m_atoms = 0;
}
}
}

View File

@@ -1,128 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 __avmplus_AtomArray__
#define __avmplus_AtomArray__
namespace avmplus
{
class AtomArray
{
public:
AtomArray(int initialCapacity = 0);
~AtomArray();
/////////////////////////////////////////////////////
// Array AS API support
/////////////////////////////////////////////////////
// Pop last element off the end of the array and shrink length
Atom pop();
// n arguments are pushed on the array (argc is returned)
uint32 push(Atom *args, int argc);
// Reverse array elements
void reverse();
// return 0th element, shift rest down
Atom shift();
// insertPoint arg - place to insert
// insertCount arg - number to insert
// deleteCount - number to delete
// args - #insertCount args to insert
// offset - offset in args to start the insertion from.
void splice(uint32 insertPoint, uint32 insertCount, uint32 deleteCount, AtomArray *args, int offset=0);
// insert array of arguments at front of array
Atom unshift(Atom *args, int argc);
/////////////////////////////////////////////////////
uint32 getLength() const { return m_length; };
void setLength(uint32 len) { m_length = len; }
uint32 capacity() const
{
return MMgc::GC::Size(m_atoms)/sizeof(Atom);
}
void push (Atom a);
void push (const AtomArray *a);
void removeAt (uint32 index);
void insert (uint32 index, Atom a);
void setAt (uint32 index, Atom a);
void clear();
Atom operator[](uint32 index) const { return getAt(index); };
Atom getAt(uint32 index) const;
// ONLY USE THIS IF YOU PRE-CHECK THE LENGTH
Atom getAtFast(uint32 index) const
{
AvmAssert(index < m_length);
return m_atoms[index];
};
/**
* Compacts the AtomArray so it is exactly large enough
* to hold the contents of the array.
*
* This is useful for conserving memory.
*/
void pack();
void checkCapacity (int newLength);
private:
uint32 m_length;
Atom* m_atoms;
const static uint32 kMinCapacity = 4;
void setAtInternal(uint32 index, Atom a)
{
// m_arr[index] = a;
WBATOM( MMgc::GC::GetGC(m_atoms), m_atoms, m_atoms + index, a);
}
void setAtoms(MMgc::GC *gc, Atom *atoms)
{
WB(gc, gc->FindBeginning(this), &m_atoms, atoms);
}
};
}
#endif /* __avmplus_AtomArray__ */

View File

@@ -1,38 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
}

View File

@@ -1,142 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AtomConstants__
#define __avmplus_AtomConstants__
namespace avmplus
{
/**
* The AtomConstants namespace defines constants for
* manipulating atoms.
*
* The atom is a primitive value in ActionScript. Since
* ActionScript is a dynamically typed language, an atom can
* belong to one of several types: null, undefined, number,
* integer, string, boolean, object reference.
*
* Atoms are encoded with care to take up the minimum
* possible space. An atom is represented by a 32-bit
* integer, with the bottom 3 bits indicating the type.
*
* 32 bit atom
*
* 31 16 15 8 7 3 210
* dddddddd dddddddd dddddddd ddddd TTT
*
* TTT
* 000 - untagged
* 001 object
* 010 string
* 011 namespace
* 100 undefined
* 101 boolean
* 110 integer
* 111 double
*
* - using last 3 bits means allocations must be 8-byte aligned.
* - related types are 1 bit apart, e.g. int/double
*
* kInteger atoms are used to represent integer values from -2^28..2^28-1,
* regardless of whether the context implies int, uint, or Number.
* If a number doesn't fit into that range it is stored as a kDoubleType
*
*/
namespace AtomConstants
{
/**
* @name Atom types
* These are the type values that appear in the bottom
* 3 bits of an atom.
*/
/*@{*/
// cannot use 0 as tag, breaks atomWriteBarrier
const Atom kObjectType = 1; // null=1
const Atom kStringType = 2; // null=2
const Atom kNamespaceType = 3; // null=3
const Atom kSpecialType = 4; // undefined=4
const Atom kBooleanType = 5; // false=5 true=13
const Atom kIntegerType = 6;
const Atom kDoubleType = 7;
/*@}*/
#define ISNULL(a) (((unsigned)a) < kSpecialType)
/*
other things you can do with math on atoms
isNull (unsigned)a < 4
isUndefined a == undefinedAtom
isSpecial (unsigned)a <= 4
isNumber a & 6 == 6
^8 jlt(a<8) ^2 jle(a<=4)
true 1110 0110 t 1100 f
false 0110 1110 f 0100 t
undefined 0100 1100 f 0110 f
*/
/**
* @name Special atom values
* These are the atoms for undefined, null, true
* and false.
*/
/*@{*/
// there is no single null atom. use isNull() to test, or
// one of the following typed null atoms. if you must, use NULL (0).
const Atom nullObjectAtom = kObjectType|0;
const Atom nullStringAtom = kStringType|0;
const Atom nullNsAtom = kNamespaceType|0;
const Atom undefinedAtom = kSpecialType|0; // 0x03
const Atom trueAtom = kBooleanType|0x08; // 0x0D
const Atom falseAtom = kBooleanType|0x00; // 0x05
/*@}*/
/**
* @name BIND constants
* These BIND constants are used similarly to atom kinds. Since we
* have a conservative collector, the codes aren't important.
*/
/*@{*/
const Binding BIND_NONE = 0; // no such binding
const Binding BIND_AMBIGUOUS = -1;
const Binding BIND_METHOD = 1; // int disp_id local method number
const Binding BIND_VAR = 2; // int local slot number (r/w var)
const Binding BIND_CONST = 3; // int local slot number (r/o const)
const Binding BIND_ACCESSOR = 4; // Accessor* pair of get/set bindings
const Binding BIND_ITRAMP = 5; // interface trampoline in imt table
/*@}*/
}
}
#endif /* __avmplus_AtomConstants__ */

View File

@@ -1,89 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AtomWriteBarrier__
#define __avmplus_AtomWriteBarrier__
namespace avmplus
{
#ifndef WRITE_BARRIERS
#define ATOM_WB Atom
#define WBATOM(gc, c, a, v) *(a) = v
#else
// Optimized Atom write barrier
class AtomWB
{
public:
AtomWB() {}
AtomWB(Atom t)
{
set(t);
}
AtomWB(const AtomWB& toCopy)
{
set(toCopy.atom);
}
~AtomWB() { set(0); }
const Atom& operator=(const AtomWB& wb)
{
return set(wb.atom);
}
const Atom& operator=(const Atom& tNew)
{
return set(tNew);
}
operator const Atom&() const { return atom; }
private:
Atom& set(const Atom& atomNew)
{
if(atom == atomNew)
return atom;
MMgc::GC *gc = MMgc::GC::GetGC(this);
AvmCore::atomWriteBarrier(gc, gc->FindBeginning(this), (Atom*)this, atomNew);
return atom;
}
Atom atom;
};
#define ATOM_WB AtomWB
#define WBATOM(gc, c, a, v) AvmCore::atomWriteBarrier(gc, c, a, v)
#endif // WRITE_BARRIERS
}
#endif /* __avmplus_AtomWriteBarrier__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,109 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 __AvmDebug__
#define __AvmDebug__
#include "avmplusTypes.h"
#ifdef WIN32
#include <windows.h>
#endif
#ifdef _MAC
#if !TARGET_RT_MAC_MACHO
typedef const unsigned char* ConstStr255Param;
extern "C"
{
#ifdef powerc
extern pascal void DebugStr(ConstStr255Param aStr);
#else
// extern pascal void DebugStr(ConstStr255Param aStr) = 0xABFF;
extern pascal void SysBreakStr(ConstStr255Param aStr) = {0x303C, 0xFE15, 0xA9C9};
#endif
}
#endif
#endif
namespace avmplus
{
void AvmDebugMsg(bool debuggerBreak, const char* format, ...);
void AvmDebugMsg(const char* msg, bool debuggerBreak);
void AvmDebugMsg(const wchar* msg, bool debuggerBreak);
#ifdef _DEBUG
inline void _AvmAssertMsg(int32 assertion, const char* msg)
{
if (assertion == 0)
AvmDebugMsg(msg, true);
}
#define AvmAssertMsg(x,y) do { _AvmAssertMsg((x), (y)); } while (0) /* no semi */
#define AvmAssert(x) _AvmAssert((x), __LINE__,__FILE__)
#define _AvmAssert(x, line_, file_) __AvmAssert((x), line_, file_)
#define __AvmAssert(x, line_, file_) do { AvmAssertMsg((x), "Assertion failed: \"" #x "\" (" #file_ ":" #line_ ")"); } while (0) /* no semi */
#else
#define AvmAssertMsg(x,y) do { } while (0) /* no semi */
#define AvmAssert(x) do { } while (0) /* no semi */
#endif
/*************************************************************************/
/******************************* Debugging *******************************/
/*************************************************************************/
/* This mess serves to define the DebugMsg function on each platform.
* DebugMsg is only defined when the Debug flag is turned on; it halts
* program execution and drops into the debugger with the given message.
* We define it as in inline so that when you fall into the debugger,
* you're in the function that issued the call and not in a "DebugMsg"
* subroutine.
*/
#if defined(_MAC) && !defined(DARWIN)
// WARNING: this function is NOT THREAD SAFE
/*plugin_export*/ ConstStr255Param MakePascalMsg(const char* theString);
#if SOFT_ASSERTS
inline void DebugMsg_(const char* msg) { }
#else
#ifdef powerc
inline void DebugMsg_(const char* msg) { DebugStr(MakePascalMsg(msg)); }
#else
inline void DebugMsg_(const char* msg) { SysBreakStr(MakePascalMsg(msg)); }
#endif
#endif // SOFT_ASSERTS
#endif
}
#endif /* __AvmDebug__ */

View File

@@ -1,98 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef _DEBUG
#include <malloc.h>
#include <DbgHelp.h>
#include <strsafe.h>
#endif
/*************************************************************************/
/******************************* Debugging *******************************/
/*************************************************************************/
#ifndef MB_SERVICE_NOTIFICATION
#define MB_SERVICE_NOTIFICATION 0x00200000L
#endif
namespace avmplus
{
const static bool logToStdErr=true;
void AvmDebugMsg(bool debuggerBreak, const char *format, ...)
{
// [ggrossman 09.24.04]
// Changed this to _DEBUG only because we don't link to
// CRT in Release builds, so vsprintf is unavailable!!
#ifdef _DEBUG
va_list argptr;
va_start(argptr, format);
int bufferSize = _vscprintf(format, argptr);
char *buffer = (char*)alloca(bufferSize+1);
if (buffer) {
StringCbVPrintf(buffer, bufferSize, format, argptr);
AvmDebugMsg(buffer, debuggerBreak);
}
#else
(void)format;
(void)debuggerBreak;
#endif
}
void AvmDebugMsg(const char* msg, bool debugBreak)
{
OutputDebugString(msg);
if(logToStdErr) {
fprintf( stderr, "%s", msg );
}
if (debugBreak) {
DebugBreak();
}
}
void AvmDebugMsg(const wchar* msg, bool debugBreak)
{
OutputDebugStringW((LPCWSTR)msg);
if (debugBreak) {
DebugBreak();
}
}
}

View File

@@ -1,44 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AvmError__
#define __avmplus_AvmError__
#ifdef DEBUGGER
struct AvmError
{
int id;
const char *message;
};
#endif
#endif /* __avmplus_AvmError__ */

View File

@@ -1,39 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
using namespace MMgc;
namespace avmplus
{
}

View File

@@ -1,47 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_AvmPlusScriptableObject__
#define __avmplus_AvmPlusScriptableObject__
namespace avmplus
{
class AvmPlusScriptableObject : public MMgc::RCFinalizedObject
{
public:
// used by WeakValueHashtable to correctly atom'ize a pointer to one of these
virtual Atom toAtom() const { return undefinedAtom; }
};
}
#endif //__avmplus_AvmPlusScriptableObject__

View File

@@ -1,636 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 <math.h>
#include "avmplus.h"
#include "BigInteger.h"
#define X86_MATH
namespace avmplus
{
void BigInteger::setFromDouble(double value)
{
int e;
uint64 mantissa = MathUtils::frexp(value,&e); // value = mantissa*2^e, mantissa and e are integers.
numWords = (2 + ((e > 0 ? e : -e) /32));
AvmAssert(numWords <= kMaxBigIntegerBufferSize);
wordBuffer[1] = (uint32)(mantissa >> 32);
wordBuffer[0] = (uint32)(mantissa & 0xffffffff);
numWords = (wordBuffer[1] == 0 ? 1 : 2);
if(e < 0)
rshiftBy(-e);
else
lshiftBy(e);
}
void BigInteger::setFromBigInteger(const BigInteger* from, int32 offset, int32 amount)
{
numWords = amount;
AvmAssert(numWords <= kMaxBigIntegerBufferSize);
memcpy( (byte*)wordBuffer,
(byte*)&(from->wordBuffer[offset]),
amount*sizeof(uint32));
}
double BigInteger::doubleValueOf() const
{
// todo: there's got to be a quicker/smaller code alg for this.
if (numWords == 1)
return (double)wordBuffer[0];
// determine how many of bits are used by the top word
int bitsInTopWord=1;
for(uint32 topWord = wordBuffer[numWords-1]; topWord > 1; topWord >>= 1)
bitsInTopWord++;
// start result with top word. We will accumulate the most significant 53 bits of data into it.
int nextWord = numWords-1;
// used for rounding:
bool bit53 = false;
bool bit54 = false;
bool rest = false;
const uint64 ONEL = 1UL;
uint64 resultMantissa = 0;
uint64 w = 0;
int pos = 53;
int bits = bitsInTopWord;
int wshift = 0;
while(pos > 0)
{
// extract word and | it in
w = wordBuffer[nextWord--];
resultMantissa |= (w >> wshift);
pos -= bits;
if (pos > 0)
{
if (nextWord > -1)
{
// ready for next word
bits = (pos > 31) ? 32 : pos;
wshift = (pos > 31) ? 0 : 32-bits;
resultMantissa <<= bits;
}
else
{
break; // not enough data for full 53 bits
}
}
}
// rounding
if (pos > 0)
{
; // insufficient data for rounding
}
else
{
bit53 = ( resultMantissa & 0x1 ) ? true : false;
if (bits == 32)
{
// last extract was exactly 32 bits, so rest of bits are in next word if there is one
if (nextWord > -1)
{
w = wordBuffer[nextWord--];
bit54 = ( w & (ONEL<<31) ) ? true : false;
rest = ( w & ((ONEL<<31)-1) ) ? true : false;
}
}
else
{
// we know bit54 is in this word but the rest of the data may be in the next
AvmAssert(bits < 32 && wshift > 0);
bit54 = ( w & (ONEL<<(wshift-1)) ) ? true : false;
if (wshift > 1)
rest = ( w & ((ONEL<<(wshift-1))-1) ) ? true : false;
// pick up any residual bits
if (nextWord > -1)
rest = rest || (wordBuffer[nextWord--] != 0);
}
}
/**
* ieee rounding is to nearest even value (bit54 is 2^-1)
* x...1 1.. -> round up since odd (but53 set)
* x...0 1...1.. -> round up since value > 1/2
*/
if (bit54 && (bit53 || rest))
resultMantissa += 1;
double result=0;
int32 expBase2 = lg2() + 1 - 53; // if negative, then we've already captured all the data in the mantissaResult and we can ignore.
result = (double)resultMantissa;
if (expBase2 > 0)
{
if (expBase2 < 64)
{
uint64 uint64_1 = 1;
result *= (double)(uint64_1 << expBase2);
}
else
{
result *= MathUtils::pow(2,expBase2);
}
}
return result;
}
// Compare this vs other, return -1 if this < other, 0 if this == other, or 1 if this > other.
// (todo: optimization for D2A would be to check if comparison was larger than an argument value
// currently, we add the argument to this and compare the result with other).
int32 BigInteger::compare(const BigInteger *other) const
{
// if a is bigger than other, subtract has to be positive (assuming unsigned value)
int result = 0;
if (numWords > other->numWords)
result = 1;
else if (numWords < other->numWords)
result = -1;
else
{
// otherwise, they are they same number of uint32 words. need to check numWords by numWords
for(int x = numWords-1; x > -1 ; x--)
{
if (wordBuffer[x] != other->wordBuffer[x])
{
result = (wordBuffer[x] < other->wordBuffer[x]) ? -1 : 1;
break;
}
}
}
return result;
}
// Multiply by an integer factor and add an integer increment. The addition is essentially free,
// use this with a zero second argument for basic multiplication.
void BigInteger::multAndIncrementBy(int32 factor, int32 addition)
{
uint64 opResult;
// perform mult op, moving carry forward.
uint64 carry = addition; // init cary with first addition
int x;
for(x=0; x < numWords; x++)
{
opResult = (uint64)wordBuffer[x] * (uint64)factor + carry;
carry = opResult >> 32;
wordBuffer[x] = (uint32)(opResult & 0xffffffff);
}
// if carry goes over the existing top, may need to expand wordBuffer
if (carry)
{
setNumWords(numWords+1);
wordBuffer[x] = (uint32)carry;
}
}
// Multiply by another BigInteger. If optional arg result is not null, reuse it for
// result, else allocate a new result.
// (note, despite the name "smallerNum", argument does not need to be smaller than this).
BigInteger* BigInteger::mult(const BigInteger* smallerNum, BigInteger* result) const
{
// Need to know which is the bigger number in terms of number of words.
const BigInteger *biggerNum = this;
if (biggerNum->numWords < smallerNum->numWords)
{
const BigInteger *temp = biggerNum;
biggerNum = smallerNum;
smallerNum = temp;
}
// Make sure result is big enough, initialize with zeros
int maxNewNumWords = biggerNum->numWords + smallerNum->numWords;
result->setNumWords(maxNewNumWords); // we'll trim the excess at the end.
// wipe entire buffer (initToZero flag in setNumWords only sets new elements to zero)
for(int x = 0; x < maxNewNumWords; x++)
result->wordBuffer[x] = 0;
// do the math like gradeschool. To optimize, use an FFT (http://numbers.computation.free.fr/Constants/Algorithms/fft.html)
for(int x = 0; x < smallerNum->numWords; x++)
{
uint64 factor = (uint64) smallerNum->wordBuffer[x];
if (factor) // if 0, nothing to do.
{
uint32* pResult = result->wordBuffer+x; // each pass we rewrite elements of result offset by the pass iteration
uint64 product;
uint64 carry = 0;
for(int y = 0; y < biggerNum->numWords; y++)
{
product = (biggerNum->wordBuffer[y] * factor) + *pResult + carry;
carry = product >> 32;
*pResult++ = (uint32)(product & 0xffffffff);
}
*pResult = (uint32)carry;
}
}
// remove leading zeros
result->trimLeadingZeros();
return result;
}
// Divide this by divisor, put the remainder (i.e. this % divisor) into residual. If optional third argument result
// is not null, use it to store the result of the div, else allocate a new BigInteger for the result.
// Note: this has been hard to get right. If bugs do show up, use divideByReciprocalMethod instead
// Note2: this is optimized for the types of numerator/denominators generated by D2A. It will not work when
// the result would be a value bigger than 9. For general purpose BigInteger division, use divideByReciprocalMethod.
BigInteger* BigInteger::quickDivMod(const BigInteger* divisor, BigInteger* residual, BigInteger* result)
{
// handle easy cases where divisor is >= this
int compareTo = this->compare(divisor);
if (compareTo == -1)
{
residual->copyFrom(this);
result->setValue(0);
return result;
}
else if (compareTo == 0)
{
residual->setValue(0);
result->setValue(1);
return result;
}
int dWords = divisor->numWords;
/* this section only necessary for true division instead of special case division needed by D2A. We are
assuming the result is a single digit value < 10 and > -1
int next = this->numWords - dWords;
residual->copyFrom(this, next, dWords); // residual holds a divisor->numWords sized chunk of this.
*/
residual->copyFrom(this,0,numWords);
BigInteger decrement;
decrement.setFromInteger(0);
result->setNumWords(divisor->numWords, true);
uint64 factor;
//do // need to loop over dword chunks of residual to make this handle division of any arbitrary bigIntegers
{
// guess largest factor that * divisor will fit into residual
factor = (uint64)(residual->wordBuffer[residual->numWords-1]) / divisor->wordBuffer[dWords-1];
if ( ((factor <= 0) || (factor > 10)) // over estimate of 9 could be 10
&& residual->numWords > 1 && dWords > 1)
{
uint64 bigR = ( ((uint64)residual->wordBuffer[residual->numWords-1]) << 32)
+ (residual->wordBuffer[residual->numWords-2]);
factor = bigR / divisor->wordBuffer[dWords-1];
if (factor > 9)
{ // Note: This only works because of the relative size of the two operands
// which the D2A class produces. todo: try generating a numerator out of the
// the top 32 significant bits of residual (may have to get bits from two seperate words)
// and a denominator out of the top 24 significant bits of divisor and use them for
// the factor guess. Same principal as above applied to 8 bit units.
factor = 9;
/*
BigInteger::free(decrement);
return divideByReciprocalMethod(divisor, residual, result);
*/
}
}
if (factor)
{
decrement.copyFrom(divisor);
decrement.multAndIncrementBy( (uint32)factor,0);
// check for overestimate
// fix bug 121952: must check for larger overestimate, which
// can occur despite the checks above in some rare cases.
// To see this case, use:
// this=4398046146304000200000000
// divisor=439804651110400000000000
while (decrement.compare(residual) == 1 && factor > 0)
{
decrement.decrementBy(divisor);
factor--;
}
// reduce dividend (aka residual) by factor*divisor, leave remainder in residual
residual->decrementBy(&decrement);
}
// check for factor 0 underestimate
int comparedTo = residual->compare(divisor);
if (comparedTo == 1) // correct guess if its an off by one estimate
{
residual->decrementBy(divisor);
factor++;
}
result->wordBuffer[0] = (uint32)factor;
/* The above works for the division requirements of D2A, where divisor is always around 10 larger
than the dividend and the result is always a digit 1-9.
To make this routine work for general division, the following would need to be fleshed out /debugged.
residual->trimLeadingZeros();
// While we have more words to divide by and the residual has less words than the
// divisor,
if (--next >= 0)
{
do
{
result->lshiftBy(32); // shift current result over by a word
residual->lshiftBy(32);// shift remainder over by a word
residual->wordBuffer[0] = this->wordBuffer[next]; // drop next word of "this" into bottom word of remainder
}
while(residual->numWords < dWords);
}
} while(next >= 0);
*/
}
// trim zeros off top of residual
result->trimLeadingZeros();
return result;
}
/* Was hoping dividing via a Newton's approximation of the reciprocal would be faster, but
its not (makes D2A about twice as slow!). Its not the 32bit divide above that's slow,
its how many times you have to iterate over entire BigIntegers. Below uses a shift,
and three multiplies:
*/
BigInteger* BigInteger::divideByReciprocalMethod(const BigInteger* divisor, BigInteger* residual, BigInteger* result)
{
// handle easy cases where divisor is >= this
int compareTo = this->compare(divisor);
if (compareTo == -1)
{
residual->copyFrom(this);
result->setValue(0);
return result;
}
else if (compareTo == 0)
{
residual->setValue(0);
result->setValue(1);
return result;
}
uint32 d2Prec = divisor->lg2();
uint32 e = 1 + d2Prec;
uint32 ag = 1;
uint32 ar = 31 + this->lg2() - d2Prec;
BigInteger u;
u.setFromInteger(1);
BigInteger ush;
ush.setFromInteger(1);
BigInteger usq;
usq.setFromInteger(0);
while (1)
{
u.lshift(e + 1,&ush);
divisor->mult(&u,&usq); // usq = divisor*u^2
usq.multBy(&u);
ush.subtract(&usq, &u); // u = ush - usq;
int32 ush2 = u.lg2(); // ilg2(u);
e *= 2;
ag *= 2;
int32 usq2 = 4 + ag;
ush2 -= usq2; // BigInteger* diff = ush->subtract(usq); // ush -= usq; ush > 0
if (ush2 > 0) // (ush->compare(usq) == 1)
{
u.rshiftBy(ush2); // u >>= ush;
e -= ush2;
}
if (ag > ar)
break;
}
result = this->mult(&u,result); // mult by reciprocal (scaled by e)
result->rshiftBy(e); // remove scaling
BigInteger temp;
temp.setFromInteger(0);
divisor->mult(result, &temp); // compute residual as this - divisor*result
this->subtract(&temp,residual); // todo: should be a more optimal way of doing this
// ... doesn't work, e is the wrong scale for this (too large)....
// residual = this->lshift(e,residual); // residual = (this*2^e - result) / 2^e
// residual->decrementBy(result);
// residual->rshiftBy(e); // remove scaling
return(result);
}
// q = this->divBy(divisor) is equilvalent to: q = this->quickDivMod(divisor,remainderResult); this = remainderResult;
BigInteger* BigInteger::divBy(const BigInteger* divisor, BigInteger* divResult)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
quickDivMod(divisor, &tempInt, divResult); // this has been hard to get right. If bugs do show up,
//divResult = divideByReciprocalMethod(divisor,tempInt,divResult); // try this version instead Its slower, but less likely to be buggy
this->copyFrom(&tempInt);
return divResult;
}
uint32 BigInteger::lg2() const
{
uint32 powersOf2 = (numWords-1)*32;
for(uint32 topWord = wordBuffer[numWords-1]; topWord > 1; topWord >>= 1)
powersOf2++;
return powersOf2;
}
// Shift a BigInteger by <shiftBy> bits to left. If
// result is not NULL, write result into it, else allocate a new BigInteger.
BigInteger* BigInteger::lshift(uint32 shiftBy, BigInteger* result) const
{
// calculate how much larger the result will be
int numNewWords = shiftBy >> 5; // i.e. div by 32
int totalWords = numNewWords + numWords + 1; // overallocate by 1, trim if necessary at end.
result->setNumWords(totalWords,true);
// make sure we don't create more words for 0
if ( numWords == 1 && wordBuffer[0] == 0 )
{
result->setValue(0); // 0 << num is still 0
return result;
}
const uint32* pSourceBuff = wordBuffer;
uint32* pResultBuff = result->wordBuffer;
for(int x = 0; x < numNewWords; x++)
*pResultBuff++ = 0;
// move bits from wordBuffer into result's wordBuffer shifted by (shiftBy % 32)
shiftBy &= 0x1f;
if (shiftBy) {
uint32 carry = 0;
int shiftCarry = 32 - shiftBy;
for(int x=0; x < numWords; x++)
{
*pResultBuff++ = *pSourceBuff << shiftBy | carry;
carry = *pSourceBuff++ >> shiftCarry;
}
*pResultBuff = carry; // final carry may add a word
if (*pResultBuff)
++totalWords; // prevent trim of overallocated extra word
}
else for(int x=0; x < numWords; x++) // shift was by a clean multiple of 32, just move words
{
*pResultBuff++ = *pSourceBuff++;
}
result->numWords = totalWords - 1; // trim over allocated extra word
return result;
}
// Shift a BigInteger by <shiftBy> bits to right. If
// result is not NULL, write result into it, else allocate a new BigInteger.
// (todo: might be possible to combine rshift and lshift into a single function
// with argument specifying which direction to shift, but result might be messy/harder to get right)
BigInteger* BigInteger::rshift(uint32 shiftBy, BigInteger* result) const
{
int numRemovedWords = shiftBy >> 5; // i.e. div by 32
// calculate how much larger the result will be
int totalWords = numWords - numRemovedWords;
result->setNumWords(totalWords,true);
// check for underflow
if (numRemovedWords > numWords)
{
result->setValue(0);
return result;
}
// move bits from wordBuffer into result's wordBuffer shifted by (shiftBy % 32)
uint32* pResultBuff = &(result->wordBuffer[totalWords-1]);
const uint32* pSourceBuff = &(wordBuffer[numWords-1]);
shiftBy &= 0x1f;
if (shiftBy)
{
int shiftCarry = 32 - shiftBy;
uint32 carry = 0;
for(int x=totalWords-1; x > -1; x--)
{
*pResultBuff-- = *pSourceBuff >> shiftBy | carry;
carry = *pSourceBuff-- << shiftCarry;
}
}
else for(int x=totalWords-1; x > -1; x--) // shift was by a clean multiple of 32, just move words
{
*pResultBuff-- = *pSourceBuff--;
}
result->numWords = totalWords;
result->trimLeadingZeros(); // shrink numWords down to correct value
return result;
}
// Add or subtract two BigIntegers. If subtract, we assume the argument is smaller than this since we
// don't support negative numbers. If optional third argument result is not null, reuse it for result
// else allocate a new BigInteger for the result.
BigInteger *BigInteger::addOrSubtract(const BigInteger* smallerNum, bool isAdd, BigInteger* result) const
{
// figure out which operand is the biggest in terms of number of words.
int comparedTo = compare(smallerNum);
const BigInteger* biggerNum = this;
if (comparedTo < 0)
{
const BigInteger* temp = biggerNum;
biggerNum = smallerNum;
smallerNum = temp;
AvmAssert(isAdd || comparedTo >= 0); // the d2a/a2d code should never subtract a larger from a smaller.
// all of the BigInteger code assumes positive numbers. Proper
// handling would be to create a negative result here (and check for
// negative results everywhere).
}
result->setNumWords(biggerNum->numWords+1, true);
if (!isAdd && !comparedTo) // i.e. this - smallerNum == 0
{
result->setValue(0);
return result;
}
// do the math: loop over common words of both numbers, performing - or + and carrying the
// overflow/borrow forward to next word.
uint64 borrow = 0;
uint64 x;
int index;
for( index = 0; index < smallerNum->numWords; index++)
{
if (isAdd)
x = ((uint64)biggerNum->wordBuffer[index]) + smallerNum->wordBuffer[index] + borrow;
else
x = ((uint64)biggerNum->wordBuffer[index]) - smallerNum->wordBuffer[index] - borrow; // note x is unsigned. Ok even if result would be negative however
borrow = x >> 32 & (uint32)1;
result->wordBuffer[index] = (uint32)(x & 0xffffffff);
}
// loop over remaining words of the larger number, carying borrow/overflow forward
for( ; index < biggerNum->numWords; index++)
{
if (isAdd)
x = ((uint64)biggerNum->wordBuffer[index]) + borrow;
else
x = ((uint64)biggerNum->wordBuffer[index]) - borrow;
borrow = x >> 32 & (uint32)1;
result->wordBuffer[index] = (uint32)(x & 0xffffffff);
}
// handle final overflow if this is add
if (isAdd && borrow)
{
result->wordBuffer[index] = (uint32)(borrow & 0xffffffff);
index++;
}
// loop backwards over result, removing leading zeros from our numWords count
while( !(result->wordBuffer[--index]) )
{
}
result->numWords = index+1;
return result;
}
}

View File

@@ -1,256 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 __avmplus_BigInteger__
#define __avmplus_BigInteger__
//
// BigInteger is an implementation of arbitrary precision integers. This class is used by the
// D2A class in mathutils.h to print doubles to greater than 15 digits of precision. It has
// been implemented with that use in mind, so if you want to use it for some other purpose
// be aware that certain basic features have not been implemented: divide() assumes the result
// is a single digit, there is no support for negative values, and subtract() assumes that the
// term being subtracted from is larger than the operand.
//
// By far, memory allocation is the gating speed factor. D2A never uses more than 8 or so values
// during a given run, so a simple memoryCache is used to keep 8 temporaries around for quick reuse.
// This would likely have to be adjusted for more general use.
namespace avmplus
{
class BigInteger
{
public:
// Memory management
// --------------------------------------------------------
BigInteger()
{
numWords = 0;
}
~BigInteger()
{
}
inline void setFromInteger(int32 initVal)
{
wordBuffer[0] = initVal;
numWords = 1;
}
void setFromDouble(double value);
void setFromBigInteger(const BigInteger* from, int32 offset, int32 amount);
double doubleValueOf() const; // returns double approximation of this integer
// operations
// --------------------------------------------------------
// Compare (sum = this+offset) vs other. if sum > other, return 1. if sum < other,
// return -1, else return 0. Note that all terms are assumed to be positive.
int32 compare(const BigInteger *other) const;
// same as above, but compare this+offset with other.
int32 compareOffset(const BigInteger *other, const BigInteger *offset)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
add(offset,&tempInt);
return tempInt.compare(other);
}
// Add or subtract one BigInteger from another. isAdd determines if + or - is performed.
// If result is specified, write result into it (allows for reuse of temporaries), else
// allocate a new BigInteger for the result.
BigInteger* addOrSubtract(const BigInteger* other, bool isAdd, BigInteger* result) const;
// syntactic sugar for simple case of adding two BigIntegers
inline BigInteger* add(const BigInteger* other, BigInteger* result) const
{
return addOrSubtract(other, true, result);
}
// syntactic sugar for simple case of subtracting two BigIntegers
inline BigInteger* subtract(const BigInteger* other, BigInteger* result) const
{
return addOrSubtract(other, false, result);
}
// Increment this by other. other is assumed to be positive
inline void incrementBy(const BigInteger* other)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
addOrSubtract(other,true,&tempInt);
copyFrom(&tempInt);
}
// Decrement this by other. other is assumed to be positive and smaller than this.
inline void decrementBy(const BigInteger* other)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
addOrSubtract(other,false,&tempInt);
copyFrom(&tempInt);
}
// Shift a BigInteger by <shiftBy> bits to right or left. If
// result is not NULL, write result into it, else allocate a new BigInteger.
BigInteger* rshift(uint32 shiftBy, BigInteger* result) const;
BigInteger* lshift(uint32 shiftBy, BigInteger* result) const;
// Same as above but store result back into "this"
void lshiftBy(uint32 shiftBy)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
lshift(shiftBy,&tempInt);
copyFrom(&tempInt);
}
void rshiftBy(uint32 shiftBy)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
rshift(shiftBy,&tempInt);
copyFrom(&tempInt);
}
// Multiply this by an integer factor and add an integer increment. Store result back in this.
// Note, the addition is essentially free
void multAndIncrementBy( int32 factor, int32 addition);
inline void multBy( int32 factor)
{
multAndIncrementBy(factor,0);
}
// Shorthand for multiplying this by a double valued factor (and storing result back in this).
inline void multBy(double factor)
{
BigInteger bigFactor;
bigFactor.setFromDouble(factor);
multBy(&bigFactor);
}
// Multiply by another BigInteger. If optional arg result is not null, reuse it for
// result, else allocate a new result.
// (note, despite the name "smallerNum", argument does not need to be smaller than this).
BigInteger* mult(const BigInteger* other, BigInteger* result) const;
void multBy(const BigInteger *other)
{
BigInteger tempInt;
tempInt.setFromInteger(0);
mult(other,&tempInt);
copyFrom(&tempInt);
}
// divide this by divisor, put the remainder (i.e. this % divisor) into residual. If optional third argument result
// is not null, use it to store the result of the div, else allocate a new BigInteger for the result.
// Note: this has been hard to get right. If bugs do show up, use divideByReciprocalMethod instead
// Note2: this is optimized for the types of numerator/denominators generated by D2A. It will not work when
// the result would be a value bigger than 9. For general purpose BigInteger division, use divideByReciprocalMethod.
BigInteger* quickDivMod(const BigInteger* divisor, BigInteger* modResult, BigInteger* divResult);
/* Thought this would be faster than the above, but its not */
BigInteger* divideByReciprocalMethod(const BigInteger* divisor, BigInteger* modResult, BigInteger* divResult);
uint32 lg2() const;
// q = this->divBy(divisor) is equilvalent to: q = this->divMod(divisor,remainderResult); this = remainderResult;
BigInteger* divBy(const BigInteger* divisor, BigInteger* divResult);
// copy words from another BigInteger. By default, copy all words into this. If copyOffsetWords
// is not -1, then copy numCopyWords starting at word copyOffsetWords.
void copyFrom(const BigInteger *other, int32 copyOffsetWords=-1, int32 numCopyWords=-1)
{
int32 numCopy = (numCopyWords == -1) ? other->numWords : numCopyWords;
int32 copyOffset = (copyOffsetWords == -1) ? 0 : copyOffsetWords;
copyBuffer(other->wordBuffer+copyOffset, numCopy);
}
// Data members
// --------------------------------------------------------
static const int kMaxBigIntegerBufferSize=128;
uint32 wordBuffer[kMaxBigIntegerBufferSize];
int32 numWords;
private:
// sign; Simplifications are made assuming all numbers are positive
// Utility methods
// --------------------------------------------------------
// set value to a simple integer
inline void setValue(uint32 val)
{
this->numWords = 1;
this->wordBuffer[0] = val;
}
// copy wordBuffer from another BigInteger
inline void copyBuffer(const uint32 *newBuff, int32 size)
{
numWords = size;
AvmAssert(newBuff != wordBuffer);
AvmAssert(numWords <= kMaxBigIntegerBufferSize);
memcpy(wordBuffer, newBuff, numWords*sizeof(uint32));
}
inline void setNumWords( int32 newNumWords,bool initToZero=false)
{
int32 oldNumWords = numWords;
numWords = newNumWords;
AvmAssert(numWords <= kMaxBigIntegerBufferSize);
if (initToZero && oldNumWords < numWords)
{
for( int32 x = oldNumWords-1; x < numWords; x++)
wordBuffer[x] = 0;
}
}
// remove leading zero words from number.
inline void trimLeadingZeros()
{
int32 x;
for( x = numWords-1; x >= 0 && wordBuffer[x] == 0; x--)
;
this->numWords = (x == -1) ? 1 : x+1; // make sure a zero value has numWords = 1
}
};
}
#endif // __avmplus_BigInteger__

View File

@@ -1,157 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_BitSet__
#define __avmplus_BitSet__
namespace avmplus
{
/**
* Bit vectors are an efficent method of keeping True/False information
* on a set of items or conditions. Class BitSet provides functions
* to manipulate individual bits in the vector.
*
* Since most vectors are rather small an array of longs is used by
* default to house the value of the bits. If more bits are needed
* then an array is allocated dynamically outside of this object.
*
* This object is not optimized for a fixed sized bit vector
* it instead allows for dynamically growing the bit vector.
*/
class BitSet: public MMgc::GCFinalizedObject
{
public:
enum { kUnit = 8*sizeof(long),
kDefaultCapacity = 4 };
BitSet()
{
capacity = kDefaultCapacity;
for(int i=0; i<capacity; i++)
bits.ar[i] = 0;
}
~BitSet()
{
if (capacity > kDefaultCapacity)
delete [] bits.ptr;
capacity = 0;
}
void set(int bitNbr)
{
int index = bitNbr / kUnit;
int bit = bitNbr % kUnit;
if (index >= capacity)
grow(index+1);
if (capacity > kDefaultCapacity)
bits.ptr[index] |= (1<<bit);
else
bits.ar[index] |= (1<<bit);
}
void clear(int bitNbr)
{
int index = bitNbr / kUnit;
int bit = bitNbr % kUnit;
if (index < capacity)
{
if (capacity > kDefaultCapacity)
bits.ptr[index] &= ~(1<<bit);
else
bits.ar[index] &= ~(1<<bit);
}
}
bool get(int bitNbr) const
{
int index = bitNbr / kUnit;
int bit = bitNbr % kUnit;
bool value = false;
if (index < capacity)
{
if (capacity > kDefaultCapacity)
value = ( bits.ptr[index] & (1<<bit) ) ? true : false;
else
value = ( bits.ar[index] & (1<<bit) ) ? true : false;
}
return value;
}
private:
// Grow the array until at least newCapacity big
void grow(int newCapacity)
{
// create vector that is 2x bigger than requested
newCapacity *= 2;
//MEMTAG("BitVector::Grow - long[]");
long* newBits = new long[newCapacity];
// copy the old one
for(int i=0; i<capacity; i++)
{
if (capacity > kDefaultCapacity)
newBits[i] = bits.ptr[i];
else
newBits[i] = bits.ar[i];
}
// clear out the rest
for(int i=capacity; i<newCapacity; i++)
newBits[i] = 0;
// in with the new out with the old
if (capacity > kDefaultCapacity)
delete [] bits.ptr;
bits.ptr = newBits;
capacity = newCapacity;
}
// by default we use the array, but if the vector
// size grows beyond kDefaultCapacity we allocate
// space dynamically.
int capacity;
union
{
long ar[kDefaultCapacity];
long* ptr;
}
bits;
};
}
#endif /* __avmplus_BitSet__ */

View File

@@ -1,82 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 ***** */
package
{
public final class Boolean extends Object
{
// Boolean.length = 1 per ES3
// E262 {ReadOnly, DontDelete, DontEnum }
public static const length:int = 1
AS3 function toString():String {
return this ? "true" : "false"
}
AS3 function valueOf():Boolean { return this }
prototype.toString = function():String
{
if (this === prototype)
return "false"
if (!(this is Boolean)) {
// cause TypeError if this is not a Boolean value
// kInvokeOnIncompatibleObjectError
Error.throwError( TypeError, 1004, "Boolean.prototype.toString" );
}
return this ? "true" : "false"
}
prototype.valueOf = function()
{
if (this === prototype)
return false
if (!(this is Boolean)) {
// cause TypeError if this is not a Boolean value
// kInvokeOnIncompatibleObjectError
Error.throwError( TypeError, 1004, "Boolean.prototype.valueOf" );
}
return this;
}
// Dummy constructor function - This is neccessary so the compiler can do arg # checking for the ctor in strict mode
// The code for the actual ctor is in BooleanClass::construct in the avmplus
public function Boolean(value = void 0)
{}
_dontEnumPrototype(prototype);
}
}

View File

@@ -1,55 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
BEGIN_NATIVE_MAP(BooleanClass)
END_NATIVE_MAP()
BooleanClass::BooleanClass(VTable* cvtable)
: ClassClosure(cvtable)
{
toplevel()->booleanClass = this;
createVanillaPrototype();
}
Atom BooleanClass::construct(int argc, Atom* argv)
{
// TODO throw arg error if argc > 1
if (argc == 0)
return falseAtom;
else
return core()->booleanAtom(argv[1]);
}
}

View File

@@ -1,64 +0,0 @@
/* ***** 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 ] Adobe Systems Incorporated. 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 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 __avmplus_BooleanClass__
#define __avmplus_BooleanClass__
namespace avmplus
{
/**
* class Boolean
*/
class BooleanClass : public ClassClosure
{
public:
BooleanClass(VTable* vtable);
// this = argv[0] (ignored)
// arg1 = argv[1]
// argN = argv[argc]
Atom construct(int argc, Atom* argv);
// this = argv[0]
// arg1 = argv[1]
// argN = argv[argc]
Atom call(int argc, Atom* argv)
{
return construct(argc, argv);
}
DECLARE_NATIVE_MAP(BooleanClass)
};
}
#endif /* __avmplus_BooleanClass__ */

View File

@@ -1,150 +0,0 @@
/* ***** 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)[ 1993-2006 ] Adobe Systems Incorporated. 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 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 "avmplus.h"
namespace avmplus
{
BuiltinTraits::BuiltinTraits()
{
memset(this, 0, sizeof(BuiltinTraits));
}
// this is called after core types are defined. we don't want to do
// it earlier because we need Void and int
void BuiltinTraits::initInstanceTypes(PoolObject* pool)
{
AvmCore* core = pool->core;
class_itraits = pool->getBuiltinTraits(core->constantString("Class"));
namespace_itraits = pool->getBuiltinTraits(core->constantString("Namespace"));
function_itraits = pool->getBuiltinTraits(core->constantString("Function"));
boolean_itraits = pool->getBuiltinTraits(core->constantString("Boolean"));
number_itraits = pool->getBuiltinTraits(core->constantString("Number"));
int_itraits = pool->getBuiltinTraits(core->constantString("int"));
uint_itraits = pool->getBuiltinTraits(core->constantString("uint"));
string_itraits = pool->getBuiltinTraits(core->constantString("String"));
array_itraits = pool->getBuiltinTraits(core->constantString("Array"));
regexp_itraits = pool->getBuiltinTraits(core->constantString("RegExp"));
date_itraits = pool->getBuiltinTraits(core->constantString("Date"));
error_itraits = pool->getBuiltinTraits(core->constantString("Error"));
qName_itraits = pool->getBuiltinTraits(core->constantString("QName"));
xml_itraits = pool->getBuiltinTraits(core->constantString("XML"));
xmlList_itraits = pool->getBuiltinTraits(core->constantString("XMLList"));
null_itraits = core->newTraits(NULL, 0, 0, 0);
null_itraits->pool = pool;
null_itraits->ns = core->publicNamespace;
null_itraits->name = core->constantString("null");
null_itraits->final = true;
null_itraits->linked = true;
void_itraits = core->newTraits(NULL, 0, 0, 0);
void_itraits->pool = pool;
void_itraits->ns = core->publicNamespace;
void_itraits->name = core->constantString("void");
void_itraits->final = true;
void_itraits->linked = true;
// we have fast equality checks in the core that only work
// because these two classes are final. If they become non-final
// then these checks need to be updated to account for possible
// subclassing.
AvmAssert(xml_itraits->final);
AvmAssert(xmlList_itraits->final);
object_itraits->isMachineType = true;
void_itraits->isMachineType = true;
int_itraits->isMachineType = true;
uint_itraits->isMachineType = true;
boolean_itraits->isMachineType = true;
number_itraits->isMachineType = true;
int_itraits->isNumeric = true;
uint_itraits->isNumeric = true;
number_itraits->isNumeric = true;
// XML and XMLList are dynamic but do not need the
// standard dynamic hash table
xml_itraits->needsHashtable = false;
xmlList_itraits->needsHashtable = false;
// All these types including XML, XMLList and QName
// are marked as not derived objects.
//array_itraits->notDerivedObjectOrXML = true;
boolean_itraits->notDerivedObjectOrXML = true;
class_itraits->notDerivedObjectOrXML = true;
//date_itraits->notDerivedObjectOrXML = true;
function_itraits->notDerivedObjectOrXML = true;
namespace_itraits->notDerivedObjectOrXML= true;
null_itraits->notDerivedObjectOrXML = true;
number_itraits->notDerivedObjectOrXML = true;
int_itraits->notDerivedObjectOrXML = true;
uint_itraits->notDerivedObjectOrXML = true;
object_itraits->notDerivedObjectOrXML = true;
//regexp_itraits->notDerivedObjectOrXML = true;
string_itraits->notDerivedObjectOrXML = true;
//toplevel_itraits->notDerivedObjectOrXML = true;
void_itraits->notDerivedObjectOrXML = true;
xml_itraits->notDerivedObjectOrXML = true;
xmlList_itraits->notDerivedObjectOrXML = true;
qName_itraits->notDerivedObjectOrXML = true;
Traits* methodClosure_itraits;
methodClosure_itraits = pool->getBuiltinTraits(core->constantString("MethodClosure"));
methodClosure_itraits->notDerivedObjectOrXML = true;
}
void BuiltinTraits::initClassTypes(PoolObject* pool)
{
math_ctraits = findCTraits("Math$", pool);
number_ctraits = findCTraits("Number$", pool);
int_ctraits = findCTraits("int$", pool);
uint_ctraits = findCTraits("uint$", pool);
boolean_ctraits = findCTraits("Boolean$", pool);
string_ctraits = findCTraits("String$", pool);
}
Traits* BuiltinTraits::findCTraits(const char* cname, PoolObject* pool)
{
Stringp name = pool->core->constantString(cname);
for (int i=0, n=pool->cinits.capacity(); i < n; i++)
{
AbstractFunction* cinit = pool->cinits[i];
if (cinit && cinit->declaringTraits->name == name)
{
return cinit->declaringTraits;
}
}
return NULL;
}
}

Some files were not shown because too many files have changed in this diff Show More