mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 22:32:51 +00:00
Bug 1437530: Cache template literal objects per call site again. r=arai
This commit is contained in:
parent
3971a035c7
commit
04c864d3c5
@ -774,7 +774,6 @@ 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) \
|
||||
macro(Other, MallocHeap, scriptCountsMap)
|
||||
|
@ -2484,7 +2484,6 @@ GCRuntime::sweepZoneAfterCompacting(Zone* zone)
|
||||
c->objectGroups.sweep(fop);
|
||||
c->sweepRegExps();
|
||||
c->sweepSavedStacks();
|
||||
c->sweepTemplateLiteralMap();
|
||||
c->sweepVarNames();
|
||||
c->sweepGlobalObject();
|
||||
c->sweepSelfHostingScriptSource();
|
||||
@ -5362,7 +5361,6 @@ SweepMisc(JSRuntime* runtime)
|
||||
c->sweepGlobalObject();
|
||||
c->sweepTemplateObjects();
|
||||
c->sweepSavedStacks();
|
||||
c->sweepTemplateLiteralMap();
|
||||
c->sweepSelfHostingScriptSource();
|
||||
c->sweepNativeIterators();
|
||||
}
|
||||
|
@ -1693,11 +1693,11 @@ bool
|
||||
BaselineCompiler::emit_JSOP_CALLSITEOBJ()
|
||||
{
|
||||
RootedObject cso(cx, script->getObject(pc));
|
||||
RootedArrayObject raw(cx, &script->getObject(GET_UINT32_INDEX(pc) + 1)->as<ArrayObject>());
|
||||
RootedObject raw(cx, script->getObject(GET_UINT32_INDEX(pc) + 1));
|
||||
if (!cso || !raw)
|
||||
return false;
|
||||
|
||||
if (!cx->compartment()->getTemplateLiteralObject(cx, raw, &cso))
|
||||
if (!ProcessCallSiteObjOperation(cx, cso, raw))
|
||||
return false;
|
||||
|
||||
frame.push(ObjectValue(*cso));
|
||||
|
@ -2244,16 +2244,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
||||
return jsop_regexp(info().getRegExp(pc));
|
||||
|
||||
case JSOP_CALLSITEOBJ:
|
||||
if (info().analysisMode() == Analysis_ArgumentsUsage) {
|
||||
// When analyzing arguments usage, it is possible that the
|
||||
// template object is not yet canonicalized. Push an incorrect
|
||||
// object; it does not matter for arguments analysis.
|
||||
pushConstant(ObjectValue(*info().getObject(pc)));
|
||||
} else {
|
||||
ArrayObject* raw = &script()->getObject(GET_UINT32_INDEX(pc) + 1)->as<ArrayObject>();
|
||||
JSObject* obj = script()->compartment()->getExistingTemplateLiteralObject(raw);
|
||||
pushConstant(ObjectValue(*obj));
|
||||
}
|
||||
pushConstant(ObjectValue(*info().getObject(pc)));
|
||||
return Ok();
|
||||
|
||||
case JSOP_OBJECT:
|
||||
|
@ -459,3 +459,11 @@ skip script test262/harness/detachArrayBuffer.js
|
||||
####################################################
|
||||
# Tests disabled due to invalid test expectations #
|
||||
####################################################
|
||||
|
||||
# https://github.com/tc39/test262/pull/972
|
||||
skip script test262/language/expressions/tagged-template/cache-identical-source-new-function.js
|
||||
skip script test262/language/expressions/tagged-template/cache-differing-expressions-new-function.js
|
||||
skip script test262/language/expressions/tagged-template/cache-differing-expressions.js
|
||||
skip script test262/language/expressions/tagged-template/cache-identical-source.js
|
||||
skip script test262/language/expressions/tagged-template/cache-differing-expressions-eval.js
|
||||
skip script test262/language/expressions/tagged-template/cache-identical-source-eval.js
|
||||
|
@ -203,7 +203,7 @@ for (var i = 1; i < 3; i++)
|
||||
// Same call site object behavior
|
||||
assertEq(callSiteObj[1], callSiteObj[2]);
|
||||
// Template objects are canonicalized
|
||||
assertEq(callSiteObj[0], callSiteObj[1]);
|
||||
assertEq(callSiteObj[0] !== callSiteObj[1], true);
|
||||
assertEq("raw" in callSiteObj[0], true);
|
||||
|
||||
// Array length
|
||||
@ -227,7 +227,7 @@ function test() {
|
||||
a[i] = eval("x``");
|
||||
}
|
||||
test();
|
||||
assertEq(a[0], a[1]);
|
||||
assertEq(a[0] !== a[1], true);
|
||||
|
||||
// Test that |obj.method`template`| works
|
||||
var newObj = {
|
||||
|
@ -684,6 +684,24 @@ InitArrayElemOperation(JSContext* cx, jsbytecode* pc, HandleObject obj, uint32_t
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
ProcessCallSiteObjOperation(JSContext* cx, HandleObject cso, HandleObject raw)
|
||||
{
|
||||
MOZ_ASSERT(cso->is<ArrayObject>());
|
||||
MOZ_ASSERT(raw->is<ArrayObject>());
|
||||
|
||||
if (cso->nonProxyIsExtensible()) {
|
||||
RootedValue rawValue(cx, ObjectValue(*raw));
|
||||
if (!DefineDataProperty(cx, cso, cx->names().raw, rawValue, 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). */ \
|
||||
|
@ -3317,7 +3317,7 @@ CASE(JSOP_CALLSITEOBJ)
|
||||
ReservedRooted<JSObject*> cso(&rootObject0, script->getObject(REGS.pc));
|
||||
ReservedRooted<JSObject*> raw(&rootObject1, script->getObject(GET_UINT32_INDEX(REGS.pc) + 1));
|
||||
|
||||
if (!cx->compartment()->getTemplateLiteralObject(cx, raw.as<ArrayObject>(), &cso))
|
||||
if (!ProcessCallSiteObjOperation(cx, cso, raw))
|
||||
goto error;
|
||||
|
||||
PUSH_OBJECT(*cso);
|
||||
|
@ -156,7 +156,6 @@ JSCompartment::init(JSContext* maybecx)
|
||||
|
||||
if (!savedStacks_.init() ||
|
||||
!varNames_.init() ||
|
||||
!templateLiteralMap_.init() ||
|
||||
!iteratorCache.init())
|
||||
{
|
||||
if (maybecx)
|
||||
@ -620,70 +619,6 @@ JSCompartment::addToVarNames(JSContext* cx, JS::Handle<JSAtom*> name)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ HashNumber
|
||||
TemplateRegistryHashPolicy::hash(const Lookup& lookup)
|
||||
{
|
||||
size_t length = lookup->as<NativeObject>().getDenseInitializedLength();
|
||||
HashNumber hash = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
JSAtom& lookupAtom = lookup->as<NativeObject>().getDenseElement(i).toString()->asAtom();
|
||||
hash = mozilla::AddToHash(hash, lookupAtom.hash());
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
TemplateRegistryHashPolicy::match(const Key& key, const Lookup& lookup)
|
||||
{
|
||||
size_t length = lookup->as<NativeObject>().getDenseInitializedLength();
|
||||
if (key->as<NativeObject>().getDenseInitializedLength() != length)
|
||||
return false;
|
||||
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
JSAtom* a = &key->as<NativeObject>().getDenseElement(i).toString()->asAtom();
|
||||
JSAtom* b = &lookup->as<NativeObject>().getDenseElement(i).toString()->asAtom();
|
||||
if (a != b)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::getTemplateLiteralObject(JSContext* cx, HandleArrayObject 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 {
|
||||
MOZ_ASSERT(templateObj->nonProxyIsExtensible());
|
||||
RootedValue rawValue(cx, ObjectValue(*rawStrings));
|
||||
if (!DefineDataProperty(cx, templateObj, cx->names().raw, rawValue, 0))
|
||||
return false;
|
||||
if (!FreezeObject(cx, rawStrings))
|
||||
return false;
|
||||
if (!FreezeObject(cx, templateObj))
|
||||
return false;
|
||||
|
||||
if (!templateLiteralMap_.relookupOrAdd(p, rawStrings, templateObj))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
JSCompartment::getExistingTemplateLiteralObject(ArrayObject* rawStrings)
|
||||
{
|
||||
TemplateRegistry::Ptr p = templateLiteralMap_.lookup(rawStrings);
|
||||
MOZ_ASSERT(p);
|
||||
return p->value();
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::traceOutgoingCrossCompartmentWrappers(JSTracer* trc)
|
||||
{
|
||||
@ -725,10 +660,6 @@ JSCompartment::traceGlobal(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);
|
||||
@ -836,12 +767,6 @@ JSCompartment::sweepSavedStacks()
|
||||
savedStacks_.sweep();
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::sweepTemplateLiteralMap()
|
||||
{
|
||||
templateLiteralMap_.sweep();
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::sweepGlobalObject()
|
||||
{
|
||||
@ -1098,7 +1023,6 @@ JSCompartment::clearTables()
|
||||
MOZ_ASSERT(!jitCompartment_);
|
||||
MOZ_ASSERT(!debugEnvs);
|
||||
MOZ_ASSERT(enumerators->next() == enumerators);
|
||||
MOZ_ASSERT(templateLiteralMap_.empty());
|
||||
|
||||
objectGroups.clearTables();
|
||||
if (savedStacks_.initialized())
|
||||
@ -1381,7 +1305,6 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* savedStacksSet,
|
||||
size_t* varNamesSet,
|
||||
size_t* nonSyntacticLexicalEnvironmentsArg,
|
||||
size_t* templateLiteralMap,
|
||||
size_t* jitCompartment,
|
||||
size_t* privateData,
|
||||
size_t* scriptCountsMapArg)
|
||||
@ -1403,7 +1326,6 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
if (nonSyntacticLexicalEnvironments_)
|
||||
*nonSyntacticLexicalEnvironmentsArg +=
|
||||
nonSyntacticLexicalEnvironments_->sizeOfIncludingThis(mallocSizeOf);
|
||||
*templateLiteralMap += templateLiteralMap_.sizeOfExcludingThis(mallocSizeOf);
|
||||
if (jitCompartment_)
|
||||
*jitCompartment += jitCompartment_->sizeOfIncludingThis(mallocSizeOf);
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include "vm/ReceiverGuard.h"
|
||||
#include "vm/RegExpShared.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/TemplateRegistry.h"
|
||||
#include "vm/Time.h"
|
||||
#include "wasm/WasmCompartment.h"
|
||||
|
||||
@ -779,7 +778,6 @@ struct JSCompartment
|
||||
size_t* savedStacksSet,
|
||||
size_t* varNamesSet,
|
||||
size_t* nonSyntacticLexicalScopes,
|
||||
size_t* templateLiteralMap,
|
||||
size_t* jitCompartment,
|
||||
size_t* privateData,
|
||||
size_t* scriptCountsMapArg);
|
||||
@ -822,12 +820,6 @@ 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 head of a list of incoming pointers from gray cells.
|
||||
@ -955,7 +947,6 @@ struct JSCompartment
|
||||
|
||||
void sweepCrossCompartmentWrappers();
|
||||
void sweepSavedStacks();
|
||||
void sweepTemplateLiteralMap();
|
||||
void sweepGlobalObject();
|
||||
void sweepSelfHostingScriptSource();
|
||||
void sweepJitCompartment(js::FreeOp* fop);
|
||||
@ -1001,16 +992,6 @@ 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::HandleArrayObject rawStrings,
|
||||
js::MutableHandleObject templateObj);
|
||||
|
||||
// Per above, but an entry must already exist in the template registry.
|
||||
JSObject* getExistingTemplateLiteralObject(js::ArrayObject* rawStrings);
|
||||
|
||||
void findOutgoingEdges(js::gc::ZoneComponentFinder& finder);
|
||||
|
||||
js::DtoaCache dtoaCache;
|
||||
|
@ -361,7 +361,6 @@ StatsCompartmentCallback(JSContext* cx, void* data, JSCompartment* compartment)
|
||||
&cStats.savedStacksSet,
|
||||
&cStats.varNamesSet,
|
||||
&cStats.nonSyntacticLexicalScopesTable,
|
||||
&cStats.templateLiteralMap,
|
||||
&cStats.jitCompartment,
|
||||
&cStats.privateData,
|
||||
&cStats.scriptCountsMap);
|
||||
|
@ -1,38 +0,0 @@
|
||||
/* -*- 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 "gc/Marking.h"
|
||||
#include "js/GCHashTable.h"
|
||||
#include "vm/JSObject.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
|
@ -1830,10 +1830,6 @@ 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.");
|
||||
|
Loading…
x
Reference in New Issue
Block a user