Bug 1134425 - Part 1: move the allocator interface code out of line; r=jonco

--HG--
extra : rebase_source : cbeb8097a3c55397cc0c0f476deb0011ad496f62
This commit is contained in:
Terrence Cole 2015-03-04 09:32:02 -08:00
Родитель a26a5496a6
Коммит bb7d88df07
27 изменённых файлов: 469 добавлений и 347 удалений

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

@ -19,6 +19,7 @@
#include "jspubtd.h"
#include "js/HashTable.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
#include "js/Vector.h"

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

@ -37,6 +37,7 @@
#include "frontend/Parser.h"
#include "jit/IonCode.h"
#include "js/Class.h"
#include "js/Conversions.h"
#include "js/MemoryMetrics.h"
@ -50,9 +51,10 @@ using namespace js;
using namespace jit;
using namespace frontend;
using mozilla::BinarySearch;
using mozilla::Compression::LZ4;
using mozilla::PodCopy;
using mozilla::PodEqual;
using mozilla::Compression::LZ4;
using mozilla::PodZero;
using mozilla::Swap;
static uint8_t *

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

@ -55,6 +55,7 @@
#include "prmjtime.h"
#include "js/Class.h"
#include "vm/GlobalObject.h"
#include "vm/SharedTypedArrayObject.h"
#include "vm/TypedArrayObject.h"

355
js/src/gc/Allocator.cpp Normal file
Просмотреть файл

