зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1134425 - Part 1: move the allocator interface code out of line; r=jonco
--HG-- extra : rebase_source : cbeb8097a3c55397cc0c0f476deb0011ad496f62
This commit is contained in:
Родитель
a26a5496a6
Коммит
bb7d88df07
|
@ -19,6 +19,7 @@
|
||||||
#include "jspubtd.h"
|
#include "jspubtd.h"
|
||||||
|
|
||||||
#include "js/HashTable.h"
|
#include "js/HashTable.h"
|
||||||
|
#include "js/TracingAPI.h"
|
||||||
#include "js/Utility.h"
|
#include "js/Utility.h"
|
||||||
#include "js/Vector.h"
|
#include "js/Vector.h"
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
|
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
#include "jit/IonCode.h"
|
#include "jit/IonCode.h"
|
||||||
|
#include "js/Class.h"
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "js/MemoryMetrics.h"
|
#include "js/MemoryMetrics.h"
|
||||||
|
|
||||||
|
@ -50,9 +51,10 @@ using namespace js;
|
||||||
using namespace jit;
|
using namespace jit;
|
||||||
using namespace frontend;
|
using namespace frontend;
|
||||||
using mozilla::BinarySearch;
|
using mozilla::BinarySearch;
|
||||||
|
using mozilla::Compression::LZ4;
|
||||||
using mozilla::PodCopy;
|
using mozilla::PodCopy;
|
||||||
using mozilla::PodEqual;
|
using mozilla::PodEqual;
|
||||||
using mozilla::Compression::LZ4;
|
using mozilla::PodZero;
|
||||||
using mozilla::Swap;
|
using mozilla::Swap;
|
||||||
|
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
|
|
||||||
#include "prmjtime.h"
|
#include "prmjtime.h"
|
||||||
|
|
||||||
|
#include "js/Class.h"
|
||||||
#include "vm/GlobalObject.h"
|
#include "vm/GlobalObject.h"
|
||||||
#include "vm/SharedTypedArrayObject.h"
|
#include "vm/SharedTypedArrayObject.h"
|
||||||
#include "vm/TypedArrayObject.h"
|
#include "vm/TypedArrayObject.h"
|
||||||
|
|
|
@ -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);
|
|
@ -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/TypedArrayObject.h"
|
||||||
#include "vm/TypeInference.h"
|
#include "vm/TypeInference.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
#include "vm/NativeObject-inl.h"
|
#include "vm/NativeObject-inl.h"
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "gc/Statistics.h"
|
#include "gc/Statistics.h"
|
||||||
#include "vm/ArgumentsObject.h"
|
#include "vm/ArgumentsObject.h"
|
||||||
|
#include "vm/Runtime.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
#include "jsgcinlines.h"
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
#include "jit/CompileInfo.h"
|
#include "jit/CompileInfo.h"
|
||||||
#include "jit/JitCommon.h"
|
#include "jit/JitCommon.h"
|
||||||
#include "jit/JitSpewer.h"
|
#include "jit/JitSpewer.h"
|
||||||
|
#include "vm/Debugger.h"
|
||||||
#include "vm/Interpreter.h"
|
#include "vm/Interpreter.h"
|
||||||
#include "vm/TraceLogging.h"
|
#include "vm/TraceLogging.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
#include "jsopcodeinlines.h"
|
#include "jsopcodeinlines.h"
|
||||||
#include "jsscriptinlines.h"
|
#include "jsscriptinlines.h"
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
#include "vm/TraceLogging.h"
|
#include "vm/TraceLogging.h"
|
||||||
|
|
||||||
#include "jscompartmentinlines.h"
|
#include "jscompartmentinlines.h"
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "jit/CompileInfo.h"
|
#include "jit/CompileInfo.h"
|
||||||
#include "jit/JitAllocPolicy.h"
|
#include "jit/JitAllocPolicy.h"
|
||||||
#include "jit/JitCompartment.h"
|
#include "jit/JitCompartment.h"
|
||||||
|
#include "jit/MIR.h"
|
||||||
#ifdef JS_ION_PERF
|
#ifdef JS_ION_PERF
|
||||||
# include "jit/PerfSpewer.h"
|
# include "jit/PerfSpewer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "vm/TraceLogging.h"
|
#include "vm/TraceLogging.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
#include "vm/Interpreter-inl.h"
|
#include "vm/Interpreter-inl.h"
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "mozilla/SizePrintfMacros.h"
|
#include "mozilla/SizePrintfMacros.h"
|
||||||
|
|
||||||
|
#include "jsprf.h"
|
||||||
|
|
||||||
#include "ds/Sort.h"
|
#include "ds/Sort.h"
|
||||||
#include "jit/IonBuilder.h"
|
#include "jit/IonBuilder.h"
|
||||||
#include "jit/JitcodeMap.h"
|
#include "jit/JitcodeMap.h"
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "ds/Sort.h"
|
#include "ds/Sort.h"
|
||||||
#include "gc/Heap.h"
|
#include "gc/Heap.h"
|
||||||
|
#include "js/Class.h"
|
||||||
#include "js/Conversions.h"
|
#include "js/Conversions.h"
|
||||||
#include "vm/ArgumentsObject.h"
|
#include "vm/ArgumentsObject.h"
|
||||||
#include "vm/Interpreter.h"
|
#include "vm/Interpreter.h"
|
||||||
|
|
|
@ -35,6 +35,7 @@ using namespace js::gc;
|
||||||
using namespace js::jit;
|
using namespace js::jit;
|
||||||
|
|
||||||
using mozilla::DebugOnly;
|
using mozilla::DebugOnly;
|
||||||
|
using mozilla::PodArrayZero;
|
||||||
|
|
||||||
JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
|
JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options = JS::CompartmentOptions())
|
||||||
: options_(options),
|
: options_(options),
|
||||||
|
|
|
@ -29,12 +29,6 @@ GetGCObjectKind(const Class *clasp)
|
||||||
return GetGCObjectKind(nslots);
|
return GetGCObjectKind(nslots);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
|
||||||
ShouldNurseryAllocateObject(const Nursery &nursery, InitialHeap heap)
|
|
||||||
{
|
|
||||||
return nursery.isEnabled() && heap != TenuredHeap;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline JSGCTraceKind
|
inline JSGCTraceKind
|
||||||
GetGCThingTraceKind(const void *thing)
|
GetGCThingTraceKind(const void *thing)
|
||||||
{
|
{
|
||||||
|
@ -378,325 +372,7 @@ class GCZoneGroupIter {
|
||||||
|
|
||||||
typedef CompartmentsIterT<GCZoneGroupIter> GCCompartmentGroupIter;
|
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 */
|
} /* 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 */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* jsgcinlines_h */
|
#endif /* jsgcinlines_h */
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include "jstypes.h"
|
#include "jstypes.h"
|
||||||
#include "prmjtime.h"
|
#include "prmjtime.h"
|
||||||
|
|
||||||
|
#include "js/Class.h"
|
||||||
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "builtin/MapObject.h"
|
#include "builtin/MapObject.h"
|
||||||
#include "builtin/TypedObject.h"
|
#include "builtin/TypedObject.h"
|
||||||
|
#include "gc/Allocator.h"
|
||||||
#include "vm/ArrayObject.h"
|
#include "vm/ArrayObject.h"
|
||||||
#include "vm/DateObject.h"
|
#include "vm/DateObject.h"
|
||||||
#include "vm/NumberObject.h"
|
#include "vm/NumberObject.h"
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
|
|
||||||
#include "vm/Shape.h"
|
#include "vm/Shape.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
|
|
||||||
#include "vm/Shape-inl.h"
|
#include "vm/Shape-inl.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
|
@ -120,6 +120,7 @@ UNIFIED_SOURCES += [
|
||||||
'frontend/ParseMaps.cpp',
|
'frontend/ParseMaps.cpp',
|
||||||
'frontend/ParseNode.cpp',
|
'frontend/ParseNode.cpp',
|
||||||
'frontend/TokenStream.cpp',
|
'frontend/TokenStream.cpp',
|
||||||
|
'gc/Allocator.cpp',
|
||||||
'gc/Barrier.cpp',
|
'gc/Barrier.cpp',
|
||||||
'gc/GCTrace.cpp',
|
'gc/GCTrace.cpp',
|
||||||
'gc/Iteration.cpp',
|
'gc/Iteration.cpp',
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "vm/ArrayObject.h"
|
#include "vm/ArrayObject.h"
|
||||||
|
|
||||||
|
#include "gc/GCTrace.h"
|
||||||
#include "vm/String.h"
|
#include "vm/String.h"
|
||||||
|
|
||||||
#include "vm/TypeInference-inl.h"
|
#include "vm/TypeInference-inl.h"
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "vm/ArrayObject.h"
|
#include "vm/ArrayObject.h"
|
||||||
#include "vm/UnboxedObject.h"
|
#include "vm/UnboxedObject.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "vm/ProxyObject.h"
|
#include "vm/ProxyObject.h"
|
||||||
|
|
||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
|
|
||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
|
|
||||||
|
#include "gc/Allocator.h"
|
||||||
|
#include "gc/GCTrace.h"
|
||||||
#include "vm/Probes.h"
|
#include "vm/Probes.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -25,13 +25,13 @@ NewObjectCache::lookupProto(const Class *clasp, JSObject *proto, gc::AllocKind k
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
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);
|
return lookup(clasp, global, kind, pentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
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)
|
gc::AllocKind kind, NativeObject *obj)
|
||||||
{
|
{
|
||||||
//MOZ_ASSERT(global == obj->getGlobal());
|
//MOZ_ASSERT(global == obj->getGlobal());
|
||||||
|
@ -39,7 +39,7 @@ NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
inline NativeObject *
|
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.
|
// The new object cache does not account for metadata attached via callbacks.
|
||||||
MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
|
MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
|
||||||
|
@ -59,11 +59,11 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::I
|
||||||
if (cx->runtime()->gc.upcomingZealousGC())
|
if (cx->runtime()->gc.upcomingZealousGC())
|
||||||
return nullptr;
|
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) {
|
if (obj) {
|
||||||
copyCachedToObject(obj, templateObj, entry->kind);
|
copyCachedToObject(obj, templateObj, entry->kind);
|
||||||
probes::CreateObject(cx, obj);
|
probes::CreateObject(cx, obj);
|
||||||
js::gc::TraceCreateObject(obj);
|
gc::TraceCreateObject(obj);
|
||||||
return 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
|
// 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.
|
// that the index it uses to fill the cache is still correct after this GC.
|
||||||
mozilla::DebugOnly<JSObject *> obj2 =
|
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);
|
MOZ_ASSERT(!obj2);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
|
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
|
|
||||||
|
#include "gc/Allocator.h"
|
||||||
#include "vm/Interpreter.h"
|
#include "vm/Interpreter.h"
|
||||||
#include "vm/ScopeObject.h"
|
#include "vm/ScopeObject.h"
|
||||||
#include "vm/TypedArrayCommon.h"
|
#include "vm/TypedArrayCommon.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
#include "jscntxtinlines.h"
|
#include "jscntxtinlines.h"
|
||||||
#include "jsgcinlines.h"
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
|
|
@ -14,10 +14,9 @@
|
||||||
|
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
|
|
||||||
|
#include "gc/Allocator.h"
|
||||||
#include "gc/Marking.h"
|
#include "gc/Marking.h"
|
||||||
|
|
||||||
#include "jsgcinlines.h"
|
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
// Allocate a thin inline string if possible, and a fat inline string if not.
|
// Allocate a thin inline string if possible, and a fat inline string if not.
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
#include "jscompartment.h"
|
#include "jscompartment.h"
|
||||||
|
|
||||||
#include "builtin/SymbolObject.h"
|
#include "builtin/SymbolObject.h"
|
||||||
|
#include "gc/Allocator.h"
|
||||||
#include "gc/Rooting.h"
|
#include "gc/Rooting.h"
|
||||||
#include "vm/StringBuffer.h"
|
#include "vm/StringBuffer.h"
|
||||||
|
|
||||||
#include "jscompartmentinlines.h"
|
#include "jscompartmentinlines.h"
|
||||||
#include "jsgcinlines.h"
|
|
||||||
|
|
||||||
using JS::Symbol;
|
using JS::Symbol;
|
||||||
using namespace js;
|
using namespace js;
|
||||||
|
@ -26,7 +26,7 @@ Symbol::newInternal(ExclusiveContext *cx, JS::SymbolCode code, JSAtom *descripti
|
||||||
MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
|
MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
|
||||||
|
|
||||||
// Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
|
// Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
|
||||||
Symbol *p = gc::AllocateNonObject<Symbol, NoGC>(cx);
|
Symbol *p = NewGCSymbol<NoGC>(cx);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
ReportOutOfMemory(cx);
|
ReportOutOfMemory(cx);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include "vm/UnboxedObject.h"
|
#include "vm/UnboxedObject.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
#include "jsgcinlines.h"
|
|
||||||
#include "jsscriptinlines.h"
|
#include "jsscriptinlines.h"
|
||||||
|
|
||||||
#include "vm/NativeObject-inl.h"
|
#include "vm/NativeObject-inl.h"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче