Bug 634155: Account for NewCompartment's memory, and change allocation APIs (r=nnethercote)

This changes the allocation API, in the following way:

  js_malloc -> {cx->,rt->,OffTheBooks::}malloc
  js_calloc -> {cx->,rt->,OffTheBooks::}calloc
  js_realloc -> {cx->,rt->,OffTheBooks::}realloc
  js_free -> {cx->,rt->,Foreground::,UnwantedForeground::}free
  js_new -> {cx->,rt->,OffTheBooks::}new_
  js_new_array -> {cx->,rt->,OffTheBooks::}new_array
  js_delete -> {cx->,rt->,Foreground::,UnwantedForeground::}delete_

This is to move as many allocations as possible through a JSContext (so that they may be aken into account by gcMallocBytes) and to move as many deallocations to the background as possible (except on error paths).
This commit is contained in:
Paul Biggar 2011-03-31 01:13:49 -07:00
Родитель 1b3a06bc73
Коммит 1e46fe8cee
57 изменённых файлов: 701 добавлений и 419 удалений

44
config/check_source_count.py Executable file
Просмотреть файл

@ -0,0 +1,44 @@
#!/usr/bin/env python
# Usage: check_source_count.py SEARCH_TERM COUNT ERROR_LOCATION REPLACEMENT [FILES...]
# Checks that FILES contains exactly COUNT matches of SEARCH_TERM. If it does
# not, an error message is printed, quoting ERROR_LOCATION, which should
# probably be the filename and line number of the erroneous call to
# check_source_count.py.
import sys
import os
import re
search_string = sys.argv[1]
expected_count = int(sys.argv[2])
error_location = sys.argv[3]
replacement = sys.argv[4]
files = sys.argv[5:]
details = {}
count = 0
for f in files:
text = file(f).read()
match = re.findall(search_string, text)
if match:
num = len(match)
count += num
details[f] = num
if count == expected_count:
print "TEST-PASS | check_source_count.py %s | %d" % (search_string, expected_count)
else:
print "TEST-UNEXPECTED-FAIL | check_source_count.py %s | " % (search_string),
if count < expected_count:
print "There are less occurences of /%s/ than expected. This may mean that you have removed some, but forgotten to account for it %s." % (search_string, error_location)
else:
print "There are more occurences of /%s/ than expected. We're trying to prevent an increase in the number of %s's, using %s if possible. If it in unavoidable, you should update the expected count %s." % (search_string, search_string, replacement, error_location)
print "Expected: %d; found: %d" % (expected_count, count)
for k in sorted(details):
print "Found %d occurences in %s" % (details[k],k)
sys.exit(-1)

Просмотреть файл

@ -19,7 +19,7 @@
#
# If this script fails:
# - You need to find the uses of vanilla new/delete and replace them with
# js_new()/js_delete().
# {js::OffTheBooks,JSContext,JSRuntime}::{new_,/array_new}.
# - Run this script on each of the .o files, that should narrow it down.
# - After that, one way to find them is to run 'objdump -r -C' on the
# relevant .o files. For example, you might search for 'operator new' and

Просмотреть файл

@ -592,11 +592,40 @@ endif
# number to go down over time, by fixing OOMs.
ifdef DEBUG
check-ooms:
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/config/find_OOM_errors.py --regression 129
$(wildcard $(RUN_TEST_PROGRAM)) $(PYTHON) -u $(srcdir)/config/find_OOM_errors.py --regression 125
check:: check-ooms
endif
## Prevent regressing in our deprecation of non-preferred memory management functions.
# We use all the files in the distribution so that different configurations
# don't give different results. We skip the contents of objdirs using |find|
# (it can't be done with %-expansion, because the files we want to skip aren't
# in the vpath).
ALL_FILES=$(shell find $(srcdir) \( -name "*.cpp" -o -name "*.h" \) -not -path "*/dist/*")
check-malloc-function-usage: $(filter-out %jsutil.h %jscntxt.h, $(ALL_FILES))
# js_malloc and friends are only used by other memory managers, and should
# never be used elsewhere directly.
$(srcdir)/config/check_source_count.py "\bjs_malloc\b" 0 \
"in Makefile.in" "cx->malloc_ or rt->malloc_" $^
$(srcdir)/config/check_source_count.py "\bjs_calloc\b" 0 \
"in Makefile.in" "cx->calloc_ or rt->calloc_" $^
$(srcdir)/config/check_source_count.py "\bjs_realloc\b" 0 \
"in Makefile.in" "cx->realloc_ or rt->realloc_" $^
$(srcdir)/config/check_source_count.py "\bjs_free\b" 0 \
"in Makefile.in" "cx->free_" $^
# We desire these numbers to go down, not up. See "User guide to memory
# management within SpiderMonkey" in jsutil.h.
$(srcdir)/config/check_source_count.py OffTheBooks:: 54 \
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
# This should go to zero, if possible.
$(srcdir)/config/check_source_count.py UnwantedForeground:: 36 \
"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^
check:: check-malloc-function-usage
ifndef WINCE
JITFLAGS = ,m,j,mj,mjp,am,amj,amjp,amd
check::

Просмотреть файл

