Bug 1281529 part 9 - Move JSRuntime caches into a new ContextCaches class. r=jorendorff

--HG--
rename : js/src/vm/Runtime-inl.h => js/src/vm/Caches-inl.h
This commit is contained in:
Jan de Mooij 2016-07-02 13:45:10 +02:00
parent 8b89bcc511
commit d051fdf152
28 changed files with 448 additions and 394 deletions

View File

@ -93,7 +93,7 @@ class EvalScriptGuard
EvalCacheEntry cacheEntry = {lookupStr_, script_, lookup_.callerScript, lookup_.pc};
lookup_.str = lookupStr_;
if (lookup_.str && IsEvalCacheCandidate(script_)) {
bool ok = cx_->runtime()->evalCache.relookupOrAdd(p_, lookup_, cacheEntry);
bool ok = cx_->caches.evalCache.relookupOrAdd(p_, lookup_, cacheEntry);
(void)ok; // Ignore failure to add cache entry.
}
}
@ -106,10 +106,10 @@ class EvalScriptGuard
lookup_.callerScript = callerScript;
lookup_.version = cx_->findVersion();
lookup_.pc = pc;
p_ = cx_->runtime()->evalCache.lookupForAdd(lookup_);
p_ = cx_->caches.evalCache.lookupForAdd(lookup_);
if (p_) {
script_ = p_->script;
cx_->runtime()->evalCache.remove(p_);
cx_->caches.evalCache.remove(p_);
script_->uncacheForEval();
}
}

View File

@ -451,7 +451,7 @@ js::Nursery::collect(JSRuntime* rt, JS::gcreason::Reason reason, ObjectGroupList
TIME_END(markDebugger);
TIME_START(clearNewObjectCache);
rt->newObjectCache.clearNurseryObjects(rt);
rt->contextFromMainThread()->caches.newObjectCache.clearNurseryObjects(rt);
TIME_END(clearNewObjectCache);
// Most of the work is done here. This loop iterates over objects that have

View File

@ -47,7 +47,7 @@ BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript
bool
BaselineCompiler::init()
{
if (!analysis_.init(alloc_, cx->runtime()->gsnCache))
if (!analysis_.init(alloc_, cx->caches.gsnCache))
return false;
if (!labels_.init(alloc_, script->length()))

View File

@ -290,7 +290,7 @@ DoTypeUpdateFallback(JSContext* cx, BaselineFrame* frame, ICUpdatedStub* stub, H
MOZ_ASSERT(obj->isNative() || obj->is<UnboxedPlainObject>());
jsbytecode* pc = stub->getChainFallback()->icEntry()->pc(script);
if (*pc == JSOP_SETALIASEDVAR || *pc == JSOP_INITALIASEDLEXICAL)
id = NameToId(ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc));
id = NameToId(ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc));
else
id = NameToId(script->getName(pc));
AddTypePropertyId(cx, obj, id, value);
@ -4495,7 +4495,7 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
RootedPropertyName name(cx);
if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL)
name = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc);
name = ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc);
else
name = script->getName(pc);
RootedId id(cx, NameToId(name));

View File

@ -77,7 +77,7 @@ CompileRuntime::addressOfActivation()
const void*
CompileRuntime::addressOfLastCachedNativeIterator()
{
return &runtime()->nativeIterCache.last;
return &static_cast<JSContext*>(runtime())->caches.nativeIterCache.last;
}
#ifdef JS_GC_ZEAL
@ -187,12 +187,6 @@ CompileRuntime::DOMcallbacks()
return GetDOMCallbacks(runtime());
}
const MathCache*
CompileRuntime::maybeGetMathCache()
{
return runtime()->maybeGetMathCache();
}
const Nursery&
CompileRuntime::gcNursery()
{

View File

@ -88,8 +88,6 @@ class CompileRuntime
// DOM callbacks must be threadsafe (and will hopefully be removed soon).
const DOMCallbacks* DOMcallbacks();
const MathCache* maybeGetMathCache();
const Nursery& gcNursery();
void setMinorGCShouldCancelIonCompilations();
};

View File

