Compare commits
3 Commits
Flash9_Dot
...
Bugzilla_P
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b52a1dc48a | ||
|
|
48b5f960fd | ||
|
|
73bf11394f |
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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__ */
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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__ */
|
||||
@@ -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_
|
||||
@@ -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"
|
||||
@@ -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.
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
}
|
||||
@@ -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
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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__
|
||||
@@ -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
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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 environment’s 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(k–1).
|
||||
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
@@ -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__ */
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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
@@ -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__ */
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
@@ -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__
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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__
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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
Reference in New Issue
Block a user