@ -70,6 +70,8 @@ namespace JSC {
// These are reference-counted. A new one starts with a count of 1.
class ExecutablePool {
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
friend class ExecutableAllocator;
private:
struct Allocation {
@ -100,9 +102,7 @@ public:
JS_ASSERT(m_refCount != 0);
JS_ASSERT_IF(willDestroy, m_refCount = 1);
if (--m_refCount == 0) {
/* We can't (easily) use js_delete() here because the destructor is private. */
this->~ExecutablePool();
js_free(this);
js::UnwantedForeground::delete_(this);
}
}
@ -236,9 +236,7 @@ private:
if (!a.pages)
return NULL;
/* We can't (easily) use js_new() here because the constructor is private. */
void *memory = js_malloc(sizeof(ExecutablePool));
return memory ? new(memory) ExecutablePool(a) : NULL;
return js::OffTheBooks::new_<ExecutablePool>(a);
}
ExecutablePool* poolForSize(size_t n)

Просмотреть файл

@ -0,0 +1,44 @@
#!/usr/bin/env python
# Usage: check_source_count.py SEARCH_TERM COUNT ERROR_LOCATION REPLACEMENT [FILES...]
# Checks that FILES contains exactly COUNT matches of SEARCH_TERM. If it does
# not, an error message is printed, quoting ERROR_LOCATION, which should
# probably be the filename and line number of the erroneous call to
# check_source_count.py.
import sys
import os
import re
search_string = sys.argv[1]
expected_count = int(sys.argv[2])
error_location = sys.argv[3]
replacement = sys.argv[4]
files = sys.argv[5:]
details = {}
count = 0
for f in files:
text = file(f).read()
match = re.findall(search_string, text)
if match:
num = len(match)
count += num
details[f] = num
if count == expected_count:
print "TEST-PASS | check_source_count.py %s | %d" % (search_string, expected_count)
else:
print "TEST-UNEXPECTED-FAIL | check_source_count.py %s | " % (search_string),
if count < expected_count:
print "There are less occurences of /%s/ than expected. This may mean that you have removed some, but forgotten to account for it %s." % (search_string, error_location)
else:
print "There are more occurences of /%s/ than expected. We're trying to prevent an increase in the number of %s's, using %s if possible. If it in unavoidable, you should update the expected count %s." % (search_string, search_string, replacement, error_location)
print "Expected: %d; found: %d" % (expected_count, count)
for k in sorted(details):
print "Found %d occurences in %s" % (details[k],k)
sys.exit(-1)

Просмотреть файл

@ -19,7 +19,7 @@
#
# If this script fails:
# - You need to find the uses of vanilla new/delete and replace them with
# js_new()/js_delete().
# {js::OffTheBooks,JSContext,JSRuntime}::{new_,/array_new}.
# - Run this script on each of the .o files, that should narrow it down.
# - After that, one way to find them is to run 'objdump -r -C' on the
# relevant .o files. For example, you might search for 'operator new' and

Просмотреть файл

@ -1844,7 +1844,7 @@ ImplicitConvert(JSContext* cx,
return false;
char** charBuffer = static_cast<char**>(buffer);
*charBuffer = js_array_new<char>(nbytes + 1);
*charBuffer = cx->array_new<char>(nbytes + 1);
if (!*charBuffer) {
JS_ReportAllocationOverflow(cx);
return false;
@ -1861,7 +1861,7 @@ ImplicitConvert(JSContext* cx,
// JSString's buffer, but this approach is safer if the caller happens
// to modify the string.)
jschar** jscharBuffer = static_cast<jschar**>(buffer);
*jscharBuffer = js_array_new<jschar>(sourceLength + 1);
*jscharBuffer = cx->array_new<jschar>(sourceLength + 1);
if (!*jscharBuffer) {
JS_ReportAllocationOverflow(cx);
return false;
@ -1946,7 +1946,7 @@ ImplicitConvert(JSContext* cx,
// Convert into an intermediate, in case of failure.
size_t elementSize = CType::GetSize(cx, baseType);
size_t arraySize = elementSize * targetLength;
AutoPtr<char>::Array intermediate(js_array_new<char>(arraySize));
AutoPtr<char>::Array intermediate(cx->array_new<char>(arraySize));
if (!intermediate) {
JS_ReportAllocationOverflow(cx);
return false;
@ -1983,7 +1983,7 @@ ImplicitConvert(JSContext* cx,
// Convert into an intermediate, in case of failure.
size_t structSize = CType::GetSize(cx, targetType);
AutoPtr<char>::Array intermediate(js_array_new<char>(structSize));
AutoPtr<char>::Array intermediate(cx->array_new<char>(structSize));
if (!intermediate) {
JS_ReportAllocationOverflow(cx);
return false;
@ -2702,7 +2702,7 @@ CType::Finalize(JSContext* cx, JSObject* obj)
// Free the FunctionInfo.
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FNINFO, &slot));
if (!JSVAL_IS_VOID(slot))
js_delete(static_cast<FunctionInfo*>(JSVAL_TO_PRIVATE(slot)));
cx->delete_(static_cast<FunctionInfo*>(JSVAL_TO_PRIVATE(slot)));
break;
}
@ -2711,7 +2711,7 @@ CType::Finalize(JSContext* cx, JSObject* obj)
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FIELDINFO, &slot));
if (!JSVAL_IS_VOID(slot)) {
void* info = JSVAL_TO_PRIVATE(slot);
js_delete(static_cast<FieldInfoHash*>(info));
cx->delete_(static_cast<FieldInfoHash*>(info));
}
}
@ -2721,8 +2721,8 @@ CType::Finalize(JSContext* cx, JSObject* obj)
ASSERT_OK(JS_GetReservedSlot(cx, obj, SLOT_FFITYPE, &slot));
if (!JSVAL_IS_VOID(slot)) {
ffi_type* ffiType = static_cast<ffi_type*>(JSVAL_TO_PRIVATE(slot));
js_array_delete(ffiType->elements);
js_delete(ffiType);
cx->array_delete(ffiType->elements);
cx->delete_(ffiType);
}
break;
@ -3701,7 +3701,7 @@ ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
// values. It would be nice to not do all the work of setting up 'elements',
// but some libffi platforms currently require that it be meaningful. I'm
// looking at you, x86_64.
AutoPtr<ffi_type> ffiType(js_new<ffi_type>());
AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
if (!ffiType) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -3710,7 +3710,7 @@ ArrayType::BuildFFIType(JSContext* cx, JSObject* obj)
ffiType->type = FFI_TYPE_STRUCT;
ffiType->size = CType::GetSize(cx, obj);
ffiType->alignment = CType::GetAlignment(cx, obj);
ffiType->elements = js_array_new<ffi_type*>(length + 1);
ffiType->elements = cx->array_new<ffi_type*>(length + 1);
if (!ffiType->elements) {
JS_ReportAllocationOverflow(cx);
return NULL;
@ -4033,7 +4033,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj, JSObject* fieldsObj
// its constituents. (We cannot simply stash the hash in a reserved slot now
// to get GC safety for free, since if anything in this function fails we
// do not want to mutate 'typeObj'.)
AutoPtr<FieldInfoHash> fields(js_new<FieldInfoHash>());
AutoPtr<FieldInfoHash> fields(cx->new_<FieldInfoHash>());
Array<jsval, 16> fieldRootsArray;
if (!fields || !fields->init(len) || !fieldRootsArray.appendN(JSVAL_VOID, len)) {
JS_ReportOutOfMemory(cx);
@ -4142,7 +4142,7 @@ StructType::BuildFFIType(JSContext* cx, JSObject* obj)
size_t structSize = CType::GetSize(cx, obj);
size_t structAlign = CType::GetAlignment(cx, obj);
AutoPtr<ffi_type> ffiType(js_new<ffi_type>());
AutoPtr<ffi_type> ffiType(cx->new_<ffi_type>());
if (!ffiType) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -4151,7 +4151,7 @@ StructType::BuildFFIType(JSContext* cx, JSObject* obj)
AutoPtr<ffi_type*>::Array elements;
if (len != 0) {
elements = js_array_new<ffi_type*>(len + 1);
elements = cx->array_new<ffi_type*>(len + 1);
if (!elements) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -4170,7 +4170,7 @@ StructType::BuildFFIType(JSContext* cx, JSObject* obj)
// Represent an empty struct as having a size of 1 byte, just like C++.
JS_ASSERT(structSize == 1);
JS_ASSERT(structAlign == 1);
elements = js_array_new<ffi_type*>(2);
elements = cx->array_new<ffi_type*>(2);
if (!elements) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -4511,14 +4511,14 @@ struct AutoValue
~AutoValue()
{
js_array_delete(static_cast<char*>(mData));
UnwantedForeground::array_delete(static_cast<char*>(mData));
}
bool SizeToType(JSContext* cx, JSObject* type)
{
// Allocate a minimum of sizeof(ffi_arg) to handle small integers.
size_t size = Align(CType::GetSize(cx, type), sizeof(ffi_arg));
mData = js_array_new<char>(size);
mData = cx->array_new<char>(size);
if (mData)
memset(mData, 0, size);
return mData != NULL;
@ -4723,7 +4723,7 @@ NewFunctionInfo(JSContext* cx,
jsval* argTypes,
uintN argLength)
{
AutoPtr<FunctionInfo> fninfo(js_new<FunctionInfo>());
AutoPtr<FunctionInfo> fninfo(cx->new_<FunctionInfo>());
if (!fninfo) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -5199,7 +5199,7 @@ CClosure::Create(JSContext* cx,
JS_ASSERT(!fninfo->mIsVariadic);
JS_ASSERT(GetABICode(cx, fninfo->mABI) != ABI_WINAPI);
AutoPtr<ClosureInfo> cinfo(js_new<ClosureInfo>());
AutoPtr<ClosureInfo> cinfo(cx->new_<ClosureInfo>());
if (!cinfo) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -5312,7 +5312,7 @@ CClosure::Finalize(JSContext* cx, JSObject* obj)
if (cinfo->closure)
ffi_closure_free(cinfo->closure);
js_delete(cinfo);
cx->delete_(cinfo);
}
void
@ -5489,7 +5489,7 @@ CData::Create(JSContext* cx,
// attach the buffer. since it might not be 2-byte aligned, we need to
// allocate an aligned space for it and store it there. :(
char** buffer = js_new<char*>();
char** buffer = cx->new_<char*>();
if (!buffer) {
JS_ReportOutOfMemory(cx);
return NULL;
@ -5501,11 +5501,11 @@ CData::Create(JSContext* cx,
} else {
// Initialize our own buffer.
size_t size = CType::GetSize(cx, typeObj);
data = js_array_new<char>(size);
data = cx->array_new<char>(size);
if (!data) {
// Report a catchable allocation error.
JS_ReportAllocationOverflow(cx);
js_delete(buffer);
Foreground::delete_(buffer);
return NULL;
}
@ -5518,8 +5518,8 @@ CData::Create(JSContext* cx,
*buffer = data;
if (!JS_SetReservedSlot(cx, dataObj, SLOT_DATA, PRIVATE_TO_JSVAL(buffer))) {
if (ownResult)
js_array_delete(data);
js_delete(buffer);
Foreground::array_delete(data);
Foreground::delete_(buffer);
return NULL;
}
@ -5541,8 +5541,8 @@ CData::Finalize(JSContext* cx, JSObject* obj)
char** buffer = static_cast<char**>(JSVAL_TO_PRIVATE(slot));
if (owns)
js_array_delete(*buffer);
js_delete(buffer);
cx->array_delete(*buffer);
cx->delete_(buffer);
}
JSObject*
@ -5826,14 +5826,14 @@ Int64Base::Construct(JSContext* cx,
js::AutoObjectRooter root(cx, result);
// attach the Int64's data
JSUint64* buffer = js_new<JSUint64>(data);
JSUint64* buffer = cx->new_<JSUint64>(data);
if (!buffer) {
JS_ReportOutOfMemory(cx);
return NULL;
}
if (!JS_SetReservedSlot(cx, result, SLOT_INT64, PRIVATE_TO_JSVAL(buffer))) {
js_delete(buffer);
Foreground::delete_(buffer);
return NULL;
}
@ -5850,7 +5850,7 @@ Int64Base::Finalize(JSContext* cx, JSObject* obj)
if (!JS_GetReservedSlot(cx, obj, SLOT_INT64, &slot) || JSVAL_IS_VOID(slot))
return;
js_delete(static_cast<JSUint64*>(JSVAL_TO_PRIVATE(slot)));
cx->delete_(static_cast<JSUint64*>(JSVAL_TO_PRIVATE(slot)));
}
JSUint64

Просмотреть файл

@ -56,18 +56,18 @@ template<class T>
class OperatorDelete
{
public:
static void destroy(T* ptr) { js_delete(ptr); }
static void destroy(T* ptr) { UnwantedForeground::delete_(ptr); }
};
template<class T>
class OperatorArrayDelete
{
public:
static void destroy(T* ptr) { js_array_delete(ptr); }
static void destroy(T* ptr) { UnwantedForeground::array_delete(ptr); }
};
// Class that takes ownership of a pointer T*, and calls js_delete() or
// js_array_delete() upon destruction.
// Class that takes ownership of a pointer T*, and calls cx->delete_() or
// cx->array_delete() upon destruction.
template<class T, class DeleteTraits = OperatorDelete<T> >
class AutoPtr {
private:

Двоичные данные
js/src/js.mdp

Двоичный файл не отображается.

Просмотреть файл

@ -669,13 +669,19 @@ JSRuntime::init(uint32 maxbytes)
propTreeDumpFilename = getenv("JS_PROPTREE_DUMPFILE");
#endif
if (!(atomsCompartment = js_new<JSCompartment>(this)) ||
if (!js_InitGC(this, maxbytes))
return false;
if (!(atomsCompartment = this->new_<JSCompartment>(this)) ||
!atomsCompartment->init() ||
!compartments.append(atomsCompartment)) {
Foreground::delete_(atomsCompartment);
return false;
}
if (!js_InitGC(this, maxbytes) || !js_InitAtomState(this))
atomsCompartment->setGCLastBytes(8192);
if (!js_InitAtomState(this))
return false;
wrapObjectCallback = js::TransparentObjectWrapper;
@ -774,7 +780,7 @@ JS_NewRuntime(uint32 maxbytes)
}
#endif /* DEBUG */
void *mem = js_calloc(sizeof(JSRuntime));
void *mem = OffTheBooks::calloc(sizeof(JSRuntime));
if (!mem)
return NULL;
@ -790,9 +796,7 @@ JS_NewRuntime(uint32 maxbytes)
JS_PUBLIC_API(void)
JS_DestroyRuntime(JSRuntime *rt)
{
rt->~JSRuntime();
js_free(rt);
Foreground::delete_(rt);
}
#ifdef JS_REPRMETER
@ -1198,11 +1202,11 @@ JS_EnterCrossCompartmentCall(JSContext *cx, JSObject *target)
CHECK_REQUEST(cx);
JS_ASSERT(target);
AutoCompartment *call = js_new<AutoCompartment>(cx, target);
AutoCompartment *call = cx->new_<AutoCompartment>(cx, target);
if (!call)
return NULL;
if (!call->enter()) {
js_delete(call);
Foreground::delete_(call);
return NULL;
}
return reinterpret_cast<JSCrossCompartmentCall *>(call);
@ -1240,7 +1244,7 @@ JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
AutoCompartment *realcall = reinterpret_cast<AutoCompartment *>(call);
CHECK_REQUEST(realcall->context);
realcall->leave();
js_delete(realcall);
Foreground::delete_(realcall);
}
bool
@ -2472,7 +2476,7 @@ DumpNotify(JSTracer *trc, void *thing, uint32 kind)
}
edgeNameSize = strlen(edgeName) + 1;
node = (JSHeapDumpNode *) js_malloc(offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
node = (JSHeapDumpNode *) cx->malloc(offsetof(JSHeapDumpNode, edgeName) + edgeNameSize);
if (!node) {
dtrc->ok = JS_FALSE;
return;
@ -2624,7 +2628,7 @@ JS_DumpHeap(JSContext *cx, FILE *fp, void* startThing, uint32 startKind,
for (;;) {
next = node->next;
parent = node->parent;
js_free(node);
cx->free(node);
node = next;
if (node)
break;
@ -4670,7 +4674,7 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
bool hitEOF = false;
while (!hitEOF) {
len *= 2;
jschar* tmpbuf = (jschar *) js_realloc(buf, len * sizeof(jschar));
jschar* tmpbuf = (jschar *) cx->realloc(buf, len * sizeof(jschar));
if (!tmpbuf) {
cx->free(buf);
return NULL;
@ -4687,7 +4691,7 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
}
}
} else {
buf = (jschar *) js_malloc(len * sizeof(jschar));
buf = (jschar *) cx->malloc(len * sizeof(jschar));
if (!buf)
return NULL;
@ -4701,7 +4705,7 @@ CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT;
script = Compiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len, filename, 1,
cx->findVersion());
js_free(buf);
cx->free(buf);
if (!script)
return NULL;

Просмотреть файл

@ -47,7 +47,6 @@
#include <stdio.h>
#include "js-config.h"
#include "jspubtd.h"
#include "jsutil.h"
JS_BEGIN_EXTERN_C
@ -3238,7 +3237,7 @@ class JSAutoByteString {
}
~JSAutoByteString() {
js_free(mBytes);
js::UnwantedForeground::free(mBytes);
}
/* Take ownership of the given byte array. */
@ -3255,7 +3254,7 @@ class JSAutoByteString {
}
void clear() {
js_free(mBytes);
js::UnwantedForeground::free(mBytes);
mBytes = NULL;
}
@ -3328,7 +3327,7 @@ JS_ReadStructuredClone(JSContext *cx, const uint64 *data, size_t nbytes,
const JSStructuredCloneCallbacks *optionalCallbacks,
void *closure);
/* Note: On success, the caller is responsible for calling js_free(*datap). */
/* Note: On success, the caller is responsible for calling js::Foreground::free(*datap). */
JS_PUBLIC_API(JSBool)
JS_WriteStructuredClone(JSContext *cx, jsval v, uint64 **datap, size_t *nbytesp,
const JSStructuredCloneCallbacks *optionalCallbacks,

Просмотреть файл

@ -50,6 +50,8 @@
#include "jsarena.h"
#include "jsprvtd.h"
using namespace js;
#ifdef JS_ARENAMETER
static JSArenaStats *arena_stats_list;
@ -160,12 +162,12 @@ JS_ArenaAllocate(JSArenaPool *pool, size_t nb)
if (pool->quotap) {
if (gross > *pool->quotap)
return NULL;
b = (JSArena *) js_malloc(gross);
b = (JSArena *) OffTheBooks::malloc(gross);
if (!b)
return NULL;
*pool->quotap -= gross;
} else {
b = (JSArena *) js_malloc(gross);
b = (JSArena *) OffTheBooks::malloc(gross);
if (!b)
return NULL;
}
@ -227,12 +229,12 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
growth = gross - (a->limit - (jsuword) a);
if (growth > *pool->quotap)
return NULL;
a = (JSArena *) js_realloc(a, gross);
a = (JSArena *) OffTheBooks::realloc(a, gross);
if (!a)
return NULL;
*pool->quotap -= growth;
} else {
a = (JSArena *) js_realloc(a, gross);
a = (JSArena *) OffTheBooks::realloc(a, gross);
if (!a)
return NULL;
}
@ -315,7 +317,7 @@ FreeArenaList(JSArenaPool *pool, JSArena *head)
*pool->quotap += a->limit - (jsuword) a;
JS_CLEAR_ARENA(a);
JS_COUNT_ARENA(pool,--);
js_free(a);
UnwantedForeground::free(a);
} while ((a = *ap) != NULL);
pool->current = head;
@ -354,7 +356,7 @@ JS_FinishArenaPool(JSArenaPool *pool)
JSArenaStats *stats, **statsp;
if (pool->stats.name) {
js_free(pool->stats.name);
UnwantedForeground::free(pool->stats.name);
pool->stats.name = NULL;
}
for (statsp = &arena_stats_list; (stats = *statsp) != 0;

Просмотреть файл

@ -202,7 +202,7 @@ struct JSArenaPool {
if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
*(pnext) = (a)->next; \
JS_CLEAR_ARENA(a); \
js_free(a); \
js::UnwantedForeground::free(a); \
(a) = NULL; \
JS_END_MACRO

Просмотреть файл

@ -565,13 +565,13 @@ static JSThread *
NewThread(void *id)
{
JS_ASSERT(js_CurrentThreadId() == id);
JSThread *thread = (JSThread *) js_calloc(sizeof(JSThread));
JSThread *thread = (JSThread *) OffTheBooks::calloc(sizeof(JSThread));
if (!thread)
return NULL;
JS_INIT_CLIST(&thread->contextList);
thread->id = id;
if (!thread->data.init()) {
js_free(thread);
Foreground::free(thread);
return NULL;
}
return thread;
@ -590,7 +590,7 @@ DestroyThread(JSThread *thread)
JS_ASSERT(!thread->data.conservativeGC.hasStackToScan());
thread->data.finish();
js_free(thread);
Foreground::free(thread);
}
JSThread *
@ -747,7 +747,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
* runtime list. After that it can be accessed from another thread via
* js_ContextIterator.
*/
void *mem = js_calloc(sizeof *cx);
void *mem = OffTheBooks::calloc(sizeof *cx);
if (!mem)
return NULL;
@ -1123,7 +1123,7 @@ FreeContext(JSContext *cx)
JS_FinishArenaPool(&cx->regExpPool);
if (cx->lastMessage)
js_free(cx->lastMessage);
cx->free(cx->lastMessage);
/* Remove any argument formatters. */
JSArgumentFormatMap *map = cx->argumentFormatMap;
@ -1136,8 +1136,7 @@ FreeContext(JSContext *cx)
JS_ASSERT(!cx->resolvingList);
/* Finally, free cx itself. */
cx->~JSContext();
js_free(cx);
Foreground::delete_(cx);
}
JSContext *
@ -1368,8 +1367,8 @@ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
warning = JSREPORT_IS_WARNING(report.flags);
ReportError(cx, message, &report, NULL, NULL);
js_free(message);
cx->free(ucmessage);
Foreground::free(message);
Foreground::free(ucmessage);
return warning;
}
@ -1592,7 +1591,7 @@ js_ReportErrorAgain(JSContext *cx, const char *message, JSErrorReport *reportp)
return;
if (cx->lastMessage)
js_free(cx->lastMessage);
Foreground::free(cx->lastMessage);
cx->lastMessage = JS_strdup(cx, message);
if (!cx->lastMessage)
return;
@ -2100,11 +2099,11 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
#ifdef JS_THREADSAFE
gcHelperThread.waitBackgroundSweepEnd(this);
if (!p)
p = ::js_malloc(nbytes);
p = OffTheBooks::malloc(nbytes);
else if (p == reinterpret_cast<void *>(1))
p = ::js_calloc(nbytes);
p = OffTheBooks::calloc(nbytes);
else
p = ::js_realloc(p, nbytes);
p = OffTheBooks::realloc(p, nbytes);
if (p)
return p;
#endif

Просмотреть файл

@ -1383,7 +1383,13 @@ struct JSRuntime {
return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
}
void free(void* p) { ::js_free(p); }
inline void free(void* p) {
/* FIXME: Making this free in the background is buggy. Can it work? */
js::Foreground::free(p);
}
JS_DECLARE_NEW_METHODS(malloc, JS_ALWAYS_INLINE)
JS_DECLARE_DELETE_METHODS(free, JS_ALWAYS_INLINE)
bool isGCMallocLimitReached() const { return gcMallocBytes <= 0; }
@ -2021,43 +2027,8 @@ struct JSContext
runtime->free(p);
}
/*
* In the common case that we'd like to allocate the memory for an object
* with cx->malloc/free, we cannot use overloaded C++ operators (no
* placement delete). Factor the common workaround into one place.
*/
#define CREATE_BODY(parms) \
void *memory = this->malloc(sizeof(T)); \
if (!memory) \
return NULL; \
return new(memory) T parms;
template <class T>
JS_ALWAYS_INLINE T *create() {
CREATE_BODY(())
}
template <class T, class P1>
JS_ALWAYS_INLINE T *create(const P1 &p1) {
CREATE_BODY((p1))
}
template <class T, class P1, class P2>
JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2) {
CREATE_BODY((p1, p2))
}
template <class T, class P1, class P2, class P3>
JS_ALWAYS_INLINE T *create(const P1 &p1, const P2 &p2, const P3 &p3) {
CREATE_BODY((p1, p2, p3))
}
#undef CREATE_BODY
template <class T>
JS_ALWAYS_INLINE void destroy(T *p) {
p->~T();
this->free(p);
}
JS_DECLARE_NEW_METHODS(malloc, inline)
JS_DECLARE_DELETE_METHODS(free, inline)
void purge();

Просмотреть файл

@ -100,7 +100,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
JSCompartment::~JSCompartment()
{
#if ENABLE_YARR_JIT
js_delete(regExpAllocator);
Foreground::delete_(regExpAllocator);
#endif
#if defined JS_TRACER
@ -108,10 +108,10 @@ JSCompartment::~JSCompartment()
#endif
#ifdef JS_METHODJIT
js_delete(jaegerCompartment);
Foreground::delete_(jaegerCompartment);
#endif
js_delete(mathCache);
Foreground::delete_(mathCache);
#ifdef DEBUG
for (size_t i = 0; i != JS_ARRAY_LENGTH(scriptsToGC); ++i)
@ -141,12 +141,12 @@ JSCompartment::init()
#endif
#ifdef JS_TRACER
if (!InitJIT(&traceMonitor))
if (!InitJIT(&traceMonitor, rt))
return false;
#endif
#if ENABLE_YARR_JIT
regExpAllocator = js_new<JSC::ExecutableAllocator>();
regExpAllocator = rt->new_<JSC::ExecutableAllocator>();
if (!regExpAllocator)
return false;
#endif
@ -155,7 +155,7 @@ JSCompartment::init()
return false;
#ifdef JS_METHODJIT
if (!(jaegerCompartment = js_new<mjit::JaegerCompartment>()))
if (!(jaegerCompartment = rt->new_<mjit::JaegerCompartment>()))
return false;
return jaegerCompartment->Initialize();
#else
@ -574,7 +574,7 @@ MathCache *
JSCompartment::allocMathCache(JSContext *cx)
{
JS_ASSERT(!mathCache);
mathCache = js_new<MathCache>();
mathCache = cx->new_<MathCache>();
if (!mathCache)
js_ReportOutOfMemory(cx);
return mathCache;

Просмотреть файл

@ -2406,7 +2406,7 @@ date_toSource(JSContext *cx, uintN argc, Value *vp)
}
JSString *str = JS_NewStringCopyZ(cx, bytes);
js_free(bytes);
cx->free(bytes);
if (!str)
return false;
vp->setString(str);

Просмотреть файл

@ -47,7 +47,9 @@
#include "jsstdint.h"
#include "jsbit.h"
#include "jsdhash.h"
#include "jsutil.h" /* for JS_ASSERT */
#include "jsutil.h"
using namespace js;
#ifdef JS_DHASHMETER
# if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
@ -111,13 +113,13 @@
JS_PUBLIC_API(void *)
JS_DHashAllocTable(JSDHashTable *table, uint32 nbytes)
{
return js_malloc(nbytes);
return OffTheBooks::malloc(nbytes);
}
JS_PUBLIC_API(void)
JS_DHashFreeTable(JSDHashTable *table, void *ptr)
{
js_free(ptr);
UnwantedForeground::free(ptr);
}
JS_PUBLIC_API(JSDHashNumber)
@ -180,7 +182,7 @@ JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry)
{
const JSDHashEntryStub *stub = (const JSDHashEntryStub *)entry;
js_free((void *) stub->key);
UnwantedForeground::free((void *) stub->key);
memset(entry, 0, table->entrySize);
}
@ -212,11 +214,11 @@ JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32 entrySize,
{
JSDHashTable *table;
table = (JSDHashTable *) js_malloc(sizeof *table);
table = (JSDHashTable *) OffTheBooks::malloc(sizeof *table);
if (!table)
return NULL;
if (!JS_DHashTableInit(table, ops, data, entrySize, capacity)) {
js_free(table);
Foreground::free(table);
return NULL;
}
return table;
@ -226,7 +228,7 @@ JS_PUBLIC_API(void)
JS_DHashTableDestroy(JSDHashTable *table)
{
JS_DHashTableFinish(table);
js_free(table);
UnwantedForeground::free(table);
}
JS_PUBLIC_API(JSBool)

Просмотреть файл

@ -53,6 +53,8 @@
#include "jsobjinlines.h"
using namespace js;
#ifdef IS_LITTLE_ENDIAN
#define IEEE_8087
#else
@ -77,9 +79,16 @@
#endif
*/
/*
* MALLOC gets declared external, and that doesn't work for class members, so
* wrap.
*/
inline void* dtoa_malloc(size_t size) { return OffTheBooks::malloc(size); }
inline void dtoa_free(void* p) { return UnwantedForeground::free(p); }
#define NO_GLOBAL_STATE
#define MALLOC js_malloc
#define FREE js_free
#define MALLOC dtoa_malloc
#define FREE dtoa_free
#include "dtoa.c"
/* Mapping of JSDToStrMode -> js_dtoa mode */
@ -327,7 +336,7 @@ js_dtobasestr(DtoaState *state, int base, double dinput)
JS_ASSERT(base >= 2 && base <= 36);
dval(d) = dinput;
buffer = (char*) js_malloc(DTOBASESTR_BUFFER_SIZE);
buffer = (char*) OffTheBooks::malloc(DTOBASESTR_BUFFER_SIZE);
if (!buffer)
return NULL;
p = buffer;
@ -371,7 +380,7 @@ js_dtobasestr(DtoaState *state, int base, double dinput)
if (!b) {
nomem1:
Bfree(PASS_STATE b);
js_free(buffer);
UnwantedForeground::free(buffer);
return NULL;
}
do {
@ -407,7 +416,7 @@ js_dtobasestr(DtoaState *state, int base, double dinput)
if (mlo != mhi)
Bfree(PASS_STATE mlo);
Bfree(PASS_STATE mhi);
js_free(buffer);
UnwantedForeground::free(buffer);
return NULL;
}
JS_ASSERT(e < 0);

Просмотреть файл

@ -138,7 +138,7 @@ js_dtostr(DtoaState *state, char *buffer, size_t bufferSize, JSDToStrMode mode,
* not equal to itself).
*
* Return NULL if out of memory. If the result is not NULL, it must be
* released via js_free().
* released via cx->free().
*/
char *
js_dtobasestr(DtoaState *state, int base, double d);

Просмотреть файл

@ -2301,7 +2301,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
UpvarCookie *vector = cg->upvarMap.vector;
uint32 length = cg->lexdeps.count;
if (!vector || cg->upvarMap.length != length) {
vector = (UpvarCookie *) js_realloc(vector, length * sizeof *vector);
vector = (UpvarCookie *) cx->realloc(vector, length * sizeof *vector);
if (!vector) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;

Просмотреть файл

@ -572,8 +572,6 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes)
rt->gcTriggerFactor = uint32(100.0f * GC_HEAP_GROWTH_FACTOR);
rt->atomsCompartment->setGCLastBytes(8192);
/*
* The assigned value prevents GC from running when GC memory is too low
* (during JS engine start).
@ -869,7 +867,7 @@ js_FinishGC(JSRuntime *rt)
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
JSCompartment *comp = *c;
comp->finishArenaLists();
js_delete(comp);
Foreground::delete_(comp);
}
rt->compartments.clear();
rt->atomsCompartment = NULL;
@ -2050,7 +2048,7 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
do {
if (freeCursor && !freeVector.append(freeCursorEnd - FREE_ARRAY_LENGTH))
break;
freeCursor = (void **) js_malloc(FREE_ARRAY_SIZE);
freeCursor = (void **) OffTheBooks::malloc(FREE_ARRAY_SIZE);
if (!freeCursor) {
freeCursorEnd = NULL;
break;
@ -2059,7 +2057,7 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
*freeCursor++ = ptr;
return;
} while (false);
js_free(ptr);
Foreground::free(ptr);
}
void
@ -2132,7 +2130,7 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
(void) callback(cx, compartment, JSCOMPARTMENT_DESTROY);
if (compartment->principals)
JSPRINCIPALS_DROP(cx, compartment->principals);
js_delete(compartment);
cx->delete_(compartment);
continue;
}
*write++ = compartment;
@ -2724,9 +2722,9 @@ JSCompartment *
NewCompartment(JSContext *cx, JSPrincipals *principals)
{
JSRuntime *rt = cx->runtime;
JSCompartment *compartment = js_new<JSCompartment>(rt);
JSCompartment *compartment = cx->new_<JSCompartment>(rt);
if (!compartment || !compartment->init()) {
js_delete(compartment);
Foreground::delete_(compartment);
JS_ReportOutOfMemory(cx);
return NULL;
}
@ -2743,6 +2741,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
if (!rt->compartments.append(compartment)) {
AutoUnlockGC unlock(rt);
Foreground::delete_(compartment);
JS_ReportOutOfMemory(cx);
return NULL;
}
@ -2752,7 +2751,7 @@ NewCompartment(JSContext *cx, JSPrincipals *principals)
if (callback && !callback(cx, compartment, JSCOMPARTMENT_NEW)) {
AutoLockGC lock(rt);
rt->compartments.popBack();
js_delete(compartment);
Foreground::delete_(compartment);
return NULL;
}
return compartment;

Просмотреть файл

@ -904,8 +904,8 @@ class GCHelperThread {
static void freeElementsAndArray(void **array, void **end) {
JS_ASSERT(array <= end);
for (void **p = array; p != end; ++p)
js_free(*p);
js_free(array);
js::Foreground::free(*p);
js::Foreground::free(array);
}
static void threadMain(void* arg);

Просмотреть файл

@ -48,6 +48,8 @@
#include "jsutil.h"
#include "jshash.h"
using namespace js;
/* Compute the number of buckets in ht */
#define NBUCKETS(ht) JS_BIT(JS_HASH_BITS - (ht)->shift)
@ -67,26 +69,26 @@
static void *
DefaultAllocTable(void *pool, size_t size)
{
return js_malloc(size);
return OffTheBooks::malloc(size);
}
static void
DefaultFreeTable(void *pool, void *item, size_t size)
{
js_free(item);
UnwantedForeground::free(item);
}
static JSHashEntry *
DefaultAllocEntry(void *pool, const void *key)
{
return (JSHashEntry*) js_malloc(sizeof(JSHashEntry));
return (JSHashEntry*) OffTheBooks::malloc(sizeof(JSHashEntry));
}
static void
DefaultFreeEntry(void *pool, JSHashEntry *he, uintN flag)
{
if (flag == HT_FREE_ENTRY)
js_free(he);
UnwantedForeground::free(he);
}
static JSHashAllocOps defaultHashAllocOps = {

Просмотреть файл

@ -1723,7 +1723,7 @@ js_DumpOpMeters()
# define SIGNIFICANT(count,total) (200. * (count) >= (total))
graph = (Edge *) js_calloc(nedges * sizeof graph[0]);
graph = (Edge *) OffTheBooks::calloc(nedges * sizeof graph[0]);
if (!graph)
return;
for (i = nedges = 0; i < JSOP_LIMIT; i++) {
@ -1754,7 +1754,7 @@ js_DumpOpMeters()
graph[i].from, graph[i].to,
(unsigned long)graph[i].count, style);
}
js_free(graph);
cx->free(graph);
fputs("}\n", fp);
fclose(fp);

Просмотреть файл

@ -364,7 +364,7 @@ js_FinishLock(JSThinLock *tl)
static JSFatLock *
NewFatlock()
{
JSFatLock *fl = (JSFatLock *)js_malloc(sizeof(JSFatLock)); /* for now */
JSFatLock *fl = (JSFatLock *) OffTheBooks::malloc(sizeof(JSFatLock)); /* for now */
if (!fl) return NULL;
fl->susp = 0;
fl->next = NULL;
@ -379,7 +379,7 @@ DestroyFatlock(JSFatLock *fl)
{
PR_DestroyLock(fl->slock);
PR_DestroyCondVar(fl->svar);
js_free(fl);
UnwantedForeground::free(fl);
}
static JSFatLock *
@ -473,7 +473,7 @@ js_SetupLocks(int listc, int globc)
global_locks_log2 = JS_CeilingLog2(globc);
global_locks_mask = JS_BITMASK(global_locks_log2);
global_lock_count = JS_BIT(global_locks_log2);
global_locks = (PRLock **) js_malloc(global_lock_count * sizeof(PRLock*));
global_locks = (PRLock **) OffTheBooks::malloc(global_lock_count * sizeof(PRLock*));
if (!global_locks)
return JS_FALSE;
for (i = 0; i < global_lock_count; i++) {
@ -484,7 +484,7 @@ js_SetupLocks(int listc, int globc)
return JS_FALSE;
}
}
fl_list_table = (JSFatLockTable *) js_malloc(i * sizeof(JSFatLockTable));
fl_list_table = (JSFatLockTable *) OffTheBooks::malloc(i * sizeof(JSFatLockTable));
if (!fl_list_table) {
js_CleanupLocks();
return JS_FALSE;
@ -506,7 +506,7 @@ js_CleanupLocks()
if (global_locks) {
for (i = 0; i < global_lock_count; i++)
PR_DestroyLock(global_locks[i]);
js_free(global_locks);
UnwantedForeground::free(global_locks);
global_locks = NULL;
global_lock_count = 1;
global_locks_log2 = 0;
@ -519,7 +519,7 @@ js_CleanupLocks()
DeleteListOfFatlocks(fl_list_table[i].taken);
fl_list_table[i].taken = NULL;
}
js_free(fl_list_table);
UnwantedForeground::free(fl_list_table);
fl_list_table = NULL;
fl_list_table_len = 0;
}

Просмотреть файл

@ -597,7 +597,7 @@ ToCStringBuf::ToCStringBuf() :dbuf(NULL)
ToCStringBuf::~ToCStringBuf()
{
if (dbuf)
js_free(dbuf);
UnwantedForeground::free(dbuf);
}
JSString * JS_FASTCALL

Просмотреть файл

@ -224,7 +224,7 @@ struct ToCStringBuf
*/
static const size_t sbufSize = 34;
char sbuf[sbufSize];
char *dbuf; /* must be allocated with js_malloc() */
char *dbuf;
ToCStringBuf();
~ToCStringBuf();

Просмотреть файл

@ -525,7 +525,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
if (!chars) {
/* If outermost, allocate 4 + 1 for "({})" and the terminator. */
chars = (jschar *) cx->runtime->malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
chars = (jschar *) cx->malloc(((outermost ? 4 : 2) + 1) * sizeof(jschar));
nchars = 0;
if (!chars)
goto error;
@ -536,9 +536,9 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
MAKE_SHARP(he);
nchars = js_strlen(chars);
chars = (jschar *)
js_realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
cx->realloc((ochars = chars), (nchars + 2 + 1) * sizeof(jschar));
if (!chars) {
js_free(ochars);
Foreground::free(ochars);
goto error;
}
if (outermost) {
@ -739,7 +739,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
goto overflow;
/* Allocate 1 + 1 at end for closing brace and terminating 0. */
chars = (jschar *) js_realloc((ochars = chars), curlen * sizeof(jschar));
chars = (jschar *) cx->realloc((ochars = chars), curlen * sizeof(jschar));
if (!chars) {
chars = ochars;
goto overflow;
@ -787,7 +787,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
if (!ok) {
if (chars)
js_free(chars);
Foreground::free(chars);
goto out;
}
@ -799,7 +799,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
make_string:
str = js_NewString(cx, chars, nchars);
if (!str) {
js_free(chars);
cx->free(chars);
ok = JS_FALSE;
goto out;
}
@ -810,7 +810,7 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
overflow:
cx->free(vsharp);
js_free(chars);
cx->free(chars);
chars = NULL;
goto error;
}

Просмотреть файл

@ -715,7 +715,7 @@ js_BeginJSONParse(JSContext *cx, Value *rootVal, bool suppressErrors /*= false*/
if (!arr)
return NULL;
JSONParser *jp = cx->create<JSONParser>(cx);
JSONParser *jp = cx->new_<JSONParser>(cx);
if (!jp)
return NULL;
@ -771,7 +771,7 @@ js_FinishJSONParse(JSContext *cx, JSONParser *jp, const Value &reviver)
ok = Revive(cx, reviver, vp);
}
cx->destroy(jp);
cx->delete_(jp);
return ok;
}

Просмотреть файл

@ -697,7 +697,7 @@ Sprint(Sprinter *sp, const char *format, ...)
return -1;
}
offset = SprintCString(sp, bp);
js_free(bp);
sp->context->free_(bp);
return offset;
}
@ -941,7 +941,7 @@ js_printf(JSPrinter *jp, const char *format, ...)
cc = strlen(bp);
if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
cc = -1;
js_free(bp);
jp->sprinter.context->free(bp);
va_end(ap);
return cc;

Просмотреть файл

@ -1016,11 +1016,11 @@ struct JSFunctionBoxQueue {
bool init(uint32 count) {
lengthMask = JS_BITMASK(JS_CeilingLog2(count));
vector = js_array_new<JSFunctionBox*>(length());
vector = js::OffTheBooks::array_new<JSFunctionBox*>(length());
return !!vector;
}
~JSFunctionBoxQueue() { js_array_delete(vector); }
~JSFunctionBoxQueue() { js::UnwantedForeground::array_delete(vector); }
void push(JSFunctionBox *funbox) {
if (!funbox->queued) {

Просмотреть файл

@ -52,6 +52,8 @@
#include "jspubtd.h"
#include "jsstr.h"
using namespace js;
/*
** Note: on some platforms va_list is defined as an array,
** and requires array notation.
@ -412,7 +414,7 @@ static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
if (!s)
return -1; /* JSStuffFunc error indicator. */
result = cvt_s(ss, s, width, prec, flags);
js_free(s);
UnwantedForeground::free(s);
} else {
result = cvt_s(ss, NULL, width, prec, flags);
}
@ -630,7 +632,7 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv,
if( *rv < 0 ){
if( nas != nasArray )
js_free( nas );
UnwantedForeground::free( nas );
return NULL;
}
@ -667,7 +669,7 @@ static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv,
default:
if( nas != nasArray )
js_free( nas );
UnwantedForeground::free( nas );
*rv = -1;
return NULL;
}
@ -756,7 +758,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
if( nas[i-1].type == TYPE_UNKNOWN ){
if( nas && ( nas != nasArray ) )
js_free( nas );
UnwantedForeground::free( nas );
return -1;
}
@ -1037,7 +1039,7 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
rv = (*ss->stuff)(ss, "\0", 1);
if( nas && ( nas != nasArray ) ){
js_free( nas );
UnwantedForeground::free( nas );
}
return rv;
@ -1098,9 +1100,9 @@ static int GrowStuff(SprintfState *ss, const char *sp, JSUint32 len)
/* Grow the buffer */
newlen = ss->maxlen + ((len > 32) ? len : 32);
if (ss->base) {
newbase = (char*) js_realloc(ss->base, newlen);
newbase = (char*) OffTheBooks::realloc(ss->base, newlen);
} else {
newbase = (char*) js_malloc(newlen);
newbase = (char*) OffTheBooks::malloc(newlen);
}
if (!newbase) {
/* Ran out of memory */
@ -1139,7 +1141,7 @@ JS_PUBLIC_API(char *) JS_smprintf(const char *fmt, ...)
*/
JS_PUBLIC_API(void) JS_smprintf_free(char *mem)
{
js_free(mem);
Foreground::free(mem);
}
JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap)
@ -1154,7 +1156,7 @@ JS_PUBLIC_API(char *) JS_vsmprintf(const char *fmt, va_list ap)
rv = dosprintf(&ss, fmt, ap);
if (rv < 0) {
if (ss.base) {
js_free(ss.base);
Foreground::free(ss.base);
}
return 0;
}
@ -1253,7 +1255,7 @@ JS_PUBLIC_API(char *) JS_vsprintf_append(char *last, const char *fmt, va_list ap
rv = dosprintf(&ss, fmt, ap);
if (rv < 0) {
if (ss.base) {
js_free(ss.base);
Foreground::free(ss.base);
}
return 0;
}

Просмотреть файл

@ -80,13 +80,9 @@ PropertyTree::newShape(JSContext *cx)
static KidsHash *
HashChildren(Shape *kid1, Shape *kid2)
{
void *mem = js_malloc(sizeof(KidsHash));
if (!mem)
return NULL;
KidsHash *hash = new (mem) KidsHash();
if (!hash->init(2)) {
js_free(hash);
KidsHash *hash = OffTheBooks::new_<KidsHash>();
if (!hash || !hash->init(2)) {
Foreground::delete_(hash);
return NULL;
}
@ -344,7 +340,7 @@ Shape::finalize(JSContext *cx)
parent->removeChild(this);
if (kids.isHash())
js_delete(kids.toHash());
cx->delete_(kids.toHash());
}
freeTable(cx);

Просмотреть файл

@ -79,7 +79,7 @@ static void
resc_finalize(JSContext *cx, JSObject *obj)
{
RegExpStatics *res = static_cast<RegExpStatics *>(obj->getPrivate());
cx->destroy<RegExpStatics>(res);
cx->delete_(res);
}
static void

Просмотреть файл

@ -70,7 +70,7 @@ regexp_statics_construct(JSContext *cx, JSObject *parent)
JSObject *obj = NewObject<WithProto::Given>(cx, &regexp_statics_class, NULL, parent);
if (!obj)
return NULL;
RegExpStatics *res = cx->create<RegExpStatics>();
RegExpStatics *res = cx->new_<RegExpStatics>();
if (!res)
return NULL;
obj->setPrivate(static_cast<void *>(res));
@ -117,6 +117,8 @@ class RegExp
#endif
{ }
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
~RegExp() {
#if !ENABLE_YARR_JIT
if (compiled)
@ -124,9 +126,6 @@ class RegExp
#endif
}
/* Constructor/destructor are hidden; called by cx->create/destroy. */
friend struct ::JSContext;
bool compileHelper(JSContext *cx, JSLinearString &pattern);
bool compile(JSContext *cx);
static const uint32 allFlags = JSREG_FOLD | JSREG_GLOB | JSREG_MULTILINE | JSREG_STICKY;
@ -419,11 +418,11 @@ RegExp::create(JSContext *cx, JSString *source, uint32 flags)
JSLinearString *flatSource = source->ensureLinear(cx);
if (!flatSource)
return RetType(NULL);
RegExp *self = cx->create<RegExp>(flatSource, flags, cx->compartment);
RegExp *self = cx->new_<RegExp>(flatSource, flags, cx->compartment);
if (!self)
return RetType(NULL);
if (!self->compile(cx)) {
cx->destroy<RegExp>(self);
Foreground::delete_(self);
return RetType(NULL);
}
return RetType(self);
@ -576,7 +575,7 @@ RegExp::decref(JSContext *cx)
assertSameCompartment(cx, compartment);
#endif
if (--refCount == 0)
cx->destroy<RegExp>(this);
cx->delete_(this);
}
inline RegExp *

Просмотреть файл

@ -187,10 +187,10 @@ bool
Shape::hashify(JSRuntime *rt)
{
JS_ASSERT(!hasTable());
void* mem = rt->malloc(sizeof(PropertyTable));
if (!mem)
PropertyTable *table = rt->new_<PropertyTable>(entryCount());
if (!table)
return false;
setTable(new(mem) PropertyTable(entryCount()));
setTable(table);
return getTable()->init(rt, this);
}
@ -323,17 +323,14 @@ PropertyTable::change(int log2Delta, JSContext *cx)
JS_ASSERT(entries);
/*
* Grow, shrink, or compress by changing this->entries. Here, we prefer
* cx->runtime->calloc to js_calloc, which on OOM waits for a background
* thread to finish sweeping and retry, if appropriate. Avoid cx->calloc
* so our caller can be in charge of whether to JS_ReportOutOfMemory.
* Grow, shrink, or compress by changing this->entries.
*/
oldlog2 = JS_DHASH_BITS - hashShift;
newlog2 = oldlog2 + log2Delta;
oldsize = JS_BIT(oldlog2);
newsize = JS_BIT(newlog2);
nbytes = PROPERTY_TABLE_NBYTES(newsize);
newTable = (Shape **) cx->runtime->calloc(nbytes);
newTable = (Shape **) cx->calloc(nbytes);
if (!newTable) {
METER(tableAllocFails);
return false;
@ -358,12 +355,8 @@ PropertyTable::change(int log2Delta, JSContext *cx)
oldsize--;
}
/*
* Finally, free the old entries storage. Note that cx->runtime->free just
* calls js_free. Use js_free here to match PropertyTable::~PropertyTable,
* which cannot have a cx or rt parameter.
*/
js_free(oldTable);
/* Finally, free the old entries storage. */
cx->free(oldTable);
return true;
}

Просмотреть файл

@ -242,7 +242,7 @@ struct PropertyTable {
}
~PropertyTable() {
js_free(entries);
js::UnwantedForeground::free(entries);
}
/* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */

Просмотреть файл

@ -57,7 +57,7 @@ inline void
js::Shape::freeTable(JSContext *cx)
{
if (hasTable()) {
cx->destroy(getTable());
cx->delete_(getTable());
setTable(NULL);
}
}

Просмотреть файл

@ -803,13 +803,13 @@ typedef struct ScriptFilenameEntry {
static void *
js_alloc_table_space(void *priv, size_t size)
{
return js_malloc(size);
return OffTheBooks::malloc(size);
}
static void
js_free_table_space(void *priv, void *item, size_t size)
{
js_free(item);
UnwantedForeground::free(item);
}
static JSHashEntry *
@ -818,7 +818,7 @@ js_alloc_sftbl_entry(void *priv, const void *key)
size_t nbytes = offsetof(ScriptFilenameEntry, filename) +
strlen((const char *) key) + 1;
return (JSHashEntry *) js_malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
return (JSHashEntry *) OffTheBooks::malloc(JS_MAX(nbytes, sizeof(JSHashEntry)));
}
static void
@ -826,7 +826,7 @@ js_free_sftbl_entry(void *priv, JSHashEntry *he, uintN flag)
{
if (flag != HT_FREE_ENTRY)
return;
js_free(he);
UnwantedForeground::free(he);
}
static JSHashAllocOps sftbl_alloc_ops = {
@ -887,7 +887,7 @@ js_FreeRuntimeScriptState(JSRuntime *rt)
ScriptFilenamePrefix *sfp = (ScriptFilenamePrefix *)
rt->scriptFilenamePrefixes.next;
JS_REMOVE_LINK(&sfp->links);
js_free(sfp);
UnwantedForeground::free(sfp);
}
FinishRuntimeScriptState(rt);
}
@ -950,7 +950,7 @@ SaveScriptFilename(JSRuntime *rt, const char *filename, uint32 flags)
if (!sfp) {
/* No such prefix: add one now. */
sfp = (ScriptFilenamePrefix *) js_malloc(sizeof(ScriptFilenamePrefix));
sfp = (ScriptFilenamePrefix *) rt->malloc(sizeof(ScriptFilenamePrefix));
if (!sfp)
return NULL;
JS_INSERT_AFTER(&sfp->links, link);

Просмотреть файл

@ -217,7 +217,7 @@ AllocChars(JSContext *maybecx, size_t wholeCapacity)
size_t bytes = (wholeCapacity + 1) * sizeof(jschar);
if (maybecx)
return (jschar *)maybecx->malloc(bytes);
return (jschar *)js_malloc(bytes);
return (jschar *)OffTheBooks::malloc(bytes);
}
JSFlatString *
@ -3123,7 +3123,7 @@ tagify(JSContext *cx, const char *begin, JSLinearString *param, const char *end,
JSString *retstr = js_NewString(cx, tagbuf, taglen);
if (!retstr) {
js_free((char *)tagbuf);
Foreground::free((char *)tagbuf);
return false;
}
vp->setString(retstr);
@ -4080,7 +4080,7 @@ js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
nbytes = js_GetDeflatedStringLength(cx, chars, nchars);
if (nbytes == (size_t) -1)
return NULL;
bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1));
bytes = (char *) (cx ? cx->malloc(nbytes + 1) : OffTheBooks::malloc(nbytes + 1));
if (!bytes)
return NULL;
#ifdef DEBUG
@ -4090,7 +4090,7 @@ js_DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
JS_ASSERT(ok);
} else {
nbytes = nchars;
bytes = (char *) (cx ? cx->malloc(nbytes + 1) : js_malloc(nbytes + 1));
bytes = (char *) (cx ? cx->malloc(nbytes + 1) : OffTheBooks::malloc(nbytes + 1));
if (!bytes)
return NULL;
for (i = 0; i < nbytes; i++)

Просмотреть файл

@ -255,9 +255,9 @@ PointerRangeSize(T *begin, T *end)
class SystemAllocPolicy
{
public:
void *malloc(size_t bytes) { return js_malloc(bytes); }
void *realloc(void *p, size_t bytes) { return js_realloc(p, bytes); }
void free(void *p) { js_free(p); }
void *malloc(size_t bytes) { return js::OffTheBooks::malloc(bytes); }
void *realloc(void *p, size_t bytes) { return js::OffTheBooks::realloc(p, bytes); }
void free(void *p) { js::UnwantedForeground::free(p); }
void reportAllocOverflow() const {}
};

Просмотреть файл

@ -148,13 +148,13 @@ using namespace js::tjit;
/* Implement embedder-specific nanojit members. */
/*
* Nanojit requires infallible allocations most of the time. We satisfy this
* by reserving some space in each allocator which is used as a fallback if
* js_calloc() fails. Ideallly this reserve space should be big enough to
* allow for all infallible requests made to the allocator until the next OOM
* check occurs, but it turns out that's impossible to guarantee (though it
* should be unlikely). So we abort if the reserve runs out; this is better
* than allowing memory errors to occur.
* Nanojit requires infallible allocations most of the time. We satisfy this by
* reserving some space in each allocator which is used as a fallback if
* rt->calloc() fails. Ideally this reserve space should be big enough to allow
* for all infallible requests made to the allocator until the next OOM check
* occurs, but it turns out that's impossible to guarantee (though it should be
* unlikely). So we abort if the reserve runs out; this is better than
* allowing memory errors to occur.
*
* The space calculations are as follows... between OOM checks, each
* VMAllocator can do (ie. has been seen to do) the following maximum
@ -190,7 +190,7 @@ nanojit::Allocator::allocChunk(size_t nbytes, bool fallible)
* OOM check will still fail, which is what we want, and the success of
* request 2 makes it less likely that the reserve space will overflow.
*/
void *p = js_calloc(nbytes);
void *p = vma->mRt->calloc(nbytes);
if (p) {
vma->mSize += nbytes;
} else {
@ -211,7 +211,7 @@ void
nanojit::Allocator::freeChunk(void *p) {
VMAllocator *vma = (VMAllocator*)this;
if (p < vma->mReserve || uintptr_t(p) >= vma->mReserveLimit)
js_free(p);
UnwantedForeground::free(p);
}
void
@ -1084,7 +1084,8 @@ TraceRecorder::tprint(const char *format, LIns *ins1, LIns *ins2, LIns *ins3, LI
}
#endif
Tracker::Tracker()
Tracker::Tracker(JSContext *cx)
: cx(cx)
{
pagelist = NULL;
}
@ -1123,7 +1124,7 @@ struct Tracker::TrackerPage*
Tracker::addTrackerPage(const void* v)
{
jsuword base = getTrackerPageBase(v);
struct TrackerPage* p = (struct TrackerPage*) js_calloc(sizeof(*p));
struct TrackerPage* p = (struct TrackerPage*) cx->calloc(sizeof(*p));
p->base = base;
p->next = pagelist;
pagelist = p;
@ -1136,7 +1137,7 @@ Tracker::clear()
while (pagelist) {
TrackerPage* p = pagelist;
pagelist = pagelist->next;
js_free(p);
cx->free(p);
}
}
@ -2244,8 +2245,8 @@ TraceRecorder::TraceRecorder(JSContext* cx, TraceMonitor *tm,
lirbuf(new (tempAlloc()) LirBuffer(tempAlloc())),
mark(*traceMonitor->traceAlloc),
numSideExitsBefore(tree->sideExits.length()),
tracker(),
nativeFrameTracker(),
tracker(cx),
nativeFrameTracker(cx),
global_slots(NULL),
callDepth(anchor ? anchor->calldepth : 0),
atoms(FrameAtomBase(cx, cx->fp())),
@ -2480,9 +2481,7 @@ TraceRecorder::finishSuccessfully()
TraceMonitor* localtm = traceMonitor;
localtm->recorder = NULL;
/* We can't (easily) use js_delete() here because the destructor is private. */
this->~TraceRecorder();
js_free(this);
cx->delete_(this);
/* Catch OOM that occurred during recording. */
if (localtm->outOfMemory() || OverfullJITCache(localcx, localtm)) {
@ -2534,9 +2533,7 @@ TraceRecorder::finishAbort(const char* reason)
TraceMonitor* localtm = traceMonitor;
localtm->recorder = NULL;
/* We can't (easily) use js_delete() here because the destructor is private. */
this->~TraceRecorder();
js_free(this);
cx->delete_(this);
/* Catch OOM that occurred during recording. */
if (localtm->outOfMemory() || OverfullJITCache(localcx, localtm)) {
@ -4503,12 +4500,12 @@ TraceRecorder::compile()
#if defined DEBUG && !defined WIN32
/* Associate a filename and line number with the fragment. */
const char* filename = cx->fp()->script()->filename;
char* label = (char*)js_malloc((filename ? strlen(filename) : 7) + 16);
char* label = (char*) cx->malloc((filename ? strlen(filename) : 7) + 16);
if (label) {
sprintf(label, "%s:%u", filename ? filename : "<stdin>",
js_FramePCToLineNumber(cx, cx->fp()));
lirbuf->printer->addrNameMap->addAddrRange(fragment, sizeof(Fragment), 0, label);
js_free(label);
cx->free(label);
}
#endif
@ -5571,13 +5568,9 @@ TraceRecorder::startRecorder(JSContext* cx, TraceMonitor *tm, VMSideExit* anchor
JS_ASSERT(!tm->needFlush);
JS_ASSERT_IF(cx->fp()->hasImacropc(), f->root != f);
/* We can't (easily) use js_new() here because the constructor is private. */
void *memory = js_malloc(sizeof(TraceRecorder));
tm->recorder = memory
? new(memory) TraceRecorder(cx, tm, anchor, f, stackSlots, ngslots, typeMap,
tm->recorder = cx->new_<TraceRecorder>(cx, tm, anchor, f, stackSlots, ngslots, typeMap,
expectedInnerExit, outerScript, outerPC, outerArgc,
speculate)
: NULL;
speculate);
if (!tm->recorder || tm->outOfMemory() || OverfullJITCache(cx, tm)) {
ResetJIT(cx, tm, FR_OOM);
@ -7632,7 +7625,7 @@ SetMaxCodeCacheBytes(JSContext* cx, uint32 bytes)
}
bool
InitJIT(TraceMonitor *tm)
InitJIT(TraceMonitor *tm, JSRuntime* rt)
{
#if defined JS_JIT_SPEW
tm->profAlloc = NULL;
@ -7643,7 +7636,7 @@ InitJIT(TraceMonitor *tm)
}
/* Set up fragprofiling, if required. */
if (LogController.lcbits & LC_FragProfile) {
tm->profAlloc = js_new<VMAllocator>((char*)NULL, 0); /* no reserve needed in debug builds */
tm->profAlloc = rt->new_<VMAllocator>(rt, (char*)NULL, 0); /* no reserve needed in debug builds */
if (!tm->profAlloc)
goto error;
tm->profTab = new (*tm->profAlloc) FragStatsMap(*tm->profAlloc);
@ -7678,34 +7671,36 @@ InitJIT(TraceMonitor *tm)
did_we_check_processor_features = true;
}
#define CHECK_ALLOC(lhs, rhs) \
do { lhs = (rhs); if (!lhs) goto error; } while (0)
#define CHECK_NEW(lhs, type, args) \
do { lhs = rt->new_<type> args; if (!lhs) goto error; } while (0)
#define CHECK_MALLOC(lhs, conversion, size) \
do { lhs = (conversion)(rt->malloc(size)); if (!lhs) goto error; } while (0)
CHECK_ALLOC(tm->oracle, js_new<Oracle>());
CHECK_NEW(tm->oracle, Oracle, ());
tm->profile = NULL;
CHECK_ALLOC(tm->recordAttempts, js_new<RecordAttemptMap>());
CHECK_NEW(tm->recordAttempts, RecordAttemptMap, ());
if (!tm->recordAttempts->init(PC_HASH_COUNT))
goto error;
CHECK_ALLOC(tm->loopProfiles, js_new<LoopProfileMap>());
CHECK_NEW(tm->loopProfiles, LoopProfileMap, ());
if (!tm->loopProfiles->init(PC_HASH_COUNT))
goto error;
tm->flushEpoch = 0;
char *dataReserve, *traceReserve, *tempReserve;
CHECK_ALLOC(dataReserve, (char *)js_malloc(DataReserveSize));
CHECK_ALLOC(traceReserve, (char *)js_malloc(TraceReserveSize));
CHECK_ALLOC(tempReserve, (char *)js_malloc(TempReserveSize));
CHECK_ALLOC(tm->dataAlloc, js_new<VMAllocator>(dataReserve, DataReserveSize));
CHECK_ALLOC(tm->traceAlloc, js_new<VMAllocator>(traceReserve, TraceReserveSize));
CHECK_ALLOC(tm->tempAlloc, js_new<VMAllocator>(tempReserve, TempReserveSize));
CHECK_ALLOC(tm->codeAlloc, js_new<CodeAlloc>());
CHECK_ALLOC(tm->frameCache, js_new<FrameInfoCache>(tm->dataAlloc));
CHECK_ALLOC(tm->storage, js_new<TraceNativeStorage>());
CHECK_ALLOC(tm->cachedTempTypeMap, js_new<TypeMap>((Allocator*)NULL, tm->oracle));
CHECK_MALLOC(dataReserve, char*, DataReserveSize);
CHECK_MALLOC(traceReserve, char*, TraceReserveSize);
CHECK_MALLOC(tempReserve, char*, TempReserveSize);
CHECK_NEW(tm->dataAlloc, VMAllocator, (rt, dataReserve, DataReserveSize));
CHECK_NEW(tm->traceAlloc, VMAllocator, (rt, traceReserve, TraceReserveSize));
CHECK_NEW(tm->tempAlloc, VMAllocator, (rt, tempReserve, TempReserveSize));
CHECK_NEW(tm->codeAlloc, CodeAlloc, ());
CHECK_NEW(tm->frameCache, FrameInfoCache, (tm->dataAlloc));
CHECK_NEW(tm->storage, TraceNativeStorage, ());
CHECK_NEW(tm->cachedTempTypeMap, TypeMap, ((Allocator*)NULL, tm->oracle));
tm->flush();
verbose_only( tm->branches = NULL; )
@ -7788,9 +7783,9 @@ FinishJIT(TraceMonitor *tm)
}
#endif
js_delete(tm->recordAttempts);
js_delete(tm->loopProfiles);
js_delete(tm->oracle);
Foreground::delete_(tm->recordAttempts);
Foreground::delete_(tm->loopProfiles);
Foreground::delete_(tm->oracle);
#ifdef DEBUG
// Recover profiling data from expiring Fragments, and display
@ -7810,7 +7805,7 @@ FinishJIT(TraceMonitor *tm)
if (tm->profTab)
FragProfiling_showResults(tm);
js_delete(tm->profAlloc);
Foreground::delete_(tm->profAlloc);
} else {
NanoAssert(!tm->profTab);
@ -7820,25 +7815,25 @@ FinishJIT(TraceMonitor *tm)
PodArrayZero(tm->vmfragments);
js_delete(tm->frameCache);
Foreground::delete_(tm->frameCache);
tm->frameCache = NULL;
js_delete(tm->codeAlloc);
Foreground::delete_(tm->codeAlloc);
tm->codeAlloc = NULL;
js_delete(tm->dataAlloc);
Foreground::delete_(tm->dataAlloc);
tm->dataAlloc = NULL;
js_delete(tm->traceAlloc);
Foreground::delete_(tm->traceAlloc);
tm->traceAlloc = NULL;
js_delete(tm->tempAlloc);
Foreground::delete_(tm->tempAlloc);
tm->tempAlloc = NULL;
js_delete(tm->storage);
Foreground::delete_(tm->storage);
tm->storage = NULL;
js_delete(tm->cachedTempTypeMap);
Foreground::delete_(tm->cachedTempTypeMap);
tm->cachedTempTypeMap = NULL;
}

Просмотреть файл

@ -76,7 +76,7 @@ public:
memcpy(tmp, _data, _len * sizeof(T));
_data = tmp;
} else {
_data = (T*)js_realloc(_data, _max * sizeof(T));
_data = (T*) js::OffTheBooks::realloc(_data, _max * sizeof(T));
}
#if defined(DEBUG)
memset(&_data[_len], 0xcd, _max - _len);
@ -93,7 +93,7 @@ public:
~Queue() {
if (!alloc)
js_free(_data);
js::UnwantedForeground::free(_data);
}
bool contains(T a) {
@ -199,12 +199,15 @@ class Tracker {
};
struct TrackerPage* pagelist;
/* Keep track of memory allocation. */
JSContext* cx;
jsuword getTrackerPageBase(const void* v) const;
jsuword getTrackerPageOffset(const void* v) const;
struct TrackerPage* findTrackerPage(const void* v) const;
struct TrackerPage* addTrackerPage(const void* v);
public:
Tracker();
Tracker(JSContext* cx);
~Tracker();
bool has(const void* v) const;
@ -407,15 +410,18 @@ struct VMSideExit : public nanojit::SideExit
class VMAllocator : public nanojit::Allocator
{
public:
VMAllocator(char* reserve, size_t reserveSize)
: mOutOfMemory(false), mSize(0), mReserve(reserve),
mReserveCurr(uintptr_t(reserve)), mReserveLimit(uintptr_t(reserve + reserveSize))
VMAllocator(JSRuntime *rt, char* reserve, size_t reserveSize)
: mOutOfMemory(false)
, mSize(0)
, mReserve(reserve)
, mReserveCurr(uintptr_t(reserve))
, mReserveLimit(uintptr_t(reserve + reserveSize))
, mRt(rt)
{}
~VMAllocator() {
js_free(mReserve);
js::UnwantedForeground::free(mReserve);
}
size_t size() {
@ -472,6 +478,9 @@ public:
char* mReserve;
uintptr_t mReserveCurr;
uintptr_t mReserveLimit;
/* To keep track of allocation. */
JSRuntime* mRt;
};
struct FrameInfo {
@ -984,6 +993,8 @@ AbortProfiling(JSContext *cx);
class TraceRecorder
{
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
/*************************************************************** Recording session constants */
/* The context in which recording started. */
@ -1691,7 +1702,7 @@ extern JS_REQUIRES_STACK TraceRecorder::AbortResult
AbortRecording(JSContext* cx, const char* reason);
extern bool
InitJIT(TraceMonitor *tm);
InitJIT(TraceMonitor *tm, JSRuntime *rt);
extern void
FinishJIT(TraceMonitor *tm);

Просмотреть файл

@ -123,7 +123,7 @@ ArrayBuffer::class_finalize(JSContext *cx, JSObject *obj)
ArrayBuffer *abuf = ArrayBuffer::fromJSObject(obj);
if (abuf) {
abuf->freeStorage(cx);
cx->destroy<ArrayBuffer>(abuf);
cx->delete_(abuf);
}
}
@ -161,12 +161,12 @@ ArrayBuffer::create(JSContext *cx, int32 nbytes)
return NULL;
}
ArrayBuffer *abuf = cx->create<ArrayBuffer>();
ArrayBuffer *abuf = cx->new_<ArrayBuffer>();
if (!abuf)
return NULL;
if (!abuf->allocateStorage(cx, nbytes)) {
cx->destroy<ArrayBuffer>(abuf);
Foreground::delete_(abuf);
return NULL;
}
@ -727,7 +727,7 @@ class TypedArrayTemplate
if (!obj)
return NULL;
ThisTypeArray *tarray = cx->create<ThisTypeArray>(bufobj, byteOffset, len);
ThisTypeArray *tarray = cx->new_<ThisTypeArray>(bufobj, byteOffset, len);
if (!tarray)
return NULL;
@ -832,7 +832,7 @@ class TypedArrayTemplate
{
ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
if (tarray)
cx->destroy<ThisTypeArray>(tarray);
cx->delete_(tarray);
}
/* subarray(start[, end]) */
@ -1324,7 +1324,7 @@ class TypedArrayTemplate
break;
}
js_free(srcbuf);
UnwantedForeground::free(srcbuf);
return true;
}

Просмотреть файл

@ -321,7 +321,7 @@ CallTree(void **bp)
return NULL;
/* Create a new callsite record. */
site = (JSCallsite *) js_malloc(sizeof(JSCallsite));
site = (JSCallsite *) OffTheBooks::malloc(sizeof(JSCallsite));
if (!site)
return NULL;

Просмотреть файл

@ -228,7 +228,11 @@ extern JS_PUBLIC_DATA(JSUint32) OOM_counter; /* data race, who cares. */
#define JS_OOM_POSSIBLY_FAIL() do {} while(0)
#endif
/*
* SpiderMonkey code should not be calling these allocation functions directly.
* Instead, all calls should go through JSRuntime, JSContext or OffTheBooks.
* However, js_free() can be called directly.
*/
static JS_INLINE void* js_malloc(size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return malloc(bytes);
@ -251,94 +255,267 @@ static JS_INLINE void js_free(void* p) {
JS_END_EXTERN_C
#ifdef __cplusplus
/*
* Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
* failure instead of returning NULL, which is what SpiderMonkey expects.
* js_new()/js_array_new() should be used instead, and memory allocated with
* them should be deallocated with js_delete()/js_array_delete().
* User guide to memory memangement within SpiderMonkey:
*
* If you have a class with a private constructor or destructor, you can
* make js_new/js_delete a friend. This can be fiddly, and the interaction of
* template functions, friend functions and namespaces can overwhelm even
* modern compilers. Manual inlining is probably easier.
* Quick tips:
*
* (If you're wondering why we can't just use the 'nothrow' variant of
* new/new[], it's because we want to mediate *all* allocations within
* SpiderMonkey, to satisfy any embedders using JS_USE_CUSTOM_ALLOCATOR.)
* Allocation:
* - Prefer to allocate using JSContext:
* cx->{malloc,realloc,calloc,new_,new_array}
*
* - If no JSContext is available, use a JSRuntime:
* rt->{malloc,realloc,calloc,new_,new_array}
*
* - As a last resort, use unaccounted allocation ("OffTheBooks"):
* js::OffTheBooks::{malloc,realloc,calloc,new_,new_array}
*
* Deallocation:
* - When the deallocation occurs on a slow path, use:
* Foreground::{free,delete_,array_delete}
*
* - Otherwise deallocate on a background thread using a JSContext:
* cx->{free,delete_,array_delete}
*
* - If no JSContext is available, use a JSRuntime:
* rt->{free,delete_,array_delete}
*
* - As a last resort, use UnwantedForeground deallocation:
* js::UnwantedForeground::{free,delete_,array_delete}
*
* General tips:
*
* - Mixing and matching these allocators is allowed (you may free memory
* allocated by any allocator, with any deallocator).
*
* - Never, ever use normal C/C++ memory management:
* malloc, free, new, new[], delete, operator new, etc.
*
* - Never, ever use low-level SpiderMonkey allocators:
* js_malloc(), js_free(), js_calloc(), js_realloc()
* Their use is reserved for the other memory managers.
*
* - Classes which have private constructors or destructors should have
* JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR added to their
* declaration.
*
* Details:
*
* Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
* failure instead of returning NULL, which is what SpiderMonkey expects.
* (Even overriding them is unsafe, as the system's C++ runtime library may
* throw, which we do not support. We also can't just use the 'nothrow'
* variant of new/new[], because we want to mediate *all* allocations
* within SpiderMonkey, to satisfy any embedders using
* JS_USE_CUSTOM_ALLOCATOR.)
*
* JSContexts and JSRuntimes keep track of memory allocated, and use this
* accounting to schedule GC. OffTheBooks does not. We'd like to remove
* OffTheBooks allocations as much as possible (bug 636558).
*
* On allocation failure, a JSContext correctly reports an error, which a
* JSRuntime and OffTheBooks does not.
*
* A JSContext deallocates in a background thread. A JSRuntime might
* deallocate in the background in the future, but does not now. Foreground
* deallocation is preferable on slow paths. UnwantedForeground deallocations
* occur where we have no JSContext or JSRuntime, and the deallocation is not
* on a slow path. We want to remove UnwantedForeground deallocations (bug
* 636561).
*
* JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR makes the allocation
* classes friends with your class, giving them access to private
* constructors and destructors.
*
* |make check| does a source level check on the number of uses OffTheBooks,
* UnwantedForeground, js_malloc, js_free etc, to prevent regressions. If you
* really must add one, update Makefile.in, and run |make check|.
*
* |make check| also statically prevents the use of vanilla new/new[].
*/
#define JS_NEW_BODY(t, parms) \
void *memory = js_malloc(sizeof(t)); \
#define JS_NEW_BODY(allocator, t, parms) \
void *memory = allocator(sizeof(t)); \
return memory ? new(memory) t parms : NULL;
template <class T>
JS_ALWAYS_INLINE T *js_new() {
JS_NEW_BODY(T, ())
}
/*
* Given a class which should provide new_() methods, add
* JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
* adds new_()s with up to 12 parameters. Add more versions of new_ below if
* you need more than 12 parameters.
*
* Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
* or the build will break.
*/
#define JS_DECLARE_NEW_METHODS(ALLOCATOR, QUALIFIERS)\
template <class T>\
QUALIFIERS T *new_() {\
JS_NEW_BODY(ALLOCATOR, T, ())\
}\
\
template <class T, class P1>\
QUALIFIERS T *new_(const P1 &p1) {\
JS_NEW_BODY(ALLOCATOR, T, (p1))\
}\
\
template <class T, class P1, class P2>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2))\
}\
\
template <class T, class P1, class P2, class P3>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3))\
}\
\
template <class T, class P1, class P2, class P3, class P4>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9, const P10 &p10) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9, const P10 &p10, const P11 &p11) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))\
}\
\
template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
QUALIFIERS T *new_(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4, const P5 &p5, const P6 &p6, const P7 &p7, const P8 &p8, const P9 &p9, const P10 &p10, const P11 &p11, const P12 &p12) {\
JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))\
}\
static const int JSMinAlignment = 8;\
template <class T>\
QUALIFIERS T *array_new(size_t n) {\
/* The length is stored just before the vector memory. */\
uint64 numBytes64 = uint64(JSMinAlignment) + uint64(sizeof(T)) * uint64(n);\
size_t numBytes = size_t(numBytes64);\
if (numBytes64 != numBytes) {\
JS_ASSERT(0); /* we want to know if this happens in debug builds */\
return NULL;\
}\
void *memory = ALLOCATOR(numBytes);\
if (!memory)\
return NULL;\
*(size_t *)memory = n;\
memory = (void*)(uintptr_t(memory) + JSMinAlignment);\
return new(memory) T[n];\
}\
template <class T, class P1>
JS_ALWAYS_INLINE T *js_new(const P1 &p1) {
JS_NEW_BODY(T, (p1))
}
template <class T, class P1, class P2>
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2) {
JS_NEW_BODY(T, (p1, p2))
}
template <class T, class P1, class P2, class P3>
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3) {
JS_NEW_BODY(T, (p1, p2, p3))
}
template <class T, class P1, class P2, class P3, class P4>
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) {
JS_NEW_BODY(T, (p1, p2, p3, p4))
}
/* ...add additional js_new()s as necessary... */
#undef JS_NEW_BODY
template <class T>
JS_ALWAYS_INLINE void js_delete(T *p) {
if (p) {
p->~T();
js_free(p);
#define JS_DECLARE_DELETE_METHODS(DEALLOCATOR, QUALIFIERS)\
template <class T>\
QUALIFIERS void delete_(T *p) {\
if (p) {\
p->~T();\
DEALLOCATOR(p);\
}\
}\
\
template <class T>\
QUALIFIERS void array_delete(T *p) {\
if (p) {\
void* p0 = (void *)(uintptr_t(p) - js::OffTheBooks::JSMinAlignment);\
size_t n = *(size_t *)p0;\
for (size_t i = 0; i < n; i++)\
(p + i)->~T();\
DEALLOCATOR(p0);\
}\
}
}
static const int JSMinAlignment = 8;
template <class T>
JS_ALWAYS_INLINE T *js_array_new(size_t n) {
/* The length is stored just before the vector memory. */
uint64 numBytes64 = uint64(JSMinAlignment) + uint64(sizeof(T)) * uint64(n);
size_t numBytes = size_t(numBytes64);
if (numBytes64 != numBytes) {
JS_ASSERT(0); /* we want to know if this happens in debug builds */
return NULL;
/*
* In general, all allocations should go through a JSContext or JSRuntime, so
* that the garbage collector knows how much memory has been allocated. In
* cases where it is difficult to use a JSContext or JSRuntime, OffTheBooks can
* be used, though this is undesirable.
*/
namespace js {
class OffTheBooks {
public:
JS_DECLARE_NEW_METHODS(::js_malloc, JS_ALWAYS_INLINE static)
/*
* The parentheses around the following function names prevent the names
* from being expanded if they are defined in the system headers as macros
* (function-style macros only expand if followed by an open paratheses).
* This doesn't appear to be a problem for call-sites (ie cx->malloc()).
*/
static JS_INLINE void* (malloc)(size_t bytes) {
return ::js_malloc(bytes);
}
void *memory = js_malloc(numBytes);
if (!memory)
return NULL;
*(size_t *)memory = n;
memory = (void*)(uintptr_t(memory) + JSMinAlignment);
return new(memory) T[n];
}
template <class T>
JS_ALWAYS_INLINE void js_array_delete(T *p) {
if (p) {
void* p0 = (void *)(uintptr_t(p) - JSMinAlignment);
size_t n = *(size_t *)p0;
for (size_t i = 0; i < n; i++)
(p + i)->~T();
js_free(p0);
static JS_INLINE void* (calloc)(size_t bytes) {
return ::js_calloc(bytes);
}
}
static JS_INLINE void* (realloc)(void* p, size_t bytes) {
return ::js_realloc(p, bytes);
}
};
/*
* We generally prefer deallocating using JSContext because it can happen in
* the background. On slow paths, we may prefer foreground allocation.
*/
class Foreground {
public:
/* See parentheses comment above. */
static JS_ALWAYS_INLINE void (free)(void* p) {
::js_free(p);
}
JS_DECLARE_DELETE_METHODS(::js_free, JS_ALWAYS_INLINE static)
};
class UnwantedForeground : public Foreground {
};
} /* namespace js */
/*
* Note lack of ; in JSRuntime below. This is intentional so "calling" this
* looks "normal".
*/
#define JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR \
friend class js::OffTheBooks;\
friend class js::Foreground;\
friend class js::UnwantedForeground;\
friend struct ::JSContext;\
friend struct ::JSRuntime
/**
* The following classes are designed to cause assertions to detect

Просмотреть файл

@ -891,7 +891,7 @@ JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity)
if (cx)
cx->free(vector);
else
js_free(vector);
Foreground::free(vector);
}
vector = NULL;
} else {
@ -901,7 +901,7 @@ JSXMLArray::setCapacity(JSContext *cx, uint32 newCapacity)
#if JS_BITS_PER_WORD == 32
(size_t)newCapacity > ~(size_t)0 / sizeof(void *) ||
#endif
!(tmp = (void **) js_realloc(vector, newCapacity * sizeof(void *)))) {
!(tmp = (void **) OffTheBooks::realloc(vector, newCapacity * sizeof(void *)))) {
if (cx)
JS_ReportOutOfMemory(cx);
return false;
@ -988,7 +988,7 @@ XMLArrayAddMember(JSContext *cx, JSXMLArray *array, uint32 index, void *elt)
(size_t)capacity > ~(size_t)0 / sizeof(void *) ||
#endif
!(vector = (void **)
js_realloc(array->vector, capacity * sizeof(void *)))) {
cx->realloc(array->vector, capacity * sizeof(void *)))) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
}
@ -1072,7 +1072,7 @@ XMLArrayTruncate(JSContext *cx, JSXMLArray *array, uint32 length)
cx->free(array->vector);
vector = NULL;
} else {
vector = (void **) js_realloc(array->vector, length * sizeof(void *));
vector = (void **) cx->realloc(array->vector, length * sizeof(void *));
if (!vector)
return;
}
@ -4886,7 +4886,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep,
if (length == 0) {
statep->setInt32(0);
} else {
cursor = cx->create<JSXMLArrayCursor>(&xml->xml_kids);
cursor = cx->new_<JSXMLArrayCursor>(&xml->xml_kids);
if (!cursor)
return JS_FALSE;
statep->setPrivate(cursor);
@ -4912,7 +4912,7 @@ xml_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep,
if (!statep->isInt32(0)) {
cursor = (JSXMLArrayCursor *) statep->toPrivate();
if (cursor)
cx->destroy(cursor);
cx->delete_(cursor);
}
statep->setNull();
break;
@ -7582,7 +7582,7 @@ xmlfilter_finalize(JSContext *cx, JSObject *obj)
if (!filter)
return;
cx->destroy(filter);
cx->delete_(filter);
}
Class js_XMLFilterClass = {
@ -7652,7 +7652,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
* Init all filter fields before setPrivate exposes it to
* xmlfilter_trace or xmlfilter_finalize.
*/
filter = cx->create<JSXMLFilter>(list, &list->xml_kids);
filter = cx->new_<JSXMLFilter>(list, &list->xml_kids);
if (!filter)
return JS_FALSE;
filterobj->setPrivate(filter);

Просмотреть файл

@ -623,7 +623,7 @@ JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL);
bool
JaegerCompartment::Initialize()
{
execAlloc_ = js_new<JSC::ExecutableAllocator>();
execAlloc_ = js::OffTheBooks::new_<JSC::ExecutableAllocator>();
if (!execAlloc_)
return false;
@ -647,7 +647,7 @@ void
JaegerCompartment::Finish()
{
TrampolineCompiler::release(&trampolines);
js_delete(execAlloc_);
Foreground::delete_(execAlloc_);
#ifdef JS_METHODJIT_PROFILE_STUBS
FILE *fp = fopen("/tmp/stub-profiling", "wt");
# define OPDEF(op,val,name,image,length,nuses,ndefs,prec,format) \

Просмотреть файл

@ -157,7 +157,7 @@ class BasePolyIC : public BaseIC {
~BasePolyIC() {
releasePools();
if (areMultiplePools())
js_delete(multiplePools());
Foreground::delete_(multiplePools());
}
void reset() {
@ -192,11 +192,11 @@ class BasePolyIC : public BaseIC {
if (isOnePool()) {
JSC::ExecutablePool *oldPool = u.execPool;
JS_ASSERT(!isTagged(oldPool));
ExecPoolVector *execPools = js_new<ExecPoolVector>(SystemAllocPolicy());
ExecPoolVector *execPools = cx->new_<ExecPoolVector>(SystemAllocPolicy());
if (!execPools)
return false;
if (!execPools->append(oldPool) || !execPools->append(pool)) {
js_delete(execPools);
Foreground::delete_(execPools);
return false;
}
u.taggedExecPools = tag(execPools);

Просмотреть файл

@ -63,7 +63,7 @@ pm_construct(JSContext* cx, uintN argc, jsval* vp)
if (!JS_FreezeObject(cx, obj))
return JS_FALSE;
PerfMeasurement* p = js_new<PerfMeasurement>(PerfMeasurement::EventMask(mask));
PerfMeasurement* p = cx->new_<PerfMeasurement>(PerfMeasurement::EventMask(mask));
if (!p) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
@ -77,7 +77,7 @@ pm_construct(JSContext* cx, uintN argc, jsval* vp)
static void
pm_finalize(JSContext* cx, JSObject* obj)
{
js_delete((PerfMeasurement*) JS_GetPrivate(cx, obj));
cx->delete_((PerfMeasurement*) JS_GetPrivate(cx, obj));
}
// Property access

Просмотреть файл

@ -36,6 +36,8 @@
*
* ***** END LICENSE BLOCK ***** */
using namespace js;
#include "jsperf.h"
#include "jsutil.h"
@ -265,7 +267,7 @@ namespace JS {
#define initCtr(flag) ((eventsMeasured & flag) ? 0 : -1)
PerfMeasurement::PerfMeasurement(PerfMeasurement::EventMask toMeasure)
: impl(js_new<Impl>()),
: impl(OffTheBooks::new_<Impl>()),
eventsMeasured(impl ? static_cast<Impl*>(impl)->init(toMeasure)
: EventMask(0)),
cpu_cycles(initCtr(CPU_CYCLES)),
@ -286,7 +288,7 @@ PerfMeasurement::PerfMeasurement(PerfMeasurement::EventMask toMeasure)
PerfMeasurement::~PerfMeasurement()
{
js_delete(static_cast<Impl*>(impl));
js::Foreground::delete_(static_cast<Impl*>(impl));
}
void

Просмотреть файл

@ -2588,9 +2588,7 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
return returnError(ERR16, error);
size_t size = length + sizeof(JSRegExp);
// FIXME: bug 574459 -- no NULL check
JSRegExp* re = reinterpret_cast<JSRegExp*>(js_array_new<char>(size));
JSRegExp* re = reinterpret_cast<JSRegExp*>(js::OffTheBooks::array_new<char>(size));
if (!re)
return returnError(ERR13, error);
@ -2645,7 +2643,7 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
/* Failed to compile, or error while post-processing */
if (errorcode != ERR0) {
js_array_delete(reinterpret_cast<char*>(re));
js::Foreground::array_delete(reinterpret_cast<char*>(re));
return returnError(errorcode, error);
}
@ -2700,5 +2698,5 @@ JSRegExp* jsRegExpCompile(const UChar* pattern, int patternLength,
void jsRegExpFree(JSRegExp* re)
{
js_array_delete(reinterpret_cast<char*>(re));
js::Foreground::array_delete(reinterpret_cast<char*>(re));
}

Просмотреть файл

@ -394,7 +394,7 @@ struct MatchStack {
if (canUseStackBufferForNextFrame())
return currentFrame + 1;
// FIXME: bug 574459 -- no NULL check
MatchFrame *frame = js_new<MatchFrame>();
MatchFrame *frame = js::OffTheBooks::new_<MatchFrame>();
frame->init(regExpPool);
return frame;
}
@ -417,7 +417,7 @@ struct MatchStack {
MatchFrame* oldFrame = currentFrame;
currentFrame = currentFrame->previousFrame;
if (size > numFramesOnStack)
js_delete(oldFrame);
js::Foreground::delete_(oldFrame);
size--;
}

Просмотреть файл

@ -2630,7 +2630,7 @@ static const char _wordcharData[65536] = {
CharacterClass* digitsCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
characterClass->m_ranges.append(CharacterRange(0x30, 0x39));
return characterClass;
}
@ -2638,7 +2638,7 @@ CharacterClass* digitsCreate()
CharacterClass* nondigitsCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
characterClass->m_ranges.append(CharacterRange(0x00, 0x2f));
characterClass->m_ranges.append(CharacterRange(0x3a, 0x7f));
characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0xffff));
@ -2648,7 +2648,7 @@ CharacterClass* nondigitsCreate()
CharacterClass* newlineCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
characterClass->m_matches.append(0x0a);
characterClass->m_matches.append(0x0d);
characterClass->m_matchesUnicode.append(0x2028);
@ -2659,7 +2659,7 @@ CharacterClass* newlineCreate()
CharacterClass* spacesCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_spacesData, false));
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_spacesData, false));
characterClass->m_ranges.append(CharacterRange(0x09, 0x0d));
characterClass->m_matches.append(0x20);
characterClass->m_matchesUnicode.append(0x00a0);
@ -2677,7 +2677,7 @@ CharacterClass* spacesCreate()
CharacterClass* nonspacesCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_spacesData, true));
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_spacesData, true));
characterClass->m_ranges.append(CharacterRange(0x00, 0x08));
characterClass->m_ranges.append(CharacterRange(0x0e, 0x1f));
characterClass->m_ranges.append(CharacterRange(0x21, 0x7f));
@ -2696,7 +2696,7 @@ CharacterClass* nonspacesCreate()
CharacterClass* nonwordcharCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_wordcharData, true));
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_wordcharData, true));
characterClass->m_ranges.append(CharacterRange(0x00, 0x2f));
characterClass->m_ranges.append(CharacterRange(0x3a, 0x40));
characterClass->m_ranges.append(CharacterRange(0x5b, 0x5e));
@ -2709,7 +2709,7 @@ CharacterClass* nonwordcharCreate()
CharacterClass* wordcharCreate()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>(CharacterClassTable::create(_wordcharData, false));
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>(CharacterClassTable::create(_wordcharData, false));
characterClass->m_ranges.append(CharacterRange(0x30, 0x39));
characterClass->m_ranges.append(CharacterRange(0x41, 0x5a));
characterClass->m_matches.append(0x5f);

Просмотреть файл

@ -140,7 +140,7 @@ public:
CharacterClass* charClass()
{
// FIXME: bug 574459 -- no NULL check
CharacterClass* characterClass = js_new<CharacterClass>((CharacterClassTable*)NULL);
CharacterClass* characterClass = js::OffTheBooks::new_<CharacterClass>((CharacterClassTable*)NULL);
characterClass->m_matches.append(m_matches);
characterClass->m_ranges.append(m_ranges);
@ -346,7 +346,7 @@ public:
m_pattern.m_numSubpatterns++;
// FIXME: bug 574459 -- no NULL check
PatternDisjunction* parenthesesDisjunction = js_new<PatternDisjunction>(m_alternative);
PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
m_pattern.m_disjunctions.append(parenthesesDisjunction);
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParenthesesSubpattern, subpatternId, parenthesesDisjunction, capture));
m_alternative = parenthesesDisjunction->addNewAlternative();
@ -355,7 +355,7 @@ public:
void atomParentheticalAssertionBegin(bool invert = false)
{
// FIXME: bug 574459 -- no NULL check
PatternDisjunction* parenthesesDisjunction = js_new<PatternDisjunction>(m_alternative);
PatternDisjunction* parenthesesDisjunction = js::OffTheBooks::new_<PatternDisjunction>(m_alternative);
m_pattern.m_disjunctions.append(parenthesesDisjunction);
m_alternative->m_terms.append(PatternTerm(PatternTerm::TypeParentheticalAssertion, m_pattern.m_numSubpatterns + 1, parenthesesDisjunction, invert));
m_alternative = parenthesesDisjunction->addNewAlternative();
@ -401,7 +401,7 @@ public:
PatternDisjunction* copyDisjunction(PatternDisjunction* disjunction)
{
// FIXME: bug 574459 -- no NULL check
PatternDisjunction* newDisjunction = js_new<PatternDisjunction>();
PatternDisjunction* newDisjunction = js::OffTheBooks::new_<PatternDisjunction>();
newDisjunction->m_parent = disjunction->m_parent;
for (unsigned alt = 0; alt < disjunction->m_alternatives.length(); ++alt) {
@ -472,7 +472,7 @@ public:
void regexBegin()
{
// FIXME: bug 574459 -- no NULL check
m_pattern.m_body = js_new<PatternDisjunction>();
m_pattern.m_body = js::OffTheBooks::new_<PatternDisjunction>();
m_alternative = m_pattern.m_body->addNewAlternative();
m_pattern.m_disjunctions.append(m_pattern.m_body);
}

Просмотреть файл

@ -60,6 +60,9 @@ struct CharacterRange {
* between character classes, so it's refcounted.
*/
struct CharacterClassTable {
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
const char* m_table;
bool m_inverted;
jsrefcount m_refcount;
@ -69,13 +72,11 @@ struct CharacterClassTable {
{
// FIXME: bug 574459 -- no NULL checks done by any of the callers, all
// of which are in RegExpJitTables.h.
/* We can't (easily) use js_new() here because the constructor is private. */
void *memory = js_malloc(sizeof(CharacterClassTable));
return memory ? new(memory) CharacterClassTable(table, inverted) : NULL;
return js::OffTheBooks::new_<CharacterClassTable>(table, inverted);
}
void incref() { JS_ATOMIC_INCREMENT(&m_refcount); }
void decref() { if (JS_ATOMIC_DECREMENT(&m_refcount) == 0) js_delete(this); }
void decref() { if (JS_ATOMIC_DECREMENT(&m_refcount) == 0) js::Foreground::delete_(this); }
private:
CharacterClassTable(const char* table, bool inverted)
@ -230,6 +231,9 @@ struct PatternTerm {
};
struct PatternAlternative {
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
PatternAlternative(PatternDisjunction* disjunction)
: m_parent(disjunction)
, m_onceThrough(false)
@ -275,10 +279,13 @@ static inline void
deleteAllValues(js::Vector<T*,N,AP> &vector)
{
for (T** t = vector.begin(); t < vector.end(); ++t)
js_delete(*t);
js::Foreground::delete_(*t);
}
struct PatternDisjunction {
JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR;
PatternDisjunction(PatternAlternative* parent = 0)
: m_parent(parent)
, m_hasFixedSize(false)
@ -293,7 +300,7 @@ struct PatternDisjunction {
PatternAlternative* addNewAlternative()
{
// FIXME: bug 574459 -- no NULL check
PatternAlternative* alternative = js_new<PatternAlternative>(this);
PatternAlternative* alternative = js::OffTheBooks::new_<PatternAlternative>(this);
m_alternatives.append(alternative);
return alternative;
}