Compare commits
2 Commits
test
...
Flash9_Dot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
592abc06d3 | ||
|
|
2f6322c88a |
217
mozilla/js/tamarin/MMgc/FixedAlloc.cpp
Normal file
217
mozilla/js/tamarin/MMgc/FixedAlloc.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
299
mozilla/js/tamarin/MMgc/FixedAlloc.h
Normal file
299
mozilla/js/tamarin/MMgc/FixedAlloc.h
Normal file
@@ -0,0 +1,299 @@
|
||||
/* ***** 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__ */
|
||||
141
mozilla/js/tamarin/MMgc/FixedMalloc.cpp
Normal file
141
mozilla/js/tamarin/MMgc/FixedMalloc.cpp
Normal file
@@ -0,0 +1,141 @@
|
||||
/* ***** 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];
|
||||
}
|
||||
}
|
||||
|
||||
154
mozilla/js/tamarin/MMgc/FixedMalloc.h
Normal file
154
mozilla/js/tamarin/MMgc/FixedMalloc.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/* ***** 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__ */
|
||||
2641
mozilla/js/tamarin/MMgc/GC.cpp
Normal file
2641
mozilla/js/tamarin/MMgc/GC.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1014
mozilla/js/tamarin/MMgc/GC.h
Normal file
1014
mozilla/js/tamarin/MMgc/GC.h
Normal file
File diff suppressed because it is too large
Load Diff
608
mozilla/js/tamarin/MMgc/GCAlloc.cpp
Normal file
608
mozilla/js/tamarin/MMgc/GCAlloc.cpp
Normal file
@@ -0,0 +1,608 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
342
mozilla/js/tamarin/MMgc/GCAlloc.h
Normal file
342
mozilla/js/tamarin/MMgc/GCAlloc.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/* ***** 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__ */
|
||||
71
mozilla/js/tamarin/MMgc/GCAllocBase.cpp
Normal file
71
mozilla/js/tamarin/MMgc/GCAllocBase.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/* ***** 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
|
||||
}
|
||||
105
mozilla/js/tamarin/MMgc/GCAllocBase.h
Normal file
105
mozilla/js/tamarin/MMgc/GCAllocBase.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/* ***** 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__ */
|
||||
59
mozilla/js/tamarin/MMgc/GCAllocObject.h
Normal file
59
mozilla/js/tamarin/MMgc/GCAllocObject.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ***** 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__ */
|
||||
81
mozilla/js/tamarin/MMgc/GCAllocObjectMac.cpp
Normal file
81
mozilla/js/tamarin/MMgc/GCAllocObjectMac.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/* ***** 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
|
||||
}
|
||||
|
||||
59
mozilla/js/tamarin/MMgc/GCAllocObjectUnix.cpp
Normal file
59
mozilla/js/tamarin/MMgc/GCAllocObjectUnix.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
|
||||
59
mozilla/js/tamarin/MMgc/GCAllocObjectWin.cpp
Normal file
59
mozilla/js/tamarin/MMgc/GCAllocObjectWin.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
|
||||
108
mozilla/js/tamarin/MMgc/GCDebug.h
Normal file
108
mozilla/js/tamarin/MMgc/GCDebug.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* ***** 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__ */
|
||||
123
mozilla/js/tamarin/MMgc/GCDebugMac.cpp
Normal file
123
mozilla/js/tamarin/MMgc/GCDebugMac.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
mozilla/js/tamarin/MMgc/GCDebugUnix.cpp
Normal file
54
mozilla/js/tamarin/MMgc/GCDebugUnix.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
103
mozilla/js/tamarin/MMgc/GCDebugWin.cpp
Normal file
103
mozilla/js/tamarin/MMgc/GCDebugWin.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* ***** 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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
174
mozilla/js/tamarin/MMgc/GCHashtable.cpp
Normal file
174
mozilla/js/tamarin/MMgc/GCHashtable.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
|
||||
114
mozilla/js/tamarin/MMgc/GCHashtable.h
Normal file
114
mozilla/js/tamarin/MMgc/GCHashtable.h
Normal file
@@ -0,0 +1,114 @@
|
||||
/* ***** 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
|
||||
|
||||
1170
mozilla/js/tamarin/MMgc/GCHeap.cpp
Normal file
1170
mozilla/js/tamarin/MMgc/GCHeap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
392
mozilla/js/tamarin/MMgc/GCHeap.h
Normal file
392
mozilla/js/tamarin/MMgc/GCHeap.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/* ***** 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__ */
|
||||
368
mozilla/js/tamarin/MMgc/GCHeapMac.cpp
Normal file
368
mozilla/js/tamarin/MMgc/GCHeapMac.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
/* ***** 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
|
||||
}
|
||||
320
mozilla/js/tamarin/MMgc/GCHeapUnix.cpp
Normal file
320
mozilla/js/tamarin/MMgc/GCHeapUnix.cpp
Normal file
@@ -0,0 +1,320 @@
|
||||
/* ***** 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
|
||||
}
|
||||
547
mozilla/js/tamarin/MMgc/GCHeapWin.cpp
Normal file
547
mozilla/js/tamarin/MMgc/GCHeapWin.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
/* ***** 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
|
||||
|
||||
}
|
||||
179
mozilla/js/tamarin/MMgc/GCLargeAlloc.cpp
Normal file
179
mozilla/js/tamarin/MMgc/GCLargeAlloc.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
177
mozilla/js/tamarin/MMgc/GCLargeAlloc.h
Normal file
177
mozilla/js/tamarin/MMgc/GCLargeAlloc.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/* ***** 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__ */
|
||||
546
mozilla/js/tamarin/MMgc/GCMemoryProfiler.cpp
Normal file
546
mozilla/js/tamarin/MMgc/GCMemoryProfiler.cpp
Normal file
@@ -0,0 +1,546 @@
|
||||
/* ***** 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
|
||||
216
mozilla/js/tamarin/MMgc/GCMemoryProfiler.h
Normal file
216
mozilla/js/tamarin/MMgc/GCMemoryProfiler.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/* ***** 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__
|
||||
|
||||
79
mozilla/js/tamarin/MMgc/GCObject.cpp
Normal file
79
mozilla/js/tamarin/MMgc/GCObject.cpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/* ***** 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
|
||||
}
|
||||
390
mozilla/js/tamarin/MMgc/GCObject.h
Normal file
390
mozilla/js/tamarin/MMgc/GCObject.h
Normal file
@@ -0,0 +1,390 @@
|
||||
/* ***** 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__ */
|
||||
101
mozilla/js/tamarin/MMgc/GCSpinLockLinux.h
Normal file
101
mozilla/js/tamarin/MMgc/GCSpinLockLinux.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* ***** 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__ */
|
||||
135
mozilla/js/tamarin/MMgc/GCSpinLockMac.h
Normal file
135
mozilla/js/tamarin/MMgc/GCSpinLockMac.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/* ***** 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__ */
|
||||
99
mozilla/js/tamarin/MMgc/GCSpinLockWin.h
Normal file
99
mozilla/js/tamarin/MMgc/GCSpinLockWin.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/* ***** 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__ */
|
||||
123
mozilla/js/tamarin/MMgc/GCStack.h
Normal file
123
mozilla/js/tamarin/MMgc/GCStack.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/* ***** 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__ */
|
||||
147
mozilla/js/tamarin/MMgc/GCTests.cpp
Normal file
147
mozilla/js/tamarin/MMgc/GCTests.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/* ***** 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();
|
||||
}
|
||||
}
|
||||
42
mozilla/js/tamarin/MMgc/GCTests.h
Normal file
42
mozilla/js/tamarin/MMgc/GCTests.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* ***** 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__ */
|
||||
94
mozilla/js/tamarin/MMgc/GCTypes.h
Normal file
94
mozilla/js/tamarin/MMgc/GCTypes.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* ***** 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__ */
|
||||
107
mozilla/js/tamarin/MMgc/GCWeakRef.h
Normal file
107
mozilla/js/tamarin/MMgc/GCWeakRef.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* ***** 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_
|
||||
32
mozilla/js/tamarin/MMgc/MMgc.cpp
Normal file
32
mozilla/js/tamarin/MMgc/MMgc.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/* ***** 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"
|
||||
151
mozilla/js/tamarin/MMgc/MMgc.h
Normal file
151
mozilla/js/tamarin/MMgc/MMgc.h
Normal file
@@ -0,0 +1,151 @@
|
||||
/* ***** 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__ */
|
||||
|
||||
BIN
mozilla/js/tamarin/MMgc/MMgc.mcp
Normal file
BIN
mozilla/js/tamarin/MMgc/MMgc.mcp
Normal file
Binary file not shown.
30
mozilla/js/tamarin/MMgc/MMgc.sln
Normal file
30
mozilla/js/tamarin/MMgc/MMgc.sln
Normal file
@@ -0,0 +1,30 @@
|
||||
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
|
||||
375
mozilla/js/tamarin/MMgc/MMgc.vcproj
Normal file
375
mozilla/js/tamarin/MMgc/MMgc.vcproj
Normal file
@@ -0,0 +1,375 @@
|
||||
<?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>
|
||||
28
mozilla/js/tamarin/MMgc/MMgc_8.sln
Normal file
28
mozilla/js/tamarin/MMgc/MMgc_8.sln
Normal file
@@ -0,0 +1,28 @@
|
||||
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
|
||||
531
mozilla/js/tamarin/MMgc/MMgc_8.vcproj
Normal file
531
mozilla/js/tamarin/MMgc/MMgc_8.vcproj
Normal file
@@ -0,0 +1,531 @@
|
||||
<?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>
|
||||
108
mozilla/js/tamarin/MMgc/Makefile
Normal file
108
mozilla/js/tamarin/MMgc/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
# ***** 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
|
||||
172
mozilla/js/tamarin/MMgc/Makefile.arm
Normal file
172
mozilla/js/tamarin/MMgc/Makefile.arm
Normal file
@@ -0,0 +1,172 @@
|
||||
# ***** 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
|
||||
189
mozilla/js/tamarin/MMgc/WriteBarrier.h
Normal file
189
mozilla/js/tamarin/MMgc/WriteBarrier.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/* ***** 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_
|
||||
79
mozilla/js/tamarin/MMgc/armbuild.h
Normal file
79
mozilla/js/tamarin/MMgc/armbuild.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* ***** 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
|
||||
87
mozilla/js/tamarin/MMgc/linuxbuild.h
Normal file
87
mozilla/js/tamarin/MMgc/linuxbuild.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* ***** 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
|
||||
95
mozilla/js/tamarin/MMgc/macbuild.h
Normal file
95
mozilla/js/tamarin/MMgc/macbuild.h
Normal file
@@ -0,0 +1,95 @@
|
||||
/* ***** 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
|
||||
95
mozilla/js/tamarin/MMgc/makecommon
Normal file
95
mozilla/js/tamarin/MMgc/makecommon
Normal file
@@ -0,0 +1,95 @@
|
||||
# ***** 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)
|
||||
67
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.cpp
Normal file
67
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
60
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.sln
Normal file
60
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.sln
Normal file
@@ -0,0 +1,60 @@
|
||||
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
|
||||
188
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.vcproj
Normal file
188
mozilla/js/tamarin/MMgc/run_alloc/run_alloc.vcproj
Normal file
@@ -0,0 +1,188 @@
|
||||
<?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>
|
||||
113
mozilla/js/tamarin/MMgc/winbuild.h
Normal file
113
mozilla/js/tamarin/MMgc/winbuild.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* ***** 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
|
||||
894
mozilla/js/tamarin/codegen/ArmAssembler.cpp
Normal file
894
mozilla/js/tamarin/codegen/ArmAssembler.cpp
Normal file
@@ -0,0 +1,894 @@
|
||||
/* ***** 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 */
|
||||
}
|
||||
207
mozilla/js/tamarin/codegen/ArmAssembler.h
Normal file
207
mozilla/js/tamarin/codegen/ArmAssembler.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/* ***** 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__ */
|
||||
9851
mozilla/js/tamarin/codegen/CodegenMIR.cpp
Normal file
9851
mozilla/js/tamarin/codegen/CodegenMIR.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1499
mozilla/js/tamarin/codegen/CodegenMIR.h
Normal file
1499
mozilla/js/tamarin/codegen/CodegenMIR.h
Normal file
File diff suppressed because it is too large
Load Diff
1135
mozilla/js/tamarin/codegen/Ia32Assembler.cpp
Normal file
1135
mozilla/js/tamarin/codegen/Ia32Assembler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1298
mozilla/js/tamarin/codegen/PpcAssembler.cpp
Normal file
1298
mozilla/js/tamarin/codegen/PpcAssembler.cpp
Normal file
File diff suppressed because it is too large
Load Diff
38
mozilla/js/tamarin/core/AbcData.cpp
Normal file
38
mozilla/js/tamarin/core/AbcData.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* ***** 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"
|
||||
}
|
||||
}
|
||||
58
mozilla/js/tamarin/core/AbcEnv.cpp
Normal file
58
mozilla/js/tamarin/core/AbcEnv.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
78
mozilla/js/tamarin/core/AbcEnv.h
Normal file
78
mozilla/js/tamarin/core/AbcEnv.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/* ***** 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__
|
||||
84
mozilla/js/tamarin/core/AbcGen.cpp
Normal file
84
mozilla/js/tamarin/core/AbcGen.cpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
mozilla/js/tamarin/core/AbcGen.h
Normal file
74
mozilla/js/tamarin/core/AbcGen.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* ***** 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__
|
||||
2027
mozilla/js/tamarin/core/AbcParser.cpp
Normal file
2027
mozilla/js/tamarin/core/AbcParser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
219
mozilla/js/tamarin/core/AbcParser.h
Normal file
219
mozilla/js/tamarin/core/AbcParser.h
Normal file
@@ -0,0 +1,219 @@
|
||||
/* ***** 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__
|
||||
433
mozilla/js/tamarin/core/AbstractFunction.cpp
Normal file
433
mozilla/js/tamarin/core/AbstractFunction.cpp
Normal file
@@ -0,0 +1,433 @@
|
||||
/* ***** 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
|
||||
}
|
||||
297
mozilla/js/tamarin/core/AbstractFunction.h
Normal file
297
mozilla/js/tamarin/core/AbstractFunction.h
Normal file
@@ -0,0 +1,297 @@
|
||||
/* ***** 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__ */
|
||||
37
mozilla/js/tamarin/core/Accessor.cpp
Normal file
37
mozilla/js/tamarin/core/Accessor.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* ***** 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
|
||||
{
|
||||
}
|
||||
52
mozilla/js/tamarin/core/Accessor.h
Normal file
52
mozilla/js/tamarin/core/Accessor.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/* ***** 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
|
||||
}
|
||||
};
|
||||
}
|
||||
116
mozilla/js/tamarin/core/ActionBlockConstants.cpp
Normal file
116
mozilla/js/tamarin/core/ActionBlockConstants.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/* ***** 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"
|
||||
}
|
||||
}
|
||||
131
mozilla/js/tamarin/core/ActionBlockConstants.h
Normal file
131
mozilla/js/tamarin/core/ActionBlockConstants.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/* ***** 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__ */
|
||||
427
mozilla/js/tamarin/core/Array.as
Normal file
427
mozilla/js/tamarin/core/Array.as
Normal file
@@ -0,0 +1,427 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
1605
mozilla/js/tamarin/core/ArrayClass.cpp
Normal file
1605
mozilla/js/tamarin/core/ArrayClass.cpp
Normal file
File diff suppressed because it is too large
Load Diff
98
mozilla/js/tamarin/core/ArrayClass.h
Normal file
98
mozilla/js/tamarin/core/ArrayClass.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/* ***** 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__ */
|
||||
504
mozilla/js/tamarin/core/ArrayObject.cpp
Normal file
504
mozilla/js/tamarin/core/ArrayObject.cpp
Normal file
@@ -0,0 +1,504 @@
|
||||
/* ***** 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();
|
||||
}
|
||||
}
|
||||
137
mozilla/js/tamarin/core/ArrayObject.h
Normal file
137
mozilla/js/tamarin/core/ArrayObject.h
Normal file
@@ -0,0 +1,137 @@
|
||||
/* ***** 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__ */
|
||||
304
mozilla/js/tamarin/core/AtomArray.cpp
Normal file
304
mozilla/js/tamarin/core/AtomArray.cpp
Normal file
@@ -0,0 +1,304 @@
|
||||
/* ***** 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
128
mozilla/js/tamarin/core/AtomArray.h
Normal file
128
mozilla/js/tamarin/core/AtomArray.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/* ***** 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__ */
|
||||
38
mozilla/js/tamarin/core/AtomConstants.cpp
Normal file
38
mozilla/js/tamarin/core/AtomConstants.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/* ***** 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
|
||||
{
|
||||
}
|
||||
|
||||
142
mozilla/js/tamarin/core/AtomConstants.h
Normal file
142
mozilla/js/tamarin/core/AtomConstants.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/* ***** 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__ */
|
||||
89
mozilla/js/tamarin/core/AtomWriteBarrier.h
Normal file
89
mozilla/js/tamarin/core/AtomWriteBarrier.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* ***** 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__ */
|
||||
3697
mozilla/js/tamarin/core/AvmCore.cpp
Normal file
3697
mozilla/js/tamarin/core/AvmCore.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1259
mozilla/js/tamarin/core/AvmCore.h
Normal file
1259
mozilla/js/tamarin/core/AvmCore.h
Normal file
File diff suppressed because it is too large
Load Diff
109
mozilla/js/tamarin/core/AvmDebug.h
Normal file
109
mozilla/js/tamarin/core/AvmDebug.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/* ***** 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__ */
|
||||
98
mozilla/js/tamarin/core/AvmDebugWin.cpp
Normal file
98
mozilla/js/tamarin/core/AvmDebugWin.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/* ***** 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
44
mozilla/js/tamarin/core/AvmError.h
Normal file
44
mozilla/js/tamarin/core/AvmError.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* ***** 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__ */
|
||||
39
mozilla/js/tamarin/core/AvmPlusScriptableObject.cpp
Normal file
39
mozilla/js/tamarin/core/AvmPlusScriptableObject.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/* ***** 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
|
||||
{
|
||||
}
|
||||
47
mozilla/js/tamarin/core/AvmPlusScriptableObject.h
Normal file
47
mozilla/js/tamarin/core/AvmPlusScriptableObject.h
Normal file
@@ -0,0 +1,47 @@
|
||||
/* ***** 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__
|
||||
636
mozilla/js/tamarin/core/BigInteger.cpp
Normal file
636
mozilla/js/tamarin/core/BigInteger.cpp
Normal file
@@ -0,0 +1,636 @@
|
||||
/* ***** 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
256
mozilla/js/tamarin/core/BigInteger.h
Normal file
256
mozilla/js/tamarin/core/BigInteger.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* ***** 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__
|
||||
|
||||
157
mozilla/js/tamarin/core/BitSet.h
Normal file
157
mozilla/js/tamarin/core/BitSet.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/* ***** 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__ */
|
||||
82
mozilla/js/tamarin/core/Boolean.as
Normal file
82
mozilla/js/tamarin/core/Boolean.as
Normal file
@@ -0,0 +1,82 @@
|
||||
/* ***** 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);
|
||||
}
|
||||
}
|
||||
55
mozilla/js/tamarin/core/BooleanClass.cpp
Normal file
55
mozilla/js/tamarin/core/BooleanClass.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ***** 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]);
|
||||
}
|
||||
}
|
||||
64
mozilla/js/tamarin/core/BooleanClass.h
Normal file
64
mozilla/js/tamarin/core/BooleanClass.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/* ***** 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__ */
|
||||
150
mozilla/js/tamarin/core/BuiltinTraits.cpp
Normal file
150
mozilla/js/tamarin/core/BuiltinTraits.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/* ***** 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