@ -0,0 +1,355 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gc/Allocator.h"
#include "jscntxt.h"
#include "gc/GCTrace.h"
#include "gc/Nursery.h"
#include "jit/JitCompartment.h"
#include "vm/Runtime.h"
#include "vm/String.h"
#include "jsobjinlines.h"
using namespace js;
using namespace gc;
static inline bool
ShouldNurseryAllocateObject(const Nursery &nursery, InitialHeap heap)
{
return nursery.isEnabled() && heap != TenuredHeap;
}
/*
* Attempt to allocate a new GC thing out of the nursery. If there is not enough
* room in the nursery or there is an OOM, this method will return nullptr.
*/
template <AllowGC allowGC>
inline JSObject *
TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots, const Class *clasp)
{
MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
JSRuntime *rt = cx->runtime();
Nursery &nursery = rt->gc.nursery;
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
if (obj)
return obj;
if (allowGC && !rt->mainThread.suppressGC) {
cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
/* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
if (nursery.isEnabled()) {
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
MOZ_ASSERT(obj);
return obj;
}
}
return nullptr;
}
static inline bool
PossiblyFail()
{
JS_OOM_POSSIBLY_FAIL_BOOL();
return true;
}
static inline bool
GCIfNeeded(ExclusiveContext *cx)
{
if (cx->isJSContext()) {
JSContext *ncx = cx->asJSContext();
JSRuntime *rt = ncx->runtime();
#ifdef JS_GC_ZEAL
if (rt->gc.needZealousGC())
rt->gc.runDebugGC();
#endif
// Invoking the interrupt callback can fail and we can't usefully
// handle that here. Just check in case we need to collect instead.
if (rt->hasPendingInterrupt())
rt->gc.gcIfRequested(ncx);
// If we have grown past our GC heap threshold while in the middle of
// an incremental GC, we're growing faster than we're GCing, so stop
// the world and do a full, non-incremental GC right now, if possible.
if (rt->gc.isIncrementalGCInProgress() &&
cx->zone()->usage.gcBytes() > cx->zone()->threshold.gcTriggerBytes())
{
PrepareZoneForGC(cx->zone());
AutoKeepAtoms keepAtoms(cx->perThreadData);
rt->gc.gc(GC_NORMAL, JS::gcreason::INCREMENTAL_TOO_SLOW);
}
}
return true;
}
template <AllowGC allowGC>
static inline bool
CheckAllocatorState(ExclusiveContext *cx, AllocKind kind)
{
if (allowGC) {
if (!GCIfNeeded(cx))
return false;
}
if (!cx->isJSContext())
return true;
JSContext *ncx = cx->asJSContext();
JSRuntime *rt = ncx->runtime();
#if defined(JS_GC_ZEAL) || defined(DEBUG)
MOZ_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
kind == FINALIZE_STRING ||
kind == FINALIZE_FAT_INLINE_STRING ||
kind == FINALIZE_SYMBOL ||
kind == FINALIZE_JITCODE);
MOZ_ASSERT(!rt->isHeapBusy());
MOZ_ASSERT(rt->gc.isAllocAllowed());
#endif
// Crash if we perform a GC action when it is not safe.
if (allowGC && !rt->mainThread.suppressGC)
JS::AutoAssertOnGC::VerifyIsSafeToGC(rt);
// For testing out of memory conditions
if (!PossiblyFail()) {
ReportOutOfMemory(ncx);
return false;
}
return true;
}
template <typename T>
static inline void
CheckIncrementalZoneState(ExclusiveContext *cx, T *t)
{
#ifdef DEBUG
if (!cx->isJSContext())
return;
Zone *zone = cx->asJSContext()->zone();
MOZ_ASSERT_IF(t && zone->wasGCStarted() && (zone->isGCMarking() || zone->isGCSweeping()),
t->asTenured().arenaHeader()->allocatedDuringIncremental);
#endif
}
/*
* Allocate a new GC thing. After a successful allocation the caller must
* fully initialize the thing before calling any function that can potentially
* trigger GC. This will ensure that GC tracing never sees junk values stored
* in the partially initialized thing.
*/
template <AllowGC allowGC>
inline JSObject *
AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
const Class *clasp)
{
size_t thingSize = Arena::thingSize(kind);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0));
static_assert(sizeof(JSObject_Slots0) >= CellSize,
"All allocations must be at least the allocator-imposed minimum size.");
if (!CheckAllocatorState<allowGC>(cx, kind))
return nullptr;
if (cx->isJSContext() &&
ShouldNurseryAllocateObject(cx->asJSContext()->nursery(), heap))
{
JSObject *obj = TryNewNurseryObject<allowGC>(cx->asJSContext(), thingSize, nDynamicSlots,
clasp);
if (obj)
return obj;
}
HeapSlot *slots = nullptr;
if (nDynamicSlots) {
slots = cx->zone()->pod_malloc<HeapSlot>(nDynamicSlots);
if (MOZ_UNLIKELY(!slots))
return nullptr;
Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
}
JSObject *obj = reinterpret_cast<JSObject *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
if (!obj)
obj = reinterpret_cast<JSObject *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
if (obj)
obj->setInitialSlotsMaybeNonNative(slots);
else
js_free(slots);
CheckIncrementalZoneState(cx, obj);
TraceTenuredAlloc(obj, kind);
return obj;
}
template <typename T, AllowGC allowGC>
inline T *
AllocateNonObject(ExclusiveContext *cx)
{
static_assert(sizeof(T) >= CellSize,
"All allocations must be at least the allocator-imposed minimum size.");
AllocKind kind = MapTypeToFinalizeKind<T>::kind;
size_t thingSize = sizeof(T);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
if (!CheckAllocatorState<allowGC>(cx, kind))
return nullptr;
T *t = static_cast<T *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
if (!t)
t = static_cast<T *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
CheckIncrementalZoneState(cx, t);
TraceTenuredAlloc(t, kind);
return t;
}
/*
* When allocating for initialization from a cached object copy, we will
* potentially destroy the cache entry we want to copy if we allow GC. On the
* other hand, since these allocations are extremely common, we don't want to
* delay GC from these allocation sites. Instead we allow the GC, but still
* fail the allocation, forcing the non-cached path.
*/
template <AllowGC allowGC>
NativeObject *
js::gc::AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap,
const js::Class *clasp)
{
MOZ_ASSERT(clasp->isNative());
if (ShouldNurseryAllocateObject(cx->nursery(), heap)) {
size_t thingSize = Arena::thingSize(kind);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
if (!CheckAllocatorState<NoGC>(cx, kind))
return nullptr;
JSObject *obj = TryNewNurseryObject<NoGC>(cx, thingSize, 0, clasp);
if (!obj && allowGC) {
cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
return nullptr;
}
return reinterpret_cast<NativeObject *>(obj);
}
JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap, clasp);
if (!obj && allowGC) {
cx->runtime()->gc.maybeGC(cx->zone());
return nullptr;
}
return reinterpret_cast<NativeObject *>(obj);
}
template NativeObject *js::gc::AllocateObjectForCacheHit<CanGC>(JSContext *, AllocKind, InitialHeap,
const Class *);
template NativeObject *js::gc::AllocateObjectForCacheHit<NoGC>(JSContext *, AllocKind, InitialHeap,
const Class *);
template <AllowGC allowGC>
JSObject *
js::NewGCObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots,
InitialHeap heap, const Class *clasp)
{
MOZ_ASSERT(kind >= FINALIZE_OBJECT0 && kind <= FINALIZE_OBJECT_LAST);
return AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap, clasp);
}
template JSObject *js::NewGCObject<CanGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
const Class *);
template JSObject *js::NewGCObject<NoGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
const Class *);
template <AllowGC allowGC>
jit::JitCode *
js::NewJitCode(ExclusiveContext *cx)
{
return AllocateNonObject<jit::JitCode, allowGC>(cx);
}
template jit::JitCode *js::NewJitCode<CanGC>(ExclusiveContext *cx);
template jit::JitCode *js::NewJitCode<NoGC>(ExclusiveContext *cx);
ObjectGroup *
js::NewObjectGroup(ExclusiveContext *cx)
{
return AllocateNonObject<ObjectGroup, CanGC>(cx);
}
template <AllowGC allowGC>
JSString *
js::NewGCString(ExclusiveContext *cx)
{
return AllocateNonObject<JSString, allowGC>(cx);
}
template JSString *js::NewGCString<CanGC>(ExclusiveContext *cx);
template JSString *js::NewGCString<NoGC>(ExclusiveContext *cx);
template <AllowGC allowGC>
JSFatInlineString *
js::NewGCFatInlineString(ExclusiveContext *cx)
{
return AllocateNonObject<JSFatInlineString, allowGC>(cx);
}
template JSFatInlineString *js::NewGCFatInlineString<CanGC>(ExclusiveContext *cx);
template JSFatInlineString *js::NewGCFatInlineString<NoGC>(ExclusiveContext *cx);
JSExternalString *
js::NewGCExternalString(ExclusiveContext *cx)
{
return AllocateNonObject<JSExternalString, CanGC>(cx);
}
Shape *
js::NewGCShape(ExclusiveContext *cx)
{
return AllocateNonObject<Shape, CanGC>(cx);
}
Shape *
js::NewGCAccessorShape(ExclusiveContext *cx)
{
return AllocateNonObject<AccessorShape, CanGC>(cx);
}
JSScript *
js::NewGCScript(ExclusiveContext *cx)
{
return AllocateNonObject<JSScript, CanGC>(cx);
}
LazyScript *
js::NewGCLazyScript(ExclusiveContext *cx)
{
return AllocateNonObject<LazyScript, CanGC>(cx);
}
template <AllowGC allowGC>
BaseShape *
js::NewGCBaseShape(ExclusiveContext *cx)
{
return AllocateNonObject<BaseShape, allowGC>(cx);
}
template BaseShape *js::NewGCBaseShape<CanGC>(ExclusiveContext *cx);
template BaseShape *js::NewGCBaseShape<NoGC>(ExclusiveContext *cx);
template <AllowGC allowGC>
JS::Symbol *
js::NewGCSymbol(ExclusiveContext *cx)
{
return AllocateNonObject<JS::Symbol, allowGC>(cx);
}
template JS::Symbol *js::NewGCSymbol<CanGC>(ExclusiveContext *cx);
template JS::Symbol *js::NewGCSymbol<NoGC>(ExclusiveContext *cx);

