зеркало из https://github.com/mozilla/pjs.git
Back out bug 684039.
--HG-- rename : js/src/ds/LifoAlloc.h => js/src/jsarena.h
This commit is contained in:
Родитель
97e6ad5d4e
Коммит
926c13f10e
|
@ -59,6 +59,7 @@
|
|||
#include "nsDOMError.h"
|
||||
#include "nsDOMCID.h"
|
||||
#include "jsdbgapi.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsobj.h"
|
||||
#include "nsIXPConnect.h"
|
||||
|
|
|
@ -199,33 +199,6 @@ nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsRootedJSValueArray {
|
||||
public:
|
||||
explicit nsRootedJSValueArray(JSContext *cx) : avr(cx, vals.Length(), vals.Elements()) {}
|
||||
|
||||
PRBool SetCapacity(JSContext *cx, size_t capacity) {
|
||||
PRBool ok = vals.SetCapacity(capacity);
|
||||
if (!ok)
|
||||
return PR_FALSE;
|
||||
// Values must be safe for the GC to inspect (they must not contain garbage).
|
||||
memset(vals.Elements(), 0, vals.SizeOf());
|
||||
resetRooter(cx);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
jsval *Elements() {
|
||||
return vals.Elements();
|
||||
}
|
||||
|
||||
private:
|
||||
void resetRooter(JSContext *cx) {
|
||||
avr.changeArray(vals.Elements(), vals.Length());
|
||||
}
|
||||
|
||||
nsAutoTArray<jsval, 16> vals;
|
||||
js::AutoArrayRooter avr;
|
||||
};
|
||||
|
||||
/****************************************************************
|
||||
************************** AutoFree ****************************
|
||||
****************************************************************/
|
||||
|
@ -245,6 +218,15 @@ private:
|
|||
void *mPtr;
|
||||
};
|
||||
|
||||
class nsAutoPoolRelease {
|
||||
public:
|
||||
nsAutoPoolRelease(JSArenaPool *p, void *m) : mPool(p), mMark(m) {}
|
||||
~nsAutoPoolRelease() { JS_ARENA_RELEASE(mPool, mMark); }
|
||||
private:
|
||||
JSArenaPool *mPool;
|
||||
void *mMark;
|
||||
};
|
||||
|
||||
// A utility function for script languages to call. Although it looks small,
|
||||
// the use of nsIDocShell and nsPresContext triggers a huge number of
|
||||
// dependencies that most languages would not otherwise need.
|
||||
|
@ -1930,14 +1912,16 @@ nsJSContext::CallEventHandler(nsISupports* aTarget, void *aScope, void *aHandler
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
Maybe<nsRootedJSValueArray> tempStorage;
|
||||
Maybe<nsAutoPoolRelease> poolRelease;
|
||||
Maybe<js::AutoArrayRooter> tvr;
|
||||
|
||||
// Use |target| as the scope for wrapping the arguments, since aScope is
|
||||
// the safe scope in many cases, which isn't very useful. Wrapping aTarget
|
||||
// was OK because those typically have PreCreate methods that give them the
|
||||
// right scope anyway, and we want to make sure that the arguments end up
|
||||
// in the same scope as aTarget.
|
||||
rv = ConvertSupportsTojsvals(aargv, target, &argc, &argv, tempStorage);
|
||||
rv = ConvertSupportsTojsvals(aargv, target, &argc,
|
||||
&argv, poolRelease, tvr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
++mExecuteDepth;
|
||||
|
@ -2359,10 +2343,12 @@ nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArg
|
|||
|
||||
JSAutoRequest ar(mContext);
|
||||
|
||||
Maybe<nsRootedJSValueArray> tempStorage;
|
||||
Maybe<nsAutoPoolRelease> poolRelease;
|
||||
Maybe<js::AutoArrayRooter> tvr;
|
||||
|
||||
nsresult rv;
|
||||
rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc, &argv, tempStorage);
|
||||
rv = ConvertSupportsTojsvals(aArgs, GetNativeGlobal(), &argc,
|
||||
&argv, poolRelease, tvr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
jsval vargs;
|
||||
|
@ -2398,7 +2384,8 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
|
|||
void *aScope,
|
||||
PRUint32 *aArgc,
|
||||
jsval **aArgv,
|
||||
Maybe<nsRootedJSValueArray> &aTempStorage)
|
||||
Maybe<nsAutoPoolRelease> &aPoolRelease,
|
||||
Maybe<js::AutoArrayRooter> &aRooter)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -2433,11 +2420,16 @@ nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
|
|||
argCount = 1; // the nsISupports which is not an array
|
||||
}
|
||||
|
||||
void *mark = JS_ARENA_MARK(&mContext->tempPool);
|
||||
jsval *argv;
|
||||
size_t nbytes = argCount * sizeof(jsval);
|
||||
JS_ARENA_ALLOCATE_CAST(argv, jsval *, &mContext->tempPool, nbytes);
|
||||
NS_ENSURE_TRUE(argv, NS_ERROR_OUT_OF_MEMORY);
|
||||
memset(argv, 0, nbytes); /* initialize so GC-able */
|
||||
|
||||
// Use the caller's auto guards to release and unroot.
|
||||
aTempStorage.construct(mContext);
|
||||
PRBool ok = aTempStorage.ref().SetCapacity(mContext, argCount);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
|
||||
jsval *argv = aTempStorage.ref().Elements();
|
||||
aPoolRelease.construct(&mContext->tempPool, mark);
|
||||
aRooter.construct(mContext, argCount, argv);
|
||||
|
||||
if (argsArray) {
|
||||
for (argCtr = 0; argCtr < argCount && NS_SUCCEEDED(rv); argCtr++) {
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
#include "nsScriptNameSpaceManager.h"
|
||||
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
class nsRootedJSValueArray;
|
||||
class nsAutoPoolRelease;
|
||||
namespace js {
|
||||
class AutoArrayRooter;
|
||||
}
|
||||
|
@ -204,7 +204,8 @@ protected:
|
|||
void *aScope,
|
||||
PRUint32 *aArgc,
|
||||
jsval **aArgv,
|
||||
mozilla::Maybe<nsRootedJSValueArray> &aPoolRelease);
|
||||
mozilla::Maybe<nsAutoPoolRelease> &aPoolRelease,
|
||||
mozilla::Maybe<js::AutoArrayRooter> &aRooter);
|
||||
|
||||
nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, jsval *aArgv);
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ CPPSRCS = \
|
|||
jsalloc.cpp \
|
||||
jsanalyze.cpp \
|
||||
jsapi.cpp \
|
||||
jsarena.cpp \
|
||||
jsarray.cpp \
|
||||
jsatom.cpp \
|
||||
jsbool.cpp \
|
||||
|
@ -160,7 +161,6 @@ CPPSRCS = \
|
|||
Stack.cpp \
|
||||
String.cpp \
|
||||
ParseMaps.cpp \
|
||||
LifoAlloc.cpp \
|
||||
Unicode.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
@ -174,6 +174,7 @@ INSTALLED_HEADERS = \
|
|||
js.msg \
|
||||
jsalloc.h \
|
||||
jsapi.h \
|
||||
jsarena.h \
|
||||
jsatom.h \
|
||||
jsbit.h \
|
||||
jsclass.h \
|
||||
|
@ -240,10 +241,9 @@ INSTALLED_HEADERS = \
|
|||
VPATH += \
|
||||
$(srcdir)/vm \
|
||||
$(srcdir)/frontend \
|
||||
$(srcdir)/ds \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = vm ds
|
||||
EXPORTS_NAMESPACES = vm
|
||||
|
||||
EXPORTS_vm = \
|
||||
ArgumentsObject.h \
|
||||
|
@ -255,9 +255,6 @@ EXPORTS_vm = \
|
|||
Unicode.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_ds = \
|
||||
LifoAlloc.h
|
||||
|
||||
###############################################
|
||||
# BEGIN include sources for low-level code shared with Gecko
|
||||
#
|
||||
|
|
|
@ -1,149 +0,0 @@
|
|||
#include "LifoAlloc.h"
|
||||
|
||||
#include <new>
|
||||
|
||||
using namespace js;
|
||||
|
||||
namespace js {
|
||||
namespace detail {
|
||||
|
||||
BumpChunk *
|
||||
BumpChunk::new_(size_t chunkSize)
|
||||
{
|
||||
JS_ASSERT(RoundUpPow2(chunkSize) == chunkSize);
|
||||
void *mem = js_malloc(chunkSize);
|
||||
if (!mem)
|
||||
return NULL;
|
||||
BumpChunk *result = new (mem) BumpChunk(chunkSize - sizeof(BumpChunk));
|
||||
|
||||
/*
|
||||
* We assume that the alignment of sAlign is less than that of
|
||||
* the underlying memory allocator -- creating a new BumpChunk should
|
||||
* always satisfy the sAlign alignment constraint.
|
||||
*/
|
||||
JS_ASSERT(AlignPtr(result->bump) == result->bump);
|
||||
return result;
|
||||
}
|
||||
|
||||
void *
|
||||
BumpChunk::tryAllocUnaligned(size_t n)
|
||||
{
|
||||
char *oldBump = bump;
|
||||
char *newBump = bump + n;
|
||||
if (newBump > limit)
|
||||
return NULL;
|
||||
|
||||
setBump(newBump);
|
||||
return oldBump;
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace js */
|
||||
|
||||
void
|
||||
LifoAlloc::freeAll()
|
||||
{
|
||||
while (first) {
|
||||
BumpChunk *victim = first;
|
||||
first = first->next();
|
||||
BumpChunk::delete_(victim);
|
||||
}
|
||||
first = latest = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
LifoAlloc::freeUnused()
|
||||
{
|
||||
/* Don't free anything if we have outstanding marks. */
|
||||
if (markCount || !first)
|
||||
return;
|
||||
|
||||
JS_ASSERT(first && latest);
|
||||
|
||||
/* Rewind through any unused chunks. */
|
||||
if (!latest->used()) {
|
||||
BumpChunk *lastUsed = NULL;
|
||||
for (BumpChunk *it = first; it != latest; it = it->next()) {
|
||||
if (it->used())
|
||||
lastUsed = it;
|
||||
}
|
||||
if (!lastUsed) {
|
||||
freeAll();
|
||||
return;
|
||||
}
|
||||
latest = lastUsed;
|
||||
}
|
||||
|
||||
/* Free all chunks after |latest|. */
|
||||
size_t freed = 0;
|
||||
for (BumpChunk *victim = latest->next(); victim; victim = victim->next()) {
|
||||
BumpChunk::delete_(victim);
|
||||
freed++;
|
||||
}
|
||||
}
|
||||
|
||||
LifoAlloc::BumpChunk *
|
||||
LifoAlloc::getOrCreateChunk(size_t n)
|
||||
{
|
||||
if (first) {
|
||||
/* Look for existing, unused BumpChunks to satisfy the request. */
|
||||
while (latest->next()) {
|
||||
latest = latest->next();
|
||||
latest->resetBump(); /* This was an unused BumpChunk on the chain. */
|
||||
if (latest->canAlloc(n))
|
||||
return latest;
|
||||
}
|
||||
}
|
||||
|
||||
size_t defaultChunkFreeSpace = defaultChunkSize_ - sizeof(BumpChunk);
|
||||
size_t chunkSize = n > defaultChunkFreeSpace
|
||||
? RoundUpPow2(n + sizeof(BumpChunk))
|
||||
: defaultChunkSize_;
|
||||
|
||||
/* If we get here, we couldn't find an existing BumpChunk to fill the request. */
|
||||
BumpChunk *newChunk = BumpChunk::new_(chunkSize);
|
||||
if (!newChunk)
|
||||
return NULL;
|
||||
if (!first) {
|
||||
latest = first = newChunk;
|
||||
} else {
|
||||
JS_ASSERT(latest && !latest->next());
|
||||
latest->setNext(newChunk);
|
||||
latest = newChunk;
|
||||
}
|
||||
return newChunk;
|
||||
}
|
||||
|
||||
void *
|
||||
LifoAlloc::allocUnaligned(size_t n)
|
||||
{
|
||||
void *result;
|
||||
if (latest && (result = latest->tryAllocUnaligned(n)))
|
||||
return result;
|
||||
|
||||
return alloc(n);
|
||||
}
|
||||
|
||||
void *
|
||||
LifoAlloc::reallocUnaligned(void *origPtr, size_t origSize, size_t incr)
|
||||
{
|
||||
JS_ASSERT(first && latest);
|
||||
|
||||
/*
|
||||
* Maybe we can grow the latest allocation in a BumpChunk.
|
||||
*
|
||||
* Note: we could also realloc the whole BumpChunk in the !canAlloc
|
||||
* case, but this should not be a frequently hit case.
|
||||
*/
|
||||
if (latest
|
||||
&& origPtr == (char *) latest->mark() - origSize
|
||||
&& latest->canAllocUnaligned(incr)) {
|
||||
JS_ALWAYS_TRUE(allocUnaligned(incr));
|
||||
return origPtr;
|
||||
}
|
||||
|
||||
/* Otherwise, memcpy. */
|
||||
size_t newSize = origSize + incr;
|
||||
void *newPtr = allocUnaligned(newSize);
|
||||
return newPtr ? memcpy(newPtr, origPtr, origSize) : NULL;
|
||||
}
|
|
@ -1,339 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* June 12, 2009.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Leary <cdleary@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef LifoAlloc_h__
|
||||
#define LifoAlloc_h__
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* This data structure supports stacky LIFO allocation (mark/release and
|
||||
* LifoAllocScope). It does not maintain one contiguous segment; instead, it
|
||||
* maintains a bunch of linked memory segments. In order to prevent malloc/free
|
||||
* thrashing, unused segments are deallocated when garbage collection occurs.
|
||||
*/
|
||||
|
||||
#include "jsutil.h"
|
||||
#include "jstl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
namespace detail {
|
||||
|
||||
static const size_t LIFO_ALLOC_ALIGN = 8;
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
char *
|
||||
AlignPtr(void *orig)
|
||||
{
|
||||
typedef typename tl::StaticAssert<
|
||||
tl::FloorLog2<LIFO_ALLOC_ALIGN>::result == tl::CeilingLog2<LIFO_ALLOC_ALIGN>::result
|
||||
>::result _;
|
||||
|
||||
char *result = (char *) ((uintptr_t(orig) + (LIFO_ALLOC_ALIGN - 1)) & -LIFO_ALLOC_ALIGN);
|
||||
JS_ASSERT(uintptr_t(result) % LIFO_ALLOC_ALIGN == 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Header for a chunk of memory wrangled by the LifoAlloc. */
|
||||
class BumpChunk
|
||||
{
|
||||
char *bump;
|
||||
char *limit;
|
||||
BumpChunk *next_;
|
||||
size_t bumpSpaceSize;
|
||||
|
||||
char *base() const { return limit - bumpSpaceSize; }
|
||||
|
||||
explicit BumpChunk(size_t bumpSpaceSize)
|
||||
: bump(reinterpret_cast<char *>(this) + sizeof(BumpChunk)), limit(bump + bumpSpaceSize),
|
||||
next_(NULL), bumpSpaceSize(bumpSpaceSize) {
|
||||
JS_ASSERT(bump == AlignPtr(bump));
|
||||
}
|
||||
|
||||
void clobberUnused() {
|
||||
#ifdef DEBUG
|
||||
memset(bump, 0xcd, limit - bump);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setBump(void *ptr) {
|
||||
JS_ASSERT(base() <= ptr);
|
||||
JS_ASSERT(ptr <= limit);
|
||||
DebugOnly<char *> prevBump = bump;
|
||||
bump = static_cast<char *>(ptr);
|
||||
if (prevBump < bump)
|
||||
clobberUnused();
|
||||
}
|
||||
|
||||
public:
|
||||
BumpChunk *next() const { return next_; }
|
||||
void setNext(BumpChunk *succ) { next_ = succ; }
|
||||
|
||||
size_t used() const { return bump - base(); }
|
||||
|
||||
void resetBump() {
|
||||
setBump(reinterpret_cast<char *>(this) + sizeof(BumpChunk));
|
||||
}
|
||||
|
||||
void *mark() const { return bump; }
|
||||
|
||||
void release(void *mark) {
|
||||
JS_ASSERT(contains(mark));
|
||||
JS_ASSERT(mark <= bump);
|
||||
setBump(mark);
|
||||
}
|
||||
|
||||
bool contains(void *mark) const {
|
||||
return base() <= mark && mark <= limit;
|
||||
}
|
||||
|
||||
bool canAlloc(size_t n) {
|
||||
return AlignPtr(bump) + n <= limit;
|
||||
}
|
||||
|
||||
bool canAllocUnaligned(size_t n) {
|
||||
return bump + n <= limit;
|
||||
}
|
||||
|
||||
/* Try to perform an allocation of size |n|, return null if not possible. */
|
||||
JS_ALWAYS_INLINE
|
||||
void *tryAlloc(size_t n) {
|
||||
char *aligned = AlignPtr(bump);
|
||||
char *newBump = aligned + n;
|
||||
if (newBump > limit)
|
||||
return NULL;
|
||||
|
||||
setBump(newBump);
|
||||
return aligned;
|
||||
}
|
||||
|
||||
void *tryAllocUnaligned(size_t n);
|
||||
|
||||
void *allocInfallible(size_t n) {
|
||||
void *result = tryAlloc(n);
|
||||
JS_ASSERT(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
static BumpChunk *new_(size_t chunkSize);
|
||||
|
||||
static void delete_(BumpChunk *chunk) {
|
||||
#ifdef DEBUG
|
||||
memset(chunk, 0xcd, sizeof(*chunk) + chunk->bumpSpaceSize);
|
||||
#endif
|
||||
js_free(chunk);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/*
|
||||
* LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
|
||||
*
|
||||
* Note: |latest| is not necessary "last". We leave BumpChunks latent in the
|
||||
* chain after they've been released to avoid thrashing before a GC.
|
||||
*/
|
||||
class LifoAlloc
|
||||
{
|
||||
typedef detail::BumpChunk BumpChunk;
|
||||
|
||||
BumpChunk *first;
|
||||
BumpChunk *latest;
|
||||
size_t markCount;
|
||||
size_t defaultChunkSize_;
|
||||
|
||||
void operator=(const LifoAlloc &);
|
||||
LifoAlloc(const LifoAlloc &);
|
||||
|
||||
/*
|
||||
* Return a BumpChunk that can perform an allocation of at least size |n|
|
||||
* and add it to the chain appropriately.
|
||||
*
|
||||
* Side effect: if retval is non-null, |first| and |latest| are initialized
|
||||
* appropriately.
|
||||
*/
|
||||
BumpChunk *getOrCreateChunk(size_t n);
|
||||
|
||||
void reset(size_t defaultChunkSize) {
|
||||
JS_ASSERT(RoundUpPow2(defaultChunkSize) == defaultChunkSize);
|
||||
first = latest = NULL;
|
||||
defaultChunkSize_ = defaultChunkSize;
|
||||
markCount = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit LifoAlloc(size_t defaultChunkSize) { reset(defaultChunkSize); }
|
||||
|
||||
/* Steal allocated chunks from |other|. */
|
||||
void steal(LifoAlloc *other) {
|
||||
JS_ASSERT(!other->markCount);
|
||||
PodCopy((char *) this, (char *) other, sizeof(*this));
|
||||
other->reset(defaultChunkSize_);
|
||||
}
|
||||
|
||||
~LifoAlloc() { freeAll(); }
|
||||
|
||||
size_t defaultChunkSize() const { return defaultChunkSize_; }
|
||||
|
||||
/* Frees all held memory. */
|
||||
void freeAll();
|
||||
|
||||
/* Should be called on GC in order to release any held chunks. */
|
||||
void freeUnused();
|
||||
|
||||
JS_ALWAYS_INLINE
|
||||
void *alloc(size_t n) {
|
||||
void *result;
|
||||
if (latest && (result = latest->tryAlloc(n)))
|
||||
return result;
|
||||
|
||||
if (!getOrCreateChunk(n))
|
||||
return NULL;
|
||||
|
||||
return latest->allocInfallible(n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T *newArray(size_t count) {
|
||||
void *mem = alloc(sizeof(T) * count);
|
||||
if (!mem)
|
||||
return NULL;
|
||||
JS_STATIC_ASSERT(tl::IsPodType<T>::result);
|
||||
return (T *) mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an array with uninitialized elements of type |T|.
|
||||
* The caller is responsible for initialization.
|
||||
*/
|
||||
template <typename T>
|
||||
T *newArrayUninitialized(size_t count) {
|
||||
return static_cast<T *>(alloc(sizeof(T) * count));
|
||||
}
|
||||
|
||||
void *mark() {
|
||||
markCount++;
|
||||
|
||||
return latest ? latest->mark() : NULL;
|
||||
}
|
||||
|
||||
void release(void *mark) {
|
||||
markCount--;
|
||||
|
||||
if (!mark) {
|
||||
latest = first;
|
||||
if (latest)
|
||||
latest->resetBump();
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the chunk that contains |mark|, and make sure we don't pass
|
||||
* |latest| along the way -- we should be making the chain of active
|
||||
* chunks shorter, not longer!
|
||||
*/
|
||||
BumpChunk *container = first;
|
||||
while (true) {
|
||||
if (container->contains(mark))
|
||||
break;
|
||||
JS_ASSERT(container != latest);
|
||||
container = container->next();
|
||||
}
|
||||
latest = container;
|
||||
latest->release(mark);
|
||||
}
|
||||
|
||||
/* Get the total "used" (occupied bytes) count for the arena chunks. */
|
||||
size_t used() const {
|
||||
size_t accum = 0;
|
||||
BumpChunk *it = first;
|
||||
while (it) {
|
||||
accum += it->used();
|
||||
it = it->next();
|
||||
}
|
||||
return accum;
|
||||
}
|
||||
|
||||
/* Doesn't perform construction; useful for lazily-initialized POD types. */
|
||||
template <typename T>
|
||||
JS_ALWAYS_INLINE
|
||||
T *newPod() {
|
||||
return static_cast<T *>(alloc(sizeof(T)));
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(alloc, JS_ALWAYS_INLINE)
|
||||
|
||||
/* Some legacy clients (ab)use LifoAlloc to act like a vector, see bug 688891. */
|
||||
|
||||
void *allocUnaligned(size_t n);
|
||||
void *reallocUnaligned(void *origPtr, size_t origSize, size_t incr);
|
||||
};
|
||||
|
||||
class LifoAllocScope {
|
||||
LifoAlloc *lifoAlloc;
|
||||
void *mark;
|
||||
bool shouldRelease;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit LifoAllocScope(LifoAlloc *lifoAlloc
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: lifoAlloc(lifoAlloc), shouldRelease(true) {
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
mark = lifoAlloc->mark();
|
||||
}
|
||||
|
||||
~LifoAllocScope() {
|
||||
if (shouldRelease)
|
||||
lifoAlloc->release(mark);
|
||||
}
|
||||
|
||||
void releaseEarly() {
|
||||
JS_ASSERT(shouldRelease);
|
||||
lifoAlloc->release(mark);
|
||||
shouldRelease = false;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
|
@ -39,7 +39,6 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "ParseMaps-inl.h"
|
||||
#include "jscompartment.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
|
@ -126,12 +125,13 @@ DumpAtomDefnMap(const AtomDefnMapPtr &map)
|
|||
AtomDeclNode *
|
||||
AtomDecls::allocNode(JSDefinition *defn)
|
||||
{
|
||||
AtomDeclNode *p = cx->tempLifoAlloc().new_<AtomDeclNode>(defn);
|
||||
AtomDeclNode *p;
|
||||
JS_ARENA_ALLOCATE_TYPE(p, AtomDeclNode, &cx->tempPool);
|
||||
if (!p) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
return new (p) AtomDeclNode(defn);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -109,7 +109,8 @@ Bytecode::mergeDefines(JSContext *cx, ScriptAnalysis *script, bool initial,
|
|||
* with progressively smaller sets of defined variables.
|
||||
*/
|
||||
if (!owned) {
|
||||
uint32 *reallocArray = cx->typeLifoAlloc().newArray<uint32>(defineCount);
|
||||
uint32 *reallocArray =
|
||||
ArenaArray<uint32>(cx->compartment->pool, defineCount);
|
||||
if (!reallocArray) {
|
||||
script->setOOM(cx);
|
||||
return false;
|
||||
|
@ -133,11 +134,12 @@ void
|
|||
PrintBytecode(JSContext *cx, JSScript *script, jsbytecode *pc)
|
||||
{
|
||||
printf("#%u:", script->id());
|
||||
LifoAlloc lifoAlloc(1024);
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &lifoAlloc, 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
js_Disassemble1(cx, script, pc, pc - script->code, true, &sprinter);
|
||||
fprintf(stdout, "%s", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -155,7 +157,7 @@ ScriptAnalysis::addJump(JSContext *cx, unsigned offset,
|
|||
Bytecode *&code = codeArray[offset];
|
||||
bool initial = (code == NULL);
|
||||
if (initial) {
|
||||
code = cx->typeLifoAlloc().new_<Bytecode>();
|
||||
code = ArenaNew<Bytecode>(cx->compartment->pool);
|
||||
if (!code) {
|
||||
setOOM(cx);
|
||||
return false;
|
||||
|
@ -276,16 +278,16 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
|||
{
|
||||
JS_ASSERT(cx->compartment->activeAnalysis);
|
||||
JS_ASSERT(!ranBytecode());
|
||||
LifoAlloc &tla = cx->typeLifoAlloc();
|
||||
JSArenaPool &pool = cx->compartment->pool;
|
||||
|
||||
unsigned length = script->length;
|
||||
unsigned nargs = script->hasFunction ? script->function()->nargs : 0;
|
||||
|
||||
numSlots = TotalSlots(script);
|
||||
|
||||
codeArray = tla.newArray<Bytecode*>(length);
|
||||
definedLocals = tla.newArray<uint32>(script->nfixed);
|
||||
escapedSlots = tla.newArray<JSPackedBool>(numSlots);
|
||||
codeArray = ArenaArray<Bytecode*>(pool, length);
|
||||
definedLocals = ArenaArray<uint32>(pool, script->nfixed);
|
||||
escapedSlots = ArenaArray<JSPackedBool>(pool, numSlots);
|
||||
|
||||
if (!codeArray || !definedLocals || !escapedSlots) {
|
||||
setOOM(cx);
|
||||
|
@ -369,7 +371,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
|||
unsigned forwardCatch = 0;
|
||||
|
||||
/* Fill in stack depth and definitions at initial bytecode. */
|
||||
Bytecode *startcode = tla.new_<Bytecode>();
|
||||
Bytecode *startcode = ArenaNew<Bytecode>(pool);
|
||||
if (!startcode) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -701,7 +703,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
|||
if (definedLocals[local] == LOCAL_CONDITIONALLY_DEFINED) {
|
||||
if (forwardJump) {
|
||||
/* Add this local to the variables defined after this bytecode. */
|
||||
uint32 *newArray = tla.newArray<uint32>(defineCount + 1);
|
||||
uint32 *newArray = ArenaArray<uint32>(pool, defineCount + 1);
|
||||
if (!newArray) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -793,7 +795,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
|||
bool initial = (nextcode == NULL);
|
||||
|
||||
if (initial) {
|
||||
nextcode = tla.new_<Bytecode>();
|
||||
nextcode = ArenaNew<Bytecode>(pool);
|
||||
if (!nextcode) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -837,9 +839,9 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
return;
|
||||
}
|
||||
|
||||
LifoAlloc &tla = cx->typeLifoAlloc();
|
||||
JSArenaPool &pool = cx->compartment->pool;
|
||||
|
||||
lifetimes = tla.newArray<LifetimeVariable>(numSlots);
|
||||
lifetimes = ArenaArray<LifetimeVariable>(pool, numSlots);
|
||||
if (!lifetimes) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -967,7 +969,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
/* Restore all saved variables. :FIXME: maybe do this precisely. */
|
||||
for (unsigned i = 0; i < savedCount; i++) {
|
||||
LifetimeVariable &var = *saved[i];
|
||||
var.lifetime = tla.new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
var.lifetime = ArenaNew<Lifetime>(pool, offset, var.savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
cx->free_(saved);
|
||||
setOOM(cx);
|
||||
|
@ -1034,7 +1036,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
if (loop && loop->entry > loop->lastBlock)
|
||||
loop->lastBlock = loop->entry;
|
||||
|
||||
LoopAnalysis *nloop = tla.new_<LoopAnalysis>();
|
||||
LoopAnalysis *nloop = ArenaNew<LoopAnalysis>(pool);
|
||||
if (!nloop) {
|
||||
cx->free_(saved);
|
||||
setOOM(cx);
|
||||
|
@ -1083,7 +1085,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
|
|||
* Jumping to a place where this variable is live. Make a new
|
||||
* lifetime segment for the variable.
|
||||
*/
|
||||
var.lifetime = tla.new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
var.lifetime = ArenaNew<Lifetime>(pool, offset, var.savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
cx->free_(saved);
|
||||
setOOM(cx);
|
||||
|
@ -1147,7 +1149,7 @@ ScriptAnalysis::addVariable(JSContext *cx, LifetimeVariable &var, unsigned offse
|
|||
}
|
||||
}
|
||||
}
|
||||
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
var.lifetime = ArenaNew<Lifetime>(cx->compartment->pool, offset, var.savedEnd, var.saved);
|
||||
if (!var.lifetime) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1164,7 +1166,7 @@ ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offs
|
|||
/* Make a point lifetime indicating the write. */
|
||||
if (!var.saved)
|
||||
saved[savedCount++] = &var;
|
||||
var.saved = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
|
||||
var.saved = ArenaNew<Lifetime>(cx->compartment->pool, offset, var.savedEnd, var.saved);
|
||||
if (!var.saved) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1250,7 +1252,7 @@ ScriptAnalysis::extendVariable(JSContext *cx, LifetimeVariable &var,
|
|||
}
|
||||
JS_ASSERT(savedEnd <= end);
|
||||
if (savedEnd > segment->end) {
|
||||
Lifetime *tail = cx->typeLifoAlloc().new_<Lifetime>(savedEnd, 0, segment->next);
|
||||
Lifetime *tail = ArenaNew<Lifetime>(cx->compartment->pool, savedEnd, 0, segment->next);
|
||||
if (!tail) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1327,7 +1329,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
|||
return;
|
||||
}
|
||||
|
||||
LifoAlloc &tla = cx->typeLifoAlloc();
|
||||
JSArenaPool &pool = cx->compartment->pool;
|
||||
unsigned maxDepth = script->nslots - script->nfixed;
|
||||
|
||||
/*
|
||||
|
@ -1488,7 +1490,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
|||
unsigned xuses = ExtendedUse(pc) ? nuses + 1 : nuses;
|
||||
|
||||
if (xuses) {
|
||||
code->poppedValues = tla.newArray<SSAValue>(xuses);
|
||||
code->poppedValues = (SSAValue *)ArenaArray<SSAValue>(pool, xuses);
|
||||
if (!code->poppedValues) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1511,7 +1513,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
|||
}
|
||||
|
||||
if (xuses) {
|
||||
SSAUseChain *useChains = tla.newArray<SSAUseChain>(xuses);
|
||||
SSAUseChain *useChains = ArenaArray<SSAUseChain>(cx->compartment->pool, xuses);
|
||||
if (!useChains) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1538,7 +1540,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
|
|||
|
||||
unsigned xdefs = ExtendedDef(pc) ? ndefs + 1 : ndefs;
|
||||
if (xdefs) {
|
||||
code->pushedUses = tla.newArray<SSAUseChain *>(xdefs);
|
||||
code->pushedUses = ArenaArray<SSAUseChain *>(cx->compartment->pool, xdefs);
|
||||
if (!code->pushedUses) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1729,8 +1731,8 @@ PhiNodeCapacity(unsigned length)
|
|||
bool
|
||||
ScriptAnalysis::makePhi(JSContext *cx, uint32 slot, uint32 offset, SSAValue *pv)
|
||||
{
|
||||
SSAPhiNode *node = cx->typeLifoAlloc().new_<SSAPhiNode>();
|
||||
SSAValue *options = cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(0));
|
||||
SSAPhiNode *node = ArenaNew<SSAPhiNode>(cx->compartment->pool);
|
||||
SSAValue *options = ArenaArray<SSAValue>(cx->compartment->pool, PhiNodeCapacity(0));
|
||||
if (!node || !options) {
|
||||
setOOM(cx);
|
||||
return false;
|
||||
|
@ -1762,7 +1764,7 @@ ScriptAnalysis::insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v)
|
|||
if (trackUseChain(v)) {
|
||||
SSAUseChain *&uses = useChain(v);
|
||||
|
||||
SSAUseChain *use = cx->typeLifoAlloc().new_<SSAUseChain>();
|
||||
SSAUseChain *use = ArenaNew<SSAUseChain>(cx->compartment->pool);
|
||||
if (!use) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1780,8 +1782,8 @@ ScriptAnalysis::insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v)
|
|||
return;
|
||||
}
|
||||
|
||||
SSAValue *newOptions =
|
||||
cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(node->length + 1));
|
||||
SSAValue *newOptions = ArenaArray<SSAValue>(cx->compartment->pool,
|
||||
PhiNodeCapacity(node->length + 1));
|
||||
if (!newOptions) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
@ -1920,7 +1922,7 @@ ScriptAnalysis::freezeNewValues(JSContext *cx, uint32 offset)
|
|||
return;
|
||||
}
|
||||
|
||||
code.newValues = cx->typeLifoAlloc().newArray<SlotValue>(count + 1);
|
||||
code.newValues = ArenaArray<SlotValue>(cx->compartment->pool, count + 1);
|
||||
if (!code.newValues) {
|
||||
setOOM(cx);
|
||||
return;
|
||||
|
|
|
@ -41,13 +41,11 @@
|
|||
#ifndef jsanalyze_h___
|
||||
#define jsanalyze_h___
|
||||
|
||||
#include "jsarena.h"
|
||||
#include "jscompartment.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsinfer.h"
|
||||
#include "jsscript.h"
|
||||
#include "jstl.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
|
||||
struct JSScript;
|
||||
|
||||
|
@ -85,6 +83,11 @@ namespace analyze {
|
|||
* analyses are independent from type inference.
|
||||
*/
|
||||
|
||||
class SSAValue;
|
||||
struct SSAUseChain;
|
||||
struct LoopAnalysis;
|
||||
struct SlotValue;
|
||||
|
||||
/* Information about a bytecode instruction. */
|
||||
class Bytecode
|
||||
{
|
||||
|
@ -1369,16 +1372,4 @@ void PrintBytecode(JSContext *cx, JSScript *script, jsbytecode *pc);
|
|||
} /* namespace analyze */
|
||||
} /* namespace js */
|
||||
|
||||
namespace js {
|
||||
namespace tl {
|
||||
|
||||
template <> struct IsPodType<js::analyze::LifetimeVariable> { static const bool result = true; };
|
||||
template <> struct IsPodType<js::analyze::LoopAnalysis> { static const bool result = true; };
|
||||
template <> struct IsPodType<js::analyze::SlotValue> { static const bool result = true; };
|
||||
template <> struct IsPodType<js::analyze::SSAValue> { static const bool result = true; };
|
||||
template <> struct IsPodType<js::analyze::SSAUseChain> { static const bool result = true; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
||||
#endif // jsanalyze_h___
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <sys/stat.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsclist.h"
|
||||
#include "jsdhash.h"
|
||||
|
@ -99,7 +100,6 @@
|
|||
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "ds/LifoAlloc.h"
|
||||
|
||||
#if ENABLE_YARR_JIT
|
||||
#include "assembler/jit/ExecutableAllocator.h"
|
||||
|
@ -2608,6 +2608,10 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
|
|||
|
||||
LeaveTrace(cx);
|
||||
|
||||
/* Don't nuke active arenas if executing or compiling. */
|
||||
if (cx->tempPool.current == &cx->tempPool.first)
|
||||
JS_FinishArenaPool(&cx->tempPool);
|
||||
|
||||
GCREASON(PUBLIC_API);
|
||||
js_GC(cx, comp, GC_NORMAL);
|
||||
}
|
||||
|
@ -2624,6 +2628,10 @@ JS_MaybeGC(JSContext *cx)
|
|||
{
|
||||
LeaveTrace(cx);
|
||||
|
||||
/* Don't nuke active arenas if executing or compiling. */
|
||||
if (cx->tempPool.current == &cx->tempPool.first)
|
||||
JS_FinishArenaPool(&cx->tempPool);
|
||||
|
||||
MaybeGC(cx);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "jsalloc.h"
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/* If JSArena's length is a multiple of 8, that ensures its payload is 8-aligned. */
|
||||
JS_STATIC_ASSERT(sizeof(JSArena) % 8 == 0);
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, size_t align)
|
||||
{
|
||||
/* Restricting ourselves to some simple alignments keeps things simple. */
|
||||
if (align == 1 || align == 2 || align == 4 || align == 8) {
|
||||
pool->mask = align - 1;
|
||||
} else {
|
||||
/* This shouldn't happen, but set pool->mask reasonably if it does. */
|
||||
JS_NOT_REACHED("JS_InitArenaPool: bad align");
|
||||
pool->mask = 7;
|
||||
}
|
||||
pool->first.next = NULL;
|
||||
/* pool->first is a zero-sized dummy arena that's never allocated from. */
|
||||
pool->first.base = pool->first.avail = pool->first.limit =
|
||||
JS_ARENA_ALIGN(pool, &pool->first + 1);
|
||||
pool->current = &pool->first;
|
||||
pool->arenasize = size;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, size_t nb)
|
||||
{
|
||||
/*
|
||||
* Search pool from current forward till we find or make enough space.
|
||||
*
|
||||
* NB: subtract nb from a->limit in the loop condition, instead of adding
|
||||
* nb to a->avail, to avoid overflow (possible when running a 32-bit
|
||||
* program on a 64-bit system where the kernel maps the heap up against the
|
||||
* top of the 32-bit address space, see bug 279273). Note that this
|
||||
* necessitates a comparison between nb and a->limit that looks like a
|
||||
* (conceptual) type error but isn't.
|
||||
*/
|
||||
JS_ASSERT((nb & pool->mask) == 0);
|
||||
JSArena *a;
|
||||
/*
|
||||
* Comparing nb to a->limit looks like a (conceptual) type error, but it's
|
||||
* necessary to avoid wrap-around. Yuk.
|
||||
*/
|
||||
for (a = pool->current; nb > a->limit || a->avail > a->limit - nb; pool->current = a) {
|
||||
JSArena **ap = &a->next;
|
||||
if (!*ap) {
|
||||
/* Not enough space in pool, so we must malloc. */
|
||||
size_t gross = sizeof(JSArena) + JS_MAX(nb, pool->arenasize);
|
||||
a = (JSArena *) OffTheBooks::malloc_(gross);
|
||||
if (!a)
|
||||
return NULL;
|
||||
|
||||
a->next = NULL;
|
||||
a->base = a->avail = jsuword(a) + sizeof(JSArena);
|
||||
/*
|
||||
* Because malloc returns 8-aligned pointers and sizeof(JSArena) is
|
||||
* a multiple of 8, a->base will always be 8-aligned, which should
|
||||
* suffice for any valid pool.
|
||||
*/
|
||||
JS_ASSERT(a->base == JS_ARENA_ALIGN(pool, a->base));
|
||||
a->limit = (jsuword)a + gross;
|
||||
|
||||
*ap = a;
|
||||
continue;
|
||||
}
|
||||
a = *ap; /* move to next arena */
|
||||
}
|
||||
|
||||
void* p = (void *)a->avail;
|
||||
a->avail += nb;
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
return p;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
|
||||
{
|
||||
/* If we've called JS_ArenaRealloc, the new size must be bigger than pool->arenasize. */
|
||||
JS_ASSERT(size + incr > pool->arenasize);
|
||||
|
||||
/* Find the arena containing |p|. */
|
||||
JSArena *a;
|
||||
JSArena **ap = &pool->first.next;
|
||||
while (true) {
|
||||
a = *ap;
|
||||
if (JS_IS_IN_ARENA(a, p))
|
||||
break;
|
||||
JS_ASSERT(a != pool->current);
|
||||
ap = &a->next;
|
||||
}
|
||||
/* If we've called JS_ArenaRealloc, p must be at the start of an arena. */
|
||||
JS_ASSERT(a->base == jsuword(p));
|
||||
|
||||
size_t gross = sizeof(JSArena) + JS_ARENA_ALIGN(pool, size + incr);
|
||||
a = (JSArena *) OffTheBooks::realloc_(a, gross);
|
||||
if (!a)
|
||||
return NULL;
|
||||
|
||||
a->base = jsuword(a) + sizeof(JSArena);
|
||||
a->avail = a->limit = jsuword(a) + gross;
|
||||
/*
|
||||
* Because realloc returns 8-aligned pointers and sizeof(JSArena) is a
|
||||
* multiple of 8, a->base will always be 8-aligned, which should suffice
|
||||
* for any valid pool.
|
||||
*/
|
||||
JS_ASSERT(a->base == JS_ARENA_ALIGN(pool, a->base));
|
||||
|
||||
if (a != *ap) {
|
||||
/* realloc moved the allocation: update other pointers to a. */
|
||||
if (pool->current == *ap)
|
||||
pool->current = a;
|
||||
*ap = a;
|
||||
}
|
||||
|
||||
return (void *)a->base;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr)
|
||||
{
|
||||
void *newp;
|
||||
|
||||
/*
|
||||
* If p points to an oversized allocation, it owns an entire arena, so we
|
||||
* can simply realloc the arena.
|
||||
*/
|
||||
if (size > pool->arenasize)
|
||||
return JS_ArenaRealloc(pool, p, size, incr);
|
||||
|
||||
JS_ARENA_ALLOCATE(newp, pool, size + incr);
|
||||
if (newp)
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free tail arenas linked after head, which may not be the true list head.
|
||||
* Reset pool->current to point to head in case it pointed at a tail arena.
|
||||
*/
|
||||
static void
|
||||
FreeArenaList(JSArenaPool *pool, JSArena *head)
|
||||
{
|
||||
JSArena **ap, *a;
|
||||
|
||||
ap = &head->next;
|
||||
a = *ap;
|
||||
if (!a)
|
||||
return;
|
||||
|
||||
#ifdef DEBUG
|
||||
do {
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
a->avail = a->base;
|
||||
JS_CLEAR_UNUSED(a);
|
||||
} while ((a = a->next) != NULL);
|
||||
a = *ap;
|
||||
#endif
|
||||
|
||||
do {
|
||||
*ap = a->next;
|
||||
JS_CLEAR_ARENA(a);
|
||||
UnwantedForeground::free_(a);
|
||||
} while ((a = *ap) != NULL);
|
||||
|
||||
pool->current = head;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark)
|
||||
{
|
||||
JSArena *a;
|
||||
|
||||
for (a = &pool->first; a; a = a->next) {
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
|
||||
if (JS_IS_IN_ARENA(a, mark)) {
|
||||
a->avail = JS_ARENA_ALIGN(pool, mark);
|
||||
JS_ASSERT(a->avail <= a->limit);
|
||||
FreeArenaList(pool, a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool)
|
||||
{
|
||||
FreeArenaList(pool, &pool->first);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ArenaFinish()
|
||||
{
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ArenaShutDown(void)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,317 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jsarena_h___
|
||||
#define jsarena_h___
|
||||
/*
|
||||
* Lifetime-based fast allocation, inspired by much prior art, including
|
||||
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
||||
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
||||
*
|
||||
* Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
#include "jsstaticcheck.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef struct JSArena JSArena;
|
||||
typedef struct JSArenaPool JSArenaPool;
|
||||
|
||||
struct JSArena {
|
||||
JSArena *next; /* next arena for this lifetime */
|
||||
jsuword base; /* aligned base address, follows this header */
|
||||
jsuword limit; /* one beyond last byte in arena */
|
||||
jsuword avail; /* points to next available byte */
|
||||
};
|
||||
|
||||
struct JSArenaPool {
|
||||
JSArena first; /* first arena in pool list */
|
||||
JSArena *current; /* arena from which to allocate space */
|
||||
size_t arenasize; /* net exact size of a new arena */
|
||||
jsuword mask; /* alignment mask (power-of-2 - 1) */
|
||||
};
|
||||
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
|
||||
#define JS_ARENA_ALLOCATE(p, pool, nb) \
|
||||
JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb)
|
||||
|
||||
#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \
|
||||
JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0)
|
||||
|
||||
#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \
|
||||
JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit)
|
||||
|
||||
/*
|
||||
* NB: In JS_ARENA_ALLOCATE_CAST and JS_ARENA_GROW_CAST, always subtract _nb
|
||||
* from a->limit rather than adding _nb to _p, to avoid overflow (possible when
|
||||
* running a 32-bit program on a 64-bit system where the kernel maps the heap
|
||||
* up against the top of the 32-bit address space, see bug 279273). Note that
|
||||
* this necessitates a comparison between nb and a->limit that looks like a
|
||||
* (conceptual) type error but isn't.
|
||||
*/
|
||||
#define JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, guard) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
size_t _nb = JS_ARENA_ALIGN(pool, nb); \
|
||||
jsuword _p = _a->avail; \
|
||||
if ((guard) || _p > _a->limit - _nb) \
|
||||
_p = (jsuword)JS_ArenaAllocate(pool, _nb); \
|
||||
else \
|
||||
_a->avail = _p + _nb; \
|
||||
p = (type) _p; \
|
||||
STATIC_ASSUME(!p || ubound((char *)p) >= nb); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_GROW(p, pool, size, incr) \
|
||||
JS_ARENA_GROW_CAST(p, void *, pool, size, incr)
|
||||
|
||||
#define JS_ARENA_GROW_CAST(p, type, pool, size, incr) \
|
||||
JS_BEGIN_MACRO \
|
||||
JSArena *_a = (pool)->current; \
|
||||
if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) { \
|
||||
/* p was the last thing allocated in the current arena... */ \
|
||||
size_t _nb = (size) + (incr); \
|
||||
_nb = JS_ARENA_ALIGN(pool, _nb); \
|
||||
if (_a->limit >= _nb && (jsuword)(p) <= _a->limit - _nb) { \
|
||||
/* ... and we have space, so just extend p in-place */ \
|
||||
_a->avail = (jsuword)(p) + _nb; \
|
||||
} else if ((jsuword)(p) == _a->base) { \
|
||||
/* ... p is also the 1st thing in this arena */ \
|
||||
p = (type) JS_ArenaRealloc(pool, p, size, incr); \
|
||||
} else { \
|
||||
/* hard case */ \
|
||||
p = (type) JS_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
} else { \
|
||||
/* hard case */ \
|
||||
p = (type) JS_ArenaGrow(pool, p, size, incr); \
|
||||
} \
|
||||
STATIC_ASSUME(!p || ubound((char *)p) >= size + incr); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail)
|
||||
#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q))
|
||||
|
||||
/*
|
||||
* Check if the mark is inside arena's allocated area.
|
||||
*/
|
||||
#define JS_IS_IN_ARENA(a, mark) \
|
||||
(JS_UPTRDIFF(mark, (a)->base) <= JS_UPTRDIFF((a)->avail, (a)->base))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \
|
||||
memset((void*)(a)->avail, JS_FREE_PATTERN, \
|
||||
(a)->limit - (a)->avail))
|
||||
#define JS_CLEAR_ARENA(a) memset((void*)(a), JS_FREE_PATTERN, \
|
||||
(a)->limit - (jsuword)(a))
|
||||
#else
|
||||
#define JS_CLEAR_UNUSED(a) /* nothing */
|
||||
#define JS_CLEAR_ARENA(a) /* nothing */
|
||||
#endif
|
||||
|
||||
#define JS_ARENA_RELEASE(pool, mark) \
|
||||
JS_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
JSArena *_a = (pool)->current; \
|
||||
if (_a != &(pool)->first && JS_IS_IN_ARENA(_a, _m)) { \
|
||||
_a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
|
||||
JS_ASSERT(_a->avail <= _a->limit); \
|
||||
JS_CLEAR_UNUSED(_a); \
|
||||
} else { \
|
||||
JS_ArenaRelease(pool, _m); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_ARENA_DESTROY(pool, a, pnext) \
|
||||
JS_BEGIN_MACRO \
|
||||
JS_COUNT_ARENA(pool,--); \
|
||||
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
|
||||
*(pnext) = (a)->next; \
|
||||
JS_CLEAR_ARENA(a); \
|
||||
js::UnwantedForeground::free_(a); \
|
||||
(a) = NULL; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
* Initialize an arena pool with a minimum size per arena of |size| bytes.
|
||||
* |align| must be 1, 2, 4 or 8.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size,
|
||||
size_t align);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool. The user may continue to allocate from pool
|
||||
* after calling this function. There is no need to call JS_InitArenaPool()
|
||||
* again unless JS_FinishArenaPool(pool) has been called.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_FreeArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool and finish using it altogether.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Deprecated do-nothing function.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
* Deprecated do-nothing function.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaShutDown(void);
|
||||
|
||||
/*
|
||||
* Friend functions used by the JS_ARENA_*() macros.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, size_t nb);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace js {
|
||||
|
||||
template <typename T>
|
||||
inline T *
|
||||
ArenaArray(JSArenaPool &pool, unsigned count)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, count * sizeof(T));
|
||||
return (T *) v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T() : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename A>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool, const A &a)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T(a) : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename A, typename B>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool, const A &a, const B &b)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T(a, b) : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename A, typename B, typename C>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool, const A &a, const B &b, const C &c)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T(a, b, c) : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename A, typename B, typename C, typename D>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool, const A &a, const B &b, const C &c, const D &d)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T(a, b, c, d) : NULL;
|
||||
}
|
||||
|
||||
template <typename T, typename A, typename B, typename C, typename D, typename E>
|
||||
inline T *
|
||||
ArenaNew(JSArenaPool &pool, const A &a, const B &b, const C &c, const D &d, const E &e)
|
||||
{
|
||||
void *v;
|
||||
JS_ARENA_ALLOCATE(v, &pool, sizeof(T));
|
||||
return v ? new (v) T(a, b, c, d, e) : NULL;
|
||||
}
|
||||
|
||||
inline uintN
|
||||
ArenaAllocatedSize(const JSArenaPool &pool)
|
||||
{
|
||||
uintN res = 0;
|
||||
const JSArena *a = &pool.first;
|
||||
while (a) {
|
||||
res += (a->limit - (jsuword)a);
|
||||
a = a->next;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Move the contents of oldPool into newPool, and reset oldPool. */
|
||||
inline void
|
||||
MoveArenaPool(JSArenaPool *oldPool, JSArenaPool *newPool)
|
||||
{
|
||||
*newPool = *oldPool;
|
||||
JS_InitArenaPool(oldPool, NULL, newPool->arenasize, newPool->mask + 1);
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* jsarena_h___ */
|
|
@ -57,6 +57,7 @@
|
|||
#include "jsstdint.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsclist.h"
|
||||
#include "jsprf.h"
|
||||
|
@ -111,7 +112,6 @@ ThreadData::ThreadData()
|
|||
maxCodeCacheBytes(DEFAULT_JIT_CACHE_SIZE),
|
||||
#endif
|
||||
waiveGCQuota(false),
|
||||
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
dtoaState(NULL),
|
||||
nativeStackBase(GetNativeStackBase()),
|
||||
pendingProxyOperation(NULL),
|
||||
|
@ -316,6 +316,9 @@ js_PurgeThreads(JSContext *cx)
|
|||
#endif
|
||||
}
|
||||
|
||||
static const size_t ARENA_HEADER_SIZE_HACK = 40;
|
||||
static const size_t TEMP_POOL_CHUNK_SIZE = 4096 - ARENA_HEADER_SIZE_HACK;
|
||||
|
||||
JSContext *
|
||||
js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
||||
{
|
||||
|
@ -342,6 +345,9 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
JS_InitArenaPool(&cx->tempPool, "temp", TEMP_POOL_CHUNK_SIZE, sizeof(jsdouble));
|
||||
JS_InitArenaPool(&cx->regExpPool, "regExp", TEMP_POOL_CHUNK_SIZE, sizeof(int));
|
||||
|
||||
JS_ASSERT(cx->resolveFlags == 0);
|
||||
|
||||
if (!cx->busyArrays.init()) {
|
||||
|
@ -1367,6 +1373,9 @@ JSContext::~JSContext()
|
|||
if (parseMapPool_)
|
||||
Foreground::delete_<ParseMapPool>(parseMapPool_);
|
||||
|
||||
JS_FinishArenaPool(®ExpPool);
|
||||
JS_FinishArenaPool(&tempPool);
|
||||
|
||||
if (lastMessage)
|
||||
Foreground::free_(lastMessage);
|
||||
|
||||
|
@ -1493,9 +1502,25 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release pool's arenas if the stackPool has existed for longer than the
|
||||
* limit specified by gcEmptyArenaPoolLifespan.
|
||||
*/
|
||||
static void
|
||||
FreeOldArenas(JSRuntime *rt, JSArenaPool *pool)
|
||||
{
|
||||
JSArena *a = pool->current;
|
||||
if (a == pool->first.next && a->avail == a->base + sizeof(int64)) {
|
||||
int64 age = JS_Now() - *(int64 *) a->base;
|
||||
if (age > int64(rt->gcEmptyArenaPoolLifespan) * 1000)
|
||||
JS_FreeArenaPool(pool);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSContext::purge()
|
||||
{
|
||||
FreeOldArenas(runtime, ®ExpPool);
|
||||
if (!activeCompilations) {
|
||||
Foreground::delete_<ParseMapPool>(parseMapPool_);
|
||||
parseMapPool_ = NULL;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "jsprvtd.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsclist.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsdhash.h"
|
||||
|
@ -63,7 +64,6 @@
|
|||
#include "jsvector.h"
|
||||
#include "prmjtime.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
#include "vm/Stack.h"
|
||||
#include "vm/String.h"
|
||||
|
||||
|
@ -190,10 +190,6 @@ struct ThreadData {
|
|||
*/
|
||||
bool waiveGCQuota;
|
||||
|
||||
/* Temporary arena pool used while compiling and decompiling. */
|
||||
static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
|
||||
LifoAlloc tempLifoAlloc;
|
||||
|
||||
/*
|
||||
* The GSN cache is per thread since even multi-cx-per-thread embeddings
|
||||
* do not interleave js_GetSrcNote calls.
|
||||
|
@ -228,7 +224,6 @@ struct ThreadData {
|
|||
}
|
||||
|
||||
void purge(JSContext *cx) {
|
||||
tempLifoAlloc.freeUnused();
|
||||
gsnCache.purge();
|
||||
|
||||
/* FIXME: bug 506341. */
|
||||
|
@ -999,11 +994,17 @@ struct JSContext
|
|||
/* Wrap cx->exception for the current compartment. */
|
||||
void wrapPendingException();
|
||||
|
||||
/* Temporary arena pool used while compiling and decompiling. */
|
||||
JSArenaPool tempPool;
|
||||
|
||||
private:
|
||||
/* Lazily initialized pool of maps used during parse/emit. */
|
||||
js::ParseMapPool *parseMapPool_;
|
||||
|
||||
public:
|
||||
/* Temporary arena pool used while evaluate regular expressions. */
|
||||
JSArenaPool regExpPool;
|
||||
|
||||
/* Top-level object and pointer to top stack frame's scope chain. */
|
||||
JSObject *globalObject;
|
||||
|
||||
|
@ -1143,9 +1144,6 @@ struct JSContext
|
|||
bool hasWErrorOption() const { return hasRunOption(JSOPTION_WERROR); }
|
||||
bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
|
||||
|
||||
js::LifoAlloc &tempLifoAlloc() { return JS_THREAD_DATA(this)->tempLifoAlloc; }
|
||||
inline js::LifoAlloc &typeLifoAlloc();
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
private:
|
||||
JSThread *thread_;
|
||||
|
@ -1879,6 +1877,28 @@ class AutoKeepAtoms {
|
|||
~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
|
||||
};
|
||||
|
||||
class AutoArenaAllocator {
|
||||
JSArenaPool *pool;
|
||||
void *mark;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
explicit AutoArenaAllocator(JSArenaPool *pool
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: pool(pool), mark(JS_ARENA_MARK(pool))
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~AutoArenaAllocator() { JS_ARENA_RELEASE(pool, mark); }
|
||||
|
||||
template <typename T>
|
||||
T *alloc(size_t elems) {
|
||||
void *ptr;
|
||||
JS_ARENA_ALLOCATE(ptr, pool, elems * sizeof(T));
|
||||
return static_cast<T *>(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
class AutoReleasePtr {
|
||||
JSContext *cx;
|
||||
void *ptr;
|
||||
|
|
|
@ -407,12 +407,6 @@ inline js::mjit::JaegerCompartment *JSContext::jaegerCompartment()
|
|||
}
|
||||
#endif
|
||||
|
||||
inline js::LifoAlloc &
|
||||
JSContext::typeLifoAlloc()
|
||||
{
|
||||
return compartment->typeLifoAlloc;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSContext::ensureGeneratorStackSpace()
|
||||
{
|
||||
|
|
|
@ -74,7 +74,6 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
|||
gcTriggerBytes(0),
|
||||
gcLastBytes(0),
|
||||
hold(false),
|
||||
typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
#ifdef JS_TRACER
|
||||
traceMonitor_(NULL),
|
||||
#endif
|
||||
|
@ -133,6 +132,11 @@ JSCompartment::init(JSContext *cx)
|
|||
activeAnalysis = activeInference = false;
|
||||
types.init(cx);
|
||||
|
||||
/* Duplicated from jscntxt.cpp. :XXX: bug 675150 fix hack. */
|
||||
static const size_t ARENA_HEADER_SIZE_HACK = 40;
|
||||
|
||||
JS_InitArenaPool(&pool, "analysis", 4096 - ARENA_HEADER_SIZE_HACK, 8);
|
||||
|
||||
if (!crossCompartmentWrappers.init())
|
||||
return false;
|
||||
|
||||
|
@ -618,8 +622,8 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
|||
* Clear the analysis pool, but don't release its data yet. While
|
||||
* sweeping types any live data will be allocated into the pool.
|
||||
*/
|
||||
LifoAlloc oldAlloc(typeLifoAlloc.defaultChunkSize());
|
||||
oldAlloc.steal(&typeLifoAlloc);
|
||||
JSArenaPool oldPool;
|
||||
MoveArenaPool(&pool, &oldPool);
|
||||
|
||||
/*
|
||||
* Sweep analysis information and everything depending on it from the
|
||||
|
@ -652,6 +656,9 @@ JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
|||
JSScript *script = i.get<JSScript>();
|
||||
script->clearAnalysis();
|
||||
}
|
||||
|
||||
/* Reset the analysis pool, releasing all analysis and intermediate type data. */
|
||||
JS_FinishArenaPool(&oldPool);
|
||||
}
|
||||
|
||||
active = false;
|
||||
|
|
|
@ -408,8 +408,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||
* Cleared on every GC, unless the GC happens during analysis (indicated
|
||||
* by activeAnalysis, which is implied by activeInference).
|
||||
*/
|
||||
static const size_t TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
|
||||
js::LifoAlloc typeLifoAlloc;
|
||||
JSArenaPool pool;
|
||||
bool activeAnalysis;
|
||||
bool activeInference;
|
||||
|
||||
|
|
|
@ -485,9 +485,10 @@ JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp)
|
|||
return NULL;
|
||||
|
||||
/* Munge data into the API this method implements. Avert your eyes! */
|
||||
*markp = cx->tempLifoAlloc().mark();
|
||||
*markp = JS_ARENA_MARK(&cx->tempPool);
|
||||
|
||||
jsuword *names = cx->tempLifoAlloc().newArray<jsuword>(localNames.length());
|
||||
jsuword *names;
|
||||
JS_ARENA_ALLOCATE_CAST(names, jsuword *, &cx->tempPool, localNames.length() * sizeof *names);
|
||||
if (!names) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
|
@ -512,7 +513,7 @@ JS_AtomKey(JSAtom *atom)
|
|||
extern JS_PUBLIC_API(void)
|
||||
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark)
|
||||
{
|
||||
cx->tempLifoAlloc().release(mark);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
|
@ -2166,9 +2167,9 @@ JS_PUBLIC_API(void)
|
|||
JS_DumpBytecode(JSContext *cx, JSScript *script)
|
||||
{
|
||||
#if defined(DEBUG)
|
||||
LifoAlloc lifoAlloc(1024);
|
||||
AutoArenaAllocator mark(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &lifoAlloc, 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
|
||||
fprintf(stdout, "--- SCRIPT %s:%d ---\n", script->filename, script->lineno);
|
||||
js_Disassemble(cx, script, true, &sprinter);
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsprf.h"
|
||||
|
@ -74,7 +75,6 @@
|
|||
#include "jsscriptinlines.h"
|
||||
|
||||
#include "frontend/ParseMaps-inl.h"
|
||||
#include "ds/LifoAlloc.h"
|
||||
|
||||
/* Allocation chunk counts, must be powers of two in general. */
|
||||
#define BYTECODE_CHUNK_LENGTH 1024 /* initial bytecode chunk length */
|
||||
|
@ -515,7 +515,8 @@ AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp)
|
|||
if (jt) {
|
||||
cg->jtFreeList = jt->kids[JT_LEFT];
|
||||
} else {
|
||||
jt = args->cx->tempLifoAlloc().new_<JSJumpTarget>();
|
||||
JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool,
|
||||
sizeof *jt);
|
||||
if (!jt) {
|
||||
js_ReportOutOfMemory(args->cx);
|
||||
return 0;
|
||||
|
@ -3311,7 +3312,9 @@ EmitNumberOp(JSContext *cx, jsdouble dval, JSCodeGenerator *cg)
|
|||
static Value *
|
||||
AllocateSwitchConstant(JSContext *cx)
|
||||
{
|
||||
return cx->tempLifoAlloc().new_<Value>();
|
||||
Value *pv;
|
||||
JS_ARENA_ALLOCATE_TYPE(pv, Value, &cx->tempPool);
|
||||
return pv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7749,12 +7752,14 @@ static JSBool
|
|||
NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
|
||||
uintN stackDepth, size_t start, size_t end)
|
||||
{
|
||||
JSTryNode *tryNode;
|
||||
|
||||
JS_ASSERT((uintN)(uint16)stackDepth == stackDepth);
|
||||
JS_ASSERT(start <= end);
|
||||
JS_ASSERT((size_t)(uint32)start == start);
|
||||
JS_ASSERT((size_t)(uint32)end == end);
|
||||
|
||||
JSTryNode *tryNode = cx->tempLifoAlloc().new_<JSTryNode>();
|
||||
JS_ARENA_ALLOCATE_TYPE(tryNode, JSTryNode, &cx->tempPool);
|
||||
if (!tryNode) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -668,9 +668,11 @@ struct JSCodeGenerator : public JSTreeContext
|
|||
}
|
||||
|
||||
/*
|
||||
* Note that cgs are magic: they own the arena "top-of-stack" space above
|
||||
* their tempMark points. This means that you cannot alloc from tempPool
|
||||
* and save the pointer beyond the next JSCodeGenerator destructor call.
|
||||
* Release cg->codePool, cg->notePool, and parser->context->tempPool to
|
||||
* marks set by JSCodeGenerator's ctor. Note that cgs are magic: they own
|
||||
* the arena pool "tops-of-stack" space above their codeMark, noteMark, and
|
||||
* tempMark points. This means you cannot alloc from tempPool and save the
|
||||
* pointer beyond the next JSCodeGenerator destructor call.
|
||||
*/
|
||||
~JSCodeGenerator();
|
||||
|
||||
|
|
|
@ -2181,8 +2181,8 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
|||
* for a terminating 0. Mark cx->tempPool for later release, to free
|
||||
* collected_args and its tokenstream in one swoop.
|
||||
*/
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
jschar *cp = cx->tempLifoAlloc().newArray<jschar>(args_length + 1);
|
||||
AutoArenaAllocator aaa(&cx->tempPool);
|
||||
jschar *cp = aaa.alloc<jschar>(args_length + 1);
|
||||
if (!cp) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
|
|
@ -352,7 +352,7 @@ TypeSet::make(JSContext *cx, const char *name)
|
|||
{
|
||||
JS_ASSERT(cx->compartment->activeInference);
|
||||
|
||||
TypeSet *res = cx->typeLifoAlloc().new_<TypeSet>();
|
||||
TypeSet *res = ArenaNew<TypeSet>(cx->compartment->pool);
|
||||
if (!res) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return NULL;
|
||||
|
@ -492,7 +492,7 @@ public:
|
|||
void
|
||||
TypeSet::addSubset(JSContext *cx, TypeSet *target)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintSubset>(target));
|
||||
add(cx, ArenaNew<TypeConstraintSubset>(cx->compartment->pool, target));
|
||||
}
|
||||
|
||||
/* Constraints for reads/writes on object properties. */
|
||||
|
@ -527,14 +527,14 @@ void
|
|||
TypeSet::addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
TypeSet *target, jsid id)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintProp>(script, pc, target, id, false));
|
||||
add(cx, ArenaNew<TypeConstraintProp>(cx->compartment->pool, script, pc, target, id, false));
|
||||
}
|
||||
|
||||
void
|
||||
TypeSet::addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
TypeSet *target, jsid id)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintProp>(script, pc, target, id, true));
|
||||
add(cx, ArenaNew<TypeConstraintProp>(cx->compartment->pool, script, pc, target, id, true));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -575,7 +575,7 @@ TypeSet::addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid i
|
|||
if (JSOp(*callpc) == JSOP_NEW)
|
||||
return;
|
||||
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintCallProp>(script, callpc, id));
|
||||
add(cx, ArenaNew<TypeConstraintCallProp>(cx->compartment->pool, script, callpc, id));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -608,8 +608,8 @@ void
|
|||
TypeSet::addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
TypeSet *objectTypes, TypeSet *valueTypes)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintSetElement>(script, pc, objectTypes,
|
||||
valueTypes));
|
||||
add(cx, ArenaNew<TypeConstraintSetElement>(cx->compartment->pool, script, pc,
|
||||
objectTypes, valueTypes));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -633,7 +633,7 @@ public:
|
|||
void
|
||||
TypeSet::addCall(JSContext *cx, TypeCallsite *site)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintCall>(site));
|
||||
add(cx, ArenaNew<TypeConstraintCall>(cx->compartment->pool, site));
|
||||
}
|
||||
|
||||
/* Constraints for arithmetic operations. */
|
||||
|
@ -658,7 +658,7 @@ public:
|
|||
void
|
||||
TypeSet::addArith(JSContext *cx, TypeSet *target, TypeSet *other)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintArith>(target, other));
|
||||
add(cx, ArenaNew<TypeConstraintArith>(cx->compartment->pool, target, other));
|
||||
}
|
||||
|
||||
/* Subset constraint which transforms primitive values into appropriate objects. */
|
||||
|
@ -678,7 +678,7 @@ public:
|
|||
void
|
||||
TypeSet::addTransformThis(JSContext *cx, JSScript *script, TypeSet *target)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintTransformThis>(script, target));
|
||||
add(cx, ArenaNew<TypeConstraintTransformThis>(cx->compartment->pool, script, target));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -709,7 +709,7 @@ TypeSet::addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc, Type
|
|||
if (JSOp(*callpc) == JSOP_NEW)
|
||||
return;
|
||||
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintPropagateThis>(script, callpc, type, types));
|
||||
add(cx, ArenaNew<TypeConstraintPropagateThis>(cx->compartment->pool, script, callpc, type, types));
|
||||
}
|
||||
|
||||
/* Subset constraint which filters out primitive types. */
|
||||
|
@ -752,7 +752,7 @@ public:
|
|||
void
|
||||
TypeSet::addFilterPrimitives(JSContext *cx, TypeSet *target, FilterKind filter)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFilterPrimitive>(target, filter));
|
||||
add(cx, ArenaNew<TypeConstraintFilterPrimitive>(cx->compartment->pool, target, filter));
|
||||
}
|
||||
|
||||
/* If id is a normal slotful 'own' property of an object, get its shape. */
|
||||
|
@ -876,7 +876,7 @@ public:
|
|||
void
|
||||
TypeSet::addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintSubsetBarrier>(script, pc, target));
|
||||
add(cx, ArenaNew<TypeConstraintSubsetBarrier>(cx->compartment->pool, script, pc, target));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -904,7 +904,7 @@ public:
|
|||
void
|
||||
TypeSet::addLazyArguments(JSContext *cx, TypeSet *target)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintLazyArguments>(target));
|
||||
add(cx, ArenaNew<TypeConstraintLazyArguments>(cx->compartment->pool, target));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
@ -1086,8 +1086,9 @@ TypeConstraintCallProp::newType(JSContext *cx, TypeSet *source, Type type)
|
|||
if (!types->hasPropagatedProperty())
|
||||
object->getFromPrototypes(cx, id, types);
|
||||
/* Bypass addPropagateThis, we already have the callpc. */
|
||||
types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintPropagateThis>(
|
||||
script, callpc, type, (TypeSet *) NULL));
|
||||
types->add(cx, ArenaNew<TypeConstraintPropagateThis>(cx->compartment->pool,
|
||||
script, callpc, type,
|
||||
(TypeSet *) NULL));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1388,8 +1389,8 @@ public:
|
|||
void
|
||||
TypeSet::addFreeze(JSContext *cx)
|
||||
{
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreeze>(
|
||||
cx->compartment->types.compiledScript), false);
|
||||
add(cx, ArenaNew<TypeConstraintFreeze>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript), false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1472,8 +1473,8 @@ TypeSet::getKnownTypeTag(JSContext *cx)
|
|||
JS_ASSERT_IF(empty, type == JSVAL_TYPE_UNKNOWN);
|
||||
|
||||
if (cx->compartment->types.compiledScript && (empty || type != JSVAL_TYPE_UNKNOWN)) {
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeTypeTag>(
|
||||
cx->compartment->types.compiledScript), false);
|
||||
add(cx, ArenaNew<TypeConstraintFreezeTypeTag>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript), false);
|
||||
}
|
||||
|
||||
return type;
|
||||
|
@ -1552,8 +1553,9 @@ public:
|
|||
TypeSet *types = object->getProperty(cx, JSID_EMPTY, false);
|
||||
if (!types)
|
||||
return;
|
||||
types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
|
||||
script, flags, &marked), false);
|
||||
types->add(cx,
|
||||
ArenaNew<TypeConstraintFreezeObjectFlags>(cx->compartment->pool,
|
||||
script, flags, &marked), false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -1594,8 +1596,8 @@ TypeSet::hasObjectFlags(JSContext *cx, TypeObjectFlags flags)
|
|||
* Watch for new objects of different kind, and re-traverse existing types
|
||||
* in this set to add any needed FreezeArray constraints.
|
||||
*/
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlagsSet>(
|
||||
cx->compartment->types.compiledScript, flags));
|
||||
add(cx, ArenaNew<TypeConstraintFreezeObjectFlagsSet>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript, flags));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1609,8 +1611,9 @@ TypeSet::HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags flags
|
|||
TypeSet *types = object->getProperty(cx, JSID_EMPTY, false);
|
||||
if (!types)
|
||||
return true;
|
||||
types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
|
||||
cx->compartment->types.compiledScript, flags), false);
|
||||
types->add(cx,
|
||||
ArenaNew<TypeConstraintFreezeObjectFlags>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript, flags), false);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1691,9 +1694,9 @@ TypeSet::WatchObjectStateChange(JSContext *cx, TypeObject *obj)
|
|||
* Use a constraint which triggers recompilation when markStateChange is
|
||||
* called, which will set 'force' to true.
|
||||
*/
|
||||
types->add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeObjectFlags>(
|
||||
cx->compartment->types.compiledScript,
|
||||
0));
|
||||
types->add(cx, ArenaNew<TypeConstraintFreezeObjectFlags>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript,
|
||||
0));
|
||||
}
|
||||
|
||||
class TypeConstraintFreezeOwnProperty : public TypeConstraint
|
||||
|
@ -1746,7 +1749,7 @@ TypeSet::isOwnProperty(JSContext *cx, TypeObject *object, bool configurable)
|
|||
if (isOwnProperty(configurable))
|
||||
return true;
|
||||
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeOwnProperty>(
|
||||
add(cx, ArenaNew<TypeConstraintFreezeOwnProperty>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript,
|
||||
configurable), false);
|
||||
return false;
|
||||
|
@ -1758,8 +1761,8 @@ TypeSet::knownNonEmpty(JSContext *cx)
|
|||
if (baseFlags() != 0 || baseObjectCount() != 0)
|
||||
return true;
|
||||
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreeze>(
|
||||
cx->compartment->types.compiledScript), false);
|
||||
add(cx, ArenaNew<TypeConstraintFreeze>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript), false);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1818,7 +1821,7 @@ TypeSet::getSingleton(JSContext *cx, bool freeze)
|
|||
return NULL;
|
||||
|
||||
if (freeze) {
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreeze>(
|
||||
add(cx, ArenaNew<TypeConstraintFreeze>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript), false);
|
||||
}
|
||||
|
||||
|
@ -1876,8 +1879,9 @@ TypeSet::hasGlobalObject(JSContext *cx, JSObject *global)
|
|||
return false;
|
||||
}
|
||||
|
||||
add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeGlobal>(
|
||||
cx->compartment->types.compiledScript, global), false);
|
||||
add(cx, ArenaNew<TypeConstraintFreezeGlobal>(cx->compartment->pool,
|
||||
cx->compartment->types.compiledScript,
|
||||
global), false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2305,7 +2309,8 @@ ScriptAnalysis::addTypeBarrier(JSContext *cx, const jsbytecode *pc, TypeSet *tar
|
|||
InferSpewColor(target), target, InferSpewColorReset(),
|
||||
TypeString(type));
|
||||
|
||||
barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, type, (JSObject *) NULL, JSID_VOID);
|
||||
barrier = ArenaNew<TypeBarrier>(cx->compartment->pool, target, type,
|
||||
(JSObject *) NULL, JSID_VOID);
|
||||
|
||||
barrier->next = code.typeBarriers;
|
||||
code.typeBarriers = barrier;
|
||||
|
@ -2330,7 +2335,8 @@ ScriptAnalysis::addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc, Typ
|
|||
InferSpewColor(target), target, InferSpewColorReset(),
|
||||
(void *) singleton, TypeIdString(singletonId));
|
||||
|
||||
TypeBarrier *barrier = cx->typeLifoAlloc().new_<TypeBarrier>(target, Type::UndefinedType(),
|
||||
TypeBarrier *barrier =
|
||||
ArenaNew<TypeBarrier>(cx->compartment->pool, target, Type::UndefinedType(),
|
||||
singleton, singletonId);
|
||||
|
||||
barrier->next = code.typeBarriers;
|
||||
|
@ -2695,7 +2701,7 @@ bool
|
|||
TypeObject::addProperty(JSContext *cx, jsid id, Property **pprop)
|
||||
{
|
||||
JS_ASSERT(!*pprop);
|
||||
Property *base = cx->typeLifoAlloc().new_<Property>(id);
|
||||
Property *base = ArenaNew<Property>(cx->compartment->pool, id);
|
||||
if (!base) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
return false;
|
||||
|
@ -3245,7 +3251,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
if (ExtendedDef(pc))
|
||||
defCount++;
|
||||
|
||||
TypeSet *pushed = cx->typeLifoAlloc().newArrayUninitialized<TypeSet>(defCount);
|
||||
TypeSet *pushed = ArenaArray<TypeSet>(cx->compartment->pool, defCount);
|
||||
if (!pushed)
|
||||
return false;
|
||||
PodZero(pushed, defCount);
|
||||
|
@ -3768,7 +3774,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
|
||||
/* Construct the base call information about this site. */
|
||||
unsigned argCount = GetUseCount(script, offset) - 2;
|
||||
TypeCallsite *callsite = cx->typeLifoAlloc().new_<TypeCallsite>(
|
||||
TypeCallsite *callsite = ArenaNew<TypeCallsite>(cx->compartment->pool,
|
||||
cx, script, pc, op == JSOP_NEW, argCount);
|
||||
if (!callsite || (argCount && !callsite->argumentTypes)) {
|
||||
cx->compartment->types.setPendingNukeTypes(cx);
|
||||
|
@ -4490,7 +4496,8 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, JSO
|
|||
if (!parentTypes || parentTypes->unknown())
|
||||
return false;
|
||||
parentObject->getFromPrototypes(cx, id, parentTypes);
|
||||
parentTypes->add(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSetter>(type));
|
||||
parentTypes->add(cx,
|
||||
ArenaNew<TypeConstraintClearDefiniteSetter>(cx->compartment->pool, type));
|
||||
} else if (op == JSOP_FUNCALL && uses->u.which == GET_ARGC(pc) - 1) {
|
||||
/*
|
||||
* Passed as the first parameter to Function.call. Follow control
|
||||
|
@ -4539,9 +4546,9 @@ AnalyzeNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun, JSO
|
|||
* should the Function.call or callee itself change in the future.
|
||||
*/
|
||||
analysis->pushedTypes(calleev.pushedOffset(), 0)->add(cx,
|
||||
cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
|
||||
ArenaNew<TypeConstraintClearDefiniteSingle>(cx->compartment->pool, type));
|
||||
analysis->pushedTypes(calleev.pushedOffset(), 1)->add(cx,
|
||||
cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
|
||||
ArenaNew<TypeConstraintClearDefiniteSingle>(cx->compartment->pool, type));
|
||||
|
||||
TypeNewScript::Initializer pushframe(TypeNewScript::Initializer::FRAME_PUSH, uses->offset);
|
||||
if (!initializerList->append(pushframe)) {
|
||||
|
@ -5417,7 +5424,7 @@ JSScript::makeAnalysis(JSContext *cx)
|
|||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
types->analysis = cx->typeLifoAlloc().new_<ScriptAnalysis>(this);
|
||||
types->analysis = ArenaNew<ScriptAnalysis>(cx->compartment->pool, this);
|
||||
|
||||
if (!types->analysis)
|
||||
return false;
|
||||
|
@ -5808,7 +5815,7 @@ TypeObject::sweep(JSContext *cx)
|
|||
for (unsigned i = 0; i < oldCapacity; i++) {
|
||||
Property *prop = oldArray[i];
|
||||
if (prop && prop->types.isOwnProperty(false)) {
|
||||
Property *newProp = compartment->typeLifoAlloc.new_<Property>(*prop);
|
||||
Property *newProp = ArenaNew<Property>(compartment->pool, *prop);
|
||||
if (newProp) {
|
||||
Property **pentry =
|
||||
HashSetInsert<jsid,Property,Property>
|
||||
|
@ -5828,7 +5835,7 @@ TypeObject::sweep(JSContext *cx)
|
|||
} else if (propertyCount == 1) {
|
||||
Property *prop = (Property *) propertySet;
|
||||
if (prop->types.isOwnProperty(false)) {
|
||||
Property *newProp = compartment->typeLifoAlloc.new_<Property>(*prop);
|
||||
Property *newProp = ArenaNew<Property>(compartment->pool, *prop);
|
||||
if (newProp) {
|
||||
propertySet = (Property **) newProp;
|
||||
newProp->types.sweep(cx, compartment);
|
||||
|
@ -6102,7 +6109,7 @@ JS_GetTypeInferenceMemoryStats(JSContext *cx, JSCompartment *compartment,
|
|||
* by being copied to the replacement pool. This memory will be counted too
|
||||
* and deducted from the amount of temporary data.
|
||||
*/
|
||||
stats->temporary += compartment->typeLifoAlloc.used();
|
||||
stats->temporary += ArenaAllocatedSize(compartment->pool);
|
||||
|
||||
/* Pending arrays are cleared on GC along with the analysis pool. */
|
||||
stats->temporary += sizeof(TypeCompartment::PendingWork) * compartment->types.pendingCapacity;
|
||||
|
|
|
@ -43,16 +43,29 @@
|
|||
#define jsinfer_h___
|
||||
|
||||
#include "jsalloc.h"
|
||||
#include "jsarena.h"
|
||||
#include "jscell.h"
|
||||
#include "jstl.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jshashtable.h"
|
||||
|
||||
#include "ds/LifoAlloc.h"
|
||||
namespace js {
|
||||
class CallArgs;
|
||||
namespace analyze {
|
||||
class ScriptAnalysis;
|
||||
}
|
||||
class GlobalObject;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
namespace types {
|
||||
|
||||
/* Forward declarations. */
|
||||
class TypeSet;
|
||||
struct TypeCallsite;
|
||||
struct TypeObject;
|
||||
struct TypeCompartment;
|
||||
|
||||
/* Type set entry for either a JSObject with singleton type or a non-singleton TypeObject. */
|
||||
struct TypeObjectKey {
|
||||
static intptr_t keyBits(TypeObjectKey *obj) { return (intptr_t) obj; }
|
||||
|
|
|
@ -820,7 +820,7 @@ HashSetInsertTry(JSCompartment *compartment, U **&values, unsigned &count, T key
|
|||
return &values[insertpos];
|
||||
}
|
||||
|
||||
U **newValues = compartment->typeLifoAlloc.newArray<U*>(newCapacity);
|
||||
U **newValues = ArenaArray<U*>(compartment->pool, newCapacity);
|
||||
if (!newValues)
|
||||
return NULL;
|
||||
PodZero(newValues, newCapacity);
|
||||
|
@ -861,7 +861,7 @@ HashSetInsert(JSCompartment *compartment, U **&values, unsigned &count, T key)
|
|||
if (KEY::getKey(oldData) == key)
|
||||
return (U **) &values;
|
||||
|
||||
values = compartment->typeLifoAlloc.newArray<U*>(SET_ARRAY_SIZE);
|
||||
values = ArenaArray<U*>(compartment->pool, SET_ARRAY_SIZE);
|
||||
if (!values) {
|
||||
values = (U **) oldData;
|
||||
return NULL;
|
||||
|
@ -1097,7 +1097,7 @@ TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
thisTypes(NULL), returnTypes(NULL)
|
||||
{
|
||||
/* Caller must check for failure. */
|
||||
argumentTypes = cx->typeLifoAlloc().newArray<TypeSet*>(argumentCount);
|
||||
argumentTypes = ArenaArray<TypeSet*>(cx->compartment->pool, argumentCount);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <math.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsutil.h"
|
||||
#include "jshash.h"
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include "jsapi.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsbool.h"
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsprf.h"
|
||||
#include "jsapi.h"
|
||||
|
@ -318,7 +319,9 @@ js_DisassembleAtPC(JSContext *cx, JSScript *script, JSBool lines, jsbytecode *pc
|
|||
else
|
||||
SprintCString(sp, " ");
|
||||
}
|
||||
len = js_Disassemble1(cx, script, next, next - script->code, lines, sp);
|
||||
len = js_Disassemble1(cx, script, next,
|
||||
next - script->code,
|
||||
lines, sp);
|
||||
if (!len)
|
||||
return JS_FALSE;
|
||||
next += len;
|
||||
|
@ -335,22 +338,24 @@ js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, Sprinter *sp)
|
|||
JS_FRIEND_API(JSBool)
|
||||
js_DumpPC(JSContext *cx)
|
||||
{
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
JSBool ok = js_DisassembleAtPC(cx, cx->fp()->script(), true, cx->regs().pc, &sprinter);
|
||||
fprintf(stdout, "%s", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return ok;
|
||||
}
|
||||
|
||||
JSBool
|
||||
js_DumpScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
JSBool ok = js_Disassemble(cx, script, true, &sprinter);
|
||||
fprintf(stdout, "%s", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -362,13 +367,13 @@ ToDisassemblySource(JSContext *cx, jsval v, JSAutoByteString *bytes)
|
|||
{
|
||||
if (JSVAL_IS_STRING(v)) {
|
||||
Sprinter sprinter;
|
||||
LifoAlloc &tla = cx->tempLifoAlloc();
|
||||
LifoAllocScope las(&tla);
|
||||
INIT_SPRINTER(cx, &sprinter, &tla, 0);
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
char *nbytes = QuoteString(&sprinter, JSVAL_TO_STRING(v), '"');
|
||||
if (!nbytes)
|
||||
return false;
|
||||
nbytes = JS_sprintf_append(NULL, "%s", nbytes);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!nbytes)
|
||||
return false;
|
||||
bytes->initBytes(nbytes);
|
||||
|
@ -682,10 +687,11 @@ SprintEnsureBuffer(Sprinter *sp, size_t len)
|
|||
if (nb < 0)
|
||||
return JS_TRUE;
|
||||
base = sp->base;
|
||||
if (!base)
|
||||
base = static_cast<char *>(sp->pool->allocUnaligned(nb));
|
||||
else
|
||||
base = static_cast<char *>(sp->pool->reallocUnaligned(base, sp->size, nb));
|
||||
if (!base) {
|
||||
JS_ARENA_ALLOCATE_CAST(base, char *, sp->pool, nb);
|
||||
} else {
|
||||
JS_ARENA_GROW_CAST(base, char *, sp->pool, sp->size, nb);
|
||||
}
|
||||
if (!base) {
|
||||
js_ReportOutOfMemory(sp->context);
|
||||
return JS_FALSE;
|
||||
|
@ -870,11 +876,16 @@ QuoteString(Sprinter *sp, JSString *str, uint32 quote)
|
|||
JSString *
|
||||
js_QuoteString(JSContext *cx, JSString *str, jschar quote)
|
||||
{
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark;
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
char *bytes = QuoteString(&sprinter, str, quote);
|
||||
JSString *escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
|
||||
char *bytes;
|
||||
JSString *escstr;
|
||||
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
bytes = QuoteString(&sprinter, str, quote);
|
||||
escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return escstr;
|
||||
}
|
||||
|
||||
|
@ -882,7 +893,7 @@ js_QuoteString(JSContext *cx, JSString *str, jschar quote)
|
|||
|
||||
struct JSPrinter {
|
||||
Sprinter sprinter; /* base class state */
|
||||
LifoAlloc pool; /* string allocation pool */
|
||||
JSArenaPool pool; /* string allocation pool */
|
||||
uintN indent; /* indentation in spaces */
|
||||
bool pretty; /* pretty-print: indent, use newlines */
|
||||
bool grouped; /* in parenthesized expression context */
|
||||
|
@ -898,11 +909,13 @@ JSPrinter *
|
|||
js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
|
||||
uintN indent, JSBool pretty, JSBool grouped, JSBool strict)
|
||||
{
|
||||
JSPrinter *jp = (JSPrinter *) cx->malloc_(sizeof(JSPrinter));
|
||||
JSPrinter *jp;
|
||||
|
||||
jp = (JSPrinter *) cx->malloc_(sizeof(JSPrinter));
|
||||
if (!jp)
|
||||
return NULL;
|
||||
INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
|
||||
new (&jp->pool) LifoAlloc(1024);
|
||||
JS_InitArenaPool(&jp->pool, name, 256, 1);
|
||||
jp->indent = indent;
|
||||
jp->pretty = !!pretty;
|
||||
jp->grouped = !!grouped;
|
||||
|
@ -925,7 +938,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
|
|||
void
|
||||
js_DestroyPrinter(JSPrinter *jp)
|
||||
{
|
||||
jp->pool.freeAll();
|
||||
JS_FinishArenaPool(&jp->pool);
|
||||
Foreground::delete_(jp->localNames);
|
||||
jp->sprinter.context->free_(jp);
|
||||
}
|
||||
|
@ -942,7 +955,7 @@ js_GetPrinterOutput(JSPrinter *jp)
|
|||
str = JS_NewStringCopyZ(cx, jp->sprinter.base);
|
||||
if (!str)
|
||||
return NULL;
|
||||
jp->pool.freeAll();
|
||||
JS_FreeArenaPool(&jp->pool);
|
||||
INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);
|
||||
return str;
|
||||
}
|
||||
|
@ -1893,12 +1906,15 @@ DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
|
|||
static JSBool
|
||||
InitSprintStack(JSContext *cx, SprintStack *ss, JSPrinter *jp, uintN depth)
|
||||
{
|
||||
INIT_SPRINTER(cx, &ss->sprinter, &cx->tempLifoAlloc(), PAREN_SLOP);
|
||||
size_t offsetsz, opcodesz;
|
||||
void *space;
|
||||
|
||||
INIT_SPRINTER(cx, &ss->sprinter, &cx->tempPool, PAREN_SLOP);
|
||||
|
||||
/* Allocate the parallel (to avoid padding) offset and opcode stacks. */
|
||||
size_t offsetsz = depth * sizeof(ptrdiff_t);
|
||||
size_t opcodesz = depth * sizeof(jsbytecode);
|
||||
void *space = cx->tempLifoAlloc().alloc(offsetsz + opcodesz);
|
||||
offsetsz = depth * sizeof(ptrdiff_t);
|
||||
opcodesz = depth * sizeof(jsbytecode);
|
||||
JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz);
|
||||
if (!space) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return JS_FALSE;
|
||||
|
@ -4048,6 +4064,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
#if JS_HAS_GENERATOR_EXPRS
|
||||
sn = js_GetSrcNote(jp->script, pc);
|
||||
if (sn && SN_TYPE(sn) == SRC_GENEXP) {
|
||||
void *mark;
|
||||
Vector<JSAtom *> *innerLocalNames;
|
||||
Vector<JSAtom *> *outerLocalNames;
|
||||
JSScript *inner, *outer;
|
||||
|
@ -4062,7 +4079,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
* Therefore after InitSprintStack succeeds, we must
|
||||
* release to mark before returning.
|
||||
*/
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
if (fun->script()->bindings.hasLocalNames()) {
|
||||
innerLocalNames = cx->new_<Vector<JSAtom *> >(cx);
|
||||
if (!innerLocalNames ||
|
||||
|
@ -4074,8 +4091,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
innerLocalNames = NULL;
|
||||
}
|
||||
inner = fun->script();
|
||||
if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner)))
|
||||
if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner))) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return NULL;
|
||||
}
|
||||
ss2.inGenExp = JS_TRUE;
|
||||
|
||||
/*
|
||||
|
@ -4103,8 +4122,10 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
jp->script = outer;
|
||||
jp->fun = outerfun;
|
||||
jp->localNames = outerLocalNames;
|
||||
if (!ok)
|
||||
if (!ok) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Advance over this op and its global |this| push, and
|
||||
|
@ -4174,7 +4195,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
* from cx's tempPool.
|
||||
*/
|
||||
rval = JS_strdup(cx, PopStr(&ss2, op));
|
||||
las.releaseEarly();
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!rval)
|
||||
return NULL;
|
||||
todo = SprintCString(&ss->sprinter, rval);
|
||||
|
@ -4812,6 +4833,8 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
|
|||
uintN depth, i;
|
||||
SprintStack ss;
|
||||
JSContext *cx;
|
||||
void *mark;
|
||||
JSBool ok;
|
||||
JSScript *oldscript;
|
||||
char *last;
|
||||
|
||||
|
@ -4822,9 +4845,10 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
|
|||
AutoScriptUntrapper untrapper(cx, script, &pc);
|
||||
|
||||
/* Initialize a sprinter for use with the offset stack. */
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
if (!InitSprintStack(cx, &ss, jp, depth))
|
||||
return false;
|
||||
mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
ok = InitSprintStack(cx, &ss, jp, depth);
|
||||
if (!ok)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* If we are called from js_DecompileValueGenerator with a portion of
|
||||
|
@ -4848,7 +4872,7 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
|
|||
/* Call recursive subroutine to do the hard work. */
|
||||
oldscript = jp->script;
|
||||
jp->script = script;
|
||||
bool ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL;
|
||||
ok = Decompile(&ss, pc, len, JSOP_NOP) != NULL;
|
||||
jp->script = oldscript;
|
||||
|
||||
/* If the given code didn't empty the stack, do it now. */
|
||||
|
@ -4859,6 +4883,9 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len,
|
|||
js_printf(jp, "%s", last);
|
||||
}
|
||||
|
||||
out:
|
||||
/* Free all temporary stuff allocated under this call. */
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -4971,6 +4998,7 @@ js_DecompileFunction(JSPrinter *jp)
|
|||
JSScript *script = fun->script();
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
SprintStack ss;
|
||||
void *mark;
|
||||
#endif
|
||||
|
||||
/* Print the parameters. */
|
||||
|
@ -4982,7 +5010,7 @@ js_DecompileFunction(JSPrinter *jp)
|
|||
#if JS_HAS_DESTRUCTURING
|
||||
ss.printer = NULL;
|
||||
jp->script = script;
|
||||
LifoAllocScope las(&jp->sprinter.context->tempLifoAlloc());
|
||||
mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool);
|
||||
#endif
|
||||
|
||||
for (i = 0; i < fun->nargs; i++) {
|
||||
|
@ -5033,7 +5061,7 @@ js_DecompileFunction(JSPrinter *jp)
|
|||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
jp->script = NULL;
|
||||
las.releaseEarly();
|
||||
JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark);
|
||||
#endif
|
||||
if (!ok)
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsarena.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -504,7 +505,7 @@ DecompileValueGenerator(JSContext *cx, intN spindex, const Value &v,
|
|||
*/
|
||||
struct Sprinter {
|
||||
JSContext *context; /* context executing the decompiler */
|
||||
LifoAlloc *pool; /* string allocation pool */
|
||||
JSArenaPool *pool; /* string allocation pool */
|
||||
char *base; /* base address of buffer in pool */
|
||||
size_t size; /* size of buffer allocated at base */
|
||||
ptrdiff_t offset; /* offset of next free char in buffer */
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <math.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsarray.h"
|
||||
|
@ -208,9 +209,9 @@ Parser::init(const jschar *base, size_t length, const char *filename, uintN line
|
|||
JSContext *cx = context;
|
||||
if (!cx->ensureParseMapPool())
|
||||
return false;
|
||||
tempPoolMark = cx->tempLifoAlloc().mark();
|
||||
tempPoolMark = JS_ARENA_MARK(&cx->tempPool);
|
||||
if (!tokenStream.init(base, length, filename, lineno, version)) {
|
||||
cx->tempLifoAlloc().release(tempPoolMark);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -222,7 +223,7 @@ Parser::~Parser()
|
|||
|
||||
if (principals)
|
||||
JSPRINCIPALS_DROP(cx, principals);
|
||||
cx->tempLifoAlloc().release(tempPoolMark);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
|
||||
cx->activeCompilations--;
|
||||
}
|
||||
|
||||
|
@ -246,7 +247,8 @@ Parser::newObjectBox(JSObject *obj)
|
|||
* containing the entries must be alive until we are done with scanning,
|
||||
* parsing and code generation for the whole script or top-level function.
|
||||
*/
|
||||
JSObjectBox *objbox = context->tempLifoAlloc().new_<JSObjectBox>();
|
||||
JSObjectBox *objbox;
|
||||
JS_ARENA_ALLOCATE_TYPE(objbox, JSObjectBox, &context->tempPool);
|
||||
if (!objbox) {
|
||||
js_ReportOutOfMemory(context);
|
||||
return NULL;
|
||||
|
@ -271,7 +273,8 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc)
|
|||
* containing the entries must be alive until we are done with scanning,
|
||||
* parsing and code generation for the whole script or top-level function.
|
||||
*/
|
||||
JSFunctionBox *funbox = context->tempLifoAlloc().newPod<JSFunctionBox>();
|
||||
JSFunctionBox *funbox;
|
||||
JS_ARENA_ALLOCATE_TYPE(funbox, JSFunctionBox, &context->tempPool);
|
||||
if (!funbox) {
|
||||
js_ReportOutOfMemory(context);
|
||||
return NULL;
|
||||
|
@ -674,7 +677,8 @@ NewOrRecycledNode(JSTreeContext *tc)
|
|||
pn = tc->parser->nodeList;
|
||||
if (!pn) {
|
||||
JSContext *cx = tc->parser->context;
|
||||
pn = cx->tempLifoAlloc().new_<JSParseNode>();
|
||||
|
||||
JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool);
|
||||
if (!pn)
|
||||
js_ReportOutOfMemory(cx);
|
||||
} else {
|
||||
|
|
|
@ -159,8 +159,6 @@ class UpvarCookie;
|
|||
class TempAllocPolicy;
|
||||
class RuntimeAllocPolicy;
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
template <class T,
|
||||
size_t MinInlineCapacity = 0,
|
||||
class AllocPolicy = TempAllocPolicy>
|
||||
|
@ -185,8 +183,6 @@ template <typename K,
|
|||
size_t InlineElems>
|
||||
class InlineMap;
|
||||
|
||||
class LifoAlloc;
|
||||
|
||||
class PropertyCache;
|
||||
struct PropertyCacheEntry;
|
||||
|
||||
|
@ -214,26 +210,6 @@ typedef JSPropertyOp PropertyOp;
|
|||
typedef JSStrictPropertyOp StrictPropertyOp;
|
||||
typedef JSPropertyDescriptor PropertyDescriptor;
|
||||
|
||||
namespace analyze {
|
||||
|
||||
struct LifetimeVariable;
|
||||
class LoopAnalysis;
|
||||
class ScriptAnalysis;
|
||||
class SlotValue;
|
||||
class SSAValue;
|
||||
class SSAUseChain;
|
||||
|
||||
} /* namespace analyze */
|
||||
|
||||
namespace types {
|
||||
|
||||
class TypeSet;
|
||||
struct TypeCallsite;
|
||||
struct TypeObject;
|
||||
struct TypeCompartment;
|
||||
|
||||
} /* namespace types */
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
} /* export "C++" */
|
||||
|
|
|
@ -149,6 +149,7 @@ class RegExp
|
|||
void reportPCREError(JSContext *cx, int error);
|
||||
#endif
|
||||
void reportYarrError(JSContext *cx, TokenStream *ts, JSC::Yarr::ErrorCode error);
|
||||
static inline bool initArena(JSContext *cx);
|
||||
static inline void checkMatchPairs(JSString *input, int *buf, size_t matchItemCount);
|
||||
static JSObject *createResult(JSContext *cx, JSString *input, int *buf, size_t matchItemCount);
|
||||
inline bool executeInternal(JSContext *cx, RegExpStatics *res, JSString *input,
|
||||
|
@ -254,6 +255,27 @@ class RegExpMatchBuilder
|
|||
|
||||
/* RegExp inlines. */
|
||||
|
||||
inline bool
|
||||
RegExp::initArena(JSContext *cx)
|
||||
{
|
||||
if (cx->regExpPool.first.next)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* The regular expression arena pool is special... we want to hang on to it
|
||||
* until a GC is performed so rapid subsequent regexp executions don't
|
||||
* thrash malloc/freeing arena chunks.
|
||||
*
|
||||
* Stick a timestamp at the base of that pool.
|
||||
*/
|
||||
int64 *timestamp;
|
||||
JS_ARENA_ALLOCATE_CAST(timestamp, int64 *, &cx->regExpPool, sizeof *timestamp);
|
||||
if (!timestamp)
|
||||
return false;
|
||||
*timestamp = JS_Now();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
RegExp::checkMatchPairs(JSString *input, int *buf, size_t matchItemCount)
|
||||
{
|
||||
|
@ -317,8 +339,11 @@ RegExp::executeInternal(JSContext *cx, RegExpStatics *res, JSString *inputstr,
|
|||
const size_t bufCount = pairCount * 3; /* Should be x2, but PCRE has... needs. */
|
||||
const size_t matchItemCount = pairCount * 2;
|
||||
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
int *buf = cx->tempLifoAlloc().newArray<int>(bufCount);
|
||||
if (!initArena(cx))
|
||||
return false;
|
||||
|
||||
AutoArenaAllocator aaa(&cx->regExpPool);
|
||||
int *buf = aaa.alloc<int>(bufCount);
|
||||
if (!buf)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsprf.h"
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include <string.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsclist.h"
|
||||
#include "jsdhash.h"
|
||||
|
|
|
@ -384,7 +384,14 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||
Bindings bindings(cx);
|
||||
uint32 nameCount = nargs + nvars + nupvars;
|
||||
if (nameCount > 0) {
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
struct AutoMark {
|
||||
JSArenaPool * const pool;
|
||||
void * const mark;
|
||||
AutoMark(JSArenaPool *pool) : pool(pool), mark(JS_ARENA_MARK(pool)) { }
|
||||
~AutoMark() {
|
||||
JS_ARENA_RELEASE(pool, mark);
|
||||
}
|
||||
} automark(&cx->tempPool);
|
||||
|
||||
/*
|
||||
* To xdr the names we prefix the names with a bitmap descriptor and
|
||||
|
@ -395,7 +402,9 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp)
|
|||
* name is declared as const, not as ordinary var.
|
||||
* */
|
||||
uintN bitmapLength = JS_HOWMANY(nameCount, JS_BITS_PER_UINT32);
|
||||
uint32 *bitmap = cx->tempLifoAlloc().newArray<uint32>(bitmapLength);
|
||||
uint32 *bitmap;
|
||||
JS_ARENA_ALLOCATE_CAST(bitmap, uint32 *, &cx->tempPool,
|
||||
bitmapLength * sizeof *bitmap);
|
||||
if (!bitmap) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
|
|
|
@ -146,6 +146,8 @@ typedef struct JSConstArray {
|
|||
uint32 length;
|
||||
} JSConstArray;
|
||||
|
||||
struct JSArenaPool;
|
||||
|
||||
namespace js {
|
||||
|
||||
struct GlobalSlotArray {
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
#ifndef jstl_h_
|
||||
#define jstl_h_
|
||||
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsbit.h"
|
||||
#include "jsstaticcheck.h"
|
||||
#include "jsstdint.h"
|
||||
|
@ -167,7 +167,6 @@ template <> struct IsPodType<long long> { static const bool result =
|
|||
template <> struct IsPodType<unsigned long long> { static const bool result = true; };
|
||||
template <> struct IsPodType<float> { static const bool result = true; };
|
||||
template <> struct IsPodType<double> { static const bool result = true; };
|
||||
template <> struct IsPodType<wchar_t> { static const bool result = true; };
|
||||
template <typename T> struct IsPodType<T *> { static const bool result = true; };
|
||||
|
||||
/* Return the size/end of an array without using macros. */
|
||||
|
|
|
@ -7390,9 +7390,9 @@ TraceRecorder::monitorRecording(JSOp op)
|
|||
|
||||
debug_only_stmt(
|
||||
if (LogController.lcbits & LC_TMRecorder) {
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
|
||||
debug_only_print0(LC_TMRecorder, "\n");
|
||||
js_Disassemble1(cx, cx->fp()->script(), cx->regs().pc,
|
||||
|
@ -7401,6 +7401,7 @@ TraceRecorder::monitorRecording(JSOp op)
|
|||
!cx->fp()->hasImacropc(), &sprinter);
|
||||
|
||||
fprintf(stdout, "%s", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -10414,13 +10415,14 @@ TraceRecorder::record_EnterFrame()
|
|||
callDepth);
|
||||
debug_only_stmt(
|
||||
if (LogController.lcbits & LC_TMRecorder) {
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
|
||||
js_Disassemble(cx, cx->fp()->script(), JS_TRUE, &sprinter);
|
||||
|
||||
debug_only_printf(LC_TMTracer, "%s", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
debug_only_print0(LC_TMTracer, "----\n");
|
||||
}
|
||||
)
|
||||
|
|
|
@ -70,8 +70,6 @@ using namespace mozilla;
|
|||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define JS_UPTRDIFF(a_, b_) (uintptr_t(a_) - uintptr_t(b_))
|
||||
|
||||
#define JS_CRASH_UNLESS(__cond) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!(__cond)) { \
|
||||
|
|
|
@ -1462,12 +1462,13 @@ public:
|
|||
JS_BEGIN_MACRO \
|
||||
if (IsJaegerSpewChannelActive(JSpew_JSOps)) { \
|
||||
JaegerSpew(JSpew_JSOps, " %2d ", frame.stackDepth()); \
|
||||
LifoAllocScope las(&cx->tempLifoAlloc()); \
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool); \
|
||||
Sprinter sprinter; \
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0); \
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0); \
|
||||
js_Disassemble1(cx, script, PC, PC - script->code, \
|
||||
JS_TRUE, &sprinter); \
|
||||
fprintf(stdout, "%s", sprinter.base); \
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark); \
|
||||
} \
|
||||
JS_END_MACRO;
|
||||
#else
|
||||
|
@ -6682,7 +6683,7 @@ mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow, bool *tramp
|
|||
if (cx->typeInferenceEnabled()) {
|
||||
RegisterAllocation *&alloc = analysis->getAllocation(target);
|
||||
if (!alloc) {
|
||||
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
|
||||
alloc = ArenaNew<RegisterAllocation>(cx->compartment->pool, false);
|
||||
if (!alloc)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -575,7 +575,7 @@ RegisterAllocation *
|
|||
FrameState::computeAllocation(jsbytecode *target)
|
||||
{
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
RegisterAllocation *alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
|
||||
RegisterAllocation *alloc = ArenaNew<RegisterAllocation>(cx->compartment->pool, false);
|
||||
if (!alloc)
|
||||
return NULL;
|
||||
|
||||
|
@ -853,7 +853,7 @@ FrameState::discardForJoin(RegisterAllocation *&alloc, uint32 stackDepth)
|
|||
* This shows up for loop entries which are not reachable from the
|
||||
* loop head, and for exception, switch target and trap safe points.
|
||||
*/
|
||||
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
|
||||
alloc = ArenaNew<RegisterAllocation>(cx->compartment->pool, false);
|
||||
if (!alloc)
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ LoopState::init(jsbytecode *head, Jump entry, jsbytecode *entryTarget)
|
|||
RegisterAllocation *&alloc = outerAnalysis->getAllocation(head);
|
||||
JS_ASSERT(!alloc);
|
||||
|
||||
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(true);
|
||||
alloc = ArenaNew<RegisterAllocation>(cx->compartment->pool, true);
|
||||
if (!alloc)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include <locale.h>
|
||||
#include "jstypes.h"
|
||||
#include "jsstdint.h"
|
||||
#include "jsarena.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsprf.h"
|
||||
#include "jswrapper.h"
|
||||
|
@ -1954,13 +1955,16 @@ SrcNotes(JSContext *cx, JSScript *script, Sprinter *sp)
|
|||
static JSBool
|
||||
Notes(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
uintN i;
|
||||
JSScript *script;
|
||||
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
|
||||
jsval *argv = JS_ARGV(cx, vp);
|
||||
for (uintN i = 0; i < argc; i++) {
|
||||
JSScript *script = ValueToScript(cx, argv[i]);
|
||||
for (i = 0; i < argc; i++) {
|
||||
script = ValueToScript(cx, argv[i]);
|
||||
if (!script)
|
||||
continue;
|
||||
|
||||
|
@ -1968,6 +1972,7 @@ Notes(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
JSString *str = JS_NewStringCopyZ(cx, sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
|
||||
|
@ -2108,9 +2113,9 @@ DisassembleToString(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!p.parse(cx))
|
||||
return false;
|
||||
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
Sprinter *sp = &sprinter;
|
||||
|
||||
bool ok = true;
|
||||
|
@ -2134,6 +2139,7 @@ DisassembleToString(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
JSString *str = ok ? JS_NewStringCopyZ(cx, sprinter.base) : NULL;
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!str)
|
||||
return false;
|
||||
JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
|
||||
|
@ -2147,9 +2153,9 @@ Disassemble(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!p.parse(cx))
|
||||
return false;
|
||||
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
Sprinter *sp = &sprinter;
|
||||
|
||||
bool ok = true;
|
||||
|
@ -2174,6 +2180,7 @@ Disassemble(JSContext *cx, uintN argc, jsval *vp)
|
|||
|
||||
if (ok)
|
||||
fprintf(stdout, "%s\n", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return ok;
|
||||
}
|
||||
|
@ -2209,12 +2216,13 @@ DisassFile(JSContext *cx, uintN argc, jsval *vp)
|
|||
if (!script)
|
||||
return false;
|
||||
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
|
||||
bool ok = DisassembleScript(cx, script, NULL, p.lines, p.recursive, &sprinter);
|
||||
if (ok)
|
||||
fprintf(stdout, "%s\n", sprinter.base);
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
|
@ -2258,17 +2266,18 @@ DisassWithSrc(JSContext *cx, uintN argc, jsval *vp)
|
|||
pc = script->code;
|
||||
end = pc + script->length;
|
||||
|
||||
LifoAllocScope las(&cx->tempLifoAlloc());
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
Sprinter sprinter;
|
||||
Sprinter *sp = &sprinter;
|
||||
INIT_SPRINTER(cx, sp, &cx->tempLifoAlloc(), 0);
|
||||
INIT_SPRINTER(cx, sp, &cx->tempPool, 0);
|
||||
|
||||
/* burn the leading lines */
|
||||
line2 = JS_PCToLineNumber(cx, script, pc);
|
||||
for (line1 = 0; line1 < line2 - 1; line1++) {
|
||||
char *tmp = fgets(linebuf, LINE_BUF_LEN, file);
|
||||
if (!tmp) {
|
||||
JS_ReportError(cx, "failed to read %s fully", script->filename);
|
||||
JS_ReportError(cx, "failed to read %s fully",
|
||||
script->filename);
|
||||
ok = JS_FALSE;
|
||||
goto bail;
|
||||
}
|
||||
|
@ -2309,6 +2318,7 @@ DisassWithSrc(JSContext *cx, uintN argc, jsval *vp)
|
|||
}
|
||||
|
||||
bail:
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
fclose(file);
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
|
|
|
@ -183,7 +183,6 @@ struct DebugOnly
|
|||
DebugOnly& operator=(const T&) { return *this; }
|
||||
void operator++(int) {}
|
||||
void operator--(int) {}
|
||||
bool operator<(const T&) { return false; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче