зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
1b3a06bc73
Коммит
1e46fe8cee
|
@ -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
Двоичные данные
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, ®exp_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;
|
||||
|
||||
|
|
321
js/src/jsutil.h
321
js/src/jsutil.h
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче