mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 835966 - Refactor {cx,rt,allocator}->malloc_ (r=luke)
This commit is contained in:
parent
c41e351bdc
commit
8ac8251ea5
@ -1343,7 +1343,13 @@ JSRuntime::setGCMaxMallocBytes(size_t value)
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::updateMallocCounter(JSCompartment *comp, size_t nbytes)
|
||||
JSRuntime::updateMallocCounter(size_t nbytes)
|
||||
{
|
||||
updateMallocCounter(NULL, nbytes);
|
||||
}
|
||||
|
||||
void
|
||||
JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
|
||||
{
|
||||
/* We tolerate any thread races when updating gcMallocBytes. */
|
||||
ptrdiff_t oldCount = gcMallocBytes;
|
||||
@ -1351,8 +1357,8 @@ JSRuntime::updateMallocCounter(JSCompartment *comp, size_t nbytes)
|
||||
gcMallocBytes = newCount;
|
||||
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
|
||||
onTooMuchMalloc();
|
||||
else if (comp)
|
||||
comp->updateMallocCounter(nbytes);
|
||||
else if (zone)
|
||||
zone->updateMallocCounter(nbytes);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
@ -1361,6 +1367,12 @@ JSRuntime::onTooMuchMalloc()
|
||||
TriggerGC(this, gcreason::TOO_MUCH_MALLOC);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JSRuntime::onOutOfMemory(void *p, size_t nbytes)
|
||||
{
|
||||
return onOutOfMemory(p, nbytes, NULL);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
|
||||
{
|
||||
|
212
js/src/jscntxt.h
212
js/src/jscntxt.h
@ -495,15 +495,87 @@ class PerThreadData : public js::PerThreadDataFriendFields
|
||||
bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
|
||||
};
|
||||
|
||||
template<class Client>
|
||||
struct MallocProvider
|
||||
{
|
||||
void *malloc_(size_t bytes) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
client->updateMallocCounter(bytes);
|
||||
void *p = js_malloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : client->onOutOfMemory(NULL, bytes);
|
||||
}
|
||||
|
||||
void *calloc_(size_t bytes) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
client->updateMallocCounter(bytes);
|
||||
void *p = js_calloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : client->onOutOfMemory(reinterpret_cast<void *>(1), bytes);
|
||||
}
|
||||
|
||||
void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
JS_ASSERT(oldBytes < newBytes);
|
||||
client->updateMallocCounter(newBytes - oldBytes);
|
||||
void *p2 = js_realloc(p, newBytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes);
|
||||
}
|
||||
|
||||
void *realloc_(void *p, size_t bytes) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
/*
|
||||
* For compatibility we do not account for realloc that increases
|
||||
* previously allocated memory.
|
||||
*/
|
||||
if (!p)
|
||||
client->updateMallocCounter(bytes);
|
||||
void *p2 = js_realloc(p, bytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, bytes);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_malloc() {
|
||||
return (T *)malloc_(sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_calloc() {
|
||||
return (T *)calloc_(sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_malloc(size_t numElems) {
|
||||
if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
client->reportAllocationOverflow();
|
||||
return NULL;
|
||||
}
|
||||
return (T *)malloc_(numElems * sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_calloc(size_t numElems, JSCompartment *comp = NULL, JSContext *cx = NULL) {
|
||||
if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
|
||||
Client *client = static_cast<Client *>(this);
|
||||
client->reportAllocationOverflow();
|
||||
return NULL;
|
||||
}
|
||||
return (T *)calloc_(numElems * sizeof(T));
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
|
||||
};
|
||||
|
||||
namespace gc {
|
||||
class MarkingValidator;
|
||||
} // namespace gc
|
||||
|
||||
} // namespace js
|
||||
|
||||
struct JSRuntime : js::RuntimeFriendFields
|
||||
struct JSRuntime : js::RuntimeFriendFields,
|
||||
public js::MallocProvider<JSRuntime>
|
||||
{
|
||||
/* Per-thread data for the main thread that is associated with
|
||||
/*
|
||||
* Per-thread data for the main thread that is associated with
|
||||
* this JSRuntime, as opposed to any worker threads used in
|
||||
* parallel sections. See definition of |PerThreadData| struct
|
||||
* above for more details.
|
||||
@ -512,7 +584,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
* sizeof(RuntimeFriendFields). See
|
||||
* PerThreadDataFriendFields::getMainThread.
|
||||
*/
|
||||
js::PerThreadData mainThread;
|
||||
js::PerThreadData mainThread;
|
||||
|
||||
/* Default compartment. */
|
||||
JSCompartment *atomsCompartment;
|
||||
@ -1121,52 +1193,6 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
|
||||
JSRuntime *thisFromCtor() { return this; }
|
||||
|
||||
/*
|
||||
* Call the system malloc while checking for GC memory pressure and
|
||||
* reporting OOM error when cx is not null. We will not GC from here.
|
||||
*/
|
||||
inline void *malloc_(size_t bytes, JSCompartment *comp = NULL, JSContext *cx = NULL);
|
||||
|
||||
/*
|
||||
* Call the system calloc while checking for GC memory pressure and
|
||||
* reporting OOM error when cx is not null. We will not GC from here.
|
||||
*/
|
||||
inline void *calloc_(size_t bytes, JSCompartment *comp = NULL, JSContext *cx = NULL);
|
||||
|
||||
inline void *realloc_(void *p, size_t oldBytes, size_t newBytes, JSCompartment *comp = NULL, JSContext *cx = NULL);
|
||||
|
||||
inline void *realloc_(void *p, size_t bytes, JSCompartment *comp = NULL, JSContext *cx = NULL);
|
||||
|
||||
template <class T>
|
||||
T *pod_malloc(JSCompartment *comp = NULL, JSContext *cx = NULL) {
|
||||
return (T *)malloc_(sizeof(T), comp, cx);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_calloc(JSCompartment *comp = NULL, JSContext *cx = NULL) {
|
||||
return (T *)calloc_(sizeof(T), comp, cx);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_malloc(size_t numElems, JSCompartment *comp = NULL, JSContext *cx = NULL) {
|
||||
if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
|
||||
js_ReportAllocationOverflow(cx);
|
||||
return NULL;
|
||||
}
|
||||
return (T *)malloc_(numElems * sizeof(T), comp, cx);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_calloc(size_t numElems, JSCompartment *comp = NULL, JSContext *cx = NULL) {
|
||||
if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
|
||||
js_ReportAllocationOverflow(cx);
|
||||
return NULL;
|
||||
}
|
||||
return (T *)calloc_(numElems * sizeof(T), comp, cx);
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
|
||||
|
||||
void setGCMaxMallocBytes(size_t value);
|
||||
|
||||
void resetGCMallocBytes() { gcMallocBytes = ptrdiff_t(gcMaxMallocBytes); }
|
||||
@ -1179,7 +1205,10 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
* The function must be called outside the GC lock and in case of OOM error
|
||||
* the caller must ensure that no deadlock possible during OOM reporting.
|
||||
*/
|
||||
void updateMallocCounter(JSCompartment *comp, size_t nbytes);
|
||||
void updateMallocCounter(size_t nbytes);
|
||||
void updateMallocCounter(JS::Zone *zone, size_t nbytes);
|
||||
|
||||
void reportAllocationOverflow() { js_ReportAllocationOverflow(NULL); }
|
||||
|
||||
bool isTooMuchMalloc() const {
|
||||
return gcMallocBytes <= 0;
|
||||
@ -1198,6 +1227,7 @@ struct JSRuntime : js::RuntimeFriendFields
|
||||
*
|
||||
* The function must be called outside the GC lock.
|
||||
*/
|
||||
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
|
||||
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes, JSContext *cx);
|
||||
|
||||
void triggerOperationCallback();
|
||||
@ -1376,7 +1406,8 @@ FreeOp::free_(void *p)
|
||||
} /* namespace js */
|
||||
|
||||
struct JSContext : js::ContextFriendFields,
|
||||
public mozilla::LinkedListElement<JSContext>
|
||||
public mozilla::LinkedListElement<JSContext>,
|
||||
public js::MallocProvider<JSContext>
|
||||
{
|
||||
explicit JSContext(JSRuntime *rt);
|
||||
JSContext *thisDuringConstruction() { return this; }
|
||||
@ -1655,41 +1686,16 @@ struct JSContext : js::ContextFriendFields,
|
||||
void enterGenerator(JSGenerator *gen);
|
||||
void leaveGenerator(JSGenerator *gen);
|
||||
|
||||
inline void *malloc_(size_t bytes) {
|
||||
return runtime->malloc_(bytes, compartment, this);
|
||||
void *onOutOfMemory(void *p, size_t nbytes) {
|
||||
return runtime->onOutOfMemory(p, nbytes, this);
|
||||
}
|
||||
|
||||
inline void *calloc_(size_t bytes) {
|
||||
return runtime->calloc_(bytes, compartment, this);
|
||||
void updateMallocCounter(size_t nbytes) {
|
||||
runtime->updateMallocCounter(compartment, nbytes);
|
||||
}
|
||||
|
||||
inline void *realloc_(void *p, size_t bytes) {
|
||||
return runtime->realloc_(p, bytes, compartment, this);
|
||||
void reportAllocationOverflow() {
|
||||
js_ReportAllocationOverflow(this);
|
||||
}
|
||||
|
||||
inline void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
|
||||
return runtime->realloc_(p, oldBytes, newBytes, compartment, this);
|
||||
}
|
||||
|
||||
template <class T> T *pod_malloc() {
|
||||
return runtime->pod_malloc<T>(compartment, this);
|
||||
}
|
||||
|
||||
template <class T> T *pod_calloc() {
|
||||
return runtime->pod_calloc<T>(compartment, this);
|
||||
}
|
||||
|
||||
template <class T> T *pod_malloc(size_t numElems) {
|
||||
return runtime->pod_malloc<T>(numElems, compartment, this);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *pod_calloc(size_t numElems) {
|
||||
return runtime->pod_calloc<T>(numElems, compartment, this);
|
||||
}
|
||||
|
||||
JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
|
||||
|
||||
void purge();
|
||||
|
||||
bool isExceptionPending() {
|
||||
@ -2306,46 +2312,4 @@ class ContextAllocPolicy
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void *
|
||||
JSRuntime::malloc_(size_t bytes, JSCompartment *comp, JSContext *cx)
|
||||
{
|
||||
JS_ASSERT_IF(cx != NULL, cx->compartment == comp);
|
||||
updateMallocCounter(comp, bytes);
|
||||
void *p = js_malloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : onOutOfMemory(NULL, bytes, cx);
|
||||
}
|
||||
|
||||
void *
|
||||
JSRuntime::calloc_(size_t bytes, JSCompartment *comp, JSContext *cx)
|
||||
{
|
||||
JS_ASSERT_IF(cx != NULL, cx->compartment == comp);
|
||||
updateMallocCounter(comp, bytes);
|
||||
void *p = js_calloc(bytes);
|
||||
return JS_LIKELY(!!p) ? p : onOutOfMemory(reinterpret_cast<void *>(1), bytes, cx);
|
||||
}
|
||||
|
||||
void *
|
||||
JSRuntime::realloc_(void *p, size_t oldBytes, size_t newBytes, JSCompartment *comp, JSContext *cx)
|
||||
{
|
||||
JS_ASSERT_IF(cx != NULL, cx->compartment == comp);
|
||||
JS_ASSERT(oldBytes < newBytes);
|
||||
updateMallocCounter(comp, newBytes - oldBytes);
|
||||
void *p2 = js_realloc(p, newBytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, newBytes, cx);
|
||||
}
|
||||
|
||||
void *
|
||||
JSRuntime::realloc_(void *p, size_t bytes, JSCompartment *comp, JSContext *cx)
|
||||
{
|
||||
JS_ASSERT_IF(cx != NULL, cx->compartment == comp);
|
||||
/*
|
||||
* For compatibility we do not account for realloc that increases
|
||||
* previously allocated memory.
|
||||
*/
|
||||
if (!p)
|
||||
updateMallocCounter(comp, bytes);
|
||||
void *p2 = js_realloc(p, bytes);
|
||||
return JS_LIKELY(!!p2) ? p2 : onOutOfMemory(p, bytes, cx);
|
||||
}
|
||||
|
||||
#endif /* jscntxt_h___ */
|
||||
|
@ -132,26 +132,20 @@ namespace js {
|
||||
* parallel or sequential mode, you should make it take an
|
||||
* |Allocator*| rather than a |JSContext*|.
|
||||
*/
|
||||
class Allocator
|
||||
class Allocator : public MallocProvider<Allocator>
|
||||
{
|
||||
JSCompartment*const compartment;
|
||||
JS::Zone *zone;
|
||||
|
||||
public:
|
||||
explicit Allocator(JSCompartment *compartment);
|
||||
explicit Allocator(JS::Zone *zone);
|
||||
|
||||
js::gc::ArenaLists arenas;
|
||||
|
||||
inline void *parallelNewGCThing(gc::AllocKind thingKind, size_t thingSize);
|
||||
|
||||
inline void *malloc_(size_t bytes);
|
||||
inline void *calloc_(size_t bytes);
|
||||
inline void *realloc_(void *p, size_t bytes);
|
||||
inline void *realloc_(void *p, size_t oldBytes, size_t newBytes);
|
||||
template <class T> inline T *pod_malloc();
|
||||
template <class T> inline T *pod_calloc();
|
||||
template <class T> inline T *pod_malloc(size_t numElems);
|
||||
template <class T> inline T *pod_calloc(size_t numElems);
|
||||
JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
|
||||
inline void *onOutOfMemory(void *p, size_t nbytes);
|
||||
inline void updateMallocCounter(size_t nbytes);
|
||||
inline void reportAllocationOverflow();
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -27,62 +27,28 @@ js::AutoCompartment::~AutoCompartment()
|
||||
cx_->leaveCompartment(origin_);
|
||||
}
|
||||
|
||||
inline void *
|
||||
js::Allocator::malloc_(size_t bytes)
|
||||
void *
|
||||
js::Allocator::onOutOfMemory(void *p, size_t nbytes)
|
||||
{
|
||||
return compartment->rt->malloc_(bytes, compartment);
|
||||
return zone->rt->onOutOfMemory(p, nbytes);
|
||||
}
|
||||
|
||||
inline void *
|
||||
js::Allocator::calloc_(size_t bytes)
|
||||
void
|
||||
js::Allocator::updateMallocCounter(size_t nbytes)
|
||||
{
|
||||
return compartment->rt->calloc_(bytes, compartment);
|
||||
zone->rt->updateMallocCounter(zone, nbytes);
|
||||
}
|
||||
|
||||
inline void *
|
||||
js::Allocator::realloc_(void *p, size_t bytes)
|
||||
void
|
||||
js::Allocator::reportAllocationOverflow()
|
||||
{
|
||||
return compartment->rt->realloc_(p, bytes, compartment);
|
||||
}
|
||||
|
||||
inline void *
|
||||
js::Allocator::realloc_(void* p, size_t oldBytes, size_t newBytes)
|
||||
{
|
||||
return compartment->rt->realloc_(p, oldBytes, newBytes, compartment);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *
|
||||
js::Allocator::pod_malloc()
|
||||
{
|
||||
return compartment->rt->pod_malloc<T>(compartment);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *
|
||||
js::Allocator::pod_calloc()
|
||||
{
|
||||
return compartment->rt->pod_calloc<T>(compartment);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *
|
||||
js::Allocator::pod_malloc(size_t numElems)
|
||||
{
|
||||
return compartment->rt->pod_malloc<T>(numElems, compartment);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T *
|
||||
js::Allocator::pod_calloc(size_t numElems)
|
||||
{
|
||||
return compartment->rt->pod_calloc<T>(numElems, compartment);
|
||||
js_ReportAllocationOverflow(NULL);
|
||||
}
|
||||
|
||||
inline void *
|
||||
js::Allocator::parallelNewGCThing(gc::AllocKind thingKind, size_t thingSize)
|
||||
{
|
||||
return arenas.parallelAllocate(compartment, thingKind, thingSize);
|
||||
return arenas.parallelAllocate(zone, thingKind, thingSize);
|
||||
}
|
||||
|
||||
#endif /* jscompartment_inlines_h___ */
|
||||
|
@ -1160,8 +1160,8 @@ JSCompartment::reduceGCTriggerBytes(size_t amount)
|
||||
gcTriggerBytes -= amount;
|
||||
}
|
||||
|
||||
Allocator::Allocator(JSCompartment *compartment)
|
||||
: compartment(compartment)
|
||||
Allocator::Allocator(Zone *zone)
|
||||
: zone(zone)
|
||||
{}
|
||||
|
||||
inline void
|
||||
|
Loading…
Reference in New Issue
Block a user