84
js/src/gc/Allocator.h Normal file
Просмотреть файл

@ -0,0 +1,84 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef gc_Allocator_h
#define gc_Allocator_h
#include "gc/Heap.h"
#include "js/RootingAPI.h"
namespace JS {
class Symbol;
} // namespace JS
class JSExternalString;
class JSFatInlineString;
class JSObject;
class JSScript;
class JSString;
namespace js {
struct Class;
class BaseShape;
class LazyScript;
class ObjectGroup;
class Shape;
namespace jit {
class JitCode;
} // namespace jit
template <AllowGC allowGC>
JSObject *
NewGCObject(ExclusiveContext *cx, gc::AllocKind kind, size_t nDynamicSlots,
gc::InitialHeap heap, const Class *clasp);
template <AllowGC allowGC>
jit::JitCode *
NewJitCode(ExclusiveContext *cx);
ObjectGroup *
NewObjectGroup(ExclusiveContext *cx);
template <AllowGC allowGC>
JSString *
NewGCString(ExclusiveContext *cx);
template <AllowGC allowGC>
JSFatInlineString *
NewGCFatInlineString(ExclusiveContext *cx);
JSExternalString *
NewGCExternalString(ExclusiveContext *cx);
Shape *
NewGCShape(ExclusiveContext *cx);
Shape *
NewGCAccessorShape(ExclusiveContext *cx);
JSScript *
NewGCScript(ExclusiveContext *cx);
LazyScript *
NewGCLazyScript(ExclusiveContext *cx);
template <AllowGC allowGC>
BaseShape *
NewGCBaseShape(ExclusiveContext *cx);
template <AllowGC allowGC>
JS::Symbol *
NewGCSymbol(ExclusiveContext *cx);
namespace gc {
template <AllowGC allowGC>
NativeObject *
AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap, const Class *clasp);
} // namespace gc
} // namespace js
#endif // gc_Allocator_h

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

