mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-28 19:37:32 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
8495414910
53 changed files with 351 additions and 1527 deletions
|
|
@ -4481,14 +4481,15 @@ nsBrowserAccess.prototype = {
|
|||
}
|
||||
|
||||
let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
|
||||
let referrer = aOpener ? makeURI(aOpener.location.href) : null;
|
||||
let openerWindow = (aContext & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener;
|
||||
|
||||
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
|
||||
triggeringPrincipal: triggeringPrincipal,
|
||||
referrerURI: referrer,
|
||||
referrerPolicy: referrerPolicy,
|
||||
fromExternal: isExternal,
|
||||
inBackground: loadInBackground});
|
||||
inBackground: loadInBackground,
|
||||
opener: openerWindow });
|
||||
let browser = win.gBrowser.getBrowserForTab(tab);
|
||||
|
||||
if (gPrefService.getBoolPref("browser.tabs.noWindowActivationOnExternal")) {
|
||||
|
|
|
|||
|
|
@ -1339,6 +1339,7 @@
|
|||
var aFromExternal;
|
||||
var aRelatedToCurrent;
|
||||
var aOriginPrincipal;
|
||||
var aOpener;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
|
@ -1353,6 +1354,7 @@
|
|||
aFromExternal = params.fromExternal;
|
||||
aRelatedToCurrent = params.relatedToCurrent;
|
||||
aOriginPrincipal = params.originPrincipal;
|
||||
aOpener = params.opener;
|
||||
}
|
||||
|
||||
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
|
||||
|
|
@ -1368,7 +1370,8 @@
|
|||
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
||||
fromExternal: aFromExternal,
|
||||
originPrincipal: aOriginPrincipal,
|
||||
relatedToCurrent: aRelatedToCurrent});
|
||||
relatedToCurrent: aRelatedToCurrent,
|
||||
opener: aOpener });
|
||||
if (!bgLoad)
|
||||
this.selectedTab = tab;
|
||||
|
||||
|
|
@ -1495,6 +1498,7 @@
|
|||
var aSkipAnimation;
|
||||
var aOriginPrincipal;
|
||||
var aSkipBackgroundNotify;
|
||||
var aOpener;
|
||||
if (arguments.length == 2 &&
|
||||
typeof arguments[1] == "object" &&
|
||||
!(arguments[1] instanceof Ci.nsIURI)) {
|
||||
|
|
@ -1510,6 +1514,7 @@
|
|||
aRelatedToCurrent = params.relatedToCurrent;
|
||||
aSkipAnimation = params.skipAnimation;
|
||||
aOriginPrincipal = params.originPrincipal;
|
||||
aOpener = params.opener;
|
||||
aSkipBackgroundNotify = params.skipBackgroundNotify;
|
||||
}
|
||||
|
||||
|
|
@ -1584,6 +1589,10 @@
|
|||
b.setAttribute("showresizer", "true");
|
||||
}
|
||||
|
||||
if (aOpener) {
|
||||
b.QueryInterface(Ci.nsIFrameLoaderOwner).presetOpenerWindow(aOpener);
|
||||
}
|
||||
|
||||
if (this.hasAttribute("autocompletepopup"))
|
||||
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
||||
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
|
||||
|
|
|
|||
|
|
@ -78,8 +78,21 @@ ContentClient::CreateContentClient(CompositableForwarder* aForwarder)
|
|||
// We can't use double buffering when using image content with
|
||||
// Xrender support on Linux, as ContentHostDoubleBuffered is not
|
||||
// suited for direct uploads to the server.
|
||||
// FIXME: Even though the comment above suggests that double buffering
|
||||
// is supposed to be disabled when Xrender support is being enabled
|
||||
// (and used), it really wasn't. Historically,
|
||||
// UseImageOffscreenSurfaces() was always false in GTK2 builds, thus
|
||||
// triggering the check, regardless of UseXRender().
|
||||
// Some time later, offscreen surfaces were always enabled, but the
|
||||
// Xrender functionality broke due to not using Xlib-based surfaces.
|
||||
// Using Xlib-based surfaces compatible with Xrender operations seems
|
||||
// to lead to weird graphical artifacts (bars and stripes) on some
|
||||
// hardware (Intel-based?) when displaying quickly-changing content,
|
||||
// so contrary to the statement above we'd better enable double
|
||||
// buffering - which also seems to not have any negative performance
|
||||
// impact.
|
||||
if (!gfxPlatformGtk::GetPlatform()->UseImageOffscreenSurfaces() ||
|
||||
!gfxVars::UseXRender())
|
||||
gfxVars::UseXRender())
|
||||
#endif
|
||||
{
|
||||
useDoubleBuffering = (LayerManagerComposite::SupportsDirectTexturing() &&
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "nsSMILAnimationController.h"
|
||||
#include "gfxContext.h"
|
||||
#include "harfbuzz/hb.h"
|
||||
#include "zlib.h"
|
||||
#include "mozilla/dom/ImageTracker.h"
|
||||
|
||||
#define SVG_CONTENT_TYPE NS_LITERAL_CSTRING("image/svg+xml")
|
||||
|
|
@ -285,7 +286,44 @@ gfxSVGGlyphsDocument::gfxSVGGlyphsDocument(const uint8_t *aBuffer,
|
|||
gfxSVGGlyphs *aSVGGlyphs)
|
||||
: mOwner(aSVGGlyphs)
|
||||
{
|
||||
if (aBufLen >= 14 && aBuffer[0] == 31 && aBuffer[1] == 139) {
|
||||
// It's a gzip-compressed document; decompress it before parsing.
|
||||
// The original length (modulo 2^32) is found in the last 4 bytes
|
||||
// of the data, stored in little-endian format. We read it as
|
||||
// individual bytes to avoid possible alignment issues.
|
||||
// (Note that if the original length was >2^32, then origLen here
|
||||
// will be incorrect; but then the inflate() call will not return
|
||||
// Z_STREAM_END and we'll bail out safely.)
|
||||
size_t origLen = (size_t(aBuffer[aBufLen - 1]) << 24) +
|
||||
(size_t(aBuffer[aBufLen - 2]) << 16) +
|
||||
(size_t(aBuffer[aBufLen - 3]) << 8) +
|
||||
size_t(aBuffer[aBufLen - 4]);
|
||||
AutoTArray<uint8_t, 4096> outBuf;
|
||||
if (outBuf.SetLength(origLen, mozilla::fallible)) {
|
||||
z_stream s = {0};
|
||||
s.next_in = const_cast<Byte*>(aBuffer);
|
||||
s.avail_in = aBufLen;
|
||||
s.next_out = outBuf.Elements();
|
||||
s.avail_out = outBuf.Length();
|
||||
// The magic number 16 here is the zlib flag to expect gzip format,
|
||||
// see http://www.zlib.net/manual.html#Advanced
|
||||
if (Z_OK == inflateInit2(&s, 16 + MAX_WBITS)) {
|
||||
int result = inflate(&s, Z_FINISH);
|
||||
if (Z_STREAM_END == result) {
|
||||
MOZ_ASSERT(size_t(s.next_out - outBuf.Elements()) == origLen);
|
||||
ParseDocument(outBuf.Elements(), outBuf.Length());
|
||||
} else {
|
||||
NS_WARNING("Failed to decompress SVG glyphs document");
|
||||
}
|
||||
inflateEnd(&s);
|
||||
}
|
||||
} else {
|
||||
NS_WARNING("Failed to allocate memory for SVG glyphs document");
|
||||
}
|
||||
} else {
|
||||
ParseDocument(aBuffer, aBufLen);
|
||||
}
|
||||
|
||||
if (!mDocument) {
|
||||
NS_WARNING("Could not parse SVG glyphs document");
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1073,6 +1073,114 @@ function ArrayConcat(arg1) {
|
|||
return A;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/proposal-flatMap/
|
||||
// January 4, 2019
|
||||
function ArrayFlatMap(mapperFunction/*, thisArg*/) {
|
||||
// Step 1.
|
||||
var O = ToObject(this);
|
||||
|
||||
// Step 2.
|
||||
var sourceLen = ToLength(O.length);
|
||||
|
||||
// Step 3.
|
||||
if (!IsCallable(mapperFunction))
|
||||
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction));
|
||||
|
||||
// Step 4.
|
||||
var T = arguments.length > 1 ? arguments[1] : undefined;
|
||||
|
||||
// Step 5.
|
||||
var A = ArraySpeciesCreate(O, 0);
|
||||
|
||||
// Step 6.
|
||||
FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T);
|
||||
|
||||
// Step 7.
|
||||
return A;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/proposal-flatMap/
|
||||
// January 4, 2019
|
||||
function ArrayFlat(/* depth */) {
|
||||
// Step 1.
|
||||
var O = ToObject(this);
|
||||
|
||||
// Step 2.
|
||||
var sourceLen = ToLength(O.length);
|
||||
|
||||
// Step 3.
|
||||
var depthNum = 1;
|
||||
|
||||
// Step 4.
|
||||
if (arguments.length > 0 && arguments[0] !== undefined)
|
||||
depthNum = ToInteger(arguments[0]);
|
||||
|
||||
// Step 5.
|
||||
var A = ArraySpeciesCreate(O, 0);
|
||||
|
||||
// Step 6.
|
||||
FlattenIntoArray(A, O, sourceLen, 0, depthNum);
|
||||
|
||||
// Step 7.
|
||||
return A;
|
||||
}
|
||||
|
||||
// https://tc39.github.io/proposal-flatMap/
|
||||
// January 4, 2019
|
||||
function FlattenIntoArray(target, source, sourceLen, start, depth, mapperFunction, thisArg) {
|
||||
// Step 1.
|
||||
var targetIndex = start;
|
||||
|
||||
// Steps 2-3.
|
||||
for (var sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
|
||||
// Steps 3.a-c.
|
||||
if (sourceIndex in source) {
|
||||
// Step 3.c.i.
|
||||
var element = source[sourceIndex];
|
||||
|
||||
if (mapperFunction) {
|
||||
// Step 3.c.ii.1.
|
||||
assert(arguments.length === 7, "thisArg is present");
|
||||
|
||||
// Step 3.c.ii.2.
|
||||
element = callContentFunction(mapperFunction, thisArg, element, sourceIndex, source);
|
||||
}
|
||||
|
||||
// Step 3.c.iii.
|
||||
var shouldFlatten = false;
|
||||
|
||||
// Step 3.c.iv.
|
||||
if (depth > 0) {
|
||||
// Step 3.c.iv.1.
|
||||
shouldFlatten = IsArray(element);
|
||||
}
|
||||
|
||||
// Step 3.c.v.
|
||||
if (shouldFlatten) {
|
||||
// Step 3.c.v.1.
|
||||
var elementLen = ToLength(element.length);
|
||||
|
||||
// Step 3.c.v.2.
|
||||
// Recursive call to walk the depth.
|
||||
targetIndex = FlattenIntoArray(target, element, elementLen, targetIndex, depth - 1);
|
||||
} else {
|
||||
// Step 3.c.vi.1.
|
||||
if (targetIndex >= MAX_NUMERIC_INDEX)
|
||||
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
|
||||
|
||||
// Step 3.c.vi.2.
|
||||
_DefineDataProperty(target, targetIndex, element);
|
||||
|
||||
// Step 3.c.vi.3.
|
||||
targetIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
return targetIndex;
|
||||
}
|
||||
|
||||
function ArrayStaticConcat(arr, arg1) {
|
||||
if (arguments.length < 1)
|
||||
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ SymbolObject::create(JSContext* cx, JS::HandleSymbol symbol)
|
|||
}
|
||||
|
||||
const JSPropertySpec SymbolObject::properties[] = {
|
||||
JS_PSG("description", descriptionGetter, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
|
||||
|
|
@ -227,6 +228,34 @@ SymbolObject::toPrimitive(JSContext* cx, unsigned argc, Value* vp)
|
|||
return CallNonGenericMethod<IsSymbol, valueOf_impl>(cx, args);
|
||||
}
|
||||
|
||||
// ES2019 Stage 4 Draft / November 28, 2018
|
||||
// Symbol description accessor
|
||||
// See: https://tc39.github.io/proposal-Symbol-description/
|
||||
bool
|
||||
SymbolObject::descriptionGetter_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
// Get symbol object pointer.
|
||||
HandleValue thisv = args.thisv();
|
||||
MOZ_ASSERT(IsSymbol(thisv));
|
||||
Rooted<Symbol*> sym(cx, thisv.isSymbol()
|
||||
? thisv.toSymbol()
|
||||
: thisv.toObject().as<SymbolObject>().unbox());
|
||||
|
||||
// Return the symbol's description if present, otherwise return undefined.
|
||||
if (JSString* str = sym->description())
|
||||
args.rval().setString(str);
|
||||
else
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SymbolObject::descriptionGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
return CallNonGenericMethod<IsSymbol, descriptionGetter_impl>(cx, args);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::InitSymbolClass(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -52,6 +52,10 @@ class SymbolObject : public NativeObject
|
|||
static MOZ_MUST_USE bool valueOf(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool toPrimitive(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// Properties defined on Symbol.prototype.
|
||||
static MOZ_MUST_USE bool descriptionGetter_impl(JSContext* cx, const CallArgs& args);
|
||||
static MOZ_MUST_USE bool descriptionGetter(JSContext* cx, unsigned argc, Value *vp);
|
||||
|
||||
static const JSPropertySpec properties[];
|
||||
static const JSFunctionSpec methods[];
|
||||
static const JSFunctionSpec staticMethods[];
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "builtin/ModuleObject.h"
|
||||
#include "gc/GCInternals.h"
|
||||
#include "gc/Policy.h"
|
||||
#include "gc/StoreBuffer-inl.h"
|
||||
#include "jit/IonCode.h"
|
||||
#include "js/SliceBudget.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include "vm/Shape.h"
|
||||
#include "vm/Symbol.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
#include "wasm/WasmJS.h"
|
||||
|
||||
#include "jscompartmentinlines.h"
|
||||
|
|
@ -37,7 +37,6 @@
|
|||
|
||||
#include "gc/Nursery-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
|
@ -1395,14 +1394,6 @@ js::ObjectGroup::traceChildren(JSTracer* trc)
|
|||
if (maybePreliminaryObjects())
|
||||
maybePreliminaryObjects()->trace(trc);
|
||||
|
||||
if (maybeUnboxedLayout())
|
||||
unboxedLayout().trace(trc);
|
||||
|
||||
if (ObjectGroup* unboxedGroup = maybeOriginalUnboxedGroup()) {
|
||||
TraceManuallyBarrieredEdge(trc, &unboxedGroup, "group_original_unboxed_group");
|
||||
setOriginalUnboxedGroup(unboxedGroup);
|
||||
}
|
||||
|
||||
if (JSObject* descr = maybeTypeDescr()) {
|
||||
TraceManuallyBarrieredEdge(trc, &descr, "group_type_descr");
|
||||
setTypeDescr(&descr->as<TypeDescr>());
|
||||
|
|
@ -1436,12 +1427,6 @@ js::GCMarker::lazilyMarkChildren(ObjectGroup* group)
|
|||
if (group->maybePreliminaryObjects())
|
||||
group->maybePreliminaryObjects()->trace(this);
|
||||
|
||||
if (group->maybeUnboxedLayout())
|
||||
group->unboxedLayout().trace(this);
|
||||
|
||||
if (ObjectGroup* unboxedGroup = group->maybeOriginalUnboxedGroup())
|
||||
traverseEdge(group, unboxedGroup);
|
||||
|
||||
if (TypeDescr* descr = group->maybeTypeDescr())
|
||||
traverseEdge(group, static_cast<JSObject*>(descr));
|
||||
|
||||
|
|
@ -1484,23 +1469,6 @@ CallTraceHook(Functor f, JSTracer* trc, JSObject* obj, CheckGeneration check, Ar
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (clasp == &UnboxedPlainObject::class_) {
|
||||
JSObject** pexpando = obj->as<UnboxedPlainObject>().addressOfExpando();
|
||||
if (*pexpando)
|
||||
f(pexpando, mozilla::Forward<Args>(args)...);
|
||||
|
||||
UnboxedPlainObject& unboxed = obj->as<UnboxedPlainObject>();
|
||||
const UnboxedLayout& layout = check == CheckGeneration::DoChecks
|
||||
? unboxed.layout()
|
||||
: unboxed.layoutDontCheckGeneration();
|
||||
if (layout.traceList()) {
|
||||
VisitTraceList(f, layout.traceList(), unboxed.data(),
|
||||
mozilla::Forward<Args>(args)...);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
clasp->doTrace(trc, obj);
|
||||
|
||||
if (!clasp->isNative())
|
||||
|
|
@ -2293,18 +2261,6 @@ static inline void
|
|||
TraceWholeCell(TenuringTracer& mover, JSObject* object)
|
||||
{
|
||||
mover.traceObject(object);
|
||||
|
||||
// Additionally trace the expando object attached to any unboxed plain
|
||||
// objects. Baseline and Ion can write properties to the expando while
|
||||
// only adding a post barrier to the owning unboxed object. Note that
|
||||
// it isn't possible for a nursery unboxed object to have a tenured
|
||||
// expando, so that adding a post barrier on the original object will
|
||||
// capture any tenured->nursery edges in the expando as well.
|
||||
|
||||
if (object->is<UnboxedPlainObject>()) {
|
||||
if (UnboxedExpandoObject* expando = object->as<UnboxedPlainObject>().maybeExpando())
|
||||
expando->traceChildren(&mover);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
|
|||
|
|
@ -201,80 +201,15 @@ gc::TraceCycleCollectorChildren(JS::CallbackTracer* trc, Shape* shape)
|
|||
} while (shape);
|
||||
}
|
||||
|
||||
// Object groups can point to other object groups via an UnboxedLayout or the
|
||||
// the original unboxed group link. There can potentially be deep or cyclic
|
||||
// chains of such groups to trace through without going through a thing that
|
||||
// participates in cycle collection. These need to be handled iteratively to
|
||||
// avoid blowing the stack when running the cycle collector's callback tracer.
|
||||
struct ObjectGroupCycleCollectorTracer : public JS::CallbackTracer
|
||||
{
|
||||
explicit ObjectGroupCycleCollectorTracer(JS::CallbackTracer* innerTracer)
|
||||
: JS::CallbackTracer(innerTracer->runtime(), DoNotTraceWeakMaps),
|
||||
innerTracer(innerTracer)
|
||||
{}
|
||||
|
||||
void onChild(const JS::GCCellPtr& thing) override;
|
||||
|
||||
JS::CallbackTracer* innerTracer;
|
||||
Vector<ObjectGroup*, 4, SystemAllocPolicy> seen, worklist;
|
||||
};
|
||||
|
||||
void
|
||||
ObjectGroupCycleCollectorTracer::onChild(const JS::GCCellPtr& thing)
|
||||
{
|
||||
if (thing.is<BaseShape>()) {
|
||||
// The CC does not care about BaseShapes, and no additional GC things
|
||||
// will be reached by following this edge.
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing.is<JSObject>() || thing.is<JSScript>()) {
|
||||
// Invoke the inner cycle collector callback on this child. It will not
|
||||
// recurse back into TraceChildren.
|
||||
innerTracer->onChild(thing);
|
||||
return;
|
||||
}
|
||||
|
||||
if (thing.is<ObjectGroup>()) {
|
||||
// If this group is required to be in an ObjectGroup chain, trace it
|
||||
// via the provided worklist rather than continuing to recurse.
|
||||
ObjectGroup& group = thing.as<ObjectGroup>();
|
||||
if (group.maybeUnboxedLayout()) {
|
||||
for (size_t i = 0; i < seen.length(); i++) {
|
||||
if (seen[i] == &group)
|
||||
return;
|
||||
}
|
||||
if (seen.append(&group) && worklist.append(&group)) {
|
||||
return;
|
||||
} else {
|
||||
// If append fails, keep tracing normally. The worst that will
|
||||
// happen is we end up overrecursing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TraceChildren(this, thing.asCell(), thing.kind());
|
||||
}
|
||||
|
||||
void
|
||||
gc::TraceCycleCollectorChildren(JS::CallbackTracer* trc, ObjectGroup* group)
|
||||
{
|
||||
MOZ_ASSERT(trc->isCallbackTracer());
|
||||
|
||||
// Early return if this group is not required to be in an ObjectGroup chain.
|
||||
if (!group->maybeUnboxedLayout())
|
||||
return group->traceChildren(trc);
|
||||
|
||||
ObjectGroupCycleCollectorTracer groupTracer(trc->asCallbackTracer());
|
||||
group->traceChildren(&groupTracer);
|
||||
|
||||
while (!groupTracer.worklist.empty()) {
|
||||
ObjectGroup* innerGroup = groupTracer.worklist.popCopy();
|
||||
innerGroup->traceChildren(&groupTracer);
|
||||
}
|
||||
group->traceChildren(trc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*** Traced Edge Printer *************************************************************************/
|
||||
|
||||
static size_t
|
||||
|
|
|
|||
|
|
@ -114,8 +114,6 @@ GetObject(const MDefinition* ins)
|
|||
case MDefinition::Op_GuardObjectGroup:
|
||||
case MDefinition::Op_GuardObjectIdentity:
|
||||
case MDefinition::Op_GuardClass:
|
||||
case MDefinition::Op_GuardUnboxedExpando:
|
||||
case MDefinition::Op_LoadUnboxedExpando:
|
||||
case MDefinition::Op_LoadSlot:
|
||||
case MDefinition::Op_StoreSlot:
|
||||
case MDefinition::Op_InArray:
|
||||
|
|
|
|||
|
|
@ -96,13 +96,8 @@ VectorAppendNoDuplicate(S& list, T value)
|
|||
|
||||
static bool
|
||||
AddReceiver(const ReceiverGuard& receiver,
|
||||
BaselineInspector::ReceiverVector& receivers,
|
||||
BaselineInspector::ObjectGroupVector& convertUnboxedGroups)
|
||||
BaselineInspector::ReceiverVector& receivers)
|
||||
{
|
||||
if (receiver.group && receiver.group->maybeUnboxedLayout()) {
|
||||
if (receiver.group->unboxedLayout().nativeGroup())
|
||||
return VectorAppendNoDuplicate(convertUnboxedGroups, receiver.group);
|
||||
}
|
||||
return VectorAppendNoDuplicate(receivers, receiver);
|
||||
}
|
||||
|
||||
|
|
@ -170,16 +165,12 @@ GetCacheIRReceiverForUnboxedProperty(ICCacheIR_Monitored* stub, ReceiverGuard* r
|
|||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups)
|
||||
BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers)
|
||||
{
|
||||
// Return a list of the receivers seen by the baseline IC for the current
|
||||
// op. Empty lists indicate no receivers are known, or there was an
|
||||
// uncacheable access. convertUnboxedGroups is used for unboxed object
|
||||
// groups which have been seen, but have had instances converted to native
|
||||
// objects and should be eagerly converted by Ion.
|
||||
// uncacheable access.
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
MOZ_ASSERT(convertUnboxedGroups.empty());
|
||||
|
||||
if (!hasBaselineScript())
|
||||
return true;
|
||||
|
|
@ -207,7 +198,7 @@ BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receiv
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!AddReceiver(receiver, receivers, convertUnboxedGroups))
|
||||
if (!AddReceiver(receiver, receivers))
|
||||
return false;
|
||||
|
||||
stub = stub->next();
|
||||
|
|
@ -700,14 +691,12 @@ bool
|
|||
BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonGetter, Shape** globalShape,
|
||||
bool* isOwnProperty,
|
||||
ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups)
|
||||
ReceiverVector& receivers)
|
||||
{
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
MOZ_ASSERT(convertUnboxedGroups.empty());
|
||||
|
||||
*holder = nullptr;
|
||||
const ICEntry& entry = icEntryFromPC(pc);
|
||||
|
|
@ -719,7 +708,7 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
|||
{
|
||||
ICGetPropCallGetter* nstub = static_cast<ICGetPropCallGetter*>(stub);
|
||||
bool isOwn = nstub->isOwnGetter();
|
||||
if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers, convertUnboxedGroups))
|
||||
if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers))
|
||||
return false;
|
||||
|
||||
if (!*holder) {
|
||||
|
|
@ -751,21 +740,19 @@ BaselineInspector::commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
|||
if (!*holder)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(*isOwnProperty == (receivers.empty() && convertUnboxedGroups.empty()));
|
||||
MOZ_ASSERT(*isOwnProperty == (receivers.empty()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonSetter, bool* isOwnProperty,
|
||||
ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups)
|
||||
ReceiverVector& receivers)
|
||||
{
|
||||
if (!hasBaselineScript())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
MOZ_ASSERT(convertUnboxedGroups.empty());
|
||||
|
||||
*holder = nullptr;
|
||||
const ICEntry& entry = icEntryFromPC(pc);
|
||||
|
|
@ -774,7 +761,7 @@ BaselineInspector::commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shap
|
|||
if (stub->isSetProp_CallScripted() || stub->isSetProp_CallNative()) {
|
||||
ICSetPropCallSetter* nstub = static_cast<ICSetPropCallSetter*>(stub);
|
||||
bool isOwn = nstub->isOwnSetter();
|
||||
if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers, convertUnboxedGroups))
|
||||
if (!isOwn && !AddReceiver(nstub->receiverGuard(), receivers))
|
||||
return false;
|
||||
|
||||
if (!*holder) {
|
||||
|
|
|
|||
|
|
@ -95,8 +95,7 @@ class BaselineInspector
|
|||
public:
|
||||
typedef Vector<ReceiverGuard, 4, JitAllocPolicy> ReceiverVector;
|
||||
typedef Vector<ObjectGroup*, 4, JitAllocPolicy> ObjectGroupVector;
|
||||
MOZ_MUST_USE bool maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups);
|
||||
MOZ_MUST_USE bool maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers);
|
||||
|
||||
SetElemICInspector setElemICInspector(jsbytecode* pc) {
|
||||
return makeICInspector<SetElemICInspector>(pc, ICStub::SetElem_Fallback);
|
||||
|
|
@ -131,12 +130,10 @@ class BaselineInspector
|
|||
|
||||
MOZ_MUST_USE bool commonGetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonGetter, Shape** globalShape,
|
||||
bool* isOwnProperty, ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups);
|
||||
bool* isOwnProperty, ReceiverVector& receivers);
|
||||
MOZ_MUST_USE bool commonSetPropFunction(jsbytecode* pc, JSObject** holder, Shape** holderShape,
|
||||
JSFunction** commonSetter, bool* isOwnProperty,
|
||||
ReceiverVector& receivers,
|
||||
ObjectGroupVector& convertUnboxedGroups);
|
||||
ReceiverVector& receivers);
|
||||
|
||||
MOZ_MUST_USE bool instanceOfData(jsbytecode* pc, Shape** shape, uint32_t* slot,
|
||||
JSObject** prototypeObject);
|
||||
|
|
|
|||
|
|
@ -3031,15 +3031,6 @@ GuardReceiver(MacroAssembler& masm, const ReceiverGuard& guard,
|
|||
{
|
||||
if (guard.group) {
|
||||
masm.branchTestObjGroup(Assembler::NotEqual, obj, guard.group, miss);
|
||||
|
||||
Address expandoAddress(obj, UnboxedPlainObject::offsetOfExpando());
|
||||
if (guard.shape) {
|
||||
masm.loadPtr(expandoAddress, scratch);
|
||||
masm.branchPtr(Assembler::Equal, scratch, ImmWord(0), miss);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, scratch, guard.shape, miss);
|
||||
} else if (checkNullExpando) {
|
||||
masm.branchPtr(Assembler::NotEqual, expandoAddress, ImmWord(0), miss);
|
||||
}
|
||||
} else {
|
||||
masm.branchTestObjShape(Assembler::NotEqual, obj, guard.shape, miss);
|
||||
}
|
||||
|
|
@ -3077,13 +3068,6 @@ CodeGenerator::emitGetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
|
|||
masm.loadPtr(Address(target, NativeObject::offsetOfSlots()), scratch);
|
||||
masm.loadTypedOrValue(Address(scratch, offset), output);
|
||||
}
|
||||
} else {
|
||||
masm.comment("loadUnboxedProperty");
|
||||
const UnboxedLayout::Property* property =
|
||||
receiver.group->unboxedLayout().lookup(mir->name());
|
||||
Address propertyAddr(obj, UnboxedPlainObject::offsetOfData() + property->offset);
|
||||
|
||||
masm.loadUnboxedProperty(propertyAddr, property->type, output);
|
||||
}
|
||||
|
||||
if (i == mir->numReceivers() - 1) {
|
||||
|
|
@ -3124,8 +3108,6 @@ EmitUnboxedPreBarrier(MacroAssembler &masm, T address, JSValueType type)
|
|||
masm.patchableCallPreBarrier(address, MIRType::Object);
|
||||
else if (type == JSVAL_TYPE_STRING)
|
||||
masm.patchableCallPreBarrier(address, MIRType::String);
|
||||
else
|
||||
MOZ_ASSERT(!UnboxedTypeNeedsPreBarrier(type));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3161,13 +3143,6 @@ CodeGenerator::emitSetPropertyPolymorphic(LInstruction* ins, Register obj, Regis
|
|||
emitPreBarrier(addr);
|
||||
masm.storeConstantOrRegister(value, addr);
|
||||
}
|
||||
} else {
|
||||
const UnboxedLayout::Property* property =
|
||||
receiver.group->unboxedLayout().lookup(mir->name());
|
||||
Address propertyAddr(obj, UnboxedPlainObject::offsetOfData() + property->offset);
|
||||
|
||||
EmitUnboxedPreBarrier(masm, propertyAddr, property->type);
|
||||
masm.storeUnboxedProperty(propertyAddr, property->type, value, nullptr);
|
||||
}
|
||||
|
||||
if (i == mir->numReceivers() - 1) {
|
||||
|
|
@ -3332,27 +3307,6 @@ CodeGenerator::visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir)
|
|||
masm.bind(&done);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitGuardUnboxedExpando(LGuardUnboxedExpando* lir)
|
||||
{
|
||||
Label miss;
|
||||
|
||||
Register obj = ToRegister(lir->object());
|
||||
masm.branchPtr(lir->mir()->requireExpando() ? Assembler::Equal : Assembler::NotEqual,
|
||||
Address(obj, UnboxedPlainObject::offsetOfExpando()), ImmWord(0), &miss);
|
||||
|
||||
bailoutFrom(&miss, lir->snapshot());
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitLoadUnboxedExpando(LLoadUnboxedExpando* lir)
|
||||
{
|
||||
Register obj = ToRegister(lir->object());
|
||||
Register result = ToRegister(lir->getDef(0));
|
||||
|
||||
masm.loadPtr(Address(obj, UnboxedPlainObject::offsetOfExpando()), result);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitTypeBarrierV(LTypeBarrierV* lir)
|
||||
{
|
||||
|
|
@ -8576,21 +8530,6 @@ static const VMFunction ConvertUnboxedArrayObjectToNativeInfo =
|
|||
FunctionInfo<ConvertUnboxedObjectToNativeFn>(UnboxedArrayObject::convertToNative,
|
||||
"UnboxedArrayObject::convertToNative");
|
||||
|
||||
void
|
||||
CodeGenerator::visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir)
|
||||
{
|
||||
Register object = ToRegister(lir->getOperand(0));
|
||||
|
||||
OutOfLineCode* ool = oolCallVM(lir->mir()->group()->unboxedLayoutDontCheckGeneration().isArray()
|
||||
? ConvertUnboxedArrayObjectToNativeInfo
|
||||
: ConvertUnboxedPlainObjectToNativeInfo,
|
||||
lir, ArgList(object), StoreNothing());
|
||||
|
||||
masm.branchPtr(Assembler::Equal, Address(object, JSObject::offsetOfGroup()),
|
||||
ImmGCPtr(lir->mir()->group()), ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
typedef bool (*ArrayPopShiftFn)(JSContext*, HandleObject, MutableHandleValue);
|
||||
static const VMFunction ArrayPopDenseInfo =
|
||||
FunctionInfo<ArrayPopShiftFn>(jit::ArrayPopDense, "ArrayPopDense");
|
||||
|
|
|
|||
|
|
@ -148,8 +148,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir);
|
||||
void visitGuardObjectIdentity(LGuardObjectIdentity* guard);
|
||||
void visitGuardReceiverPolymorphic(LGuardReceiverPolymorphic* lir);
|
||||
void visitGuardUnboxedExpando(LGuardUnboxedExpando* lir);
|
||||
void visitLoadUnboxedExpando(LLoadUnboxedExpando* lir);
|
||||
void visitTypeBarrierV(LTypeBarrierV* lir);
|
||||
void visitTypeBarrierO(LTypeBarrierO* lir);
|
||||
void visitMonitorTypes(LMonitorTypes* lir);
|
||||
|
|
@ -310,7 +308,6 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitFallibleStoreElementV(LFallibleStoreElementV* lir);
|
||||
void visitFallibleStoreElementT(LFallibleStoreElementT* lir);
|
||||
void visitStoreUnboxedPointer(LStoreUnboxedPointer* lir);
|
||||
void visitConvertUnboxedObjectToNative(LConvertUnboxedObjectToNative* lir);
|
||||
void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj,
|
||||
Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
|
||||
void visitArrayPopShiftV(LArrayPopShiftV* lir);
|
||||
|
|
|
|||
|
|
@ -3515,8 +3515,6 @@ PassthroughOperand(MDefinition* def)
|
|||
return def->toConvertElementsToDoubles()->elements();
|
||||
if (def->isMaybeCopyElementsForWrite())
|
||||
return def->toMaybeCopyElementsForWrite()->object();
|
||||
if (def->isConvertUnboxedObjectToNative())
|
||||
return def->toConvertUnboxedObjectToNative()->object();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
#include "vm/EnvironmentObject-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/ObjectGroup-inl.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
|
@ -6392,7 +6391,7 @@ IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
|
|||
JSObject* templateObject = inspector->getTemplateObject(pc);
|
||||
if (!templateObject)
|
||||
return nullptr;
|
||||
if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
|
||||
if (!templateObject->is<PlainObject>())
|
||||
return nullptr;
|
||||
if (templateObject->staticPrototype() != proto)
|
||||
return nullptr;
|
||||
|
|
@ -6429,7 +6428,7 @@ IonBuilder::createThisScriptedBaseline(MDefinition* callee)
|
|||
JSObject* templateObject = inspector->getTemplateObject(pc);
|
||||
if (!templateObject)
|
||||
return nullptr;
|
||||
if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
|
||||
if (!templateObject->is<PlainObject>())
|
||||
return nullptr;
|
||||
|
||||
Shape* shape = target->lookupPure(compartment->runtime()->names().prototype);
|
||||
|
|
@ -7718,8 +7717,6 @@ IonBuilder::jsop_initprop(PropertyName* name)
|
|||
if (templateObject->is<PlainObject>()) {
|
||||
if (!templateObject->as<PlainObject>().containsPure(name))
|
||||
useSlowPath = true;
|
||||
} else {
|
||||
MOZ_ASSERT(templateObject->as<UnboxedPlainObject>().layout().lookup(name));
|
||||
}
|
||||
} else {
|
||||
useSlowPath = true;
|
||||
|
|
@ -8178,8 +8175,7 @@ IonBuilder::maybeMarkEmpty(MDefinition* ins)
|
|||
static bool
|
||||
ClassHasEffectlessLookup(const Class* clasp)
|
||||
{
|
||||
return (clasp == &UnboxedPlainObject::class_) ||
|
||||
(clasp == &UnboxedArrayObject::class_) ||
|
||||
return (clasp == &UnboxedArrayObject::class_) ||
|
||||
IsTypedObjectClass(clasp) ||
|
||||
(clasp->isNative() && !clasp->getOpsLookupProperty());
|
||||
}
|
||||
|
|
@ -9012,8 +9008,6 @@ IonBuilder::jsop_getelem()
|
|||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType::Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
bool emitted = false;
|
||||
|
||||
|
|
@ -10137,7 +10131,7 @@ IonBuilder::jsop_setelem()
|
|||
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* index = current->pop();
|
||||
MDefinition* object = convertUnboxedObjects(current->pop());
|
||||
MDefinition* object = current->pop();
|
||||
|
||||
trackTypeInfo(TrackedTypeSite::Receiver, object->type(), object->resultTypeSet());
|
||||
trackTypeInfo(TrackedTypeSite::Index, index->type(), index->resultTypeSet());
|
||||
|
|
@ -10972,11 +10966,8 @@ IonBuilder::getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_
|
|||
}
|
||||
|
||||
// Definite slots will always be fixed slots when they are in the
|
||||
// allowable range for fixed slots, except for objects which were
|
||||
// converted from unboxed objects and have a smaller allocation size.
|
||||
// allowable range for fixed slots.
|
||||
size_t nfixed = NativeObject::MAX_FIXED_SLOTS;
|
||||
if (ObjectGroup* group = key->group()->maybeOriginalUnboxedGroup())
|
||||
nfixed = gc::GetGCKindSlots(group->unboxedLayout().getAllocKind());
|
||||
|
||||
uint32_t propertySlot = property.maybeTypes()->definiteSlot();
|
||||
if (slot == UINT32_MAX) {
|
||||
|
|
@ -11033,8 +11024,6 @@ IonBuilder::getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name, JSValu
|
|||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
key->watchStateChangeForUnboxedConvertedToNative(constraints());
|
||||
|
||||
if (offset == UINT32_MAX) {
|
||||
offset = property->offset;
|
||||
*punboxedType = property->type;
|
||||
|
|
@ -11496,8 +11485,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
|||
}
|
||||
|
||||
obj = maybeUnboxForPropertyAccess(obj);
|
||||
if (obj->type() == MIRType::Object)
|
||||
obj = convertUnboxedObjects(obj);
|
||||
|
||||
BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
|
||||
obj, name, types);
|
||||
|
|
@ -11569,11 +11556,6 @@ IonBuilder::jsop_getprop(PropertyName* name)
|
|||
if (!getPropTryDefiniteSlot(&emitted, obj, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to emit loads from unboxed objects.
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_Unboxed);
|
||||
if (!getPropTryUnboxed(&emitted, obj, name, barrier, types) || emitted)
|
||||
return emitted;
|
||||
|
||||
// Try to inline a common property getter, or make a call.
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_CommonGetter);
|
||||
if (!getPropTryCommonGetter(&emitted, obj, name, types) || emitted)
|
||||
|
|
@ -11939,49 +11921,6 @@ IonBuilder::getPropTryComplexPropOfTypedObject(bool* emitted,
|
|||
fieldPrediction, fieldTypeObj);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj)
|
||||
{
|
||||
// If obj might be in any particular unboxed group which should be
|
||||
// converted to a native representation, perform that conversion. This does
|
||||
// not guarantee the object will not have such a group afterwards, if the
|
||||
// object's possible groups are not precisely known.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject() || !types->objectOrSentinel())
|
||||
return obj;
|
||||
|
||||
BaselineInspector::ObjectGroupVector list(alloc());
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = obj->resultTypeSet()->getObject(i);
|
||||
if (!key || !key->isGroup())
|
||||
continue;
|
||||
|
||||
if (UnboxedLayout* layout = key->group()->maybeUnboxedLayout()) {
|
||||
AutoEnterOOMUnsafeRegion oomUnsafe;
|
||||
if (layout->nativeGroup() && !list.append(key->group()))
|
||||
oomUnsafe.crash("IonBuilder::convertUnboxedObjects");
|
||||
}
|
||||
}
|
||||
|
||||
return convertUnboxedObjects(obj, list);
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list)
|
||||
{
|
||||
for (size_t i = 0; i < list.length(); i++) {
|
||||
ObjectGroup* group = list[i];
|
||||
if (TemporaryTypeSet* types = obj->resultTypeSet()) {
|
||||
if (!types->hasType(TypeSet::ObjectType(group)))
|
||||
continue;
|
||||
}
|
||||
obj = MConvertUnboxedObjectToNative::New(alloc(), obj, group);
|
||||
current->add(obj->toInstruction());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryDefiniteSlot(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
BarrierKind barrier, TemporaryTypeSet* types)
|
||||
|
|
@ -12132,45 +12071,14 @@ IonBuilder::loadUnboxedValue(MDefinition* elements, size_t elementsOffset,
|
|||
return load;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
BarrierKind barrier, TemporaryTypeSet* types)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
JSValueType unboxedType;
|
||||
uint32_t offset = getUnboxedOffset(obj->resultTypeSet(), name, &unboxedType);
|
||||
if (offset == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
if (obj->type() != MIRType::Object) {
|
||||
MGuardObject* guard = MGuardObject::New(alloc(), obj);
|
||||
current->add(guard);
|
||||
obj = guard;
|
||||
}
|
||||
|
||||
MInstruction* load = loadUnboxedProperty(obj, offset, unboxedType, barrier, types);
|
||||
current->push(load);
|
||||
|
||||
if (!pushTypeBarrier(load, types, barrier))
|
||||
return false;
|
||||
|
||||
trackOptimizationSuccess();
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition*
|
||||
IonBuilder::addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
|
||||
const BaselineInspector::ReceiverVector& receivers,
|
||||
const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
|
||||
bool isOwnProperty)
|
||||
{
|
||||
MOZ_ASSERT(holder);
|
||||
MOZ_ASSERT(holderShape);
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
if (isOwnProperty) {
|
||||
MOZ_ASSERT(receivers.empty());
|
||||
return addShapeGuard(obj, holderShape, Bailout_ShapeGuard);
|
||||
|
|
@ -12194,10 +12102,8 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
|||
JSObject* foundProto = nullptr;
|
||||
bool isOwnProperty = false;
|
||||
BaselineInspector::ReceiverVector receivers(alloc());
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
if (!inspector->commonGetPropFunction(pc, &foundProto, &lastProperty, &commonGetter,
|
||||
&globalShape, &isOwnProperty,
|
||||
receivers, convertUnboxedGroups))
|
||||
&globalShape, &isOwnProperty, receivers))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -12213,8 +12119,7 @@ IonBuilder::getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName
|
|||
// If type information is bad, we can still optimize the getter if we
|
||||
// shape guard.
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
|
||||
receivers, convertUnboxedGroups,
|
||||
isOwnProperty);
|
||||
receivers, isOwnProperty);
|
||||
if (!obj)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -12381,15 +12286,12 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
|
|||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
BaselineInspector::ReceiverVector receivers(alloc());
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
if (!inspector->maybeInfoForPropertyOp(pc, receivers, convertUnboxedGroups))
|
||||
if (!inspector->maybeInfoForPropertyOp(pc, receivers))
|
||||
return false;
|
||||
|
||||
if (!canInlinePropertyOpShapes(receivers))
|
||||
return true;
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
MIRType rvalType = types->getKnownMIRType();
|
||||
if (barrier != BarrierKind::NoBarrier || IsNullOrUndefined(rvalType))
|
||||
rvalType = MIRType::Value;
|
||||
|
|
@ -12412,45 +12314,6 @@ IonBuilder::getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName
|
|||
return true;
|
||||
}
|
||||
|
||||
if (receivers[0].shape) {
|
||||
// Monomorphic load from an unboxed object expando.
|
||||
spew("Inlining monomorphic unboxed expando GETPROP");
|
||||
|
||||
obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
|
||||
obj = addUnboxedExpandoGuard(obj, /* hasExpando = */ true, Bailout_ShapeGuard);
|
||||
|
||||
MInstruction* expando = MLoadUnboxedExpando::New(alloc(), obj);
|
||||
current->add(expando);
|
||||
|
||||
expando = addShapeGuard(expando, receivers[0].shape, Bailout_ShapeGuard);
|
||||
|
||||
Shape* shape = receivers[0].shape->searchLinear(NameToId(name));
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
if (!loadSlot(expando, shape, rvalType, barrier, types))
|
||||
return false;
|
||||
|
||||
trackOptimizationOutcome(TrackedOutcome::Monomorphic);
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Monomorphic load from an unboxed object.
|
||||
ObjectGroup* group = receivers[0].group;
|
||||
if (obj->resultTypeSet() && !obj->resultTypeSet()->hasType(TypeSet::ObjectType(group)))
|
||||
return true;
|
||||
|
||||
obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
|
||||
|
||||
const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
|
||||
MInstruction* load = loadUnboxedProperty(obj, property->offset, property->type, barrier, types);
|
||||
current->push(load);
|
||||
|
||||
if (!pushTypeBarrier(load, types, barrier))
|
||||
return false;
|
||||
|
||||
trackOptimizationOutcome(TrackedOutcome::Monomorphic);
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -12692,7 +12555,7 @@ bool
|
|||
IonBuilder::jsop_setprop(PropertyName* name)
|
||||
{
|
||||
MDefinition* value = current->pop();
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
MDefinition* obj = current->pop();
|
||||
|
||||
bool emitted = false;
|
||||
startTrackingOptimizations();
|
||||
|
|
@ -12725,13 +12588,6 @@ IonBuilder::jsop_setprop(PropertyName* name)
|
|||
bool barrier = PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &obj, name, &value,
|
||||
/* canModify = */ true);
|
||||
|
||||
if (!forceInlineCaches()) {
|
||||
// Try to emit stores to unboxed objects.
|
||||
trackOptimizationAttempt(TrackedStrategy::SetProp_Unboxed);
|
||||
if (!setPropTryUnboxed(&emitted, obj, name, value, barrier, objTypes) || emitted)
|
||||
return emitted;
|
||||
}
|
||||
|
||||
// Add post barrier if needed. The instructions above manage any post
|
||||
// barriers they need directly.
|
||||
if (NeedsPostBarrier(value))
|
||||
|
|
@ -12765,10 +12621,8 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
|
|||
JSObject* foundProto = nullptr;
|
||||
bool isOwnProperty;
|
||||
BaselineInspector::ReceiverVector receivers(alloc());
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
if (!inspector->commonSetPropFunction(pc, &foundProto, &lastProperty, &commonSetter,
|
||||
&isOwnProperty,
|
||||
receivers, convertUnboxedGroups))
|
||||
&isOwnProperty, receivers))
|
||||
{
|
||||
trackOptimizationOutcome(TrackedOutcome::NoProtoFound);
|
||||
return true;
|
||||
|
|
@ -12783,8 +12637,7 @@ IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
|
|||
// If type information is bad, we can still optimize the setter if we
|
||||
// shape guard.
|
||||
obj = addShapeGuardsForGetterSetter(obj, foundProto, lastProperty,
|
||||
receivers, convertUnboxedGroups,
|
||||
isOwnProperty);
|
||||
receivers, isOwnProperty);
|
||||
if (!obj)
|
||||
return false;
|
||||
}
|
||||
|
|
@ -13099,40 +12952,6 @@ IonBuilder::storeUnboxedValue(MDefinition* obj, MDefinition* elements, int32_t e
|
|||
return store;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::setPropTryUnboxed(bool* emitted, MDefinition* obj,
|
||||
PropertyName* name, MDefinition* value,
|
||||
bool barrier, TemporaryTypeSet* objTypes)
|
||||
{
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
if (barrier) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NeedsTypeBarrier);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSValueType unboxedType;
|
||||
uint32_t offset = getUnboxedOffset(obj->resultTypeSet(), name, &unboxedType);
|
||||
if (offset == UINT32_MAX)
|
||||
return true;
|
||||
|
||||
if (obj->type() != MIRType::Object) {
|
||||
MGuardObject* guard = MGuardObject::New(alloc(), obj);
|
||||
current->add(guard);
|
||||
obj = guard;
|
||||
}
|
||||
|
||||
MInstruction* store = storeUnboxedProperty(obj, offset, unboxedType, value);
|
||||
|
||||
current->push(value);
|
||||
|
||||
if (!resumeAfter(store))
|
||||
return false;
|
||||
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
||||
PropertyName* name, MDefinition* value,
|
||||
|
|
@ -13146,15 +12965,12 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
|||
}
|
||||
|
||||
BaselineInspector::ReceiverVector receivers(alloc());
|
||||
BaselineInspector::ObjectGroupVector convertUnboxedGroups(alloc());
|
||||
if (!inspector->maybeInfoForPropertyOp(pc, receivers, convertUnboxedGroups))
|
||||
if (!inspector->maybeInfoForPropertyOp(pc, receivers))
|
||||
return false;
|
||||
|
||||
if (!canInlinePropertyOpShapes(receivers))
|
||||
return true;
|
||||
|
||||
obj = convertUnboxedObjects(obj, convertUnboxedGroups);
|
||||
|
||||
if (receivers.length() == 1) {
|
||||
if (!receivers[0].group) {
|
||||
// Monomorphic store to a native object.
|
||||
|
|
@ -13174,46 +12990,6 @@ IonBuilder::setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (receivers[0].shape) {
|
||||
// Monomorphic store to an unboxed object expando.
|
||||
spew("Inlining monomorphic unboxed expando SETPROP");
|
||||
|
||||
obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
|
||||
obj = addUnboxedExpandoGuard(obj, /* hasExpando = */ true, Bailout_ShapeGuard);
|
||||
|
||||
MInstruction* expando = MLoadUnboxedExpando::New(alloc(), obj);
|
||||
current->add(expando);
|
||||
|
||||
expando = addShapeGuard(expando, receivers[0].shape, Bailout_ShapeGuard);
|
||||
|
||||
Shape* shape = receivers[0].shape->searchLinear(NameToId(name));
|
||||
MOZ_ASSERT(shape);
|
||||
|
||||
bool needsBarrier = objTypes->propertyNeedsBarrier(constraints(), NameToId(name));
|
||||
if (!storeSlot(expando, shape, value, needsBarrier))
|
||||
return false;
|
||||
|
||||
trackOptimizationOutcome(TrackedOutcome::Monomorphic);
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Monomorphic store to an unboxed object.
|
||||
spew("Inlining monomorphic unboxed SETPROP");
|
||||
|
||||
ObjectGroup* group = receivers[0].group;
|
||||
if (!objTypes->hasType(TypeSet::ObjectType(group)))
|
||||
return true;
|
||||
|
||||
obj = addGroupGuard(obj, group, Bailout_ShapeGuard);
|
||||
|
||||
const UnboxedLayout::Property* property = group->unboxedLayout().lookup(name);
|
||||
storeUnboxedProperty(obj, property->offset, property->type, value);
|
||||
|
||||
current->push(value);
|
||||
|
||||
trackOptimizationOutcome(TrackedOutcome::Monomorphic);
|
||||
*emitted = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -13884,7 +13660,7 @@ IonBuilder::jsop_setaliasedvar(EnvironmentCoordinate ec)
|
|||
bool
|
||||
IonBuilder::jsop_in()
|
||||
{
|
||||
MDefinition* obj = convertUnboxedObjects(current->pop());
|
||||
MDefinition* obj = current->pop();
|
||||
MDefinition* id = current->pop();
|
||||
|
||||
bool emitted = false;
|
||||
|
|
@ -14240,19 +14016,6 @@ IonBuilder::addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bail
|
|||
return guard;
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind)
|
||||
{
|
||||
MGuardUnboxedExpando* guard = MGuardUnboxedExpando::New(alloc(), obj, hasExpando, bailoutKind);
|
||||
current->add(guard);
|
||||
|
||||
// If a shape guard failed in the past, don't optimize group guards.
|
||||
if (failedShapeGuard_)
|
||||
guard->setNotMovable();
|
||||
|
||||
return guard;
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
IonBuilder::addGuardReceiverPolymorphic(MDefinition* obj,
|
||||
const BaselineInspector::ReceiverVector& receivers)
|
||||
|
|
@ -14262,15 +14025,6 @@ IonBuilder::addGuardReceiverPolymorphic(MDefinition* obj,
|
|||
// Monomorphic guard on a native object.
|
||||
return addShapeGuard(obj, receivers[0].shape, Bailout_ShapeGuard);
|
||||
}
|
||||
|
||||
if (!receivers[0].shape) {
|
||||
// Guard on an unboxed object that does not have an expando.
|
||||
obj = addGroupGuard(obj, receivers[0].group, Bailout_ShapeGuard);
|
||||
return addUnboxedExpandoGuard(obj, /* hasExpando = */ false, Bailout_ShapeGuard);
|
||||
}
|
||||
|
||||
// Monomorphic receiver guards are not yet supported when the receiver
|
||||
// is an unboxed object with an expando.
|
||||
}
|
||||
|
||||
MGuardReceiverPolymorphic* guard = MGuardReceiverPolymorphic::New(alloc(), obj);
|
||||
|
|
|
|||
|
|
@ -401,7 +401,6 @@ class IonBuilder
|
|||
MInstruction* addBoundsCheck(MDefinition* index, MDefinition* length);
|
||||
MInstruction* addShapeGuard(MDefinition* obj, Shape* const shape, BailoutKind bailoutKind);
|
||||
MInstruction* addGroupGuard(MDefinition* obj, ObjectGroup* group, BailoutKind bailoutKind);
|
||||
MInstruction* addUnboxedExpandoGuard(MDefinition* obj, bool hasExpando, BailoutKind bailoutKind);
|
||||
MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
|
||||
|
||||
MInstruction*
|
||||
|
|
@ -441,8 +440,6 @@ class IonBuilder
|
|||
BarrierKind barrier, TemporaryTypeSet* types);
|
||||
MOZ_MUST_USE bool getPropTryModuleNamespace(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
BarrierKind barrier, TemporaryTypeSet* types);
|
||||
MOZ_MUST_USE bool getPropTryUnboxed(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
BarrierKind barrier, TemporaryTypeSet* types);
|
||||
MOZ_MUST_USE bool getPropTryCommonGetter(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
TemporaryTypeSet* types);
|
||||
MOZ_MUST_USE bool getPropTryInlineAccess(bool* emitted, MDefinition* obj, PropertyName* name,
|
||||
|
|
@ -475,9 +472,6 @@ class IonBuilder
|
|||
MOZ_MUST_USE bool setPropTryDefiniteSlot(bool* emitted, MDefinition* obj,
|
||||
PropertyName* name, MDefinition* value,
|
||||
bool barrier, TemporaryTypeSet* objTypes);
|
||||
MOZ_MUST_USE bool setPropTryUnboxed(bool* emitted, MDefinition* obj,
|
||||
PropertyName* name, MDefinition* value,
|
||||
bool barrier, TemporaryTypeSet* objTypes);
|
||||
MOZ_MUST_USE bool setPropTryInlineAccess(bool* emitted, MDefinition* obj,
|
||||
PropertyName* name, MDefinition* value,
|
||||
bool barrier, TemporaryTypeSet* objTypes);
|
||||
|
|
@ -1041,7 +1035,6 @@ class IonBuilder
|
|||
MDefinition*
|
||||
addShapeGuardsForGetterSetter(MDefinition* obj, JSObject* holder, Shape* holderShape,
|
||||
const BaselineInspector::ReceiverVector& receivers,
|
||||
const BaselineInspector::ObjectGroupVector& convertUnboxedGroups,
|
||||
bool isOwnProperty);
|
||||
|
||||
MOZ_MUST_USE bool annotateGetPropertyCache(MDefinition* obj, PropertyName* name,
|
||||
|
|
@ -1059,9 +1052,6 @@ class IonBuilder
|
|||
ResultWithOOM<bool> testNotDefinedProperty(MDefinition* obj, jsid id);
|
||||
|
||||
uint32_t getDefiniteSlot(TemporaryTypeSet* types, PropertyName* name, uint32_t* pnfixed);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj);
|
||||
MDefinition* convertUnboxedObjects(MDefinition* obj,
|
||||
const BaselineInspector::ObjectGroupVector& list);
|
||||
uint32_t getUnboxedOffset(TemporaryTypeSet* types, PropertyName* name,
|
||||
JSValueType* punboxedType);
|
||||
MInstruction* loadUnboxedProperty(MDefinition* obj, size_t offset, JSValueType unboxedType,
|
||||
|
|
|
|||
|
|
@ -3251,14 +3251,6 @@ LIRGenerator::visitStoreUnboxedString(MStoreUnboxedString* ins)
|
|||
add(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitConvertUnboxedObjectToNative(MConvertUnboxedObjectToNative* ins)
|
||||
{
|
||||
LInstruction* check = new(alloc()) LConvertUnboxedObjectToNative(useRegister(ins->object()));
|
||||
add(check, ins);
|
||||
assignSafepoint(check, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitEffectiveAddress(MEffectiveAddress* ins)
|
||||
{
|
||||
|
|
@ -3776,24 +3768,6 @@ LIRGenerator::visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic* ins)
|
|||
redefine(ins, ins->object());
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitGuardUnboxedExpando(MGuardUnboxedExpando* ins)
|
||||
{
|
||||
LGuardUnboxedExpando* guard =
|
||||
new(alloc()) LGuardUnboxedExpando(useRegister(ins->object()));
|
||||
assignSnapshot(guard, ins->bailoutKind());
|
||||
add(guard, ins);
|
||||
redefine(ins, ins->object());
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitLoadUnboxedExpando(MLoadUnboxedExpando* ins)
|
||||
{
|
||||
LLoadUnboxedExpando* lir =
|
||||
new(alloc()) LLoadUnboxedExpando(useRegisterAtStart(ins->object()));
|
||||
define(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitAssertRange(MAssertRange* ins)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -232,7 +232,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitFallibleStoreElement(MFallibleStoreElement* ins);
|
||||
void visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins);
|
||||
void visitStoreUnboxedString(MStoreUnboxedString* ins);
|
||||
void visitConvertUnboxedObjectToNative(MConvertUnboxedObjectToNative* ins);
|
||||
void visitEffectiveAddress(MEffectiveAddress* ins);
|
||||
void visitArrayPopShift(MArrayPopShift* ins);
|
||||
void visitArrayPush(MArrayPush* ins);
|
||||
|
|
@ -256,8 +255,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitGuardObject(MGuardObject* ins);
|
||||
void visitGuardString(MGuardString* ins);
|
||||
void visitGuardReceiverPolymorphic(MGuardReceiverPolymorphic* ins);
|
||||
void visitGuardUnboxedExpando(MGuardUnboxedExpando* ins);
|
||||
void visitLoadUnboxedExpando(MLoadUnboxedExpando* ins);
|
||||
void visitPolyInlineGuard(MPolyInlineGuard* ins);
|
||||
void visitAssertRange(MAssertRange* ins);
|
||||
void visitCallGetProperty(MCallGetProperty* ins);
|
||||
|
|
|
|||
|
|
@ -615,7 +615,7 @@ IonBuilder::inlineArrayPopShift(CallInfo& callInfo, MArrayPopShift::Mode mode)
|
|||
OBJECT_FLAG_LENGTH_OVERFLOW |
|
||||
OBJECT_FLAG_ITERATED;
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
TemporaryTypeSet* thisTypes = obj->resultTypeSet();
|
||||
if (!thisTypes)
|
||||
return InliningStatus_NotInlined;
|
||||
|
|
@ -743,7 +743,7 @@ IonBuilder::inlineArrayPush(CallInfo& callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
MDefinition* value = callInfo.getArg(0);
|
||||
if (PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current,
|
||||
&obj, nullptr, &value, /* canModify = */ false))
|
||||
|
|
@ -822,7 +822,7 @@ IonBuilder::inlineArraySlice(CallInfo& callInfo)
|
|||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.thisArg());
|
||||
MDefinition* obj = callInfo.thisArg();
|
||||
|
||||
// Ensure |this| and result are objects.
|
||||
if (getInlineReturnType() != MIRType::Object)
|
||||
|
|
@ -2152,7 +2152,7 @@ IonBuilder::inlineDefineDataProperty(CallInfo& callInfo)
|
|||
if (callInfo.argc() != 3)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* obj = convertUnboxedObjects(callInfo.getArg(0));
|
||||
MDefinition* obj = callInfo.getArg(0);
|
||||
MDefinition* id = callInfo.getArg(1);
|
||||
MDefinition* value = callInfo.getArg(2);
|
||||
|
||||
|
|
|
|||
|
|
@ -4810,35 +4810,8 @@ MBeta::printOpcode(GenericPrinter& out) const
|
|||
bool
|
||||
MCreateThisWithTemplate::canRecoverOnBailout() const
|
||||
{
|
||||
MOZ_ASSERT(templateObject()->is<PlainObject>() || templateObject()->is<UnboxedPlainObject>());
|
||||
MOZ_ASSERT_IF(templateObject()->is<PlainObject>(),
|
||||
!templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OperandIndexMap::init(TempAllocator& alloc, JSObject* templateObject)
|
||||
{
|
||||
const UnboxedLayout& layout =
|
||||
templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
|
||||
|
||||
const UnboxedLayout::PropertyVector& properties = layout.properties();
|
||||
MOZ_ASSERT(properties.length() < 255);
|
||||
|
||||
// Allocate an array of indexes, where the top of each field correspond to
|
||||
// the index of the operand in the MObjectState instance.
|
||||
if (!map.init(alloc, layout.size()))
|
||||
return false;
|
||||
|
||||
// Reset all indexes to 0, which is an error code.
|
||||
for (size_t i = 0; i < map.length(); i++)
|
||||
map[i] = 0;
|
||||
|
||||
// Map the property offsets to the indexes of MObjectState operands.
|
||||
uint8_t index = 1;
|
||||
for (size_t i = 0; i < properties.length(); i++, index++)
|
||||
map[properties[i].offset] = index;
|
||||
|
||||
MOZ_ASSERT(templateObject()->is<PlainObject>());
|
||||
MOZ_ASSERT(!templateObject()->as<PlainObject>().denseElementsAreCopyOnWrite());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -4858,17 +4831,11 @@ MObjectState::MObjectState(JSObject *templateObject, OperandIndexMap* operandInd
|
|||
setResultType(MIRType::Object);
|
||||
setRecoveredOnBailout();
|
||||
|
||||
if (templateObject->is<NativeObject>()) {
|
||||
MOZ_ASSERT(templateObject->is<NativeObject>());
|
||||
|
||||
NativeObject* nativeObject = &templateObject->as<NativeObject>();
|
||||
numSlots_ = nativeObject->slotSpan();
|
||||
numFixedSlots_ = nativeObject->numFixedSlots();
|
||||
} else {
|
||||
const UnboxedLayout& layout =
|
||||
templateObject->as<UnboxedPlainObject>().layoutDontCheckGeneration();
|
||||
// Same as UnboxedLayout::makeNativeGroup
|
||||
numSlots_ = layout.properties().length();
|
||||
numFixedSlots_ = gc::GetGCKindSlots(layout.getAllocKind());
|
||||
}
|
||||
|
||||
operandIndex_ = operandIndex;
|
||||
}
|
||||
|
|
@ -4905,27 +4872,10 @@ MObjectState::initFromTemplateObject(TempAllocator& alloc, MDefinition* undefine
|
|||
// the template object. This is needed to account values which are baked in
|
||||
// the template objects and not visible in IonMonkey, such as the
|
||||
// uninitialized-lexical magic value of call objects.
|
||||
if (templateObject->is<UnboxedPlainObject>()) {
|
||||
UnboxedPlainObject& unboxedObject = templateObject->as<UnboxedPlainObject>();
|
||||
const UnboxedLayout& layout = unboxedObject.layoutDontCheckGeneration();
|
||||
const UnboxedLayout::PropertyVector& properties = layout.properties();
|
||||
|
||||
for (size_t i = 0; i < properties.length(); i++) {
|
||||
Value val = unboxedObject.getValue(properties[i], /* maybeUninitialized = */ true);
|
||||
MDefinition *def = undefinedVal;
|
||||
if (!val.isUndefined()) {
|
||||
MConstant* ins = val.isObject() ?
|
||||
MConstant::NewConstraintlessObject(alloc, &val.toObject()) :
|
||||
MConstant::New(alloc, val);
|
||||
block()->insertBefore(this, ins);
|
||||
def = ins;
|
||||
}
|
||||
initSlot(i, def);
|
||||
}
|
||||
} else {
|
||||
NativeObject& nativeObject = templateObject->as<NativeObject>();
|
||||
MOZ_ASSERT(nativeObject.slotSpan() == numSlots());
|
||||
|
||||
MOZ_ASSERT(templateObject->is<NativeObject>());
|
||||
for (size_t i = 0; i < numSlots(); i++) {
|
||||
Value val = nativeObject.getSlot(i);
|
||||
MDefinition *def = undefinedVal;
|
||||
|
|
@ -4938,7 +4888,6 @@ MObjectState::initFromTemplateObject(TempAllocator& alloc, MDefinition* undefine
|
|||
}
|
||||
initSlot(i, def);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -4948,14 +4897,7 @@ MObjectState::New(TempAllocator& alloc, MDefinition* obj)
|
|||
JSObject* templateObject = templateObjectOf(obj);
|
||||
MOZ_ASSERT(templateObject, "Unexpected object creation.");
|
||||
|
||||
OperandIndexMap* operandIndex = nullptr;
|
||||
if (templateObject->is<UnboxedPlainObject>()) {
|
||||
operandIndex = new(alloc) OperandIndexMap;
|
||||
if (!operandIndex || !operandIndex->init(alloc, templateObject))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MObjectState* res = new(alloc) MObjectState(templateObject, operandIndex);
|
||||
MObjectState* res = new(alloc) MObjectState(templateObject, nullptr);
|
||||
if (!res || !res->init(alloc, obj))
|
||||
return nullptr;
|
||||
return res;
|
||||
|
|
@ -5862,35 +5804,6 @@ MGetFirstDollarIndex::foldsTo(TempAllocator& alloc)
|
|||
return MConstant::New(alloc, Int32Value(index));
|
||||
}
|
||||
|
||||
MConvertUnboxedObjectToNative*
|
||||
MConvertUnboxedObjectToNative::New(TempAllocator& alloc, MDefinition* obj, ObjectGroup* group)
|
||||
{
|
||||
MConvertUnboxedObjectToNative* res = new(alloc) MConvertUnboxedObjectToNative(obj, group);
|
||||
|
||||
ObjectGroup* nativeGroup = group->unboxedLayout().nativeGroup();
|
||||
|
||||
// Make a new type set for the result of this instruction which replaces
|
||||
// the input group with the native group we will convert it to.
|
||||
TemporaryTypeSet* types = obj->resultTypeSet();
|
||||
if (types && !types->unknownObject()) {
|
||||
TemporaryTypeSet* newTypes = types->cloneWithoutObjects(alloc.lifoAlloc());
|
||||
if (newTypes) {
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = types->getObject(i);
|
||||
if (!key)
|
||||
continue;
|
||||
if (key->unknownProperties() || !key->isGroup() || key->group() != group)
|
||||
newTypes->addType(TypeSet::ObjectType(key), alloc.lifoAlloc());
|
||||
else
|
||||
newTypes->addType(TypeSet::ObjectType(nativeGroup), alloc.lifoAlloc());
|
||||
}
|
||||
res->setResultTypeSet(newTypes);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool
|
||||
jit::ElementAccessIsDenseNative(CompilerConstraintList* constraints,
|
||||
MDefinition* obj, MDefinition* id)
|
||||
|
|
@ -5945,8 +5858,6 @@ jit::UnboxedArrayElementType(CompilerConstraintList* constraints, MDefinition* o
|
|||
elementType = layout.elementType();
|
||||
else
|
||||
return JSVAL_TYPE_MAGIC;
|
||||
|
||||
key->watchStateChangeForUnboxedConvertedToNative(constraints);
|
||||
}
|
||||
|
||||
return elementType;
|
||||
|
|
@ -6581,23 +6492,6 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
|
|||
}
|
||||
}
|
||||
|
||||
// Perform additional filtering to make sure that any unboxed property
|
||||
// being written can accommodate the value.
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
TypeSet::ObjectKey* key = types->getObject(i);
|
||||
if (key && key->isGroup() && key->group()->maybeUnboxedLayout()) {
|
||||
const UnboxedLayout& layout = key->group()->unboxedLayout();
|
||||
if (name) {
|
||||
const UnboxedLayout::Property* property = layout.lookup(name);
|
||||
if (property && !CanStoreUnboxedType(alloc, property->type, *pvalue))
|
||||
return true;
|
||||
} else {
|
||||
if (layout.isArray() && !CanStoreUnboxedType(alloc, layout.elementType(), *pvalue))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
return false;
|
||||
|
||||
|
|
@ -6631,17 +6525,6 @@ jit::PropertyWriteNeedsTypeBarrier(TempAllocator& alloc, CompilerConstraintList*
|
|||
|
||||
MOZ_ASSERT(excluded);
|
||||
|
||||
// If the excluded object is a group with an unboxed layout, make sure it
|
||||
// does not have a corresponding native group. Objects with the native
|
||||
// group might appear even though they are not in the type set.
|
||||
if (excluded->isGroup()) {
|
||||
if (UnboxedLayout* layout = excluded->group()->maybeUnboxedLayout()) {
|
||||
if (layout->nativeGroup())
|
||||
return true;
|
||||
excluded->watchStateChangeForUnboxedConvertedToNative(constraints);
|
||||
}
|
||||
}
|
||||
|
||||
*pobj = AddGroupGuard(alloc, current, *pobj, excluded, /* bailOnEquality = */ true);
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
131
js/src/jit/MIR.h
131
js/src/jit/MIR.h
|
|
@ -30,7 +30,6 @@
|
|||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/SharedMem.h"
|
||||
#include "vm/TypedArrayCommon.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
// Undo windows.h damage on Win64
|
||||
#undef MemoryBarrier
|
||||
|
|
@ -9742,59 +9741,6 @@ class MStoreUnboxedString
|
|||
ALLOW_CLONE(MStoreUnboxedString)
|
||||
};
|
||||
|
||||
// Passes through an object, after ensuring it is converted from an unboxed
|
||||
// object to a native representation.
|
||||
class MConvertUnboxedObjectToNative
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
CompilerObjectGroup group_;
|
||||
|
||||
explicit MConvertUnboxedObjectToNative(MDefinition* obj, ObjectGroup* group)
|
||||
: MUnaryInstruction(obj),
|
||||
group_(group)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ConvertUnboxedObjectToNative)
|
||||
NAMED_OPERANDS((0, object))
|
||||
|
||||
static MConvertUnboxedObjectToNative* New(TempAllocator& alloc, MDefinition* obj,
|
||||
ObjectGroup* group);
|
||||
|
||||
ObjectGroup* group() const {
|
||||
return group_;
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!congruentIfOperandsEqual(ins))
|
||||
return false;
|
||||
return ins->toConvertUnboxedObjectToNative()->group() == group();
|
||||
}
|
||||
AliasSet getAliasSet() const override {
|
||||
// This instruction can read and write to all parts of the object, but
|
||||
// is marked as non-effectful so it can be consolidated by LICM and GVN
|
||||
// and avoid inhibiting other optimizations.
|
||||
//
|
||||
// This is valid to do because when unboxed objects might have a native
|
||||
// group they can be converted to, we do not optimize accesses to the
|
||||
// unboxed objects and do not guard on their group or shape (other than
|
||||
// in this opcode).
|
||||
//
|
||||
// Later accesses can assume the object has a native representation
|
||||
// and optimize accordingly. Those accesses cannot be reordered before
|
||||
// this instruction, however. This is prevented by chaining this
|
||||
// instruction with the object itself, in the same way as MBoundsCheck.
|
||||
return AliasSet::None();
|
||||
}
|
||||
bool appendRoots(MRootList& roots) const override {
|
||||
return roots.append(group_);
|
||||
}
|
||||
};
|
||||
|
||||
// Array.prototype.pop or Array.prototype.shift on a dense array.
|
||||
class MArrayPopShift
|
||||
: public MUnaryInstruction,
|
||||
|
|
@ -11174,11 +11120,6 @@ class MGuardShape
|
|||
setMovable();
|
||||
setResultType(MIRType::Object);
|
||||
setResultTypeSet(obj->resultTypeSet());
|
||||
|
||||
// Disallow guarding on unboxed object shapes. The group is better to
|
||||
// guard on, and guarding on the shape can interact badly with
|
||||
// MConvertUnboxedObjectToNative.
|
||||
MOZ_ASSERT(shape->getObjectClass() != &UnboxedPlainObject::class_);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -11273,11 +11214,6 @@ class MGuardObjectGroup
|
|||
setGuard();
|
||||
setMovable();
|
||||
setResultType(MIRType::Object);
|
||||
|
||||
// Unboxed groups which might be converted to natives can't be guarded
|
||||
// on, due to MConvertUnboxedObjectToNative.
|
||||
MOZ_ASSERT_IF(group->maybeUnboxedLayoutDontCheckGeneration(),
|
||||
!group->unboxedLayoutDontCheckGeneration().nativeGroup());
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -11386,73 +11322,6 @@ class MGuardClass
|
|||
ALLOW_CLONE(MGuardClass)
|
||||
};
|
||||
|
||||
// Guard on the presence or absence of an unboxed object's expando.
|
||||
class MGuardUnboxedExpando
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
bool requireExpando_;
|
||||
BailoutKind bailoutKind_;
|
||||
|
||||
MGuardUnboxedExpando(MDefinition* obj, bool requireExpando, BailoutKind bailoutKind)
|
||||
: MUnaryInstruction(obj),
|
||||
requireExpando_(requireExpando),
|
||||
bailoutKind_(bailoutKind)
|
||||
{
|
||||
setGuard();
|
||||
setMovable();
|
||||
setResultType(MIRType::Object);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(GuardUnboxedExpando)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, object))
|
||||
|
||||
bool requireExpando() const {
|
||||
return requireExpando_;
|
||||
}
|
||||
BailoutKind bailoutKind() const {
|
||||
return bailoutKind_;
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (!congruentIfOperandsEqual(ins))
|
||||
return false;
|
||||
if (requireExpando() != ins->toGuardUnboxedExpando()->requireExpando())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
};
|
||||
|
||||
// Load an unboxed plain object's expando.
|
||||
class MLoadUnboxedExpando
|
||||
: public MUnaryInstruction,
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
private:
|
||||
explicit MLoadUnboxedExpando(MDefinition* object)
|
||||
: MUnaryInstruction(object)
|
||||
{
|
||||
setResultType(MIRType::Object);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(LoadUnboxedExpando)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
NAMED_OPERANDS((0, object))
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::Load(AliasSet::ObjectFields);
|
||||
}
|
||||
};
|
||||
|
||||
// Load from vp[slot] (slots that are not inline in an object).
|
||||
class MLoadSlot
|
||||
: public MUnaryInstruction,
|
||||
|
|
|
|||
|
|
@ -187,8 +187,6 @@ namespace jit {
|
|||
_(GuardObjectGroup) \
|
||||
_(GuardObjectIdentity) \
|
||||
_(GuardClass) \
|
||||
_(GuardUnboxedExpando) \
|
||||
_(LoadUnboxedExpando) \
|
||||
_(ArrayLength) \
|
||||
_(SetArrayLength) \
|
||||
_(GetNextEntryForIterator) \
|
||||
|
|
@ -219,7 +217,6 @@ namespace jit {
|
|||
_(StoreUnboxedScalar) \
|
||||
_(StoreUnboxedObjectOrNull) \
|
||||
_(StoreUnboxedString) \
|
||||
_(ConvertUnboxedObjectToNative) \
|
||||
_(ArrayPopShift) \
|
||||
_(ArrayPush) \
|
||||
_(ArraySlice) \
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@
|
|||
#include "jit/JitcodeMap.h"
|
||||
#include "jit/JitSpewer.h"
|
||||
#include "js/TrackedOptimizationInfo.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
#include "vm/ObjectGroup-inl.h"
|
||||
#include "vm/TypeInference-inl.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include "jit/MIR.h"
|
||||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
|
|
@ -183,25 +182,6 @@ IsObjectEscaped(MInstruction* ins, JSObject* objDefault)
|
|||
JitSpewDef(JitSpew_Escape, "is escaped by\n", def);
|
||||
return true;
|
||||
|
||||
case MDefinition::Op_LoadUnboxedScalar:
|
||||
case MDefinition::Op_StoreUnboxedScalar:
|
||||
case MDefinition::Op_LoadUnboxedObjectOrNull:
|
||||
case MDefinition::Op_StoreUnboxedObjectOrNull:
|
||||
case MDefinition::Op_LoadUnboxedString:
|
||||
case MDefinition::Op_StoreUnboxedString:
|
||||
// Not escaped if it is the first argument.
|
||||
if (def->indexOf(*i) != 0) {
|
||||
JitSpewDef(JitSpew_Escape, "is escaped by\n", def);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!def->getOperand(1)->isConstant()) {
|
||||
JitSpewDef(JitSpew_Escape, "is addressed with unknown index\n", def);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MDefinition::Op_PostWriteBarrier:
|
||||
break;
|
||||
|
||||
|
|
@ -305,12 +285,6 @@ class ObjectMemoryView : public MDefinitionVisitorDefaultNoop
|
|||
void visitGuardShape(MGuardShape* ins);
|
||||
void visitFunctionEnvironment(MFunctionEnvironment* ins);
|
||||
void visitLambda(MLambda* ins);
|
||||
void visitStoreUnboxedScalar(MStoreUnboxedScalar* ins);
|
||||
void visitLoadUnboxedScalar(MLoadUnboxedScalar* ins);
|
||||
void visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins);
|
||||
void visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins);
|
||||
void visitStoreUnboxedString(MStoreUnboxedString* ins);
|
||||
void visitLoadUnboxedString(MLoadUnboxedString* ins);
|
||||
|
||||
private:
|
||||
void storeOffset(MInstruction* ins, size_t offset, MDefinition* value);
|
||||
|
|
@ -656,21 +630,6 @@ ObjectMemoryView::visitLambda(MLambda* ins)
|
|||
ins->setIncompleteObject();
|
||||
}
|
||||
|
||||
static size_t
|
||||
GetOffsetOf(MDefinition* index, size_t width, int32_t baseOffset)
|
||||
{
|
||||
int32_t idx = index->toConstant()->toInt32();
|
||||
MOZ_ASSERT(idx >= 0);
|
||||
MOZ_ASSERT(baseOffset >= 0 && size_t(baseOffset) >= UnboxedPlainObject::offsetOfData());
|
||||
return idx * width + baseOffset - UnboxedPlainObject::offsetOfData();
|
||||
}
|
||||
|
||||
static size_t
|
||||
GetOffsetOf(MDefinition* index, Scalar::Type type, int32_t baseOffset)
|
||||
{
|
||||
return GetOffsetOf(index, Scalar::byteSize(type), baseOffset);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::storeOffset(MInstruction* ins, size_t offset, MDefinition* value)
|
||||
{
|
||||
|
|
@ -700,77 +659,6 @@ ObjectMemoryView::loadOffset(MInstruction* ins, size_t offset)
|
|||
ins->block()->discard(ins);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitStoreUnboxedScalar(MStoreUnboxedScalar* ins)
|
||||
{
|
||||
// Skip stores made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
size_t offset = GetOffsetOf(ins->index(), ins->storageType(), ins->offsetAdjustment());
|
||||
storeOffset(ins, offset, ins->value());
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitLoadUnboxedScalar(MLoadUnboxedScalar* ins)
|
||||
{
|
||||
// Skip loads made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
// Replace load by the slot value.
|
||||
size_t offset = GetOffsetOf(ins->index(), ins->storageType(), ins->offsetAdjustment());
|
||||
loadOffset(ins, offset);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitStoreUnboxedObjectOrNull(MStoreUnboxedObjectOrNull* ins)
|
||||
{
|
||||
// Skip stores made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
// Clone the state and update the slot value.
|
||||
size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
|
||||
storeOffset(ins, offset, ins->value());
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull* ins)
|
||||
{
|
||||
// Skip loads made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
// Replace load by the slot value.
|
||||
size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
|
||||
loadOffset(ins, offset);
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitStoreUnboxedString(MStoreUnboxedString* ins)
|
||||
{
|
||||
// Skip stores made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
// Clone the state and update the slot value.
|
||||
size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
|
||||
storeOffset(ins, offset, ins->value());
|
||||
}
|
||||
|
||||
void
|
||||
ObjectMemoryView::visitLoadUnboxedString(MLoadUnboxedString* ins)
|
||||
{
|
||||
// Skip loads made on other objects.
|
||||
if (ins->elements() != obj_)
|
||||
return;
|
||||
|
||||
// Replace load by the slot value.
|
||||
size_t offset = GetOffsetOf(ins->index(), sizeof(uintptr_t), ins->offsetAdjustment());
|
||||
loadOffset(ins, offset);
|
||||
}
|
||||
|
||||
static bool
|
||||
IndexOf(MDefinition* ins, int32_t* res)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#endif
|
||||
#include "jit/VMFunctions.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
|
||||
#include "jit/MacroAssembler-inl.h"
|
||||
#include "vm/Interpreter-inl.h"
|
||||
|
|
|
|||
|
|
@ -5891,22 +5891,6 @@ class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0>
|
|||
}
|
||||
};
|
||||
|
||||
// If necessary, convert an unboxed object in a particular group to its native
|
||||
// representation.
|
||||
class LConvertUnboxedObjectToNative : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(ConvertUnboxedObjectToNative)
|
||||
|
||||
explicit LConvertUnboxedObjectToNative(const LAllocation& object) {
|
||||
setOperand(0, object);
|
||||
}
|
||||
|
||||
MConvertUnboxedObjectToNative* mir() {
|
||||
return mir_->toConvertUnboxedObjectToNative();
|
||||
}
|
||||
};
|
||||
|
||||
class LArrayPopShiftV : public LInstructionHelper<BOX_PIECES, 1, 2>
|
||||
{
|
||||
public:
|
||||
|
|
@ -7429,38 +7413,6 @@ class LGuardReceiverPolymorphic : public LInstructionHelper<0, 1, 1>
|
|||
}
|
||||
};
|
||||
|
||||
class LGuardUnboxedExpando : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(GuardUnboxedExpando)
|
||||
|
||||
explicit LGuardUnboxedExpando(const LAllocation& in) {
|
||||
setOperand(0, in);
|
||||
}
|
||||
const LAllocation* object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const MGuardUnboxedExpando* mir() const {
|
||||
return mir_->toGuardUnboxedExpando();
|
||||
}
|
||||
};
|
||||
|
||||
class LLoadUnboxedExpando : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(LoadUnboxedExpando)
|
||||
|
||||
explicit LLoadUnboxedExpando(const LAllocation& in) {
|
||||
setOperand(0, in);
|
||||
}
|
||||
const LAllocation* object() {
|
||||
return getOperand(0);
|
||||
}
|
||||
const MLoadUnboxedExpando* mir() const {
|
||||
return mir_->toLoadUnboxedExpando();
|
||||
}
|
||||
};
|
||||
|
||||
// Guard that a value is in a TypeSet.
|
||||
class LTypeBarrierV : public LInstructionHelper<0, BOX_PIECES, 1>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -258,8 +258,6 @@
|
|||
_(GuardObjectGroup) \
|
||||
_(GuardObjectIdentity) \
|
||||
_(GuardClass) \
|
||||
_(GuardUnboxedExpando) \
|
||||
_(LoadUnboxedExpando) \
|
||||
_(TypeBarrierV) \
|
||||
_(TypeBarrierO) \
|
||||
_(MonitorTypes) \
|
||||
|
|
@ -287,7 +285,6 @@
|
|||
_(StoreElementT) \
|
||||
_(StoreUnboxedScalar) \
|
||||
_(StoreUnboxedPointer) \
|
||||
_(ConvertUnboxedObjectToNative) \
|
||||
_(ArrayPopShiftV) \
|
||||
_(ArrayPopShiftT) \
|
||||
_(ArrayPushV) \
|
||||
|
|
|
|||
|
|
@ -6434,9 +6434,6 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v
|
|||
}
|
||||
jit::JitOptions.jumpThreshold = value;
|
||||
break;
|
||||
case JSJITCOMPILER_UNBOXED_OBJECTS:
|
||||
jit::JitOptions.disableUnboxedObjects = !value;
|
||||
break;
|
||||
case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
|
||||
jit::JitOptions.asmJSAtomicsEnable = !!value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -5794,7 +5794,6 @@ JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
|
|||
Register(BASELINE_ENABLE, "baseline.enable") \
|
||||
Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \
|
||||
Register(JUMP_THRESHOLD, "jump-threshold") \
|
||||
Register(UNBOXED_OBJECTS, "unboxed_objects") \
|
||||
Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \
|
||||
Register(WASM_TEST_MODE, "wasm.test-mode") \
|
||||
Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
|
||||
|
|
|
|||
|
|
@ -3169,6 +3169,11 @@ static const JSFunctionSpec array_methods[] = {
|
|||
|
||||
/* ES7 additions */
|
||||
JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2,0),
|
||||
|
||||
/* ES2019 additions */
|
||||
JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0,0),
|
||||
JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0),
|
||||
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
|
|
@ -3333,6 +3338,8 @@ array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
|
|||
!DefineProperty(cx, unscopables, cx->names().fill, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().find, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().findIndex, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().flat, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().flatMap, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().includes, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().keys, value) ||
|
||||
!DefineProperty(cx, unscopables, cx->names().values, value))
|
||||
|
|
|
|||
|
|
@ -6190,12 +6190,6 @@ gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
|
|||
for (auto group = source->zone()->cellIter<ObjectGroup>(); !group.done(); group.next()) {
|
||||
group->setGeneration(target->zone()->types.generation);
|
||||
group->compartment_ = target;
|
||||
|
||||
// Remove any unboxed layouts from the list in the off thread
|
||||
// compartment. These do not need to be reinserted in the target
|
||||
// compartment's list, as the list is not required to be complete.
|
||||
if (UnboxedLayout* layout = group->maybeUnboxedLayoutDontCheckGeneration())
|
||||
layout->detachFromCompartment();
|
||||
}
|
||||
|
||||
// Fixup zone pointers in source's zone to refer to target's zone.
|
||||
|
|
|
|||
|
|
@ -157,8 +157,11 @@ SortComparatorIntegerIds(jsid a, jsid b, bool* lessOrEqualp)
|
|||
}
|
||||
|
||||
static bool
|
||||
EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags, Maybe<IdSet>& ht,
|
||||
AutoIdVector* props, Handle<UnboxedPlainObject*> unboxed = nullptr)
|
||||
EnumerateNativeProperties(JSContext* cx,
|
||||
HandleNativeObject pobj,
|
||||
unsigned flags,
|
||||
Maybe<IdSet>& ht,
|
||||
AutoIdVector* props)
|
||||
{
|
||||
bool enumerateSymbols;
|
||||
if (flags & JSITER_SYMBOLSONLY) {
|
||||
|
|
@ -220,16 +223,6 @@ EnumerateNativeProperties(JSContext* cx, HandleNativeObject pobj, unsigned flags
|
|||
return false;
|
||||
}
|
||||
|
||||
if (unboxed) {
|
||||
// If |unboxed| is set then |pobj| is the expando for an unboxed
|
||||
// plain object we are enumerating. Add the unboxed properties
|
||||
// themselves here since they are all property names that were
|
||||
// given to the object before any of the expando's properties.
|
||||
MOZ_ASSERT(pobj->is<UnboxedExpandoObject>());
|
||||
if (!EnumerateExtraProperties(cx, unboxed, flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t initialLength = props->length();
|
||||
|
||||
/* Collect all unique property names from this object's shape. */
|
||||
|
|
@ -355,15 +348,6 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
|
|||
|
||||
do {
|
||||
if (pobj->getOpsEnumerate()) {
|
||||
if (pobj->is<UnboxedPlainObject>() && pobj->as<UnboxedPlainObject>().maybeExpando()) {
|
||||
// Special case unboxed objects with an expando object.
|
||||
RootedNativeObject expando(cx, pobj->as<UnboxedPlainObject>().maybeExpando());
|
||||
if (!EnumerateNativeProperties(cx, expando, flags, ht, props,
|
||||
pobj.as<UnboxedPlainObject>()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!EnumerateExtraProperties(cx, pobj, flags, ht, props))
|
||||
return false;
|
||||
|
||||
|
|
@ -371,7 +355,6 @@ Snapshot(JSContext* cx, HandleObject pobj_, unsigned flags, AutoIdVector* props)
|
|||
if (!EnumerateNativeProperties(cx, pobj.as<NativeObject>(), flags, ht, props))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (pobj->isNative()) {
|
||||
// Give the object a chance to resolve all lazy properties
|
||||
if (JSEnumerateOp enumerate = pobj->getClass()->getEnumerate()) {
|
||||
|
|
@ -785,11 +768,6 @@ CanCompareIterableObjectToCache(JSObject* obj)
|
|||
{
|
||||
if (obj->isNative())
|
||||
return obj->as<NativeObject>().hasEmptyElements();
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
if (UnboxedExpandoObject* expando = obj->as<UnboxedPlainObject>().maybeExpando())
|
||||
return expando->hasEmptyElements();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@
|
|||
#include "vm/RegExpStaticsObject.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/TypedArrayCommon.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
#include "jsboolinlines.h"
|
||||
|
|
@ -869,9 +870,6 @@ static inline JSObject*
|
|||
CreateThisForFunctionWithGroup(JSContext* cx, HandleObjectGroup group,
|
||||
NewObjectKind newKind)
|
||||
{
|
||||
if (group->maybeUnboxedLayout() && newKind != SingletonObject)
|
||||
return UnboxedPlainObject::create(cx, group, newKind);
|
||||
|
||||
if (TypeNewScript* newScript = group->newScript()) {
|
||||
if (newScript->analyzed()) {
|
||||
// The definite properties analysis has been performed for this
|
||||
|
|
@ -1166,7 +1164,7 @@ static bool
|
|||
GetScriptPlainObjectProperties(JSContext* cx, HandleObject obj,
|
||||
MutableHandle<IdValueVector> properties)
|
||||
{
|
||||
if (obj->is<PlainObject>()) {
|
||||
MOZ_ASSERT(obj->is<PlainObject>());
|
||||
PlainObject* nobj = &obj->as<PlainObject>();
|
||||
|
||||
if (!properties.appendN(IdValuePair(), nobj->slotSpan()))
|
||||
|
|
@ -1189,25 +1187,6 @@ GetScriptPlainObjectProperties(JSContext* cx, HandleObject obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (obj->is<UnboxedPlainObject>()) {
|
||||
UnboxedPlainObject* nobj = &obj->as<UnboxedPlainObject>();
|
||||
|
||||
const UnboxedLayout& layout = nobj->layout();
|
||||
if (!properties.appendN(IdValuePair(), layout.properties().length()))
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < layout.properties().length(); i++) {
|
||||
const UnboxedLayout::Property& property = layout.properties()[i];
|
||||
properties[i].get().id = NameToId(property.name);
|
||||
properties[i].get().value = nobj->getValue(property);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Bad object kind");
|
||||
}
|
||||
|
||||
static bool
|
||||
DeepCloneValue(JSContext* cx, Value* vp, NewObjectKind newKind)
|
||||
{
|
||||
|
|
@ -1227,8 +1206,9 @@ js::DeepCloneObjectLiteral(JSContext* cx, HandleObject obj, NewObjectKind newKin
|
|||
/* NB: Keep this in sync with XDRObjectLiteral. */
|
||||
MOZ_ASSERT_IF(obj->isSingleton(),
|
||||
cx->compartment()->behaviors().getSingletonsAsTemplates());
|
||||
MOZ_ASSERT(obj->is<PlainObject>() || obj->is<UnboxedPlainObject>() ||
|
||||
obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>());
|
||||
MOZ_ASSERT(obj->is<PlainObject>() ||
|
||||
obj->is<ArrayObject>() ||
|
||||
obj->is<UnboxedArrayObject>());
|
||||
MOZ_ASSERT(newKind != SingletonObject);
|
||||
|
||||
if (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) {
|
||||
|
|
@ -1347,7 +1327,6 @@ js::XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj)
|
|||
{
|
||||
if (mode == XDR_ENCODE) {
|
||||
MOZ_ASSERT(obj->is<PlainObject>() ||
|
||||
obj->is<UnboxedPlainObject>() ||
|
||||
obj->is<ArrayObject>() ||
|
||||
obj->is<UnboxedArrayObject>());
|
||||
isArray = (obj->is<ArrayObject>() || obj->is<UnboxedArrayObject>()) ? 1 : 0;
|
||||
|
|
@ -2333,11 +2312,6 @@ js::LookupOwnPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, Shape**
|
|||
// us the resolve hook won't define a property with this id.
|
||||
if (ClassMayResolveId(cx->names(), obj->getClass(), id, obj))
|
||||
return false;
|
||||
} else if (obj->is<UnboxedPlainObject>()) {
|
||||
if (obj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<NoGC>(propp);
|
||||
return true;
|
||||
}
|
||||
} else if (obj->is<UnboxedArrayObject>()) {
|
||||
if (obj->as<UnboxedArrayObject>().containsProperty(cx, id)) {
|
||||
MarkNonNativePropertyFound<NoGC>(propp);
|
||||
|
|
@ -2590,11 +2564,6 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object
|
|||
break;
|
||||
}
|
||||
|
||||
// Convert unboxed objects to their native representations before changing
|
||||
// their prototype/group, as they depend on the group for their layout.
|
||||
if (!MaybeConvertUnboxedObjectToNative(cx, obj))
|
||||
return false;
|
||||
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(proto));
|
||||
if (!SetClassAndProto(cx, obj, obj->getClass(), taggedProto))
|
||||
return false;
|
||||
|
|
@ -2618,9 +2587,6 @@ js::PreventExtensions(JSContext* cx, HandleObject obj, ObjectOpResult& result, I
|
|||
if (!obj->nonProxyIsExtensible())
|
||||
return result.succeed();
|
||||
|
||||
if (!MaybeConvertUnboxedObjectToNative(cx, obj))
|
||||
return false;
|
||||
|
||||
// Force lazy properties to be resolved.
|
||||
AutoIdVector props(cx);
|
||||
if (!js::GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY, &props))
|
||||
|
|
@ -3714,12 +3680,6 @@ JSObject::allocKindForTenure(const js::Nursery& nursery) const
|
|||
if (IsProxy(this))
|
||||
return as<ProxyObject>().allocKindForTenure();
|
||||
|
||||
// Unboxed plain objects are sized according to the data they store.
|
||||
if (is<UnboxedPlainObject>()) {
|
||||
size_t nbytes = as<UnboxedPlainObject>().layoutDontCheckGeneration().size();
|
||||
return GetGCObjectKindForBytes(UnboxedPlainObject::offsetOfData() + nbytes);
|
||||
}
|
||||
|
||||
// Unboxed arrays use inline data if their size is small enough.
|
||||
if (is<UnboxedArrayObject>()) {
|
||||
const UnboxedArrayObject* nobj = &as<UnboxedArrayObject>();
|
||||
|
|
|
|||
|
|
@ -7276,9 +7276,6 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
|
|||
if (op.getBoolOption("wasm-check-bce"))
|
||||
jit::JitOptions.wasmAlwaysCheckBounds = true;
|
||||
|
||||
if (op.getBoolOption("no-unboxed-objects"))
|
||||
jit::JitOptions.disableUnboxedObjects = true;
|
||||
|
||||
if (const char* str = op.getStringOption("cache-ir-stubs")) {
|
||||
if (strcmp(str, "on") == 0)
|
||||
jit::JitOptions.disableCacheIR = false;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ assertDeepEq(keys, [
|
|||
"fill",
|
||||
"find",
|
||||
"findIndex",
|
||||
"flat",
|
||||
"flatMap",
|
||||
"includes",
|
||||
"keys",
|
||||
"values"
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@
|
|||
macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
|
||||
macro(fix, fix, "fix") \
|
||||
macro(flags, flags, "flags") \
|
||||
macro(flat, flat, "flat") \
|
||||
macro(flatMap, flatMap, "flatMap") \
|
||||
macro(float32, float32, "float32") \
|
||||
macro(Float32x4, Float32x4, "Float32x4") \
|
||||
macro(float64, float64, "float64") \
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
#include "vm/EnvironmentObject-inl.h"
|
||||
#include "vm/Stack-inl.h"
|
||||
#include "vm/String-inl.h"
|
||||
#include "vm/UnboxedObject-inl.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
|
|
@ -337,14 +336,10 @@ InitGlobalLexicalOperation(JSContext* cx, LexicalEnvironmentObject* lexicalEnvAr
|
|||
inline bool
|
||||
InitPropertyOperation(JSContext* cx, JSOp op, HandleObject obj, HandleId id, HandleValue rhs)
|
||||
{
|
||||
if (obj->is<PlainObject>() || obj->is<JSFunction>()) {
|
||||
MOZ_ASSERT(obj->is<PlainObject>() || obj->is<JSFunction>());
|
||||
unsigned propAttrs = GetInitDataPropAttrs(op);
|
||||
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, rhs, nullptr, nullptr,
|
||||
propAttrs);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj->as<UnboxedPlainObject>().layout().lookup(id));
|
||||
return PutProperty(cx, obj, id, rhs, false);
|
||||
return NativeDefineProperty(cx, obj.as<NativeObject>(), id, rhs,
|
||||
nullptr, nullptr, propAttrs);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
|
|||
|
|
@ -4111,7 +4111,7 @@ CASE(JSOP_INITHOMEOBJECT)
|
|||
/* Load the home object */
|
||||
ReservedRooted<JSObject*> obj(&rootObject0);
|
||||
obj = ®S.sp[int(-2 - skipOver)].toObject();
|
||||
MOZ_ASSERT(obj->is<PlainObject>() || obj->is<UnboxedPlainObject>() || obj->is<JSFunction>());
|
||||
MOZ_ASSERT(obj->is<PlainObject>() || obj->is<JSFunction>());
|
||||
|
||||
func->setExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT, ObjectValue(*obj));
|
||||
}
|
||||
|
|
@ -4927,15 +4927,10 @@ js::NewObjectOperation(JSContext* cx, HandleScript script, jsbytecode* pc,
|
|||
return nullptr;
|
||||
if (group->maybePreliminaryObjects()) {
|
||||
group->maybePreliminaryObjects()->maybeAnalyze(cx, group);
|
||||
if (group->maybeUnboxedLayout())
|
||||
group->maybeUnboxedLayout()->setAllocationSite(script, pc);
|
||||
}
|
||||
|
||||
if (group->shouldPreTenure() || group->maybePreliminaryObjects())
|
||||
newKind = TenuredObject;
|
||||
|
||||
if (group->maybeUnboxedLayout())
|
||||
return UnboxedPlainObject::create(cx, group, newKind);
|
||||
}
|
||||
|
||||
RootedObject obj(cx);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include "vm/ReceiverGuard.h"
|
||||
|
||||
#include "builtin/TypedObject.h"
|
||||
#include "vm/UnboxedObject.h"
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
|
|
|||
|
|
@ -28,11 +28,6 @@ namespace js {
|
|||
// TypedObject: The structure of a typed object is determined by its group.
|
||||
// All typed objects with the same group have the same class, prototype, and
|
||||
// own properties.
|
||||
//
|
||||
// UnboxedPlainObject: The structure of an unboxed plain object is determined
|
||||
// by its group and its expando object's shape, if there is one. All unboxed
|
||||
// plain objects with the same group and expando shape have the same
|
||||
// properties except those stored in the expando's dense elements.
|
||||
|
||||
class HeapReceiverGuard;
|
||||
class RootedReceiverGuard;
|
||||
|
|
|
|||
|
|
@ -1995,17 +1995,6 @@ TypeSet::ObjectKey::watchStateChangeForTypedArrayData(CompilerConstraintList* co
|
|||
ConstraintDataFreezeObjectForTypedArrayData(tarray)));
|
||||
}
|
||||
|
||||
void
|
||||
TypeSet::ObjectKey::watchStateChangeForUnboxedConvertedToNative(CompilerConstraintList* constraints)
|
||||
{
|
||||
HeapTypeSetKey objectProperty = property(JSID_EMPTY);
|
||||
LifoAlloc* alloc = constraints->alloc();
|
||||
|
||||
typedef CompilerConstraintInstance<ConstraintDataFreezeObjectForUnboxedConvertedToNative> T;
|
||||
constraints->add(alloc->new_<T>(alloc, objectProperty,
|
||||
ConstraintDataFreezeObjectForUnboxedConvertedToNative()));
|
||||
}
|
||||
|
||||
static void
|
||||
ObjectStateChange(ExclusiveContext* cxArg, ObjectGroup* group, bool markingUnknown)
|
||||
{
|
||||
|
|
@ -3577,7 +3566,6 @@ PreliminaryObjectArrayWithTemplate::maybeAnalyze(ExclusiveContext* cx, ObjectGro
|
|||
}
|
||||
}
|
||||
|
||||
TryConvertToUnboxedLayout(cx, enter, shape(), group, preliminaryObjects);
|
||||
if (group->maybeUnboxedLayout())
|
||||
return;
|
||||
|
||||
|
|
@ -3861,10 +3849,6 @@ TypeNewScript::maybeAnalyze(JSContext* cx, ObjectGroup* group, bool* regenerate,
|
|||
PodCopy(initializerList, initializerVector.begin(), initializerVector.length());
|
||||
}
|
||||
|
||||
// Try to use an unboxed representation for the group.
|
||||
if (!TryConvertToUnboxedLayout(cx, enter, templateObject()->lastProperty(), group, preliminaryObjects))
|
||||
return false;
|
||||
|
||||
js_delete(preliminaryObjects);
|
||||
preliminaryObjects = nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -262,7 +262,6 @@ class TypeSet
|
|||
bool hasStableClassAndProto(CompilerConstraintList* constraints);
|
||||
void watchStateChangeForInlinedCall(CompilerConstraintList* constraints);
|
||||
void watchStateChangeForTypedArrayData(CompilerConstraintList* constraints);
|
||||
void watchStateChangeForUnboxedConvertedToNative(CompilerConstraintList* constraints);
|
||||
HeapTypeSetKey property(jsid id);
|
||||
void ensureTrackedProperty(JSContext* cx, jsid id);
|
||||
|
||||
|
|
|
|||
|
|
@ -1655,227 +1655,12 @@ const Class UnboxedArrayObject::class_ = {
|
|||
// API
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool
|
||||
UnboxedTypeIncludes(JSValueType supertype, JSValueType subtype)
|
||||
{
|
||||
if (supertype == JSVAL_TYPE_DOUBLE && subtype == JSVAL_TYPE_INT32)
|
||||
return true;
|
||||
if (supertype == JSVAL_TYPE_OBJECT && subtype == JSVAL_TYPE_NULL)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
CombineUnboxedTypes(const Value& value, JSValueType* existing)
|
||||
{
|
||||
JSValueType type = value.isDouble() ? JSVAL_TYPE_DOUBLE : value.extractNonDoubleType();
|
||||
|
||||
if (*existing == JSVAL_TYPE_MAGIC || *existing == type || UnboxedTypeIncludes(type, *existing)) {
|
||||
*existing = type;
|
||||
return true;
|
||||
}
|
||||
if (UnboxedTypeIncludes(*existing, type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return whether the property names and types in layout are a subset of the
|
||||
// specified vector.
|
||||
static bool
|
||||
PropertiesAreSuperset(const UnboxedLayout::PropertyVector& properties, UnboxedLayout* layout)
|
||||
{
|
||||
for (size_t i = 0; i < layout->properties().length(); i++) {
|
||||
const UnboxedLayout::Property& layoutProperty = layout->properties()[i];
|
||||
bool found = false;
|
||||
for (size_t j = 0; j < properties.length(); j++) {
|
||||
if (layoutProperty.name == properties[j].name) {
|
||||
found = (layoutProperty.type == properties[j].type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CombinePlainObjectProperties(PlainObject* obj, Shape* templateShape,
|
||||
UnboxedLayout::PropertyVector& properties)
|
||||
{
|
||||
// All preliminary objects must have been created with enough space to
|
||||
// fill in their unboxed data inline. This is ensured either by using
|
||||
// the largest allocation kind (which limits the maximum size of an
|
||||
// unboxed object), or by using an allocation kind that covers all
|
||||
// properties in the template, as the space used by unboxed properties
|
||||
// is less than or equal to that used by boxed properties.
|
||||
MOZ_ASSERT(gc::GetGCKindSlots(obj->asTenured().getAllocKind()) >=
|
||||
Min(NativeObject::MAX_FIXED_SLOTS, templateShape->slotSpan()));
|
||||
|
||||
if (obj->lastProperty() != templateShape || obj->hasDynamicElements()) {
|
||||
// Only use an unboxed representation if all created objects match
|
||||
// the template shape exactly.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < templateShape->slotSpan(); i++) {
|
||||
Value val = obj->getSlot(i);
|
||||
|
||||
JSValueType& existing = properties[i].type;
|
||||
if (!CombineUnboxedTypes(val, &existing))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
CombineArrayObjectElements(ExclusiveContext* cx, ArrayObject* obj, JSValueType* elementType)
|
||||
{
|
||||
if (obj->inDictionaryMode() ||
|
||||
obj->lastProperty()->propid() != AtomToId(cx->names().length) ||
|
||||
!obj->lastProperty()->previous()->isEmptyShape())
|
||||
{
|
||||
// Only use an unboxed representation if the object has no properties.
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
||||
Value val = obj->getDenseElement(i);
|
||||
|
||||
// For now, unboxed arrays cannot have holes.
|
||||
if (val.isMagic(JS_ELEMENTS_HOLE))
|
||||
return false;
|
||||
|
||||
if (!CombineUnboxedTypes(val, elementType))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t
|
||||
ComputePlainObjectLayout(ExclusiveContext* cx, Shape* templateShape,
|
||||
UnboxedLayout::PropertyVector& properties)
|
||||
{
|
||||
// Fill in the names for all the object's properties.
|
||||
for (Shape::Range<NoGC> r(templateShape); !r.empty(); r.popFront()) {
|
||||
size_t slot = r.front().slot();
|
||||
MOZ_ASSERT(!properties[slot].name);
|
||||
properties[slot].name = JSID_TO_ATOM(r.front().propid())->asPropertyName();
|
||||
}
|
||||
|
||||
// Fill in all the unboxed object's property offsets.
|
||||
uint32_t offset = 0;
|
||||
|
||||
// Search for an existing unboxed layout which is a subset of this one.
|
||||
// If there are multiple such layouts, use the largest one. If we're able
|
||||
// to find such a layout, use the same property offsets for the shared
|
||||
// properties, which will allow us to generate better code if the objects
|
||||
// have a subtype/supertype relation and are accessed at common sites.
|
||||
UnboxedLayout* bestExisting = nullptr;
|
||||
for (UnboxedLayout* existing : cx->compartment()->unboxedLayouts) {
|
||||
if (PropertiesAreSuperset(properties, existing)) {
|
||||
if (!bestExisting ||
|
||||
existing->properties().length() > bestExisting->properties().length())
|
||||
{
|
||||
bestExisting = existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestExisting) {
|
||||
for (size_t i = 0; i < bestExisting->properties().length(); i++) {
|
||||
const UnboxedLayout::Property& existingProperty = bestExisting->properties()[i];
|
||||
for (size_t j = 0; j < templateShape->slotSpan(); j++) {
|
||||
if (existingProperty.name == properties[j].name) {
|
||||
MOZ_ASSERT(existingProperty.type == properties[j].type);
|
||||
properties[j].offset = existingProperty.offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
offset = bestExisting->size();
|
||||
}
|
||||
|
||||
// Order remaining properties from the largest down for the best space
|
||||
// utilization.
|
||||
static const size_t typeSizes[] = { 8, 4, 1 };
|
||||
|
||||
for (size_t i = 0; i < ArrayLength(typeSizes); i++) {
|
||||
size_t size = typeSizes[i];
|
||||
for (size_t j = 0; j < templateShape->slotSpan(); j++) {
|
||||
if (properties[j].offset != UINT32_MAX)
|
||||
continue;
|
||||
JSValueType type = properties[j].type;
|
||||
if (UnboxedTypeSize(type) == size) {
|
||||
offset = JS_ROUNDUP(offset, size);
|
||||
properties[j].offset = offset;
|
||||
offset += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The final offset is the amount of data needed by the object.
|
||||
return offset;
|
||||
}
|
||||
|
||||
static bool
|
||||
SetLayoutTraceList(ExclusiveContext* cx, UnboxedLayout* layout)
|
||||
{
|
||||
// Figure out the offsets of any objects or string properties.
|
||||
Vector<int32_t, 8, SystemAllocPolicy> objectOffsets, stringOffsets;
|
||||
for (size_t i = 0; i < layout->properties().length(); i++) {
|
||||
const UnboxedLayout::Property& property = layout->properties()[i];
|
||||
MOZ_ASSERT(property.offset != UINT32_MAX);
|
||||
if (property.type == JSVAL_TYPE_OBJECT) {
|
||||
if (!objectOffsets.append(property.offset))
|
||||
return false;
|
||||
} else if (property.type == JSVAL_TYPE_STRING) {
|
||||
if (!stringOffsets.append(property.offset))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the layout's trace list.
|
||||
if (!objectOffsets.empty() || !stringOffsets.empty()) {
|
||||
Vector<int32_t, 8, SystemAllocPolicy> entries;
|
||||
if (!entries.appendAll(stringOffsets) ||
|
||||
!entries.append(-1) ||
|
||||
!entries.appendAll(objectOffsets) ||
|
||||
!entries.append(-1) ||
|
||||
!entries.append(-1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int32_t* traceList = cx->zone()->pod_malloc<int32_t>(entries.length());
|
||||
if (!traceList)
|
||||
return false;
|
||||
PodCopy(traceList, entries.begin(), entries.length());
|
||||
layout->setTraceList(traceList);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline Value
|
||||
NextValue(Handle<GCVector<Value>> values, size_t* valueCursor)
|
||||
{
|
||||
return values[(*valueCursor)++];
|
||||
}
|
||||
|
||||
static bool
|
||||
GetValuesFromPreliminaryArrayObject(ArrayObject* obj, MutableHandle<GCVector<Value>> values)
|
||||
{
|
||||
if (!values.append(Int32Value(obj->length())))
|
||||
return false;
|
||||
if (!values.append(Int32Value(obj->getDenseInitializedLength())))
|
||||
return false;
|
||||
for (size_t i = 0; i < obj->getDenseInitializedLength(); i++) {
|
||||
if (!values.append(obj->getDenseElement(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
|
||||
Handle<GCVector<Value>> values, size_t* valueCursor)
|
||||
|
|
@ -1901,16 +1686,6 @@ UnboxedArrayObject::fillAfterConvert(ExclusiveContext* cx,
|
|||
JS_ALWAYS_TRUE(initElement(cx, i, NextValue(values, valueCursor)));
|
||||
}
|
||||
|
||||
static bool
|
||||
GetValuesFromPreliminaryPlainObject(PlainObject* obj, MutableHandle<GCVector<Value>> values)
|
||||
{
|
||||
for (size_t i = 0; i < obj->slotSpan(); i++) {
|
||||
if (!values.append(obj->getSlot(i)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
|
||||
Handle<GCVector<Value>> values, size_t* valueCursor)
|
||||
|
|
@ -1921,181 +1696,6 @@ UnboxedPlainObject::fillAfterConvert(ExclusiveContext* cx,
|
|||
JS_ALWAYS_TRUE(setValue(cx, layout().properties()[i], NextValue(values, valueCursor)));
|
||||
}
|
||||
|
||||
bool
|
||||
js::TryConvertToUnboxedLayout(ExclusiveContext* cx, AutoEnterAnalysis& enter, Shape* templateShape,
|
||||
ObjectGroup* group, PreliminaryObjectArray* objects)
|
||||
{
|
||||
bool isArray = !templateShape;
|
||||
|
||||
// Unboxed arrays are nightly only for now. The getenv() call will be
|
||||
// removed when they are on by default. See bug 1153266.
|
||||
if (isArray) {
|
||||
#ifdef NIGHTLY_BUILD
|
||||
if (!getenv("JS_OPTION_USE_UNBOXED_ARRAYS")) {
|
||||
if (!cx->options().unboxedArrays())
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
} else {
|
||||
if (jit::JitOptions.disableUnboxedObjects)
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(templateShape, !templateShape->getObjectFlags());
|
||||
|
||||
if (group->runtimeFromAnyThread()->isSelfHostingGlobal(cx->global()))
|
||||
return true;
|
||||
|
||||
if (!isArray && templateShape->slotSpan() == 0)
|
||||
return true;
|
||||
|
||||
UnboxedLayout::PropertyVector properties;
|
||||
if (!isArray) {
|
||||
if (!properties.appendN(UnboxedLayout::Property(), templateShape->slotSpan()))
|
||||
return false;
|
||||
}
|
||||
JSValueType elementType = JSVAL_TYPE_MAGIC;
|
||||
|
||||
size_t objectCount = 0;
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
JSObject* obj = objects->get(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
if (obj->isSingleton() || obj->group() != group)
|
||||
return true;
|
||||
|
||||
objectCount++;
|
||||
|
||||
if (isArray) {
|
||||
if (!CombineArrayObjectElements(cx, &obj->as<ArrayObject>(), &elementType))
|
||||
return true;
|
||||
} else {
|
||||
if (!CombinePlainObjectProperties(&obj->as<PlainObject>(), templateShape, properties))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
size_t layoutSize = 0;
|
||||
if (isArray) {
|
||||
// Don't use an unboxed representation if we couldn't determine an
|
||||
// element type for the objects.
|
||||
if (UnboxedTypeSize(elementType) == 0)
|
||||
return true;
|
||||
} else {
|
||||
if (objectCount <= 1) {
|
||||
// If only one of the objects has been created, it is more likely
|
||||
// to have new properties added later. This heuristic is not used
|
||||
// for array objects, where we might want an unboxed representation
|
||||
// even if there is only one large array.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < templateShape->slotSpan(); i++) {
|
||||
// We can't use an unboxed representation if e.g. all the objects have
|
||||
// a null value for one of the properties, as we can't decide what type
|
||||
// it is supposed to have.
|
||||
if (UnboxedTypeSize(properties[i].type) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Make sure that all properties on the template shape are property
|
||||
// names, and not indexes.
|
||||
for (Shape::Range<NoGC> r(templateShape); !r.empty(); r.popFront()) {
|
||||
jsid id = r.front().propid();
|
||||
uint32_t dummy;
|
||||
if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
|
||||
return true;
|
||||
}
|
||||
|
||||
layoutSize = ComputePlainObjectLayout(cx, templateShape, properties);
|
||||
|
||||
// The entire object must be allocatable inline.
|
||||
if (UnboxedPlainObject::offsetOfData() + layoutSize > JSObject::MAX_BYTE_SIZE)
|
||||
return true;
|
||||
}
|
||||
|
||||
UniquePtr<UnboxedLayout>& layout = enter.unboxedLayoutToCleanUp;
|
||||
MOZ_ASSERT(!layout);
|
||||
layout = group->zone()->make_unique<UnboxedLayout>();
|
||||
if (!layout)
|
||||
return false;
|
||||
|
||||
if (isArray) {
|
||||
layout->initArray(elementType);
|
||||
} else {
|
||||
if (!layout->initProperties(properties, layoutSize))
|
||||
return false;
|
||||
|
||||
// The unboxedLayouts list only tracks layouts for plain objects.
|
||||
cx->compartment()->unboxedLayouts.insertFront(layout.get());
|
||||
|
||||
if (!SetLayoutTraceList(cx, layout.get()))
|
||||
return false;
|
||||
}
|
||||
|
||||
// We've determined that all the preliminary objects can use the new layout
|
||||
// just constructed, so convert the existing group to use the unboxed class,
|
||||
// and update the preliminary objects to use the new layout. Do the
|
||||
// fallible stuff first before modifying any objects.
|
||||
|
||||
// Get an empty shape which we can use for the preliminary objects.
|
||||
const Class* clasp = isArray ? &UnboxedArrayObject::class_ : &UnboxedPlainObject::class_;
|
||||
Shape* newShape = EmptyShape::getInitialShape(cx, clasp, group->proto(), 0);
|
||||
if (!newShape) {
|
||||
cx->recoverFromOutOfMemory();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Accumulate a list of all the values in each preliminary object, and
|
||||
// update their shapes.
|
||||
Rooted<GCVector<Value>> values(cx, GCVector<Value>(cx));
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
JSObject* obj = objects->get(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
bool ok;
|
||||
if (isArray)
|
||||
ok = GetValuesFromPreliminaryArrayObject(&obj->as<ArrayObject>(), &values);
|
||||
else
|
||||
ok = GetValuesFromPreliminaryPlainObject(&obj->as<PlainObject>(), &values);
|
||||
|
||||
if (!ok) {
|
||||
cx->recoverFromOutOfMemory();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (TypeNewScript* newScript = group->newScript())
|
||||
layout->setNewScript(newScript);
|
||||
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
if (JSObject* obj = objects->get(i))
|
||||
obj->as<NativeObject>().setLastPropertyMakeNonNative(newShape);
|
||||
}
|
||||
|
||||
group->setClasp(clasp);
|
||||
group->setUnboxedLayout(layout.release());
|
||||
|
||||
size_t valueCursor = 0;
|
||||
for (size_t i = 0; i < PreliminaryObjectArray::COUNT; i++) {
|
||||
JSObject* obj = objects->get(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
|
||||
if (isArray)
|
||||
obj->as<UnboxedArrayObject>().fillAfterConvert(cx, values, &valueCursor);
|
||||
else
|
||||
obj->as<UnboxedPlainObject>().fillAfterConvert(cx, values, &valueCursor);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(valueCursor == values.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
DefineBoxedOrUnboxedFunctor6(SetOrExtendBoxedOrUnboxedDenseElements,
|
||||
ExclusiveContext*, JSObject*, uint32_t, const Value*, uint32_t,
|
||||
ShouldUpdateTypes);
|
||||
|
|
|
|||
|
|
@ -317,13 +317,6 @@ class UnboxedPlainObject : public JSObject
|
|||
}
|
||||
};
|
||||
|
||||
// Try to construct an UnboxedLayout for each of the preliminary objects,
|
||||
// provided they all match the template shape. If successful, converts the
|
||||
// preliminary objects and their group to the new unboxed representation.
|
||||
bool
|
||||
TryConvertToUnboxedLayout(ExclusiveContext* cx, AutoEnterAnalysis& enter, Shape* templateShape,
|
||||
ObjectGroup* group, PreliminaryObjectArray* objects);
|
||||
|
||||
inline gc::AllocKind
|
||||
UnboxedLayout::getAllocKind() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1427,8 +1427,6 @@ ReloadPrefsCallback(const char* pref, void* data)
|
|||
|
||||
bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict");
|
||||
|
||||
bool unboxedObjects = Preferences::GetBool(JS_OPTIONS_DOT_STR "unboxed_objects");
|
||||
|
||||
sSharedMemoryEnabled = Preferences::GetBool(JS_OPTIONS_DOT_STR "shared_memory");
|
||||
|
||||
#ifdef DEBUG
|
||||
|
|
@ -1457,8 +1455,6 @@ ReloadPrefsCallback(const char* pref, void* data)
|
|||
useBaselineEager ? 0 : -1);
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_WARMUP_TRIGGER,
|
||||
useIonEager ? 0 : -1);
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_UNBOXED_OBJECTS,
|
||||
unboxedObjects);
|
||||
}
|
||||
|
||||
XPCJSContext::~XPCJSContext()
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
"pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf",
|
||||
"includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find",
|
||||
"findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys",
|
||||
"values", "constructor"];
|
||||
"values", "constructor", "flat", "flatMap"];
|
||||
if (isNightlyBuild) {
|
||||
// ...nothing now
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,3 +21,4 @@ pref(gfx.font_rendering.opentype_svg.enabled,true) fails == svg-glyph-mask.sv
|
|||
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-paint-server.svg svg-glyph-paint-server-ref.svg
|
||||
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-transform.svg svg-glyph-transform-ref.svg
|
||||
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-extents.html svg-glyph-extents-ref.html
|
||||
pref(gfx.font_rendering.opentype_svg.enabled,true) == svg-glyph-compressed.html svg-glyph-compressed-ref.html
|
||||
|
|
|
|||
BIN
layout/reftests/text-svgglyphs/resources/svg-gz.ttf
Normal file
BIN
layout/reftests/text-svgglyphs/resources/svg-gz.ttf
Normal file
Binary file not shown.
15
layout/reftests/text-svgglyphs/svg-glyph-compressed-ref.html
Normal file
15
layout/reftests/text-svgglyphs/svg-glyph-compressed-ref.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Test for compressed SVG glyphs</title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(resources/svg.woff); /* uses uncompressed SVG documents */
|
||||
}
|
||||
html { width: 400px; height: 400px; background-color: white; }
|
||||
body { margin: 0; }
|
||||
div { font: 200px test; color: fuchsia; line-height: 1; stroke: none; }
|
||||
</style>
|
||||
</head><body><div>abcdefg</div>
|
||||
<div>LMNOPQR</div>
|
||||
</body></html>
|
||||
15
layout/reftests/text-svgglyphs/svg-glyph-compressed.html
Normal file
15
layout/reftests/text-svgglyphs/svg-glyph-compressed.html
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8"><title>Test for compressed SVG glyphs</title>
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: test;
|
||||
src: url(resources/svg-gz.ttf); /* copy of svg.woff using gzip-compressed SVG documents */
|
||||
}
|
||||
html { width: 400px; height: 400px; background-color: white; }
|
||||
body { margin: 0; }
|
||||
div { font: 200px test; color: fuchsia; line-height: 1; stroke: none; }
|
||||
</style>
|
||||
</head><body><div>abcdefg</div>
|
||||
<div>LMNOPQR</div>
|
||||
</body></html>
|
||||
|
|
@ -1264,7 +1264,6 @@ pref("javascript.options.strict", false);
|
|||
#ifdef DEBUG
|
||||
pref("javascript.options.strict.debug", false);
|
||||
#endif
|
||||
pref("javascript.options.unboxed_objects", false);
|
||||
pref("javascript.options.baselinejit", true);
|
||||
pref("javascript.options.ion", true);
|
||||
pref("javascript.options.asmjs", true);
|
||||
|
|
|
|||
|
|
@ -948,9 +948,6 @@ function handleFallbackToCompleteUpdate(update, postStaging) {
|
|||
update.setProperty("patchingFailed", oldType);
|
||||
}
|
||||
|
||||
function pingStateAndStatusCodes(aUpdate, aStartup, aStatus) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Patch
|
||||
* @param patch
|
||||
|
|
@ -1538,7 +1535,6 @@ UpdateService.prototype = {
|
|||
getService(Ci.nsIUpdateManager);
|
||||
var update = um.activeUpdate;
|
||||
var status = readStatusFile(getUpdatesDir());
|
||||
pingStateAndStatusCodes(update, true, status);
|
||||
// STATE_NONE status typically means that the update.status file is present
|
||||
// but a background download error occurred.
|
||||
if (status == STATE_NONE) {
|
||||
|
|
@ -2146,8 +2142,6 @@ UpdateService.prototype = {
|
|||
if (!osApplyToDir) {
|
||||
LOG("UpdateService:applyOsUpdate - Error: osApplyToDir is not defined" +
|
||||
"in the nsIUpdate!");
|
||||
pingStateAndStatusCodes(aUpdate, false,
|
||||
STATE_FAILED + ": " + FOTA_FILE_OPERATION_ERROR);
|
||||
handleUpdateFailure(aUpdate, FOTA_FILE_OPERATION_ERROR);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2157,8 +2151,6 @@ UpdateService.prototype = {
|
|||
if (!updateFile.exists()) {
|
||||
LOG("UpdateService:applyOsUpdate - Error: OS update is not found at " +
|
||||
updateFile.path);
|
||||
pingStateAndStatusCodes(aUpdate, false,
|
||||
STATE_FAILED + ": " + FOTA_FILE_OPERATION_ERROR);
|
||||
handleUpdateFailure(aUpdate, FOTA_FILE_OPERATION_ERROR);
|
||||
return;
|
||||
}
|
||||
|
|
@ -2173,8 +2165,6 @@ UpdateService.prototype = {
|
|||
} catch (e) {
|
||||
LOG("UpdateService:applyOsUpdate - Error: Couldn't reboot into recovery" +
|
||||
" to apply FOTA update " + updateFile.path);
|
||||
pingStateAndStatusCodes(aUpdate, false,
|
||||
STATE_FAILED + ": " + FOTA_RECOVERY_ERROR);
|
||||
writeStatusFile(getUpdatesDir(), aUpdate.state = STATE_APPLIED);
|
||||
handleUpdateFailure(aUpdate, FOTA_RECOVERY_ERROR);
|
||||
}
|
||||
|
|
@ -2476,7 +2466,6 @@ UpdateManager.prototype = {
|
|||
return;
|
||||
}
|
||||
var status = readStatusFile(getUpdatesDir());
|
||||
pingStateAndStatusCodes(update, false, status);
|
||||
var parts = status.split(":");
|
||||
update.state = parts[0];
|
||||
if (update.state == STATE_FAILED && parts[1]) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue