bug 646044 - ContextAllocPolicy should not account for GC memory pressure. r=luke

This commit is contained in:
Igor Bukanov 2011-03-30 12:10:12 +02:00
parent 6c9d3889b6
commit 6a31362caa
16 changed files with 200 additions and 88 deletions

View File

@ -125,6 +125,7 @@ DIST_INSTALL = 1
VPATH = $(srcdir)
CPPSRCS = \
jsalloc.cpp \
jsanalyze.cpp \
jsapi.cpp \
jsarena.cpp \
@ -184,6 +185,7 @@ INSTALLED_HEADERS = \
jsautocfg.h \
$(CURDIR)/jsautokw.h \
js.msg \
jsalloc.h \
jsanalyze.h \
jsapi.h \
jsarray.h \
@ -610,7 +612,7 @@ endif
# (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))
check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL_FILES))
# js_malloc and friends are only used by other memory managers, and should
# never be used elsewhere directly.
@ -625,10 +627,10 @@ check-malloc-function-usage: $(filter-out %jsutil.h %jscntxt.h, $(ALL_FILES))
# 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 \
$(srcdir)/config/check_source_count.py OffTheBooks:: 52 \
"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:: 35 \
$(srcdir)/config/check_source_count.py UnwantedForeground:: 34 \
"in Makefile.in" "{cx,rt}->{free_,delete_,array_delete}" $^
ifneq ($(OS_ARCH),WINNT) # FIXME: this should be made work on Windows too.

56
js/src/jsalloc.cpp Normal file
View File

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* July 16, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "jsalloc.h"
#include "jscntxt.h"
namespace js {
void *
ContextAllocPolicy::onOutOfMemory(void *p, size_t nbytes)
{
return cx->runtime->onOutOfMemory(p, nbytes, cx);
}
void
ContextAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx);
}
} /* namespace js */

119
js/src/jsalloc.h Normal file
View File

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
* July 16, 2009.
*
* The Initial Developer of the Original Code is
* the Mozilla Corporation.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef jsalloc_h_
#define jsalloc_h_
#include "jspubtd.h"
#include "jsutil.h"
#include "jsstaticcheck.h"
namespace js {
/*
* Allocation policies. These model the concept:
* - public copy constructor, assignment, destructor
* - void *malloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *realloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void free_(void *)
* - reportAllocOverflow()
* Called on overflow before the container returns NULL.
*/
/* Policy for using system memory functions and doing no error reporting. */
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 reportAllocOverflow() const {}
};
/*
* Allocation policy that calls the system memory functions and reports errors
* to the context. Since the JSContext given on construction is stored for
* the lifetime of the container, this policy may only be used for containers
* whose lifetime is a shorter than the given JSContext.
*
* FIXME bug 647103 - rewrite this in terms of temporary allocation functions,
* not the system ones.
*/
class ContextAllocPolicy
{
JSContext *const cx;
/*
* Non-inline helper to call JSRuntime::onOutOfMemory with minimal
* code bloat.
*/
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
public:
ContextAllocPolicy(JSContext *cx) : cx(cx) {}
JSContext *context() const {
return cx;
}
void *malloc_(size_t bytes) {
void *p = js_malloc(bytes);
if (JS_UNLIKELY(!p))
p = onOutOfMemory(NULL, bytes);
return p;
}
void *realloc_(void *p, size_t bytes) {
void *p2 = js_realloc(p, bytes);
if (JS_UNLIKELY(!p2))
p2 = onOutOfMemory(p2, bytes);
return p2;
}
void free_(void *p) {
js_free(p);
}
JS_FRIEND_API(void) reportAllocOverflow() const;
};
} /* namespace js */
#endif /* jsalloc_h_ */

View File

@ -44,6 +44,7 @@
*/
#include <stdlib.h>
#include <string.h>
#include "jsalloc.h"
#include "jstypes.h"
#include "jsstdint.h"
#include "jsbit.h"

View File

@ -468,7 +468,7 @@ JSStructuredCloneWriter::startObject(JSObject *obj)
JS_ASSERT(obj->isArray() || obj->isObject());
/* Fail if obj is already on the stack. */
HashSet<JSObject *>::AddPtr p = memory.lookupForAdd(obj);
MemorySet::AddPtr p = memory.lookupForAdd(obj);
if (p) {
JSContext *cx = context();
if (callbacks && callbacks->reportError)

View File

@ -179,7 +179,8 @@ struct JSStructuredCloneWriter {
// The "memory" list described in the HTML5 internal structured cloning algorithm.
// memory has the same elements as objs.
js::HashSet<JSObject *> memory;
typedef js::HashSet<JSObject *> MemorySet;
MemorySet memory;
// The user defined callbacks that will be used for cloning.
const JSStructuredCloneCallbacks *callbacks;

View File

@ -118,27 +118,6 @@ namespace mjit {
class JaegerCompartment;
}
/*
* Allocation policy that calls JSContext memory functions and reports errors
* to the context. Since the JSContext given on construction is stored for
* the lifetime of the container, this policy may only be used for containers
* whose lifetime is a shorter than the given JSContext.
*/
class ContextAllocPolicy
{
JSContext *cx;
public:
ContextAllocPolicy(JSContext *cx) : cx(cx) {}
JSContext *context() const { return cx; }
/* Inline definitions below. */
void *malloc_(size_t bytes);
void free_(void *p);
void *realloc_(void *p, size_t bytes);
void reportAllocOverflow() const;
};
/*
* A StackSegment (referred to as just a 'segment') contains a prev-linked set
* of stack frames and the slots associated with each frame. A segment and its
@ -1449,7 +1428,6 @@ struct JSRuntime {
onTooMuchMalloc();
}
private:
/*
* The function must be called outside the GC lock.
*/
@ -3168,30 +3146,6 @@ js_RegenerateShapeForGC(JSRuntime *rt)
namespace js {
inline void *
ContextAllocPolicy::malloc_(size_t bytes)
{
return cx->malloc_(bytes);
}
inline void
ContextAllocPolicy::free_(void *p)
{
cx->free_(p);
}
inline void *
ContextAllocPolicy::realloc_(void *p, size_t bytes)
{
return cx->realloc_(p, bytes);
}
inline void
ContextAllocPolicy::reportAllocOverflow() const
{
js_ReportAllocationOverflow(cx);
}
template<class T>
class AutoVectorRooter : protected AutoGCRooter
{
@ -3251,7 +3205,8 @@ class AutoVectorRooter : protected AutoGCRooter
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<T, 8> vector;
typedef Vector<T, 8> VectorImpl;
VectorImpl vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};

View File

@ -1504,7 +1504,7 @@ AutoIdArray::trace(JSTracer *trc)
void
AutoEnumStateRooter::trace(JSTracer *trc)
{
js::gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
gc::MarkObject(trc, *obj, "js::AutoEnumStateRooter.obj");
}
inline void
@ -1585,24 +1585,24 @@ AutoGCRooter::trace(JSTracer *trc)
return;
case VALVECTOR: {
Vector<Value, 8> &vector = static_cast<js::AutoValueVector *>(this)->vector;
AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
MarkValueRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
return;
}
case STRING:
if (JSString *str = static_cast<js::AutoStringRooter *>(this)->str)
if (JSString *str = static_cast<AutoStringRooter *>(this)->str)
MarkString(trc, str, "js::AutoStringRooter.str");
return;
case IDVECTOR: {
Vector<jsid, 8> &vector = static_cast<js::AutoIdVector *>(this)->vector;
AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
MarkIdRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
return;
}
case SHAPEVECTOR: {
Vector<const Shape *, 8> &vector = static_cast<js::AutoShapeVector *>(this)->vector;
AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
MarkShapeRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
return;
}

View File

@ -43,6 +43,7 @@
#ifndef jshashtable_h_
#define jshashtable_h_
#include "jsalloc.h"
#include "jstl.h"
namespace js {

View File

@ -552,8 +552,6 @@ EnumeratedIdVectorToIterator(JSContext *cx, JSObject *obj, uintN flags, AutoIdVe
return VectorToValueIterator(cx, obj, flags, props, vp);
}
typedef Vector<uint32, 8> ShapeVector;
static inline void
UpdateNativeIterator(NativeIterator *ni, JSObject *obj)
{

View File

@ -305,7 +305,7 @@ namespace js {
struct GlobalScope {
GlobalScope(JSContext *cx, JSObject *globalObj, JSCodeGenerator *cg)
: globalObj(globalObj), cg(cg), defs(ContextAllocPolicy(cx))
: globalObj(globalObj), cg(cg), defs(cx)
{ }
struct GlobalDef {
@ -334,7 +334,7 @@ struct GlobalScope {
* A definition may either specify an existing global property, or a new
* one that must be added after compilation succeeds.
*/
Vector<GlobalDef, 16, ContextAllocPolicy> defs;
Vector<GlobalDef, 16> defs;
JSAtomList names;
};

View File

@ -1,4 +1,4 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1

View File

@ -40,6 +40,7 @@
#ifndef jstl_h_
#define jstl_h_
#include "jspubtd.h"
#include "jsbit.h"
#include "jsstaticcheck.h"
#include "jsstdint.h"
@ -233,28 +234,6 @@ PointerRangeSize(T *begin, T *end)
return (size_t(end) - size_t(begin)) / sizeof(T);
}
/*
* Allocation policies. These model the concept:
* - public copy constructor, assignment, destructor
* - void *malloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void *realloc_(size_t)
* Responsible for OOM reporting on NULL return value.
* - void free_(void *)
* - reportAllocOverflow()
* Called on overflow before the container returns NULL.
*/
/* Policy for using system memory functions and doing no error reporting. */
class SystemAllocPolicy
{
public:
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 {}
};
/*
* This utility pales in comparison to Boost's aligned_storage. The utility
* simply assumes that JSUint64 is enough alignment for anyone. This may need

View File

@ -41,6 +41,7 @@
#ifndef jsvector_h_
#define jsvector_h_
#include "jsalloc.h"
#include "jstl.h"
#include "jsprvtd.h"

View File

@ -68,7 +68,7 @@ AutoScriptRetrapper::untrap(jsbytecode *pc)
{
if (!traps.append(pc))
return false;
*pc = JS_GetTrapOpcode(cx, script, pc);
*pc = JS_GetTrapOpcode(traps.allocPolicy().context(), script, pc);
return true;
}

View File

@ -63,14 +63,13 @@ namespace mjit {
class AutoScriptRetrapper
{
public:
AutoScriptRetrapper(JSContext *cx1, JSScript *script1) :
cx(cx1), script(script1), traps(cx) {};
AutoScriptRetrapper(JSContext *cx, JSScript *script1) :
script(script1), traps(cx) {};
~AutoScriptRetrapper();
bool untrap(jsbytecode *pc);
private:
JSContext *cx;
JSScript *script;
Vector<jsbytecode*> traps;
};