@ -26,7 +26,7 @@
#include "vm/TypedArrayObject.h"
#include "vm/TypeInference.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "vm/NativeObject-inl.h"

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

@ -10,6 +10,7 @@
#include "gc/Statistics.h"
#include "vm/ArgumentsObject.h"
#include "vm/Runtime.h"
#include "jsgcinlines.h"

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

@ -14,10 +14,10 @@
#include "jit/CompileInfo.h"
#include "jit/JitCommon.h"
#include "jit/JitSpewer.h"
#include "vm/Debugger.h"
#include "vm/Interpreter.h"
#include "vm/TraceLogging.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "jsopcodeinlines.h"
#include "jsscriptinlines.h"

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

@ -46,7 +46,6 @@
#include "vm/TraceLogging.h"
#include "jscompartmentinlines.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
using namespace js;

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

@ -20,6 +20,7 @@
#include "jit/CompileInfo.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitCompartment.h"
#include "jit/MIR.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
#endif

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

@ -20,7 +20,6 @@
#include "js/Conversions.h"
#include "vm/TraceLogging.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
#include "vm/Interpreter-inl.h"

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

@ -8,6 +8,8 @@
#include "mozilla/SizePrintfMacros.h"
#include "jsprf.h"
#include "ds/Sort.h"
#include "jit/IonBuilder.h"
#include "jit/JitcodeMap.h"

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

@ -27,6 +27,7 @@
#include "ds/Sort.h"
#include "gc/Heap.h"
#include "js/Class.h"
#include "js/Conversions.h"
#include "vm/ArgumentsObject.h"
#include "vm/Interpreter.h"

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

@ -35,6 +35,7 @@ using namespace js::gc;
using namespace js::jit;
using mozilla::DebugOnly;
using mozilla::PodArrayZero;
JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
: options_(options),

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

@ -29,12 +29,6 @@ GetGCObjectKind(const Class *clasp)
return GetGCObjectKind(nslots);
}
inline bool
ShouldNurseryAllocateObject(const Nursery &nursery, InitialHeap heap)
{
return nursery.isEnabled() && heap != TenuredHeap;
}
inline JSGCTraceKind
GetGCThingTraceKind(const void *thing)
{
@ -378,325 +372,7 @@ class GCZoneGroupIter {
typedef CompartmentsIterT<GCZoneGroupIter> GCCompartmentGroupIter;
/*
* Attempt to allocate a new GC thing out of the nursery. If there is not enough
* room in the nursery or there is an OOM, this method will return nullptr.
*/
template <AllowGC allowGC>
inline JSObject *
TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots, const js::Class *clasp)
{
MOZ_ASSERT(!IsAtomsCompartment(cx->compartment()));
JSRuntime *rt = cx->runtime();
Nursery &nursery = rt->gc.nursery;
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
if (obj)
return obj;
if (allowGC && !rt->mainThread.suppressGC) {
cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
/* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
if (nursery.isEnabled()) {
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots, clasp);
MOZ_ASSERT(obj);
return obj;
}
}
return nullptr;
}
static inline bool
PossiblyFail()
{
JS_OOM_POSSIBLY_FAIL_BOOL();
return true;
}
static inline bool
GCIfNeeded(ExclusiveContext *cx)
{
if (cx->isJSContext()) {
JSContext *ncx = cx->asJSContext();
JSRuntime *rt = ncx->runtime();
#ifdef JS_GC_ZEAL
if (rt->gc.needZealousGC())
rt->gc.runDebugGC();
#endif
// Invoking the interrupt callback can fail and we can't usefully
// handle that here. Just check in case we need to collect instead.
if (rt->hasPendingInterrupt())
rt->gc.gcIfRequested(ncx);
// If we have grown past our GC heap threshold while in the middle of
// an incremental GC, we're growing faster than we're GCing, so stop
// the world and do a full, non-incremental GC right now, if possible.
if (rt->gc.isIncrementalGCInProgress() &&
cx->zone()->usage.gcBytes() > cx->zone()->threshold.gcTriggerBytes())
{
PrepareZoneForGC(cx->zone());
AutoKeepAtoms keepAtoms(cx->perThreadData);
rt->gc.gc(GC_NORMAL, JS::gcreason::INCREMENTAL_TOO_SLOW);
}
}
return true;
}
template <AllowGC allowGC>
static inline bool
CheckAllocatorState(ExclusiveContext *cx, AllocKind kind)
{
if (allowGC) {
if (!GCIfNeeded(cx))
return false;
}
if (!cx->isJSContext())
return true;
JSContext *ncx = cx->asJSContext();
JSRuntime *rt = ncx->runtime();
#if defined(JS_GC_ZEAL) || defined(DEBUG)
MOZ_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
kind == FINALIZE_STRING ||
kind == FINALIZE_FAT_INLINE_STRING ||
kind == FINALIZE_SYMBOL ||
kind == FINALIZE_JITCODE);
MOZ_ASSERT(!rt->isHeapBusy());
MOZ_ASSERT(rt->gc.isAllocAllowed());
#endif
// Crash if we perform a GC action when it is not safe.
if (allowGC && !rt->mainThread.suppressGC)
JS::AutoAssertOnGC::VerifyIsSafeToGC(rt);
// For testing out of memory conditions
if (!PossiblyFail()) {
ReportOutOfMemory(ncx);
return false;
}
return true;
}
template <typename T>
static inline void
CheckIncrementalZoneState(ExclusiveContext *cx, T *t)
{
#ifdef DEBUG
if (!cx->isJSContext())
return;
Zone *zone = cx->asJSContext()->zone();
MOZ_ASSERT_IF(t && zone->wasGCStarted() && (zone->isGCMarking() || zone->isGCSweeping()),
t->asTenured().arenaHeader()->allocatedDuringIncremental);
#endif
}
/*
* Allocate a new GC thing. After a successful allocation the caller must
* fully initialize the thing before calling any function that can potentially
* trigger GC. This will ensure that GC tracing never sees junk values stored
* in the partially initialized thing.
*/
template <AllowGC allowGC>
inline JSObject *
AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
const js::Class *clasp)
{
size_t thingSize = Arena::thingSize(kind);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0));
static_assert(sizeof(JSObject_Slots0) >= CellSize,
"All allocations must be at least the allocator-imposed minimum size.");
if (!CheckAllocatorState<allowGC>(cx, kind))
return nullptr;
if (cx->isJSContext() &&
ShouldNurseryAllocateObject(cx->asJSContext()->nursery(), heap))
{
JSObject *obj = TryNewNurseryObject<allowGC>(cx->asJSContext(), thingSize, nDynamicSlots,
clasp);
if (obj)
return obj;
}
HeapSlot *slots = nullptr;
if (nDynamicSlots) {
slots = cx->zone()->pod_malloc<HeapSlot>(nDynamicSlots);
if (MOZ_UNLIKELY(!slots))
return nullptr;
js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
}
JSObject *obj = reinterpret_cast<JSObject *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
if (!obj)
obj = reinterpret_cast<JSObject *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
if (obj)
obj->setInitialSlotsMaybeNonNative(slots);
else
js_free(slots);
CheckIncrementalZoneState(cx, obj);
js::gc::TraceTenuredAlloc(obj, kind);
return obj;
}
template <typename T, AllowGC allowGC>
inline T *
AllocateNonObject(ExclusiveContext *cx)
{
static_assert(sizeof(T) >= CellSize,
"All allocations must be at least the allocator-imposed minimum size.");
AllocKind kind = MapTypeToFinalizeKind<T>::kind;
size_t thingSize = sizeof(T);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
if (!CheckAllocatorState<allowGC>(cx, kind))
return nullptr;
T *t = static_cast<T *>(cx->arenas()->allocateFromFreeList(kind, thingSize));
if (!t)
t = static_cast<T *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
CheckIncrementalZoneState(cx, t);
js::gc::TraceTenuredAlloc(t, kind);
return t;
}
/*
* When allocating for initialization from a cached object copy, we will
* potentially destroy the cache entry we want to copy if we allow GC. On the
* other hand, since these allocations are extremely common, we don't want to
* delay GC from these allocation sites. Instead we allow the GC, but still
* fail the allocation, forcing the non-cached path.
*/
template <AllowGC allowGC>
inline NativeObject *
AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap, const js::Class *clasp)
{
MOZ_ASSERT(clasp->isNative());
if (ShouldNurseryAllocateObject(cx->nursery(), heap)) {
size_t thingSize = Arena::thingSize(kind);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
if (!CheckAllocatorState<NoGC>(cx, kind))
return nullptr;
JSObject *obj = TryNewNurseryObject<NoGC>(cx, thingSize, 0, clasp);
if (!obj && allowGC) {
cx->minorGC(JS::gcreason::OUT_OF_NURSERY);
return nullptr;
}
return reinterpret_cast<NativeObject *>(obj);
}
JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap, clasp);
if (!obj && allowGC) {
cx->runtime()->gc.maybeGC(cx->zone());
return nullptr;
}
return reinterpret_cast<NativeObject *>(obj);
}
inline bool
IsInsideGGCNursery(const js::gc::Cell *cell)
{
if (!cell)
return false;
uintptr_t addr = uintptr_t(cell);
addr &= ~js::gc::ChunkMask;
addr |= js::gc::ChunkLocationOffset;
uint32_t location = *reinterpret_cast<uint32_t *>(addr);
MOZ_ASSERT(location != 0);
return location & js::gc::ChunkLocationBitNursery;
}
} /* namespace gc */
template <js::AllowGC allowGC>
inline JSObject *
NewGCObject(js::ExclusiveContext *cx, js::gc::AllocKind kind, size_t nDynamicSlots,
js::gc::InitialHeap heap, const js::Class *clasp)
{
MOZ_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
return js::gc::AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap, clasp);
}
template <js::AllowGC allowGC>
inline jit::JitCode *
NewJitCode(js::ExclusiveContext *cx)
{
return gc::AllocateNonObject<jit::JitCode, allowGC>(cx);
}
inline
ObjectGroup *
NewObjectGroup(js::ExclusiveContext *cx)
{
return gc::AllocateNonObject<ObjectGroup, js::CanGC>(cx);
}
template <js::AllowGC allowGC>
inline JSString *
NewGCString(js::ExclusiveContext *cx)
{
return js::gc::AllocateNonObject<JSString, allowGC>(cx);
}
template <js::AllowGC allowGC>
inline JSFatInlineString *
NewGCFatInlineString(js::ExclusiveContext *cx)
{
return js::gc::AllocateNonObject<JSFatInlineString, allowGC>(cx);
}
inline JSExternalString *
NewGCExternalString(js::ExclusiveContext *cx)
{
return js::gc::AllocateNonObject<JSExternalString, js::CanGC>(cx);
}
inline Shape *
NewGCShape(ExclusiveContext *cx)
{
return gc::AllocateNonObject<Shape, CanGC>(cx);
}
inline Shape *
NewGCAccessorShape(ExclusiveContext *cx)
{
return gc::AllocateNonObject<AccessorShape, CanGC>(cx);
}
inline JSScript *
NewGCScript(ExclusiveContext *cx)
{
return gc::AllocateNonObject<JSScript, CanGC>(cx);
}
inline LazyScript *
NewGCLazyScript(ExclusiveContext *cx)
{
return gc::AllocateNonObject<LazyScript, CanGC>(cx);
}
template <AllowGC allowGC>
inline BaseShape *
NewGCBaseShape(ExclusiveContext *cx)
{
return gc::AllocateNonObject<BaseShape, allowGC>(cx);
}
} /* namespace js */
#endif /* jsgcinlines_h */

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