@ -431,7 +431,7 @@ IonBuilder::inlineMathFunction(CallInfo& callInfo, MMathFunction::Function funct
if (!IsNumberType(callInfo.getArg(0)->type()))
return InliningStatus_NotInlined;
const MathCache* cache = compartment->runtime()->maybeGetMathCache();
const MathCache* cache = GetJSContextFromMainThread()->caches.maybeGetMathCache();
callInfo.fun()->setImplicitlyUsedUnchecked();
callInfo.thisArg()->setImplicitlyUsedUnchecked();

View File

@ -42,9 +42,9 @@
#include "vm/ArgumentsObject-inl.h"
#include "vm/ArrayObject-inl.h"
#include "vm/Caches-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/Runtime-inl.h"
#include "vm/UnboxedObject-inl.h"
using namespace js;
@ -3386,8 +3386,7 @@ NewArray(ExclusiveContext* cxArg, uint32_t length,
bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, taggedProto, newKind, &ArrayObject::class_);
if (isCachable) {
JSContext* cx = cxArg->asJSContext();
JSRuntime* rt = cx->runtime();
NewObjectCache& cache = rt->newObjectCache;
NewObjectCache& cache = cx->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (cache.lookupProto(&ArrayObject::class_, proto, allocKind, &entry)) {
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
@ -3441,7 +3440,7 @@ NewArray(ExclusiveContext* cxArg, uint32_t length,
return nullptr;
if (isCachable) {
NewObjectCache& cache = cxArg->asJSContext()->runtime()->newObjectCache;
NewObjectCache& cache = cxArg->asJSContext()->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
cache.lookupProto(&ArrayObject::class_, proto, allocKind, &entry);
cache.fillProto(entry, &ArrayObject::class_, taggedProto, allocKind, arr);

View File

@ -93,6 +93,9 @@ JSContext::init(uint32_t maxBytes, uint32_t maxNurseryBytes)
if (!JSRuntime::init(maxBytes, maxNurseryBytes))
return false;
if (!caches.init())
return false;
return true;
}

View File

@ -13,6 +13,7 @@
#include "js/GCVector.h"
#include "js/Vector.h"
#include "vm/Caches.h"
#include "vm/Runtime.h"
#ifdef _MSC_VER
@ -359,6 +360,8 @@ struct JSContext : public js::ExclusiveContext,
js::jit::DebugModeOSRVolatileJitFrameIterator* liveVolatileJitFrameIterators_;
public:
js::ContextCaches caches;
int32_t reportGranularity; /* see vm/Probes.h */
js::AutoResolving* resolvingList;

View File

@ -1480,7 +1480,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
// has started.
if (canRelazify && !JS::IsIncrementalGCInProgress(cx->runtime())) {
LazyScriptCache::Lookup lookup(cx, lazy);
cx->runtime()->lazyScriptCache.lookup(lookup, script.address());
cx->caches.lazyScriptCache.lookup(lookup, script.address());
}
if (script) {
@ -1534,7 +1534,7 @@ JSFunction::createScriptForLazilyInterpretedFunction(JSContext* cx, HandleFuncti
script->setColumn(lazy->column());
LazyScriptCache::Lookup lookup(cx, lazy);
cx->runtime()->lazyScriptCache.insert(lookup, script);
cx->caches.lazyScriptCache.insert(lookup, script);
// Remember the lazy script on the compiled script, so it can be
// stored on the function again in case of re-lazification.

View File

@ -3614,12 +3614,15 @@ GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
freeUnusedLifoBlocksAfterSweeping(&rt->tempLifoAlloc);
rt->interpreterStack().purge(rt);
rt->gsnCache.purge();
rt->scopeCoordinateNameCache.purge();
rt->newObjectCache.purge();
rt->nativeIterCache.purge();
rt->uncompressedSourceCache.purge();
rt->evalCache.clear();
JSContext* cx = rt->contextFromMainThread();
cx->caches.gsnCache.purge();
cx->caches.scopeCoordinateNameCache.purge();
cx->caches.newObjectCache.purge();
cx->caches.nativeIterCache.purge();
cx->caches.uncompressedSourceCache.purge();
if (cx->caches.evalCache.initialized())
cx->caches.evalCache.clear();
if (!rt->hasActiveCompilations())
rt->parseMapPool(lock).purgeAll();
@ -5537,9 +5540,10 @@ GCRuntime::compactPhase(JS::gcreason::Reason reason, SliceBudget& sliceBudget,
break;
}
// Clear runtime caches that can contain cell pointers.
rt->newObjectCache.purge();
rt->nativeIterCache.purge();
// Clear caches that can contain cell pointers.
JSContext* cx = rt->contextFromMainThread();
cx->caches.newObjectCache.purge();
cx->caches.nativeIterCache.purge();
#ifdef DEBUG
CheckHashTablesAfterMovingGC(rt);

View File

@ -842,7 +842,7 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
if (flags == JSITER_ENUMERATE) {
// Check to see if this is the same as the most recent object which was
// iterated over.
PropertyIteratorObject* last = cx->runtime()->nativeIterCache.last;
PropertyIteratorObject* last = cx->caches.nativeIterCache.last;
if (last) {
NativeIterator* lastni = last->getNativeIterator();
if (!(lastni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
@ -882,7 +882,7 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
} while (pobj);
}
PropertyIteratorObject* iterobj = cx->runtime()->nativeIterCache.get(key);
PropertyIteratorObject* iterobj = cx->caches.nativeIterCache.get(key);
if (iterobj) {
NativeIterator* ni = iterobj->getNativeIterator();
if (!(ni->flags & (JSITER_ACTIVE|JSITER_UNREUSABLE)) &&
@ -896,7 +896,7 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
UpdateNativeIterator(ni, obj);
RegisterEnumerator(cx, iterobj, ni);
if (guards.length() == 2)
cx->runtime()->nativeIterCache.last = iterobj;
cx->caches.nativeIterCache.last = iterobj;
return true;
}
}
@ -927,10 +927,10 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
/* Cache the iterator object if possible. */
if (guards.length())
cx->runtime()->nativeIterCache.set(key, iterobj);
cx->caches.nativeIterCache.set(key, iterobj);
if (guards.length() == 2)
cx->runtime()->nativeIterCache.last = iterobj;
cx->caches.nativeIterCache.last = iterobj;
return true;
}

View File

@ -157,7 +157,7 @@ js::math_acos(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -192,7 +192,7 @@ js::math_asin(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -227,7 +227,7 @@ js::math_atan(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -346,7 +346,7 @@ js::math_cos(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -381,7 +381,7 @@ js::math_exp(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -499,7 +499,7 @@ js::math_log_handle(JSContext* cx, HandleValue val, MutableHandleValue res)
if (!ToNumber(cx, val, &in))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -827,7 +827,7 @@ js::math_sin_handle(JSContext* cx, HandleValue val, MutableHandleValue res)
if (!ToNumber(cx, val, &in))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -890,7 +890,7 @@ js::math_sqrt_handle(JSContext* cx, HandleValue number, MutableHandleValue resul
if (!ToNumber(cx, number, &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -938,7 +938,7 @@ js::math_tan(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
@ -962,7 +962,7 @@ static bool math_function(JSContext* cx, unsigned argc, Value* vp)
if (!ToNumber(cx, args[0], &x))
return false;
MathCache* mathCache = cx->runtime()->getMathCache(cx);
MathCache* mathCache = cx->caches.getMathCache(cx);
if (!mathCache)
return false;
double z = F(mathCache, x);

View File

@ -62,10 +62,10 @@
#include "vm/ArrayObject-inl.h"
#include "vm/BooleanObject-inl.h"
#include "vm/Caches-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/Runtime-inl.h"
#include "vm/Shape-inl.h"
#include "vm/StringObject-inl.h"
@ -715,8 +715,7 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
bool isCachable = NewObjectWithTaggedProtoIsCachable(cxArg, proto, newKind, clasp);
if (isCachable) {
JSContext* cx = cxArg->asJSContext();
JSRuntime* rt = cx->runtime();
NewObjectCache& cache = rt->newObjectCache;
NewObjectCache& cache = cx->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
JSObject* obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
@ -734,7 +733,7 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext* cxArg, const Class* clasp,
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
NewObjectCache& cache = cxArg->asJSContext()->runtime()->newObjectCache;
NewObjectCache& cache = cxArg->asJSContext()->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
cache.lookupProto(clasp, proto.toObject(), allocKind, &entry);
cache.fillProto(entry, clasp, proto, allocKind, &obj->as<NativeObject>());
@ -769,8 +768,7 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext* cxArg, const Class* clasp,
bool isCachable = NewObjectIsCachable(cxArg, newKind, clasp);
if (isCachable) {
JSContext* cx = cxArg->asJSContext();
JSRuntime* rt = cx->runtime();
NewObjectCache& cache = rt->newObjectCache;
NewObjectCache& cache = cx->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (cache.lookupGlobal(clasp, global, allocKind, &entry)) {
JSObject* obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
@ -801,7 +799,7 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext* cxArg, const Class* clasp,
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
NewObjectCache& cache = cxArg->asJSContext()->runtime()->newObjectCache;
NewObjectCache& cache = cxArg->asJSContext()->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
cache.lookupGlobal(clasp, global, allocKind, &entry);
cache.fillGlobal(entry, clasp, global, allocKind,
@ -836,7 +834,7 @@ js::NewObjectWithGroupCommon(ExclusiveContext* cx, HandleObjectGroup group,
bool isCachable = NewObjectWithGroupIsCachable(cx, group, newKind);
if (isCachable) {
NewObjectCache& cache = cx->asJSContext()->runtime()->newObjectCache;
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
if (cache.lookupGroup(group, allocKind, &entry)) {
JSObject* obj = cache.newObjectFromHit(cx->asJSContext(), entry,
@ -851,7 +849,7 @@ js::NewObjectWithGroupCommon(ExclusiveContext* cx, HandleObjectGroup group,
return nullptr;
if (isCachable && !obj->as<NativeObject>().hasDynamicSlots()) {
NewObjectCache& cache = cx->asJSContext()->runtime()->newObjectCache;
NewObjectCache& cache = cx->asJSContext()->caches.newObjectCache;
NewObjectCache::EntryIndex entry = -1;
cache.lookupGroup(group, allocKind, &entry);
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());

View File

@ -891,7 +891,7 @@ js::Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
case JOF_SCOPECOORD: {
RootedValue v(cx,
StringValue(ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc)));
StringValue(ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc)));
JSAutoByteString bytes;
if (!ToDisassemblySource(cx, v, &bytes))
return 0;
@ -1143,7 +1143,7 @@ ExpressionDecompiler::decompilePC(jsbytecode* pc)
return write("(intermediate value)");
}
case JSOP_GETALIASEDVAR: {
JSAtom* atom = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc);
JSAtom* atom = ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc);
MOZ_ASSERT(atom);
return write(atom);
}

View File

@ -1879,7 +1879,7 @@ ScriptSource::chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holde
}
ReturnType match(Compressed& c) {
if (const char16_t* decompressed = cx->runtime()->uncompressedSourceCache.lookup(&ss, holder))
if (const char16_t* decompressed = cx->caches.uncompressedSourceCache.lookup(&ss, holder))
return decompressed;
const size_t lengthWithNull = ss.length() + 1;
@ -1917,7 +1917,7 @@ ScriptSource::chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holde
}
ReturnType ret = decompressed.get();
if (!cx->runtime()->uncompressedSourceCache.put(&ss, Move(decompressed), holder)) {
if (!cx->caches.uncompressedSourceCache.put(&ss, Move(decompressed), holder)) {
JS_ReportOutOfMemory(cx);
return nullptr;
}
@ -3158,7 +3158,7 @@ JSScript::finalize(FreeOp* fop)
fop->free_(data);
}
fop->runtime()->lazyScriptCache.remove(this);
fop->runtime()->contextFromMainThread()->caches.lazyScriptCache.remove(this);
// In most cases, our LazyScript's script pointer will reference this
// script, and thus be nulled out by normal weakref processing. However, if
@ -3237,7 +3237,7 @@ js::GetSrcNote(GSNCache& cache, JSScript* script, jsbytecode* pc)
jssrcnote*
js::GetSrcNote(JSContext* cx, JSScript* script, jsbytecode* pc)
{
return GetSrcNote(cx->runtime()->gsnCache, script, pc);
return GetSrcNote(cx->caches.gsnCache, script, pc);
}
unsigned

View File

@ -316,6 +316,7 @@ UNIFIED_SOURCES += [
'proxy/Wrapper.cpp',
'vm/ArgumentsObject.cpp',
'vm/ArrayBufferObject.cpp',
'vm/Caches.cpp',
'vm/CallNonGenericMethod.cpp',
'vm/CharacterEncoding.cpp',
'vm/CodeCoverage.cpp',

View File

@ -4,10 +4,10 @@
* 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 vm_Runtime_inl_h
#define vm_Runtime_inl_h
#ifndef vm_Caches_inl_h
#define vm_Caches_inl_h
#include "vm/Runtime.h"
#include "vm/Caches.h"
#include "jscompartment.h"
@ -79,4 +79,4 @@ NewObjectCache::newObjectFromHit(JSContext* cx, EntryIndex entryIndex, gc::Initi
} /* namespace js */
#endif /* vm_Runtime_inl_h */
#endif /* vm_Caches_inl_h */

52
js/src/vm/Caches.cpp Normal file
View File

@ -0,0 +1,52 @@
/* -*- 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 "vm/Caches-inl.h"
#include "mozilla/PodOperations.h"
using namespace js;
using mozilla::PodZero;
MathCache*
ContextCaches::createMathCache(JSContext* cx)
{
MOZ_ASSERT(!mathCache_);
UniquePtr<MathCache> newMathCache(js_new<MathCache>());
if (!newMathCache) {
ReportOutOfMemory(cx);
return nullptr;
}
mathCache_ = Move(newMathCache);
return mathCache_.get();
}
bool
ContextCaches::init()
{
if (!evalCache.init())
return false;
return true;
}
void
NewObjectCache::clearNurseryObjects(JSRuntime* rt)
{
for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
Entry& e = entries[i];
NativeObject* obj = reinterpret_cast<NativeObject*>(&e.templateObject);
if (IsInsideNursery(e.key) ||
rt->gc.nursery.isInside(obj->slots_) ||
rt->gc.nursery.isInside(obj->elements_))
{
PodZero(&e);
}
}
}

312
js/src/vm/Caches.h Normal file
View File

@ -0,0 +1,312 @@
/* -*- 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 vm_Caches_h
#define vm_Caches_h
#include "jsatom.h"
#include "jsbytecode.h"
#include "jsobj.h"
#include "jsscript.h"
#include "ds/FixedSizeHash.h"
#include "frontend/SourceNotes.h"
#include "gc/Tracer.h"
#include "js/RootingAPI.h"
#include "js/UniquePtr.h"
#include "vm/NativeObject.h"
namespace js {
/*
* GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
* given pc in a script. We use the script->code pointer to tag the cache,
* instead of the script address itself, so that source notes are always found
* by offset from the bytecode with which they were generated.
*/
struct GSNCache {
typedef HashMap<jsbytecode*,
jssrcnote*,
PointerHasher<jsbytecode*, 0>,
SystemAllocPolicy> Map;
jsbytecode* code;
Map map;
GSNCache() : code(nullptr) { }
void purge();
};
/*
* ScopeCoordinateName cache to avoid O(n^2) growth in finding the name
* associated with a given aliasedvar operation.
*/
struct ScopeCoordinateNameCache {
typedef HashMap<uint32_t,
jsid,
DefaultHasher<uint32_t>,
SystemAllocPolicy> Map;
Shape* shape;
Map map;
ScopeCoordinateNameCache() : shape(nullptr) {}
void purge();
};
struct EvalCacheEntry
{
JSLinearString* str;
JSScript* script;
JSScript* callerScript;
jsbytecode* pc;
};
struct EvalCacheLookup
{
explicit EvalCacheLookup(JSContext* cx) : str(cx), callerScript(cx) {}
RootedLinearString str;
RootedScript callerScript;
JSVersion version;
jsbytecode* pc;
};
struct EvalCacheHashPolicy
{
typedef EvalCacheLookup Lookup;
static HashNumber hash(const Lookup& l);
static bool match(const EvalCacheEntry& entry, const EvalCacheLookup& l);
};
typedef HashSet<EvalCacheEntry, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache;
struct LazyScriptHashPolicy
{
struct Lookup {
JSContext* cx;
LazyScript* lazy;
Lookup(JSContext* cx, LazyScript* lazy)
: cx(cx), lazy(lazy)
{}
};
static const size_t NumHashes = 3;
static void hash(const Lookup& lookup, HashNumber hashes[NumHashes]);
static bool match(JSScript* script, const Lookup& lookup);
// Alternate methods for use when removing scripts from the hash without an
// explicit LazyScript lookup.
static void hash(JSScript* script, HashNumber hashes[NumHashes]);
static bool match(JSScript* script, JSScript* lookup) { return script == lookup; }
static void clear(JSScript** pscript) { *pscript = nullptr; }
static bool isCleared(JSScript* script) { return !script; }
};
typedef FixedSizeHashSet<JSScript*, LazyScriptHashPolicy, 769> LazyScriptCache;
class PropertyIteratorObject;
class NativeIterCache
{
static const size_t SIZE = size_t(1) << 8;
/* Cached native iterators. */
PropertyIteratorObject* data[SIZE];
static size_t getIndex(uint32_t key) {
return size_t(key) % SIZE;
}
public:
/* Native iterator most recently started. */
PropertyIteratorObject* last;
NativeIterCache()
: last(nullptr)
{
mozilla::PodArrayZero(data);
}
void purge() {
last = nullptr;
mozilla::PodArrayZero(data);
}
PropertyIteratorObject* get(uint32_t key) const {
return data[getIndex(key)];
}
void set(uint32_t key, PropertyIteratorObject* iterobj) {
data[getIndex(key)] = iterobj;
}
};
/*
* Cache for speeding up repetitive creation of objects in the VM.
* When an object is created which matches the criteria in the 'key' section
* below, an entry is filled with the resulting object.
*/
class NewObjectCache
{
/* Statically asserted to be equal to sizeof(JSObject_Slots16) */
static const unsigned MAX_OBJ_SIZE = 4 * sizeof(void*) + 16 * sizeof(Value);
static void staticAsserts() {
JS_STATIC_ASSERT(NewObjectCache::MAX_OBJ_SIZE == sizeof(JSObject_Slots16));
JS_STATIC_ASSERT(gc::AllocKind::OBJECT_LAST == gc::AllocKind::OBJECT16_BACKGROUND);
}
struct Entry
{
/* Class of the constructed object. */
const Class* clasp;
/*
* Key with one of three possible values:
*
* - Global for the object. The object must have a standard class for
* which the global's prototype can be determined, and the object's
* parent will be the global.
*
* - Prototype for the object (cannot be global). The object's parent
* will be the prototype's parent.
*
* - Type for the object. The object's parent will be the type's
* prototype's parent.
*/
gc::Cell* key;
/* Allocation kind for the constructed object. */
gc::AllocKind kind;
/* Number of bytes to copy from the template object. */
uint32_t nbytes;
/*
* Template object to copy from, with the initial values of fields,
* fixed slots (undefined) and private data (nullptr).
*/
char templateObject[MAX_OBJ_SIZE];
};
Entry entries[41]; // TODO: reconsider size
public:
typedef int EntryIndex;
NewObjectCache() { mozilla::PodZero(this); }
void purge() { mozilla::PodZero(this); }
/* Remove any cached items keyed on moved objects. */
void clearNurseryObjects(JSRuntime* rt);
/*
* Get the entry index for the given lookup, return whether there was a hit
* on an existing entry.
*/
inline bool lookupProto(const Class* clasp, JSObject* proto, gc::AllocKind kind, EntryIndex* pentry);
inline bool lookupGlobal(const Class* clasp, js::GlobalObject* global, gc::AllocKind kind,
EntryIndex* pentry);
bool lookupGroup(js::ObjectGroup* group, gc::AllocKind kind, EntryIndex* pentry) {
return lookup(group->clasp(), group, kind, pentry);
}
/*
* Return a new object from a cache hit produced by a lookup method, or
* nullptr if returning the object could possibly trigger GC (does not
* indicate failure).
*/
inline NativeObject* newObjectFromHit(JSContext* cx, EntryIndex entry, js::gc::InitialHeap heap);
/* Fill an entry after a cache miss. */
void fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto proto,
gc::AllocKind kind, NativeObject* obj);
inline void fillGlobal(EntryIndex entry, const Class* clasp, js::GlobalObject* global,
gc::AllocKind kind, NativeObject* obj);
void fillGroup(EntryIndex entry, js::ObjectGroup* group, gc::AllocKind kind,
NativeObject* obj)
{
MOZ_ASSERT(obj->group() == group);
return fill(entry, group->clasp(), group, kind, obj);
}
/* Invalidate any entries which might produce an object with shape/proto. */
void invalidateEntriesForShape(JSContext* cx, HandleShape shape, HandleObject proto);
private:
EntryIndex makeIndex(const Class* clasp, gc::Cell* key, gc::AllocKind kind) {
uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + size_t(kind);
return hash % mozilla::ArrayLength(entries);
}
bool lookup(const Class* clasp, gc::Cell* key, gc::AllocKind kind, EntryIndex* pentry) {
*pentry = makeIndex(clasp, key, kind);
Entry* entry = &entries[*pentry];
/* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
return entry->clasp == clasp && entry->key == key;
}
void fill(EntryIndex entry_, const Class* clasp, gc::Cell* key, gc::AllocKind kind,
NativeObject* obj) {
MOZ_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
MOZ_ASSERT(entry_ == makeIndex(clasp, key, kind));
Entry* entry = &entries[entry_];
entry->clasp = clasp;
entry->key = key;
entry->kind = kind;
entry->nbytes = gc::Arena::thingSize(kind);
js_memcpy(&entry->templateObject, obj, entry->nbytes);
}
static void copyCachedToObject(NativeObject* dst, NativeObject* src, gc::AllocKind kind) {
js_memcpy(dst, src, gc::Arena::thingSize(kind));
Shape::writeBarrierPost(&dst->shape_, nullptr, dst->shape_);
ObjectGroup::writeBarrierPost(&dst->group_, nullptr, dst->group_);
}
};
class MathCache;
class ContextCaches
{
UniquePtr<js::MathCache> mathCache_;
js::MathCache* createMathCache(JSContext* cx);
public:
js::GSNCache gsnCache;
js::ScopeCoordinateNameCache scopeCoordinateNameCache;
js::NewObjectCache newObjectCache;
js::NativeIterCache nativeIterCache;
js::UncompressedSourceCache uncompressedSourceCache;
js::EvalCache evalCache;
js::LazyScriptCache lazyScriptCache;
bool init();
js::MathCache* getMathCache(JSContext* cx) {
return mathCache_ ? mathCache_.get() : createMathCache(cx);
}
js::MathCache* maybeGetMathCache() {
return mathCache_.get();
}
};
} // namespace js
#endif /* vm_Caches_h */

View File

@ -247,7 +247,7 @@ SetAliasedVarOperation(JSContext* cx, JSScript* script, jsbytecode* pc,
// Avoid computing the name if no type updates are needed, as this may be
// expensive on scopes with large numbers of variables.
PropertyName* name = obj.isSingleton()
? ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc)
? ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc)
: nullptr;
obj.setAliasedVar(cx, sc, name, val);

View File

@ -3222,7 +3222,7 @@ CASE(JSOP_GETALIASEDVAR)
#ifdef DEBUG
// Only the .this slot can hold the TDZ MagicValue.
if (IsUninitializedLexical(val)) {
PropertyName* name = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache,
PropertyName* name = ScopeCoordinateName(cx->caches.scopeCoordinateNameCache,
script, REGS.pc);
MOZ_ASSERT(name == cx->names().dotThis);
JSOp next = JSOp(*GetNextPc(REGS.pc));
@ -4944,7 +4944,7 @@ js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber,
name = script->getName(pc);
} else {
MOZ_ASSERT(IsAliasedVarOp(op));
name = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc);
name = ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc);
}
ReportRuntimeLexicalError(cx, errorNumber, name);

View File

@ -4,8 +4,6 @@
* 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 "vm/Runtime-inl.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Atomics.h"
#include "mozilla/DebugOnly.h"
@ -226,7 +224,6 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
decimalSeparator(0),
numGrouping(0),
#endif
mathCache_(nullptr),
activeCompilations_(0),
keepAtoms_(0),
trustedPrincipals_(nullptr),
@ -337,9 +334,6 @@ JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
if (!scriptDataTable_.init())
return false;
if (!evalCache.init())
return false;
/* The garbage collector depends on everything before this point being initialized. */
gcInitialized = true;
@ -460,7 +454,6 @@ JSRuntime::destroyRuntime()
atomsCompartment_ = nullptr;
js_free(defaultLocale);
js_delete(mathCache_);
js_delete(jitRuntime_);
js_delete(ionPcScriptCache);
@ -496,21 +489,6 @@ JSRuntime::setTelemetryCallback(JSRuntime* rt, JSAccumulateTelemetryDataCallback
rt->telemetryCallback = callback;
}
void
NewObjectCache::clearNurseryObjects(JSRuntime* rt)
{
for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
Entry& e = entries[i];
NativeObject* obj = reinterpret_cast<NativeObject*>(&e.templateObject);
if (IsInsideNursery(e.key) ||
rt->gc.nursery.isInside(obj->slots_) ||
rt->gc.nursery.isInside(obj->elements_))
{
PodZero(&e);
}
}
}
void
JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes* rtSizes)
{
@ -520,7 +498,8 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
// For now, measure the size of the derived class (JSContext).
// TODO (bug 1281529): make memory reporting reflect the new
// JSContext/JSRuntime world better.
rtSizes->object += mallocSizeOf(unsafeContextFromAnyThread());
JSContext* cx = unsafeContextFromAnyThread();
rtSizes->object += mallocSizeOf(cx);
rtSizes->atomsTable += atoms(lock).sizeOfIncludingThis(mallocSizeOf);
@ -530,20 +509,23 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
rtSizes->atomsTable += permanentAtoms->sizeOfIncludingThis(mallocSizeOf);
}
rtSizes->contexts += unsafeContextFromAnyThread()->sizeOfExcludingThis(mallocSizeOf);
rtSizes->contexts += cx->sizeOfExcludingThis(mallocSizeOf);
rtSizes->temporary += tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
rtSizes->interpreterStack += interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
rtSizes->mathCache += mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
if (MathCache* cache = cx->caches.maybeGetMathCache())
rtSizes->mathCache += cache->sizeOfIncludingThis(mallocSizeOf);
if (sharedImmutableStrings_) {
rtSizes->sharedImmutableStringsCache +=
sharedImmutableStrings_->sizeOfExcludingThis(mallocSizeOf);
}
rtSizes->uncompressedSourceCache += uncompressedSourceCache.sizeOfExcludingThis(mallocSizeOf);
rtSizes->uncompressedSourceCache +=
cx->caches.uncompressedSourceCache.sizeOfExcludingThis(mallocSizeOf);
rtSizes->scriptData += scriptDataTable(lock).sizeOfExcludingThis(mallocSizeOf);
for (ScriptDataTable::Range r = scriptDataTable(lock).all(); !r.empty(); r.popFront())
@ -678,22 +660,6 @@ JSRuntime::handleInterrupt(JSContext* cx)
return true;
}
MathCache*
JSRuntime::createMathCache(JSContext* cx)
{
MOZ_ASSERT(!mathCache_);
MOZ_ASSERT(cx->runtime() == this);
MathCache* newMathCache = js_new<MathCache>();
if (!newMathCache) {
ReportOutOfMemory(cx);
return nullptr;
}
mathCache_ = newMathCache;
return mathCache_;
}
bool
JSRuntime::setDefaultLocale(const char* locale)
{

View File

@ -90,7 +90,6 @@ ReportOverRecursed(ExclusiveContext* cx);
class Activation;
class ActivationIterator;
class MathCache;
class WasmActivation;
namespace jit {
@ -111,267 +110,6 @@ namespace wasm {
class Module;
} // namespace wasm
/*
* GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
* given pc in a script. We use the script->code pointer to tag the cache,
* instead of the script address itself, so that source notes are always found
* by offset from the bytecode with which they were generated.
*/
struct GSNCache {
typedef HashMap<jsbytecode*,
jssrcnote*,
PointerHasher<jsbytecode*, 0>,
SystemAllocPolicy> Map;
jsbytecode* code;
Map map;
GSNCache() : code(nullptr) { }
void purge();
};
/*
* ScopeCoordinateName cache to avoid O(n^2) growth in finding the name
* associated with a given aliasedvar operation.
*/
struct ScopeCoordinateNameCache {
typedef HashMap<uint32_t,
jsid,
DefaultHasher<uint32_t>,
SystemAllocPolicy> Map;
Shape* shape;
Map map;
ScopeCoordinateNameCache() : shape(nullptr) {}
void purge();
};
using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
struct EvalCacheEntry
{
JSLinearString* str;
JSScript* script;
JSScript* callerScript;
jsbytecode* pc;
};
struct EvalCacheLookup
{
explicit EvalCacheLookup(JSContext* cx) : str(cx), callerScript(cx) {}
RootedLinearString str;
RootedScript callerScript;
JSVersion version;
jsbytecode* pc;
};
struct EvalCacheHashPolicy
{
typedef EvalCacheLookup Lookup;
static HashNumber hash(const Lookup& l);
static bool match(const EvalCacheEntry& entry, const EvalCacheLookup& l);
};
typedef HashSet<EvalCacheEntry, EvalCacheHashPolicy, SystemAllocPolicy> EvalCache;
struct LazyScriptHashPolicy
{
struct Lookup {
JSContext* cx;
LazyScript* lazy;
Lookup(JSContext* cx, LazyScript* lazy)
: cx(cx), lazy(lazy)
{}
};
static const size_t NumHashes = 3;
static void hash(const Lookup& lookup, HashNumber hashes[NumHashes]);
static bool match(JSScript* script, const Lookup& lookup);
// Alternate methods for use when removing scripts from the hash without an
// explicit LazyScript lookup.
static void hash(JSScript* script, HashNumber hashes[NumHashes]);
static bool match(JSScript* script, JSScript* lookup) { return script == lookup; }
static void clear(JSScript** pscript) { *pscript = nullptr; }
static bool isCleared(JSScript* script) { return !script; }
};
typedef FixedSizeHashSet<JSScript*, LazyScriptHashPolicy, 769> LazyScriptCache;
class PropertyIteratorObject;
class NativeIterCache
{
static const size_t SIZE = size_t(1) << 8;
/* Cached native iterators. */
PropertyIteratorObject* data[SIZE];
static size_t getIndex(uint32_t key) {
return size_t(key) % SIZE;
}
public:
/* Native iterator most recently started. */
PropertyIteratorObject* last;
NativeIterCache()
: last(nullptr)
{
mozilla::PodArrayZero(data);
}
void purge() {
last = nullptr;
mozilla::PodArrayZero(data);
}
PropertyIteratorObject* get(uint32_t key) const {
return data[getIndex(key)];
}
void set(uint32_t key, PropertyIteratorObject* iterobj) {
data[getIndex(key)] = iterobj;
}
};
/*
* Cache for speeding up repetitive creation of objects in the VM.
* When an object is created which matches the criteria in the 'key' section
* below, an entry is filled with the resulting object.
*/
class NewObjectCache
{
/* Statically asserted to be equal to sizeof(JSObject_Slots16) */
static const unsigned MAX_OBJ_SIZE = 4 * sizeof(void*) + 16 * sizeof(Value);
static void staticAsserts() {
JS_STATIC_ASSERT(NewObjectCache::MAX_OBJ_SIZE == sizeof(JSObject_Slots16));
JS_STATIC_ASSERT(gc::AllocKind::OBJECT_LAST == gc::AllocKind::OBJECT16_BACKGROUND);
}
struct Entry
{
/* Class of the constructed object. */
const Class* clasp;
/*
* Key with one of three possible values:
*
* - Global for the object. The object must have a standard class for
* which the global's prototype can be determined, and the object's
* parent will be the global.
*
* - Prototype for the object (cannot be global). The object's parent
* will be the prototype's parent.
*
* - Type for the object. The object's parent will be the type's
* prototype's parent.
*/
gc::Cell* key;
/* Allocation kind for the constructed object. */
gc::AllocKind kind;
/* Number of bytes to copy from the template object. */
uint32_t nbytes;
/*
* Template object to copy from, with the initial values of fields,
* fixed slots (undefined) and private data (nullptr).
*/
char templateObject[MAX_OBJ_SIZE];
};
Entry entries[41]; // TODO: reconsider size
public:
typedef int EntryIndex;
NewObjectCache() { mozilla::PodZero(this); }
void purge() { mozilla::PodZero(this); }
/* Remove any cached items keyed on moved objects. */
void clearNurseryObjects(JSRuntime* rt);
/*
* Get the entry index for the given lookup, return whether there was a hit
* on an existing entry.
*/
inline bool lookupProto(const Class* clasp, JSObject* proto, gc::AllocKind kind, EntryIndex* pentry);
inline bool lookupGlobal(const Class* clasp, js::GlobalObject* global, gc::AllocKind kind,
EntryIndex* pentry);
bool lookupGroup(js::ObjectGroup* group, gc::AllocKind kind, EntryIndex* pentry) {
return lookup(group->clasp(), group, kind, pentry);
}
/*
* Return a new object from a cache hit produced by a lookup method, or
* nullptr if returning the object could possibly trigger GC (does not
* indicate failure).
*/
inline NativeObject* newObjectFromHit(JSContext* cx, EntryIndex entry, js::gc::InitialHeap heap);
/* Fill an entry after a cache miss. */
void fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto proto,
gc::AllocKind kind, NativeObject* obj);
inline void fillGlobal(EntryIndex entry, const Class* clasp, js::GlobalObject* global,
gc::AllocKind kind, NativeObject* obj);
void fillGroup(EntryIndex entry, js::ObjectGroup* group, gc::AllocKind kind,
NativeObject* obj)
{
MOZ_ASSERT(obj->group() == group);
return fill(entry, group->clasp(), group, kind, obj);
}
/* Invalidate any entries which might produce an object with shape/proto. */
void invalidateEntriesForShape(JSContext* cx, HandleShape shape, HandleObject proto);
private:
EntryIndex makeIndex(const Class* clasp, gc::Cell* key, gc::AllocKind kind) {
uintptr_t hash = (uintptr_t(clasp) ^ uintptr_t(key)) + size_t(kind);
return hash % mozilla::ArrayLength(entries);
}
bool lookup(const Class* clasp, gc::Cell* key, gc::AllocKind kind, EntryIndex* pentry) {
*pentry = makeIndex(clasp, key, kind);
Entry* entry = &entries[*pentry];
/* N.B. Lookups with the same clasp/key but different kinds map to different entries. */
return entry->clasp == clasp && entry->key == key;
}
void fill(EntryIndex entry_, const Class* clasp, gc::Cell* key, gc::AllocKind kind,
NativeObject* obj) {
MOZ_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
MOZ_ASSERT(entry_ == makeIndex(clasp, key, kind));
Entry* entry = &entries[entry_];
entry->clasp = clasp;
entry->key = key;
entry->kind = kind;
entry->nbytes = gc::Arena::thingSize(kind);
js_memcpy(&entry->templateObject, obj, entry->nbytes);
}
static void copyCachedToObject(NativeObject* dst, NativeObject* src, gc::AllocKind kind) {
js_memcpy(dst, src, gc::Arena::thingSize(kind));
Shape::writeBarrierPost(&dst->shape_, nullptr, dst->shape_);
ObjectGroup::writeBarrierPost(&dst->group_, nullptr, dst->group_);
}
};
/*
* A FreeOp can do one thing: free memory. For convenience, it has delete_
* convenience methods that also call destructors.
@ -615,6 +353,8 @@ class PerThreadData : public PerThreadDataFriendFields
#endif
};
using ScriptAndCountsVector = GCVector<ScriptAndCounts, 0, SystemAllocPolicy>;
class AutoLockForExclusiveAccess;
} // namespace js
@ -1292,17 +1032,9 @@ struct JSRuntime : public JS::shadow::Runtime,
#endif
private:
js::MathCache* mathCache_;
js::MathCache* createMathCache(JSContext* cx);
mozilla::Maybe<js::SharedImmutableStringsCache> sharedImmutableStrings_;
public:
js::MathCache* getMathCache(JSContext* cx) {
return mathCache_ ? mathCache_ : createMathCache(cx);
}
js::MathCache* maybeGetMathCache() {
return mathCache_;
}
public:
// If this particular JSRuntime has a SharedImmutableStringsCache, return a
// pointer to it, otherwise return nullptr.
js::SharedImmutableStringsCache* maybeThisRuntimeSharedImmutableStrings() {
@ -1317,14 +1049,6 @@ struct JSRuntime : public JS::shadow::Runtime,
return parentRuntime ? parentRuntime->sharedImmutableStrings() : *sharedImmutableStrings_;
}
js::GSNCache gsnCache;
js::ScopeCoordinateNameCache scopeCoordinateNameCache;
js::NewObjectCache newObjectCache;
js::NativeIterCache nativeIterCache;
js::UncompressedSourceCache uncompressedSourceCache;
js::EvalCache evalCache;
js::LazyScriptCache lazyScriptCache;
// Pool of maps used during parse/emit. This may be modified by threads
// with an ExclusiveContext and requires a lock. Active compilations
// prevent the pool from being purged during GCs.

View File

@ -3538,7 +3538,7 @@ RemoveReferencedNames(JSContext* cx, HandleScript script, PropertyNameSet& remai
case JSOP_GETALIASEDVAR:
case JSOP_SETALIASEDVAR:
name = ScopeCoordinateName(cx->runtime()->scopeCoordinateNameCache, script, pc);
name = ScopeCoordinateName(cx->caches.scopeCoordinateNameCache, script, pc);
break;
default:

View File

@ -24,8 +24,8 @@
#include "jscompartmentinlines.h"
#include "jsobjinlines.h"
#include "vm/Caches-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/Runtime-inl.h"
using namespace js;
using namespace js::gc;
@ -1572,7 +1572,7 @@ EmptyShape::insertInitialShape(ExclusiveContext* cx, HandleShape shape, HandleOb
*/
if (cx->isJSContext()) {
JSContext* ncx = cx->asJSContext();
ncx->runtime()->newObjectCache.invalidateEntriesForShape(ncx, shape, proto);
ncx->caches.newObjectCache.invalidateEntriesForShape(ncx, shape, proto);
}
}

View File

@ -12,7 +12,7 @@
#include "gc/Barrier.h"
#include "gc/Zone.h"
#include "vm/Runtime-inl.h"
#include "vm/Caches-inl.h"
namespace js {