зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1108941 - Implement the per-global template literal registry. (r=arai,jonco)
This commit is contained in:
Родитель
9fa58ed270
Коммит
c91e65240b
|
@ -767,6 +767,7 @@ struct CompartmentStats
|
|||
macro(Other, MallocHeap, savedStacksSet) \
|
||||
macro(Other, MallocHeap, varNamesSet) \
|
||||
macro(Other, MallocHeap, nonSyntacticLexicalScopesTable) \
|
||||
macro(Other, MallocHeap, templateLiteralMap) \
|
||||
macro(Other, MallocHeap, jitCompartment) \
|
||||
macro(Other, MallocHeap, privateData)
|
||||
|
||||
|
|
|
@ -1657,10 +1657,8 @@ BaselineCompiler::emit_JSOP_CALLSITEOBJ()
|
|||
RootedObject raw(cx, script->getObject(GET_UINT32_INDEX(pc) + 1));
|
||||
if (!cso || !raw)
|
||||
return false;
|
||||
RootedValue rawValue(cx);
|
||||
rawValue.setObject(*raw);
|
||||
|
||||
if (!ProcessCallSiteObjOperation(cx, cso, raw, rawValue))
|
||||
if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso))
|
||||
return false;
|
||||
|
||||
frame.push(ObjectValue(*cso));
|
||||
|
|
|
@ -2185,6 +2185,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
return jsop_regexp(info().getRegExp(pc));
|
||||
|
||||
case JSOP_CALLSITEOBJ:
|
||||
// TODO this is wrong, need threadsafe way to get unique template obj
|
||||
pushConstant(ObjectValue(*(info().getObject(pc))));
|
||||
return Ok();
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ JSCompartment::init(JSContext* maybecx)
|
|||
if (!enumerators)
|
||||
return false;
|
||||
|
||||
if (!savedStacks_.init() || !varNames_.init()) {
|
||||
if (!savedStacks_.init() || !varNames_.init() || !templateLiteralMap_.init()) {
|
||||
if (maybecx)
|
||||
ReportOutOfMemory(maybecx);
|
||||
return false;
|
||||
|
@ -599,6 +599,64 @@ JSCompartment::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* static */ HashNumber
|
||||
TemplateRegistryHashPolicy::hash(const Lookup& lookup)
|
||||
{
|
||||
size_t length = GetAnyBoxedOrUnboxedInitializedLength(lookup);
|
||||
HashNumber hash = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
JSAtom& lookupAtom = GetAnyBoxedOrUnboxedDenseElement(lookup, i).toString()->asAtom();
|
||||
hash = mozilla::AddToHash(hash, lookupAtom.hash());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
TemplateRegistryHashPolicy::match(const Key& key, const Lookup& lookup)
|
||||
{
|
||||
size_t length = GetAnyBoxedOrUnboxedInitializedLength(lookup);
|
||||
if (GetAnyBoxedOrUnboxedInitializedLength(key) != length)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
JSAtom* a = &GetAnyBoxedOrUnboxedDenseElement(key, i).toString()->asAtom();
|
||||
JSAtom* b = &GetAnyBoxedOrUnboxedDenseElement(lookup, i).toString()->asAtom();
|
||||
if (a != b)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleObject rawStrings,
|
||||
MutableHandleObject templateObj)
|
||||
{
|
||||
if (TemplateRegistry::AddPtr p = templateLiteralMap_.lookupForAdd(rawStrings)) {
|
||||
templateObj.set(p->value());
|
||||
|
||||
// The template object must have been frozen when it was added to the
|
||||
// registry.
|
||||
MOZ_ASSERT(!templateObj->nonProxyIsExtensible());
|
||||
} else {
|
||||
// Add the template object to the registry before freezing to avoid
|
||||
// needing to call relookupOrAdd.
|
||||
if (!templateLiteralMap_.add(p, rawStrings, templateObj))
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(templateObj->nonProxyIsExtensible());
|
||||
RootedValue rawValue(cx, ObjectValue(*rawStrings));
|
||||
if (!DefineProperty(cx, templateObj, cx->names().raw, rawValue, nullptr, nullptr, 0))
|
||||
return false;
|
||||
if (!FreezeObject(cx, rawStrings))
|
||||
return false;
|
||||
if (!FreezeObject(cx, templateObj))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::traceOutgoingCrossCompartmentWrappers(JSTracer* trc)
|
||||
{
|
||||
|
@ -636,6 +694,10 @@ JSCompartment::trace(JSTracer* trc)
|
|||
{
|
||||
savedStacks_.trace(trc);
|
||||
|
||||
// The template registry strongly holds everything in it by design and
|
||||
// spec.
|
||||
templateLiteralMap_.trace(trc);
|
||||
|
||||
// Atoms are always tenured.
|
||||
if (!JS::CurrentThreadIsHeapMinorCollecting())
|
||||
varNames_.trace(trc);
|
||||
|
@ -976,6 +1038,7 @@ JSCompartment::clearTables()
|
|||
MOZ_ASSERT(!debugEnvs);
|
||||
MOZ_ASSERT(enumerators->next() == enumerators);
|
||||
MOZ_ASSERT(regExps.empty());
|
||||
MOZ_ASSERT(templateLiteralMap_.empty());
|
||||
|
||||
objectGroups.clearTables();
|
||||
if (savedStacks_.initialized())
|
||||
|
@ -1243,6 +1306,7 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
|||
size_t* savedStacksSet,
|
||||
size_t* varNamesSet,
|
||||
size_t* nonSyntacticLexicalEnvironmentsArg,
|
||||
size_t* templateLiteralMap,
|
||||
size_t* jitCompartment,
|
||||
size_t* privateData)
|
||||
{
|
||||
|
@ -1263,6 +1327,7 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
|||
if (nonSyntacticLexicalEnvironments_)
|
||||
*nonSyntacticLexicalEnvironmentsArg +=
|
||||
nonSyntacticLexicalEnvironments_->sizeOfIncludingThis(mallocSizeOf);
|
||||
*templateLiteralMap += templateLiteralMap_.sizeOfExcludingThis(mallocSizeOf);
|
||||
if (jitCompartment_)
|
||||
*jitCompartment += jitCompartment_->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "vm/GlobalObject.h"
|
||||
#include "vm/PIC.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/TemplateRegistry.h"
|
||||
#include "vm/Time.h"
|
||||
#include "wasm/WasmCompartment.h"
|
||||
|
||||
|
@ -545,6 +546,7 @@ struct JSCompartment
|
|||
size_t* savedStacksSet,
|
||||
size_t* varNamesSet,
|
||||
size_t* nonSyntacticLexicalScopes,
|
||||
size_t* templateLiteralMap,
|
||||
size_t* jitCompartment,
|
||||
size_t* privateData);
|
||||
|
||||
|
@ -586,6 +588,12 @@ struct JSCompartment
|
|||
// to use the same lexical environment to persist lexical bindings.
|
||||
js::ObjectWeakMap* nonSyntacticLexicalEnvironments_;
|
||||
|
||||
// The realm's [[TemplateMap]], used for mapping template literals to
|
||||
// unique template objects used in evaluation of tagged template literals.
|
||||
//
|
||||
// See ES 12.2.9.3.
|
||||
js::TemplateRegistry templateLiteralMap_;
|
||||
|
||||
public:
|
||||
/* During GC, stores the index of this compartment in rt->compartments. */
|
||||
unsigned gcIndex;
|
||||
|
@ -743,6 +751,13 @@ struct JSCompartment
|
|||
return varNames_.has(name);
|
||||
}
|
||||
|
||||
// Get a unique template object given a JS array of raw template strings
|
||||
// and a template object. If a template object is found in template
|
||||
// registry, that object is returned. Otherwise, the passed-in templateObj
|
||||
// is added to the registry.
|
||||
bool getTemplateLiteralObject(JSContext* cx, js::HandleObject rawStrings,
|
||||
js::MutableHandleObject templateObj);
|
||||
|
||||
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
|
||||
|
||||
MOZ_MUST_USE bool findDeadProxyZoneEdges(bool* foundAny);
|
||||
|
|
|
@ -664,25 +664,6 @@ InitArrayElemOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t
|
|||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ProcessCallSiteObjOperation(JSContext* cx, RootedObject& cso, RootedObject& raw,
|
||||
RootedValue& rawValue)
|
||||
{
|
||||
bool extensible;
|
||||
if (!IsExtensible(cx, cso, &extensible))
|
||||
return false;
|
||||
if (extensible) {
|
||||
JSAtom* name = cx->names().raw;
|
||||
if (!DefineProperty(cx, cso, name->asPropertyName(), rawValue, nullptr, nullptr, 0))
|
||||
return false;
|
||||
if (!FreezeObject(cx, raw))
|
||||
return false;
|
||||
if (!FreezeObject(cx, cso))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define RELATIONAL_OP(OP) \
|
||||
JS_BEGIN_MACRO \
|
||||
/* Optimize for two int-tagged operands (typical loop control). */ \
|
||||
|
|
|
@ -3187,12 +3187,10 @@ END_CASE(JSOP_OBJECT)
|
|||
|
||||
CASE(JSOP_CALLSITEOBJ)
|
||||
{
|
||||
|
||||
ReservedRooted<JSObject*> cso(&rootObject0, script->getObject(REGS.pc));
|
||||
ReservedRooted<JSObject*> raw(&rootObject1, script->getObject(GET_UINT32_INDEX(REGS.pc) + 1));
|
||||
ReservedRooted<Value> rawValue(&rootValue0, ObjectValue(*raw));
|
||||
|
||||
if (!ProcessCallSiteObjOperation(cx, cso, raw, rawValue))
|
||||
if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso))
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*cso);
|
||||
|
|
|
@ -357,6 +357,7 @@ StatsCompartmentCallback(JSContext* cx, void* data, JSCompartment* compartment)
|
|||
&cStats.savedStacksSet,
|
||||
&cStats.varNamesSet,
|
||||
&cStats.nonSyntacticLexicalScopesTable,
|
||||
&cStats.templateLiteralMap,
|
||||
&cStats.jitCompartment,
|
||||
&cStats.privateData);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* -*- 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_TemplateRegistry_h
|
||||
#define vm_TemplateRegistry_h
|
||||
|
||||
#include "jsobj.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "gc/Marking.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
// Data structures to maintain unique template objects mapped to by lists of
|
||||
// raw strings.
|
||||
//
|
||||
// See ES 12.2.9.3.
|
||||
|
||||
struct TemplateRegistryHashPolicy
|
||||
{
|
||||
// For use as HashPolicy. Expects keys as arrays of atoms.
|
||||
using Key = JSObject*;
|
||||
using Lookup = JSObject*;
|
||||
|
||||
static HashNumber hash(const Lookup& lookup);
|
||||
static bool match(const Key& key, const Lookup& lookup);
|
||||
};
|
||||
|
||||
using TemplateRegistry = JS::GCHashMap<JSObject*,
|
||||
JSObject*,
|
||||
TemplateRegistryHashPolicy,
|
||||
SystemAllocPolicy>;
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif // vm_TemplateRegistery_h
|
|
@ -2338,6 +2338,10 @@ ReportCompartmentStats(const JS::CompartmentStats& cStats,
|
|||
cStats.nonSyntacticLexicalScopesTable,
|
||||
"The non-syntactic lexical scopes table.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("template-literal-map"),
|
||||
cStats.templateLiteralMap,
|
||||
"The template literal registry.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("jit-compartment"),
|
||||
cStats.jitCompartment,
|
||||
"The JIT compartment.");
|
||||
|
|
Загрузка…
Ссылка в новой задаче