@ -31,6 +31,8 @@
#include "jstypes.h"
#include "prmjtime.h"
#include "js/Class.h"
#include "jsobjinlines.h"
using namespace js;

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

@ -11,6 +11,7 @@
#include "builtin/MapObject.h"
#include "builtin/TypedObject.h"
#include "gc/Allocator.h"
#include "vm/ArrayObject.h"
#include "vm/DateObject.h"
#include "vm/NumberObject.h"

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

@ -14,8 +14,6 @@
#include "vm/Shape.h"
#include "jsgcinlines.h"
#include "vm/Shape-inl.h"
using namespace js;

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

@ -120,6 +120,7 @@ UNIFIED_SOURCES += [
'frontend/ParseMaps.cpp',
'frontend/ParseNode.cpp',
'frontend/TokenStream.cpp',
'gc/Allocator.cpp',
'gc/Barrier.cpp',
'gc/GCTrace.cpp',
'gc/Iteration.cpp',

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

@ -9,6 +9,7 @@
#include "vm/ArrayObject.h"
#include "gc/GCTrace.h"
#include "vm/String.h"
#include "vm/TypeInference-inl.h"

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

@ -14,7 +14,6 @@
#include "vm/ArrayObject.h"
#include "vm/UnboxedObject.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
using namespace js;

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

@ -7,7 +7,6 @@
#include "vm/ProxyObject.h"
#include "jscompartment.h"
#include "jsgcinlines.h"
#include "jsobjinlines.h"
using namespace js;

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

@ -11,10 +11,10 @@
#include "jscompartment.h"
#include "gc/Allocator.h"
#include "gc/GCTrace.h"
#include "vm/Probes.h"
#include "jsgcinlines.h"
namespace js {
inline bool
@ -25,13 +25,13 @@ NewObjectCache::lookupProto(const Class *clasp, JSObject *proto, gc::AllocKind k
}
inline bool
NewObjectCache::lookupGlobal(const Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
NewObjectCache::lookupGlobal(const Class *clasp, GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
{
return lookup(clasp, global, kind, pentry);
}
inline void
NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObject *global,
NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, GlobalObject *global,
gc::AllocKind kind, NativeObject *obj)
{
//MOZ_ASSERT(global == obj->getGlobal());
@ -39,7 +39,7 @@ NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObjec
}
inline NativeObject *
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::InitialHeap heap)
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, gc::InitialHeap heap)
{
// The new object cache does not account for metadata attached via callbacks.
MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
@ -59,11 +59,11 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::I
if (cx->runtime()->gc.upcomingZealousGC())
return nullptr;
NativeObject *obj = js::gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
NativeObject *obj = gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
if (obj) {
copyCachedToObject(obj, templateObj, entry->kind);
probes::CreateObject(cx, obj);
js::gc::TraceCreateObject(obj);
gc::TraceCreateObject(obj);
return obj;
}
@ -76,7 +76,7 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::I
// take the slow allocation path. The callee is responsible for ensuring
// that the index it uses to fill the cache is still correct after this GC.
mozilla::DebugOnly<JSObject *> obj2 =
js::gc::AllocateObjectForCacheHit<CanGC>(cx, entry->kind, heap, group->clasp());
gc::AllocateObjectForCacheHit<CanGC>(cx, entry->kind, heap, group->clasp());
MOZ_ASSERT(!obj2);
return nullptr;
}

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

@ -13,13 +13,13 @@
#include "jsobj.h"
#include "gc/Allocator.h"
#include "vm/Interpreter.h"
#include "vm/ScopeObject.h"
#include "vm/TypedArrayCommon.h"
#include "jsatominlines.h"
#include "jscntxtinlines.h"
#include "jsgcinlines.h"
namespace js {

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

@ -14,10 +14,9 @@
#include "jscntxt.h"
#include "gc/Allocator.h"
#include "gc/Marking.h"
#include "jsgcinlines.h"
namespace js {
// Allocate a thin inline string if possible, and a fat inline string if not.

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

@ -10,11 +10,11 @@
#include "jscompartment.h"
#include "builtin/SymbolObject.h"
#include "gc/Allocator.h"
#include "gc/Rooting.h"
#include "vm/StringBuffer.h"
#include "jscompartmentinlines.h"
#include "jsgcinlines.h"
using JS::Symbol;
using namespace js;
@ -26,7 +26,7 @@ Symbol::newInternal(ExclusiveContext *cx, JS::SymbolCode code, JSAtom *descripti
MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
// Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
Symbol *p = gc::AllocateNonObject<Symbol, NoGC>(cx);
Symbol *p = NewGCSymbol<NoGC>(cx);
if (!p) {
ReportOutOfMemory(cx);
return nullptr;

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

@ -34,7 +34,6 @@
#include "vm/UnboxedObject.h"
#include "jsatominlines.h"
#include "jsgcinlines.h"
#include "jsscriptinlines.h"
#include "vm/NativeObject-inl.h"