Merge mozilla-central to autoland

This commit is contained in:
Carsten "Tomcat" Book 2016-12-06 15:53:48 +01:00
Родитель c3010f1b3e b0c54cd5ea
Коммит 809fb645df
36 изменённых файлов: 568 добавлений и 1609 удалений

Просмотреть файл

@ -3022,7 +3022,7 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
// If the mousedown happened inside a popup, don't
// try to set focus on one of its containing elements
const nsStyleDisplay* display = currFrame->StyleDisplay();
if (display->mDisplay == StyleDisplay::Popup) {
if (display->mDisplay == StyleDisplay::MozPopup) {
newFocus = nullptr;
break;
}

27
js/public/RefCounted.h Normal file
Просмотреть файл

@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_RefCounted_h
#define js_RefCounted_h
#include "mozilla/RefCounted.h"
#include "js/Utility.h"
namespace js {
// Replacement for mozilla::RefCounted and mozilla::external::AtomicRefCounted
// that default to JS::DeletePolicy.
template <typename T, typename D = JS::DeletePolicy<T>>
using RefCounted = mozilla::RefCounted<T, D>;
template <typename T, typename D = JS::DeletePolicy<T>>
using AtomicRefCounted = mozilla::external::AtomicRefCounted<T, D>;
} // namespace js
#endif /* js_RefCounted_h */

Просмотреть файл

@ -13,7 +13,7 @@
namespace js {
// Replacement for mozilla::UniquePtr that defaults to js::DefaultDelete.
// Replacement for mozilla::UniquePtr that defaults to JS::DeletePolicy.
template <typename T, typename D = JS::DeletePolicy<T>>
using UniquePtr = mozilla::UniquePtr<T, D>;

Просмотреть файл

@ -109,6 +109,7 @@ testBinary32('mul', 40, 2, 80);
testBinary32('div_s', -40, 2, -20);
testBinary32('div_u', -40, 2, 2147483628);
testBinary32('rem_s', 40, -3, 1);
testBinary32('rem_s', 0, -3, 0);
testBinary32('rem_u', 40, -3, 40);
testBinary32('and', 42, 6, 2);
testBinary32('or', 42, 6, 46);

Просмотреть файл

@ -0,0 +1,40 @@
load(libdir + "wasm.js");
let bodies = [
`
i32.const 1
i32.const 0
i32.div_s
`,
`
i32.const 1
i32.const 0
i32.rem_s
`,
`
f64.const 1797693134862315708145274e284
i64.trunc_s/f64
`,
`
f32.const 1797693134862315708145274e284
i32.trunc_s/f32
`
];
for (let body of bodies) {
wasmFullPass(`
(module
(func $f (param $x i32) (result i32)
loop $top
get_local $x
if
get_local $x
br 2
end
${body}
br $top
end
)
(export "run" $f)
)`, 42, {}, 42);
}

Просмотреть файл

@ -933,6 +933,17 @@ BaselineCacheIRCompiler::emitGuardIsString()
return true;
}
bool
BaselineCacheIRCompiler::emitGuardIsSymbol()
{
ValueOperand input = allocator.useValueRegister(masm, reader.valOperandId());
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
masm.branchTestSymbol(Assembler::NotEqual, input, failure->label());
return true;
}
bool
BaselineCacheIRCompiler::emitGuardType()
{
@ -1091,6 +1102,67 @@ BaselineCacheIRCompiler::emitGuardSpecificObject()
return true;
}
bool
BaselineCacheIRCompiler::emitGuardSpecificAtom()
{
Register str = allocator.useRegister(masm, reader.stringOperandId());
AutoScratchRegister scratch(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
Address atomAddr(stubAddress(reader.stubOffset()));
Label done;
masm.branchPtr(Assembler::Equal, atomAddr, str, &done);
// The pointers are not equal, so if the input string is also an atom it
// must be a different string.
masm.branchTest32(Assembler::NonZero, Address(str, JSString::offsetOfFlags()),
Imm32(JSString::ATOM_BIT), failure->label());
// Check the length.
masm.loadPtr(atomAddr, scratch);
masm.loadStringLength(scratch, scratch);
masm.branch32(Assembler::NotEqual, Address(str, JSString::offsetOfLength()),
scratch, failure->label());
// We have a non-atomized string with the same length. Call a helper
// function to do the comparison.
LiveRegisterSet volatileRegs(RegisterSet::Volatile());
masm.PushRegsInMask(volatileRegs);
masm.setupUnalignedABICall(scratch);
masm.loadPtr(atomAddr, scratch);
masm.passABIArg(scratch);
masm.passABIArg(str);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, EqualStringsHelper));
masm.mov(ReturnReg, scratch);
LiveRegisterSet ignore;
ignore.add(scratch);
masm.PopRegsInMaskIgnore(volatileRegs, ignore);
masm.branchIfFalseBool(scratch, failure->label());
masm.bind(&done);
return true;
}
bool
BaselineCacheIRCompiler::emitGuardSpecificSymbol()
{
Register sym = allocator.useRegister(masm, reader.symbolOperandId());
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
Address addr(stubAddress(reader.stubOffset()));
masm.branchPtr(Assembler::NotEqual, addr, sym, failure->label());
return true;
}
bool
BaselineCacheIRCompiler::emitGuardMagicValue()
{
@ -1286,6 +1358,34 @@ BaselineCacheIRCompiler::emitCallProxyGetResult()
return true;
}
typedef bool (*ProxyGetPropertyByValueFn)(JSContext*, HandleObject, HandleValue, MutableHandleValue);
static const VMFunction ProxyGetPropertyByValueInfo =
FunctionInfo<ProxyGetPropertyByValueFn>(ProxyGetPropertyByValue, "ProxyGetPropertyByValue");
bool
BaselineCacheIRCompiler::emitCallProxyGetByValueResult()
{
AutoStubFrame stubFrame(*this);
Register obj = allocator.useRegister(masm, reader.objOperandId());
ValueOperand idVal = allocator.useValueRegister(masm, reader.valOperandId());
AutoScratchRegister scratch(allocator, masm);
allocator.discardStack(masm);
stubFrame.enter(masm, scratch);
masm.Push(idVal);
masm.Push(obj);
if (!callVM(masm, ProxyGetPropertyByValueInfo))
return false;
stubFrame.leave(masm);
return true;
}
bool
BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult()
{
@ -1577,8 +1677,11 @@ BaselineCacheIRCompiler::init(CacheKind kind)
if (!allocator.init(ICStubCompiler::availableGeneralRegs(numInputs)))
return false;
MOZ_ASSERT(numInputs == 1);
allocator.initInputLocation(0, R0);
if (numInputs >= 1) {
allocator.initInputLocation(0, R0);
if (numInputs >= 2)
allocator.initInputLocation(1, R1);
}
return true;
}
@ -1631,6 +1734,12 @@ CacheIRWriter::copyStubData(uint8_t* dest) const
case StubField::Type::ObjectGroup:
InitGCPtr<ObjectGroup*>(destWords, stubFields_[i].asWord());
break;
case StubField::Type::Symbol:
InitGCPtr<JS::Symbol*>(destWords, stubFields_[i].asWord());
break;
case StubField::Type::String:
InitGCPtr<JSString*>(destWords, stubFields_[i].asWord());
break;
case StubField::Type::Id:
InitGCPtr<jsid>(destWords, stubFields_[i].asWord());
break;
@ -1725,7 +1834,7 @@ jit::AttachBaselineCacheIRStub(JSContext* cx, const CacheIRWriter& writer,
// unlimited number of stubs.
MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs);
MOZ_ASSERT(kind == CacheKind::GetProp);
MOZ_ASSERT(kind == CacheKind::GetProp || kind == CacheKind::GetElem);
uint32_t stubDataOffset = sizeof(ICCacheIR_Monitored);
JitCompartment* jitCompartment = cx->compartment()->jitCompartment();
@ -1805,6 +1914,14 @@ jit::TraceBaselineCacheIRStub(JSTracer* trc, ICStub* stub, const CacheIRStubInfo
TraceNullableEdge(trc, &stubInfo->getStubField<JSObject*>(stub, offset),
"baseline-cacheir-object");
break;
case StubField::Type::Symbol:
TraceNullableEdge(trc, &stubInfo->getStubField<JS::Symbol*>(stub, offset),
"baseline-cacheir-symbol");
break;
case StubField::Type::String:
TraceNullableEdge(trc, &stubInfo->getStubField<JSString*>(stub, offset),
"baseline-cacheir-string");
break;
case StubField::Type::Id:
TraceEdge(trc, &stubInfo->getStubField<jsid>(stub, offset), "baseline-cacheir-id");
break;
@ -1861,6 +1978,12 @@ CacheIRStubInfo::copyStubData(ICStub* src, ICStub* dest) const
case StubField::Type::ObjectGroup:
getStubField<ObjectGroup*>(dest, offset).init(getStubField<ObjectGroup*>(src, offset));
break;
case StubField::Type::Symbol:
getStubField<JS::Symbol*>(dest, offset).init(getStubField<JS::Symbol*>(src, offset));
break;
case StubField::Type::String:
getStubField<JSString*>(dest, offset).init(getStubField<JSString*>(src, offset));
break;
case StubField::Type::Id:
getStubField<jsid>(dest, offset).init(getStubField<jsid>(src, offset));
break;

Просмотреть файл

@ -698,10 +698,6 @@ RecompileBaselineScriptForDebugMode(JSContext* cx, JSScript* script,
_(Call_ScriptedApplyArray) \
_(Call_ScriptedApplyArguments) \
_(Call_ScriptedFunCall) \
_(GetElem_NativePrototypeCallNativeName) \
_(GetElem_NativePrototypeCallNativeSymbol) \
_(GetElem_NativePrototypeCallScriptedName) \
_(GetElem_NativePrototypeCallScriptedSymbol) \
_(GetProp_CallNativeGlobal) \
_(GetProp_Generic) \
_(SetProp_CallScripted) \

Просмотреть файл

@ -16,6 +16,7 @@
#include "builtin/Eval.h"
#include "builtin/SIMD.h"
#include "gc/Policy.h"
#include "jit/BaselineCacheIR.h"
#include "jit/BaselineDebugModeOSR.h"
#include "jit/BaselineJIT.h"
#include "jit/InlinableNatives.h"
@ -852,179 +853,6 @@ IsCacheableSetPropCall(JSContext* cx, JSObject* obj, JSObject* holder, Shape* sh
return true;
}
template <class T>
static bool
GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject holder,
Handle<T> key, bool needsAtomize)
{
bool indirect = (obj.get() != holder.get());
MOZ_ASSERT_IF(indirect, holder->isNative());
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
if (iter->kind() != ICStub::GetElem_NativeSlotName &&
iter->kind() != ICStub::GetElem_NativeSlotSymbol &&
iter->kind() != ICStub::GetElem_NativePrototypeSlotName &&
iter->kind() != ICStub::GetElem_NativePrototypeSlotSymbol &&
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeName &&
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeSymbol &&
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedName &&
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedSymbol)
{
continue;
}
if (indirect && (iter->kind() != ICStub::GetElem_NativePrototypeSlotName &&
iter->kind() != ICStub::GetElem_NativePrototypeSlotSymbol &&
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeName &&
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeSymbol &&
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedName &&
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedSymbol))
{
continue;
}
if(mozilla::IsSame<T, JS::Symbol*>::value !=
static_cast<ICGetElemNativeStub*>(*iter)->isSymbol())
{
continue;
}
ICGetElemNativeStubImpl<T>* getElemNativeStub =
reinterpret_cast<ICGetElemNativeStubImpl<T>*>(*iter);
if (key != getElemNativeStub->key())
continue;
if (ReceiverGuard(obj) != getElemNativeStub->receiverGuard())
continue;
// If the new stub needs atomization, and the old stub doesn't atomize, then
// an appropriate stub doesn't exist.
if (needsAtomize && !getElemNativeStub->needsAtomize())
continue;
// For prototype gets, check the holder and holder shape.
if (indirect) {
if (iter->isGetElem_NativePrototypeSlotName() ||
iter->isGetElem_NativePrototypeSlotSymbol()) {
ICGetElem_NativePrototypeSlot<T>* protoStub =
reinterpret_cast<ICGetElem_NativePrototypeSlot<T>*>(*iter);
if (holder != protoStub->holder())
continue;
if (holder->as<NativeObject>().lastProperty() != protoStub->holderShape())
continue;
} else {
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNativeName() ||
iter->isGetElem_NativePrototypeCallNativeSymbol() ||
iter->isGetElem_NativePrototypeCallScriptedName() ||
iter->isGetElem_NativePrototypeCallScriptedSymbol());
ICGetElemNativePrototypeCallStub<T>* protoStub =
reinterpret_cast<ICGetElemNativePrototypeCallStub<T>*>(*iter);
if (holder != protoStub->holder())
continue;
if (holder->as<NativeObject>().lastProperty() != protoStub->holderShape())
continue;
}
}
return true;
}
return false;
}
template <class T>
static void
RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, HandleObject obj,
HandleObject holder, Handle<T> key, bool needsAtomize)
{
bool indirect = (obj.get() != holder.get());
MOZ_ASSERT_IF(indirect, holder->isNative());
for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
switch (iter->kind()) {
case ICStub::GetElem_NativeSlotName:
case ICStub::GetElem_NativeSlotSymbol:
if (indirect)
continue;
MOZ_FALLTHROUGH;
case ICStub::GetElem_NativePrototypeSlotName:
case ICStub::GetElem_NativePrototypeSlotSymbol:
case ICStub::GetElem_NativePrototypeCallNativeName:
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
case ICStub::GetElem_NativePrototypeCallScriptedName:
case ICStub::GetElem_NativePrototypeCallScriptedSymbol:
break;
default:
continue;
}
if(mozilla::IsSame<T, JS::Symbol*>::value !=
static_cast<ICGetElemNativeStub*>(*iter)->isSymbol())
{
continue;
}
ICGetElemNativeStubImpl<T>* getElemNativeStub =
reinterpret_cast<ICGetElemNativeStubImpl<T>*>(*iter);
if (key != getElemNativeStub->key())
continue;
if (ReceiverGuard(obj) != getElemNativeStub->receiverGuard())
continue;
// For prototype gets, check the holder and holder shape.
if (indirect) {
if (iter->isGetElem_NativePrototypeSlotName() ||
iter->isGetElem_NativePrototypeSlotSymbol()) {
ICGetElem_NativePrototypeSlot<T>* protoStub =
reinterpret_cast<ICGetElem_NativePrototypeSlot<T>*>(*iter);
if (holder != protoStub->holder())
continue;
// If the holder matches, but the holder's lastProperty doesn't match, then
// this stub is invalid anyway. Unlink it.
if (holder->as<NativeObject>().lastProperty() != protoStub->holderShape()) {
iter.unlink(cx);
continue;
}
} else {
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNativeName() ||
iter->isGetElem_NativePrototypeCallNativeSymbol() ||
iter->isGetElem_NativePrototypeCallScriptedName() ||
iter->isGetElem_NativePrototypeCallScriptedSymbol());
ICGetElemNativePrototypeCallStub<T>* protoStub =
reinterpret_cast<ICGetElemNativePrototypeCallStub<T>*>(*iter);
if (holder != protoStub->holder())
continue;
// If the holder matches, but the holder's lastProperty doesn't match, then
// this stub is invalid anyway. Unlink it.
if (holder->as<NativeObject>().lastProperty() != protoStub->holderShape()) {
iter.unlink(cx);
continue;
}
}
}
// If the new stub needs atomization, and the old stub doesn't atomize, then
// remove the old stub.
if (needsAtomize && !getElemNativeStub->needsAtomize()) {
iter.unlink(cx);
continue;
}
// Should never get here, because this means a matching stub exists, and if
// a matching stub exists, this procedure should never have been called.
MOZ_CRASH("Procedure should never have been called.");
}
}
static bool
TypedArrayGetElemStubExists(ICGetElem_Fallback* stub, HandleObject obj)
{
@ -1049,31 +877,6 @@ ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which
return false;
}
template <class T>
static T
getKey(jsid id)
{
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
return false;
}
template <>
JS::Symbol* getKey<JS::Symbol*>(jsid id)
{
if (!JSID_IS_SYMBOL(id))
return nullptr;
return JSID_TO_SYMBOL(id);
}
template <>
PropertyName* getKey<PropertyName*>(jsid id)
{
uint32_t dummy;
if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
return nullptr;
return JSID_TO_ATOM(id)->asPropertyName();
}
static bool
IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
{
@ -1091,227 +894,6 @@ IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId
return true;
}
template <class T>
static bool
checkAtomize(HandleValue key)
{
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
return false;
}
template <>
bool checkAtomize<JS::Symbol*>(HandleValue key)
{
return false;
}
template <>
bool checkAtomize<PropertyName*>(HandleValue key)
{
return !key.toString()->isAtom();
}
template <class T>
static bool
TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsbytecode* pc,
ICGetElem_Fallback* stub, HandleObject obj,
HandleValue keyVal, bool* attached)
{
MOZ_ASSERT(keyVal.isString() || keyVal.isSymbol());
// Convert to id.
RootedId id(cx);
if (!ValueToId<CanGC>(cx, keyVal, &id))
return false;
Rooted<T> key(cx, getKey<T>(id));
if (!key)
return true;
bool needsAtomize = checkAtomize<T>(keyVal);
RootedShape shape(cx);
RootedObject holder(cx);
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
return false;
if (!holder || (holder != obj && !holder->isNative()))
return true;
// If a suitable stub already exists, nothing else to do.
if (GetElemNativeStubExists<T>(stub, obj, holder, key, needsAtomize))
return true;
// Remove any existing stubs that may interfere with the new stub being added.
RemoveExistingGetElemNativeStubs<T>(cx, stub, obj, holder, key, needsAtomize);
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
if (obj->is<UnboxedPlainObject>() && holder == obj) {
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
// Once unboxed objects support symbol-keys, we need to change the following accordingly
MOZ_ASSERT_IF(!keyVal.isString(), !property);
if (property) {
if (!cx->runtime()->jitSupportsFloatingPoint)
return true;
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
ICGetElemNativeCompiler<PropertyName*> compiler(cx, ICStub::GetElem_UnboxedPropertyName,
monitorStub, obj, holder,
name,
ICGetElemNativeStub::UnboxedProperty,
needsAtomize, property->offset +
UnboxedPlainObject::offsetOfData(),
property->type);
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
stub->addNewStub(newStub);
*attached = true;
return true;
}
Shape* shape = obj->as<UnboxedPlainObject>().maybeExpando()->lookup(cx, id);
if (!shape->hasDefaultGetter() || !shape->hasSlot())
return true;
bool isFixedSlot;
uint32_t offset;
GetFixedOrDynamicSlotOffset(shape, &isFixedSlot, &offset);
ICGetElemNativeStub::AccessType acctype =
isFixedSlot ? ICGetElemNativeStub::FixedSlot
: ICGetElemNativeStub::DynamicSlot;
ICGetElemNativeCompiler<T> compiler(cx, getGetElemStubKind<T>(ICStub::GetElem_NativeSlotName),
monitorStub, obj, holder, key,
acctype, needsAtomize, offset);
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
stub->addNewStub(newStub);
*attached = true;
return true;
}
if (!holder->isNative())
return true;
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
bool isFixedSlot;
uint32_t offset;
GetFixedOrDynamicSlotOffset(shape, &isFixedSlot, &offset);
ICStub::Kind kind = (obj == holder) ? ICStub::GetElem_NativeSlotName
: ICStub::GetElem_NativePrototypeSlotName;
kind = getGetElemStubKind<T>(kind);
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native %s%s slot) stub "
"(obj=%p, holder=%p, holderShape=%p)",
(obj == holder) ? "direct" : "prototype",
needsAtomize ? " atomizing" : "",
obj.get(), holder.get(), holder->as<NativeObject>().lastProperty());
AccType acctype = isFixedSlot ? ICGetElemNativeStub::FixedSlot
: ICGetElemNativeStub::DynamicSlot;
ICGetElemNativeCompiler<T> compiler(cx, kind, monitorStub, obj, holder, key,
acctype, needsAtomize, offset);
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
stub->addNewStub(newStub);
*attached = true;
return true;
}
return true;
}
template <class T>
static bool
TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecode* pc,
ICGetElem_Fallback* stub, HandleNativeObject obj,
HandleValue keyVal, bool* attached,
bool* isTemporarilyUnoptimizable)
{
MOZ_ASSERT(!*attached);
MOZ_ASSERT(keyVal.isString() || keyVal.isSymbol());
RootedId id(cx);
if (!ValueToId<CanGC>(cx, keyVal, &id))
return false;
Rooted<T> key(cx, getKey<T>(id));
if (!key)
return true;
bool needsAtomize = checkAtomize<T>(keyVal);
RootedShape shape(cx);
RootedObject baseHolder(cx);
if (!EffectlesslyLookupProperty(cx, obj, id, &baseHolder, &shape))
return false;
if (!baseHolder || !baseHolder->isNative())
return true;
HandleNativeObject holder = baseHolder.as<NativeObject>();
bool getterIsScripted = false;
if (IsCacheableGetPropCall(cx, obj, baseHolder, shape, &getterIsScripted,
isTemporarilyUnoptimizable, /*isDOMProxy=*/false))
{
RootedFunction getter(cx, &shape->getterObject()->as<JSFunction>());
// For now, we do not handle own property getters
if (obj == holder)
return true;
// If a suitable stub already exists, nothing else to do.
if (GetElemNativeStubExists<T>(stub, obj, holder, key, needsAtomize))
return true;
// Remove any existing stubs that may interfere with the new stub being added.
RemoveExistingGetElemNativeStubs<T>(cx, stub, obj, holder, key, needsAtomize);
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
ICStub::Kind kind = getterIsScripted ? ICStub::GetElem_NativePrototypeCallScriptedName
: ICStub::GetElem_NativePrototypeCallNativeName;
kind = getGetElemStubKind<T>(kind);
if (getterIsScripted) {
JitSpew(JitSpew_BaselineIC,
" Generating GetElem(Native %s%s call scripted %s:%" PRIuSIZE ") stub "
"(obj=%p, shape=%p, holder=%p, holderShape=%p)",
(obj == holder) ? "direct" : "prototype",
needsAtomize ? " atomizing" : "",
getter->nonLazyScript()->filename(), getter->nonLazyScript()->lineno(),
obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
} else {
JitSpew(JitSpew_BaselineIC,
" Generating GetElem(Native %s%s call native) stub "
"(obj=%p, shape=%p, holder=%p, holderShape=%p)",
(obj == holder) ? "direct" : "prototype",
needsAtomize ? " atomizing" : "",
obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
}
AccType acctype = getterIsScripted ? ICGetElemNativeStub::ScriptedGetter
: ICGetElemNativeStub::NativeGetter;
ICGetElemNativeCompiler<T> compiler(cx, kind, monitorStub, obj, holder, key, acctype,
needsAtomize, getter, script->pcToOffset(pc));
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
return false;
stub->addNewStub(newStub);
*attached = true;
return true;
}
return true;
}
static bool
IsPrimitiveArrayTypedObject(JSObject* obj)
{
@ -1441,27 +1023,6 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
return true;
}
// Check for NativeObject[id] and UnboxedPlainObject[id] shape-optimizable accesses.
if (obj->isNative() || obj->is<UnboxedPlainObject>()) {
RootedScript rootedScript(cx, script);
if (rhs.isString()) {
if (!TryAttachNativeOrUnboxedGetValueElemStub<PropertyName*>(cx, rootedScript, pc, stub,
obj, rhs, attached))
{
return false;
}
} else if (rhs.isSymbol()) {
if (!TryAttachNativeOrUnboxedGetValueElemStub<JS::Symbol*>(cx, rootedScript, pc, stub,
obj, rhs, attached))
{
return false;
}
}
if (*attached)
return true;
script = rootedScript;
}
// Check for UnboxedArray[int] accesses.
if (obj->is<UnboxedArrayObject>() && rhs.isInt32() && rhs.toInt32() >= 0) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(UnboxedArray[Int32]) stub");
@ -1555,29 +1116,22 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
attached = true;
}
// Try to attach an optimized getter stub.
bool isTemporarilyUnoptimizable = false;
if (!attached && lhs.isObject() && lhs.toObject().isNative()){
if (rhs.isString()) {
RootedScript rootedScript(cx, frame->script());
RootedNativeObject obj(cx, &lhs.toObject().as<NativeObject>());
if (!TryAttachNativeGetAccessorElemStub<PropertyName*>(cx, rootedScript, pc, stub,
obj, rhs, &attached,
&isTemporarilyUnoptimizable))
{
return false;
if (!attached && !JitOptions.disableCacheIR) {
ICStubEngine engine = ICStubEngine::Baseline;
GetPropIRGenerator gen(cx, pc, engine, CacheKind::GetElem, &isTemporarilyUnoptimizable,
lhs, rhs, res);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
engine, info.outerScript(cx), stub);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");
attached = true;
if (gen.shouldNotePreliminaryObjectStub())
newStub->toCacheIR_Monitored()->notePreliminaryObject();
else if (gen.shouldUnlinkPreliminaryObjectStubs())
StripPreliminaryObjectStubs(cx, stub);
}
script = rootedScript;
} else if (rhs.isSymbol()) {
RootedScript rootedScript(cx, frame->script());
RootedNativeObject obj(cx, &lhs.toObject().as<NativeObject>());
if (!TryAttachNativeGetAccessorElemStub<JS::Symbol*>(cx, rootedScript, pc, stub,
obj, rhs, &attached,
&isTemporarilyUnoptimizable))
{
return false;
}
script = rootedScript;
}
}
@ -1638,352 +1192,6 @@ ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return tailCallVM(DoGetElemFallbackInfo, masm);
}
//
// GetElem_NativeSlot
//
static bool
DoAtomizeString(JSContext* cx, HandleString string, MutableHandleValue result)
{
JitSpew(JitSpew_BaselineIC, " AtomizeString called");
RootedValue key(cx, StringValue(string));
// Convert to interned property name.
RootedId id(cx);
if (!ValueToId<CanGC>(cx, key, &id))
return false;
if (!JSID_IS_ATOM(id)) {
result.set(key);
return true;
}
result.set(StringValue(JSID_TO_ATOM(id)));
return true;
}
typedef bool (*DoAtomizeStringFn)(JSContext*, HandleString, MutableHandleValue);
static const VMFunction DoAtomizeStringInfo = FunctionInfo<DoAtomizeStringFn>(DoAtomizeString,
"DoAtomizeString");
template <class T>
bool
ICGetElemNativeCompiler<T>::emitCallNative(MacroAssembler& masm, Register objReg)
{
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
regs.takeUnchecked(objReg);
regs.takeUnchecked(ICTailCallReg);
enterStubFrame(masm, regs.getAny());
// Push object.
masm.push(objReg);
// Push native callee.
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()), objReg);
masm.push(objReg);
regs.add(objReg);
// Call helper.
if (!callVM(DoCallNativeGetterInfo, masm))
return false;
leaveStubFrame(masm);
return true;
}
template <class T>
bool
ICGetElemNativeCompiler<T>::emitCallScripted(MacroAssembler& masm, Register objReg)
{
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
regs.takeUnchecked(objReg);
regs.takeUnchecked(ICTailCallReg);
// Enter stub frame.
enterStubFrame(masm, regs.getAny());
// Align the stack such that the JitFrameLayout is aligned on
// JitStackAlignment.
masm.alignJitStackBasedOnNArgs(0);
// Push |this| for getter (target object).
{
ValueOperand val = regs.takeAnyValue();
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, val);
masm.Push(val);
regs.add(val);
}
regs.add(objReg);
Register callee = regs.takeAny();
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()), callee);
// Push argc, callee, and descriptor.
{
Register callScratch = regs.takeAny();
EmitBaselineCreateStubFrameDescriptor(masm, callScratch, JitFrameLayout::Size());
masm.Push(Imm32(0)); // ActualArgc is 0
masm.Push(callee);
masm.Push(callScratch);
regs.add(callScratch);
}
Register code = regs.takeAnyExcluding(ArgumentsRectifierReg);
masm.loadPtr(Address(callee, JSFunction::offsetOfNativeOrScript()), code);
masm.loadBaselineOrIonRaw(code, code, nullptr);
Register scratch = regs.takeAny();
// Handle arguments underflow.
Label noUnderflow;
masm.load16ZeroExtend(Address(callee, JSFunction::offsetOfNargs()), scratch);
masm.branch32(Assembler::Equal, scratch, Imm32(0), &noUnderflow);
{
// Call the arguments rectifier.
MOZ_ASSERT(ArgumentsRectifierReg != code);
JitCode* argumentsRectifier =
cx->runtime()->jitRuntime()->getArgumentsRectifier();
masm.movePtr(ImmGCPtr(argumentsRectifier), code);
masm.loadPtr(Address(code, JitCode::offsetOfCode()), code);
masm.movePtr(ImmWord(0), ArgumentsRectifierReg);
}
masm.bind(&noUnderflow);
masm.callJit(code);
leaveStubFrame(masm, true);
return true;
}
template <class T>
bool
ICGetElemNativeCompiler<T>::emitCheckKey(MacroAssembler& masm, Label& failure)
{
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
return false;
}
template <>
bool
ICGetElemNativeCompiler<JS::Symbol*>::emitCheckKey(MacroAssembler& masm, Label& failure)
{
MOZ_ASSERT(!needsAtomize_);
masm.branchTestSymbol(Assembler::NotEqual, R1, &failure);
Address symbolAddr(ICStubReg, ICGetElemNativeStubImpl<JS::Symbol*>::offsetOfKey());
Register symExtract = masm.extractObject(R1, ExtractTemp1);
masm.branchPtr(Assembler::NotEqual, symbolAddr, symExtract, &failure);
return true;
}
template <>
bool
ICGetElemNativeCompiler<PropertyName*>::emitCheckKey(MacroAssembler& masm, Label& failure)
{
masm.branchTestString(Assembler::NotEqual, R1, &failure);
// Check key identity. Don't automatically fail if this fails, since the incoming
// key maybe a non-interned string. Switch to a slowpath vm-call based check.
Address nameAddr(ICStubReg, ICGetElemNativeStubImpl<PropertyName*>::offsetOfKey());
Register strExtract = masm.extractString(R1, ExtractTemp1);
// If needsAtomize_ is true, and the string is not already an atom, then atomize the
// string before proceeding.
if (needsAtomize_) {
Label skipAtomize;
// If string is already an atom, skip the atomize.
masm.branchTest32(Assembler::NonZero,
Address(strExtract, JSString::offsetOfFlags()),
Imm32(JSString::ATOM_BIT),
&skipAtomize);
// Stow R0.
EmitStowICValues(masm, 1);
enterStubFrame(masm, R0.scratchReg());
// Atomize the string into a new value.
masm.push(strExtract);
if (!callVM(DoAtomizeStringInfo, masm))
return false;
// Atomized string is now in JSReturnOperand (R0).
// Leave stub frame, move atomized string into R1.
MOZ_ASSERT(R0 == JSReturnOperand);
leaveStubFrame(masm);
masm.moveValue(JSReturnOperand, R1);
// Unstow R0
EmitUnstowICValues(masm, 1);
// Extract string from R1 again.
DebugOnly<Register> strExtract2 = masm.extractString(R1, ExtractTemp1);
MOZ_ASSERT(Register(strExtract2) == strExtract);
masm.bind(&skipAtomize);
}
// Key has been atomized if necessary. Do identity check on string pointer.
masm.branchPtr(Assembler::NotEqual, nameAddr, strExtract, &failure);
return true;
}
template <class T>
bool
ICGetElemNativeCompiler<T>::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
Label failurePopR1;
bool popR1 = false;
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
// Unbox object.
Register objReg = masm.extractObject(R0, ExtractTemp0);
// Check object shape/group.
GuardReceiverObject(masm, ReceiverGuard(obj_), objReg, scratchReg,
ICGetElemNativeStub::offsetOfReceiverGuard(), &failure);
// Since this stub sometimes enters a stub frame, we manually set this to true (lie).
#ifdef DEBUG
entersStubFrame_ = true;
#endif
if (!emitCheckKey(masm, failure))
return false;
Register holderReg;
if (obj_ == holder_) {
holderReg = objReg;
if (obj_->is<UnboxedPlainObject>() && acctype_ != ICGetElemNativeStub::UnboxedProperty) {
// The property will be loaded off the unboxed expando.
masm.push(R1.scratchReg());
popR1 = true;
holderReg = R1.scratchReg();
masm.loadPtr(Address(objReg, UnboxedPlainObject::offsetOfExpando()), holderReg);
}
} else {
// Shape guard holder.
if (regs.empty()) {
masm.push(R1.scratchReg());
popR1 = true;
holderReg = R1.scratchReg();
} else {
holderReg = regs.takeAny();
}
if (kind == ICStub::GetElem_NativePrototypeCallNativeName ||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol)
{
masm.loadPtr(Address(ICStubReg,
ICGetElemNativePrototypeCallStub<T>::offsetOfHolder()),
holderReg);
masm.loadPtr(Address(ICStubReg,
ICGetElemNativePrototypeCallStub<T>::offsetOfHolderShape()),
scratchReg);
} else {
masm.loadPtr(Address(ICStubReg,
ICGetElem_NativePrototypeSlot<T>::offsetOfHolder()),
holderReg);
masm.loadPtr(Address(ICStubReg,
ICGetElem_NativePrototypeSlot<T>::offsetOfHolderShape()),
scratchReg);
}
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratchReg,
popR1 ? &failurePopR1 : &failure);
}
if (acctype_ == ICGetElemNativeStub::DynamicSlot ||
acctype_ == ICGetElemNativeStub::FixedSlot)
{
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub<T>::offsetOfOffset()),
scratchReg);
// Load from object.
if (acctype_ == ICGetElemNativeStub::DynamicSlot)
masm.addPtr(Address(holderReg, NativeObject::offsetOfSlots()), scratchReg);
else
masm.addPtr(holderReg, scratchReg);
Address valAddr(scratchReg, 0);
masm.loadValue(valAddr, R0);
if (popR1)
masm.addToStackPtr(ImmWord(sizeof(size_t)));
} else if (acctype_ == ICGetElemNativeStub::UnboxedProperty) {
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub<T>::offsetOfOffset()),
scratchReg);
masm.loadUnboxedProperty(BaseIndex(objReg, scratchReg, TimesOne), unboxedType_,
TypedOrValueRegister(R0));
if (popR1)
masm.addToStackPtr(ImmWord(sizeof(size_t)));
} else {
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::NativeGetter ||
acctype_ == ICGetElemNativeStub::ScriptedGetter);
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNativeName ||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
if (acctype_ == ICGetElemNativeStub::NativeGetter) {
// If calling a native getter, there is no chance of failure now.
// GetElem key (R1) is no longer needed.
if (popR1)
masm.addToStackPtr(ImmWord(sizeof(size_t)));
if (!emitCallNative(masm, objReg))
return false;
} else {
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::ScriptedGetter);
// Load function in scratchReg and ensure that it has a jit script.
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()),
scratchReg);
masm.branchIfFunctionHasNoScript(scratchReg, popR1 ? &failurePopR1 : &failure);
masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg);
masm.loadBaselineOrIonRaw(scratchReg, scratchReg, popR1 ? &failurePopR1 : &failure);
// At this point, we are guaranteed to successfully complete.
if (popR1)
masm.addToStackPtr(Imm32(sizeof(size_t)));
if (!emitCallScripted(masm, objReg))
return false;
}
}
// Enter type monitor IC to type-check result.
EmitEnterTypeMonitorIC(masm);
// Failure case - jump to next stub
if (popR1) {
masm.bind(&failurePopR1);
masm.pop(R1.scratchReg());
}
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// GetElem_String
//
@ -3364,7 +2572,7 @@ TryAttachNativeInDoesNotExistStub(JSContext* cx, HandleScript outerScript,
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
RootedObject lastProto(cx);
size_t protoChainDepth = SIZE_MAX;
if (!CheckHasNoSuchProperty(cx, obj.get(), name.get(), lastProto.address(), &protoChainDepth))
if (!CheckHasNoSuchProperty(cx, obj.get(), id, lastProto.address(), &protoChainDepth))
return true;
MOZ_ASSERT(protoChainDepth < SIZE_MAX);
@ -8179,101 +7387,6 @@ ICTypeUpdate_ObjectGroup::ICTypeUpdate_ObjectGroup(JitCode* stubCode, ObjectGrou
group_(group)
{ }
ICGetElemNativeStub::ICGetElemNativeStub(ICStub::Kind kind, JitCode* stubCode,
ICStub* firstMonitorStub,
ReceiverGuard guard, AccessType acctype,
bool needsAtomize, bool isSymbol)
: ICMonitoredStub(kind, stubCode, firstMonitorStub),
receiverGuard_(guard)
{
extra_ = (static_cast<uint16_t>(acctype) << ACCESSTYPE_SHIFT) |
(static_cast<uint16_t>(needsAtomize) << NEEDS_ATOMIZE_SHIFT) |
(static_cast<uint16_t>(isSymbol) << ISSYMBOL_SHIFT);
}
ICGetElemNativeStub::~ICGetElemNativeStub()
{ }
template <class T>
ICGetElemNativeGetterStub<T>::ICGetElemNativeGetterStub(
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
JSFunction* getter, uint32_t pcOffset)
: ICGetElemNativeStubImpl<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize),
getter_(getter),
pcOffset_(pcOffset)
{
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNativeName ||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
MOZ_ASSERT(acctype == ICGetElemNativeStub::NativeGetter ||
acctype == ICGetElemNativeStub::ScriptedGetter);
}
template <class T>
ICGetElem_NativePrototypeSlot<T>::ICGetElem_NativePrototypeSlot(
JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
const T* key, AccType acctype, bool needsAtomize, uint32_t offset,
JSObject* holder, Shape* holderShape)
: ICGetElemNativeSlotStub<T>(getGetElemStubKind<T>(ICStub::GetElem_NativePrototypeSlotName),
stubCode, firstMonitorStub, guard, key, acctype, needsAtomize, offset),
holder_(holder),
holderShape_(holderShape)
{ }
template <class T>
ICGetElemNativePrototypeCallStub<T>::ICGetElemNativePrototypeCallStub(
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype,
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
JSObject* holder, Shape* holderShape)
: ICGetElemNativeGetterStub<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize,
getter, pcOffset),
holder_(holder),
holderShape_(holderShape)
{}
template <class T>
/* static */ ICGetElem_NativePrototypeCallNative<T>*
ICGetElem_NativePrototypeCallNative<T>::Clone(JSContext* cx,
ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetElem_NativePrototypeCallNative<T>& other)
{
return ICStub::New<ICGetElem_NativePrototypeCallNative<T>>(cx, space, other.jitCode(),
firstMonitorStub, other.receiverGuard(), &other.key().get(), other.accessType(),
other.needsAtomize(), other.getter(), other.pcOffset_, other.holder(),
other.holderShape());
}
template ICGetElem_NativePrototypeCallNative<JS::Symbol*>*
ICGetElem_NativePrototypeCallNative<JS::Symbol*>::Clone(JSContext*, ICStubSpace*, ICStub*,
ICGetElem_NativePrototypeCallNative<JS::Symbol*>&);
template ICGetElem_NativePrototypeCallNative<js::PropertyName*>*
ICGetElem_NativePrototypeCallNative<js::PropertyName*>::Clone(JSContext*, ICStubSpace*, ICStub*,
ICGetElem_NativePrototypeCallNative<js::PropertyName*>&);
template <class T>
/* static */ ICGetElem_NativePrototypeCallScripted<T>*
ICGetElem_NativePrototypeCallScripted<T>::Clone(JSContext* cx,
ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetElem_NativePrototypeCallScripted<T>& other)
{
return ICStub::New<ICGetElem_NativePrototypeCallScripted<T>>(cx, space, other.jitCode(),
firstMonitorStub, other.receiverGuard(), &other.key().get(), other.accessType(),
other.needsAtomize(), other.getter(), other.pcOffset_, other.holder(),
other.holderShape());
}
template ICGetElem_NativePrototypeCallScripted<JS::Symbol*>*
ICGetElem_NativePrototypeCallScripted<JS::Symbol*>::Clone(JSContext*, ICStubSpace*, ICStub*,
ICGetElem_NativePrototypeCallScripted<JS::Symbol*>&);
template ICGetElem_NativePrototypeCallScripted<js::PropertyName*>*
ICGetElem_NativePrototypeCallScripted<js::PropertyName*>::Clone(JSContext*, ICStubSpace*, ICStub*,
ICGetElem_NativePrototypeCallScripted<js::PropertyName*>&);
ICGetElem_Dense::ICGetElem_Dense(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape)
: ICMonitoredStub(GetElem_Dense, stubCode, firstMonitorStub),
shape_(shape)

Просмотреть файл

@ -419,411 +419,6 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
};
};
class ICGetElemNativeStub : public ICMonitoredStub
{
public:
enum AccessType { FixedSlot = 0, DynamicSlot, UnboxedProperty, NativeGetter, ScriptedGetter, NumAccessTypes };
protected:
HeapReceiverGuard receiverGuard_;
static const unsigned NEEDS_ATOMIZE_SHIFT = 0;
static const uint16_t NEEDS_ATOMIZE_MASK = 0x1;
static const unsigned ACCESSTYPE_SHIFT = 1;
static const uint16_t ACCESSTYPE_MASK = 0x7;
static const unsigned ISSYMBOL_SHIFT = 4;
static const uint16_t ISSYMBOL_MASK = 0x1;
static_assert(ACCESSTYPE_MASK >= NumAccessTypes, "ACCESSTYPE_MASK must cover all possible AccessType values");
ICGetElemNativeStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, AccessType acctype, bool needsAtomize, bool isSymbol);
~ICGetElemNativeStub();
public:
HeapReceiverGuard& receiverGuard() {
return receiverGuard_;
}
static size_t offsetOfReceiverGuard() {
return offsetof(ICGetElemNativeStub, receiverGuard_);
}
AccessType accessType() const {
return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK);
}
bool needsAtomize() const {
return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK;
}
bool isSymbol() const {
return (extra_ >> ISSYMBOL_SHIFT) & ISSYMBOL_MASK;
}
};
template <class T>
class ICGetElemNativeStubImpl : public ICGetElemNativeStub
{
protected:
GCPtr<T> key_;
ICGetElemNativeStubImpl(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccessType acctype, bool needsAtomize)
: ICGetElemNativeStub(kind, stubCode, firstMonitorStub, guard, acctype, needsAtomize,
mozilla::IsSame<T, JS::Symbol*>::value),
key_(*key)
{}
public:
GCPtr<T>& key() {
return key_;
}
static size_t offsetOfKey() {
return offsetof(ICGetElemNativeStubImpl, key_);
}
};
typedef ICGetElemNativeStub::AccessType AccType;
template <class T>
class ICGetElemNativeSlotStub : public ICGetElemNativeStubImpl<T>
{
protected:
uint32_t offset_;
ICGetElemNativeSlotStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
uint32_t offset)
: ICGetElemNativeStubImpl<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize),
offset_(offset)
{
MOZ_ASSERT(kind == ICStub::GetElem_NativeSlotName ||
kind == ICStub::GetElem_NativeSlotSymbol ||
kind == ICStub::GetElem_NativePrototypeSlotName ||
kind == ICStub::GetElem_NativePrototypeSlotSymbol ||
kind == ICStub::GetElem_UnboxedPropertyName);
MOZ_ASSERT(acctype == ICGetElemNativeStub::FixedSlot ||
acctype == ICGetElemNativeStub::DynamicSlot ||
acctype == ICGetElemNativeStub::UnboxedProperty);
}
public:
uint32_t offset() const {
return offset_;
}
static size_t offsetOfOffset() {
return offsetof(ICGetElemNativeSlotStub, offset_);
}
};
template <class T>
class ICGetElemNativeGetterStub : public ICGetElemNativeStubImpl<T>
{
protected:
GCPtrFunction getter_;
uint32_t pcOffset_;
ICGetElemNativeGetterStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
JSFunction* getter, uint32_t pcOffset);
public:
GCPtrFunction& getter() {
return getter_;
}
static size_t offsetOfGetter() {
return offsetof(ICGetElemNativeGetterStub, getter_);
}
static size_t offsetOfPCOffset() {
return offsetof(ICGetElemNativeGetterStub, pcOffset_);
}
};
template <class T>
ICStub::Kind
getGetElemStubKind(ICStub::Kind kind)
{
MOZ_ASSERT(kind == ICStub::GetElem_NativeSlotName ||
kind == ICStub::GetElem_NativePrototypeSlotName ||
kind == ICStub::GetElem_NativePrototypeCallNativeName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedName);
return static_cast<ICStub::Kind>(kind + mozilla::IsSame<T, JS::Symbol*>::value);
}
template <class T>
class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub<T>
{
friend class ICStubSpace;
ICGetElem_NativeSlot(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
const T* key, AccType acctype, bool needsAtomize, uint32_t offset)
: ICGetElemNativeSlotStub<T>(getGetElemStubKind<T>(ICStub::GetElem_NativeSlotName),
stubCode, firstMonitorStub, guard,
key, acctype, needsAtomize, offset)
{}
};
class ICGetElem_NativeSlotName :
public ICGetElem_NativeSlot<PropertyName*>
{};
class ICGetElem_NativeSlotSymbol :
public ICGetElem_NativeSlot<JS::Symbol*>
{};
template <class T>
class ICGetElem_UnboxedProperty : public ICGetElemNativeSlotStub<T>
{
friend class ICStubSpace;
ICGetElem_UnboxedProperty(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype,
bool needsAtomize, uint32_t offset)
: ICGetElemNativeSlotStub<T>(ICStub::GetElem_UnboxedPropertyName, stubCode, firstMonitorStub,
guard, key, acctype, needsAtomize, offset)
{}
};
class ICGetElem_UnboxedPropertyName :
public ICGetElem_UnboxedProperty<PropertyName*>
{};
template <class T>
class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub<T>
{
friend class ICStubSpace;
GCPtrObject holder_;
GCPtrShape holderShape_;
ICGetElem_NativePrototypeSlot(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
const T* key, AccType acctype, bool needsAtomize, uint32_t offset,
JSObject* holder, Shape* holderShape);
public:
GCPtrObject& holder() {
return holder_;
}
static size_t offsetOfHolder() {
return offsetof(ICGetElem_NativePrototypeSlot, holder_);
}
GCPtrShape& holderShape() {
return holderShape_;
}
static size_t offsetOfHolderShape() {
return offsetof(ICGetElem_NativePrototypeSlot, holderShape_);
}
};
class ICGetElem_NativePrototypeSlotName :
public ICGetElem_NativePrototypeSlot<PropertyName*>
{};
class ICGetElem_NativePrototypeSlotSymbol :
public ICGetElem_NativePrototypeSlot<JS::Symbol*>
{};
template <class T>
class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub<T>
{
friend class ICStubSpace;
GCPtrObject holder_;
GCPtrShape holderShape_;
protected:
ICGetElemNativePrototypeCallStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype,
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
JSObject* holder, Shape* holderShape);
public:
GCPtrObject& holder() {
return holder_;
}
static size_t offsetOfHolder() {
return offsetof(ICGetElemNativePrototypeCallStub, holder_);
}
GCPtrShape& holderShape() {
return holderShape_;
}
static size_t offsetOfHolderShape() {
return offsetof(ICGetElemNativePrototypeCallStub, holderShape_);
}
};
template <class T>
class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub<T>
{
friend class ICStubSpace;
ICGetElem_NativePrototypeCallNative(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype,
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
JSObject* holder, Shape* holderShape)
: ICGetElemNativePrototypeCallStub<T>(getGetElemStubKind<T>(
ICStub::GetElem_NativePrototypeCallNativeName),
stubCode, firstMonitorStub, guard, key,
acctype, needsAtomize, getter, pcOffset, holder,
holderShape)
{}
public:
static ICGetElem_NativePrototypeCallNative<T>* Clone(JSContext* cx, ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetElem_NativePrototypeCallNative<T>& other);
};
class ICGetElem_NativePrototypeCallNativeName :
public ICGetElem_NativePrototypeCallNative<PropertyName*>
{};
class ICGetElem_NativePrototypeCallNativeSymbol :
public ICGetElem_NativePrototypeCallNative<JS::Symbol*>
{};
template <class T>
class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub<T>
{
friend class ICStubSpace;
ICGetElem_NativePrototypeCallScripted(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, const T* key, AccType acctype,
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
JSObject* holder, Shape* holderShape)
: ICGetElemNativePrototypeCallStub<T>(getGetElemStubKind<T>(
ICStub::GetElem_NativePrototypeCallScriptedName),
stubCode, firstMonitorStub, guard, key, acctype,
needsAtomize, getter, pcOffset, holder, holderShape)
{}
public:
static ICGetElem_NativePrototypeCallScripted<T>*
Clone(JSContext* cx, ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetElem_NativePrototypeCallScripted<T>& other);
};
class ICGetElem_NativePrototypeCallScriptedName :
public ICGetElem_NativePrototypeCallScripted<PropertyName*>
{};
class ICGetElem_NativePrototypeCallScriptedSymbol :
public ICGetElem_NativePrototypeCallScripted<JS::Symbol*>
{};
// Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs.
template <class T>
class ICGetElemNativeCompiler : public ICStubCompiler
{
ICStub* firstMonitorStub_;
HandleObject obj_;
HandleObject holder_;
Handle<T> key_;
AccType acctype_;
bool needsAtomize_;
uint32_t offset_;
JSValueType unboxedType_;
HandleFunction getter_;
uint32_t pcOffset_;
MOZ_MUST_USE bool emitCheckKey(MacroAssembler& masm, Label& failure);
MOZ_MUST_USE bool emitCallNative(MacroAssembler& masm, Register objReg);
MOZ_MUST_USE bool emitCallScripted(MacroAssembler& masm, Register objReg);
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
protected:
virtual int32_t getKey() const {
MOZ_ASSERT(static_cast<int32_t>(acctype_) <= 7);
MOZ_ASSERT(static_cast<int32_t>(unboxedType_) <= 15);
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(needsAtomize_) << 17) |
(static_cast<int32_t>(acctype_) << 18) |
(static_cast<int32_t>(unboxedType_) << 21) |
(static_cast<int32_t>(mozilla::IsSame<JS::Symbol*, T>::value) << 25) |
(HeapReceiverGuard::keyBits(obj_) << 26);
}
public:
ICGetElemNativeCompiler(JSContext* cx, ICStub::Kind kind, ICStub* firstMonitorStub,
HandleObject obj, HandleObject holder, Handle<T> key, AccType acctype,
bool needsAtomize, uint32_t offset,
JSValueType unboxedType = JSVAL_TYPE_MAGIC)
: ICStubCompiler(cx, kind, Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
obj_(obj),
holder_(holder),
key_(key),
acctype_(acctype),
needsAtomize_(needsAtomize),
offset_(offset),
unboxedType_(unboxedType),
getter_(nullptr),
pcOffset_(0)
{}
ICGetElemNativeCompiler(JSContext* cx, ICStub::Kind kind, ICStub* firstMonitorStub,
HandleObject obj, HandleObject holder, Handle<T> key, AccType acctype,
bool needsAtomize, HandleFunction getter, uint32_t pcOffset)
: ICStubCompiler(cx, kind, Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
obj_(obj),
holder_(holder),
key_(key),
acctype_(acctype),
needsAtomize_(needsAtomize),
offset_(0),
unboxedType_(JSVAL_TYPE_MAGIC),
getter_(getter),
pcOffset_(pcOffset)
{}
ICStub* getStub(ICStubSpace* space) {
RootedReceiverGuard guard(cx, ReceiverGuard(obj_));
if (kind == ICStub::GetElem_NativeSlotName || kind == ICStub::GetElem_NativeSlotSymbol) {
MOZ_ASSERT(obj_ == holder_);
return newStub<ICGetElem_NativeSlot<T>>(
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
needsAtomize_, offset_);
}
if (kind == ICStub::GetElem_UnboxedPropertyName) {
MOZ_ASSERT(obj_ == holder_);
return newStub<ICGetElem_UnboxedProperty<T>>(
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
needsAtomize_, offset_);
}
MOZ_ASSERT(obj_ != holder_);
RootedShape holderShape(cx, holder_->as<NativeObject>().lastProperty());
if (kind == ICStub::GetElem_NativePrototypeSlotName ||
kind == ICStub::GetElem_NativePrototypeSlotSymbol)
{
return newStub<ICGetElem_NativePrototypeSlot<T>>(
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
needsAtomize_, offset_, holder_, holderShape);
}
if (kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
kind == ICStub::GetElem_NativePrototypeCallNativeName) {
return newStub<ICGetElem_NativePrototypeCallNative<T>>(
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
needsAtomize_, getter_, pcOffset_, holder_, holderShape);
}
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
if (kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol) {
return newStub<ICGetElem_NativePrototypeCallScripted<T>>(
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
needsAtomize_, getter_, pcOffset_, holder_, holderShape);
}
MOZ_CRASH("Invalid kind.");
}
};
class ICGetElem_String : public ICStub
{
friend class ICStubSpace;

Просмотреть файл

@ -49,15 +49,6 @@ namespace jit {
_(Call_IsSuspendedStarGenerator) \
\
_(GetElem_Fallback) \
_(GetElem_NativeSlotName) \
_(GetElem_NativeSlotSymbol) \
_(GetElem_NativePrototypeSlotName) \
_(GetElem_NativePrototypeSlotSymbol) \
_(GetElem_NativePrototypeCallNativeName) \
_(GetElem_NativePrototypeCallNativeSymbol) \
_(GetElem_NativePrototypeCallScriptedName) \
_(GetElem_NativePrototypeCallScriptedSymbol) \
_(GetElem_UnboxedPropertyName) \
_(GetElem_String) \
_(GetElem_Dense) \
_(GetElem_UnboxedArray) \

Просмотреть файл

@ -1020,15 +1020,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
// Either an object or magic arguments.
return MIRType::Value;
case ICStub::GetElem_NativeSlotName:
case ICStub::GetElem_NativeSlotSymbol:
case ICStub::GetElem_NativePrototypeSlotName:
case ICStub::GetElem_NativePrototypeSlotSymbol:
case ICStub::GetElem_NativePrototypeCallNativeName:
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
case ICStub::GetElem_NativePrototypeCallScriptedName:
case ICStub::GetElem_NativePrototypeCallScriptedSymbol:
case ICStub::GetElem_UnboxedPropertyName:
case ICStub::GetElem_String:
case ICStub::GetElem_Dense:
case ICStub::GetElem_TypedArray:

Просмотреть файл

@ -19,16 +19,18 @@ using namespace js::jit;
using mozilla::Maybe;
GetPropIRGenerator::GetPropIRGenerator(JSContext* cx, jsbytecode* pc, ICStubEngine engine,
CacheKind cacheKind,
bool* isTemporarilyUnoptimizable,
HandleValue val, HandlePropertyName name,
HandleValue val, HandleValue idVal,
MutableHandleValue res)
: writer(cx),
cx_(cx),
pc_(pc),
val_(val),
name_(name),
idVal_(idVal),
res_(res),
engine_(engine),
cacheKind_(cacheKind),
isTemporarilyUnoptimizable_(isTemporarilyUnoptimizable),
preliminaryObjectAction_(PreliminaryObjectAction::None)
{}
@ -51,36 +53,50 @@ GetPropIRGenerator::tryAttachStub()
AutoAssertNoPendingException aanpe(cx_);
ValOperandId valId(writer.setInputOperandId(0));
if (cacheKind_ == CacheKind::GetElem) {
MOZ_ASSERT(getElemKeyValueId().id() == 1);
writer.setInputOperandId(1);
}
RootedId id(cx_);
bool nameOrSymbol;
if (!ValueToNameOrSymbolId(cx_, idVal_, &id, &nameOrSymbol)) {
cx_->clearPendingException();
return false;
}
if (val_.isObject()) {
RootedObject obj(cx_, &val_.toObject());
ObjOperandId objId = writer.guardIsObject(valId);
if (tryAttachObjectLength(obj, objId))
return true;
if (tryAttachNative(obj, objId))
return true;
if (tryAttachUnboxed(obj, objId))
return true;
if (tryAttachUnboxedExpando(obj, objId))
return true;
if (tryAttachTypedObject(obj, objId))
return true;
if (tryAttachModuleNamespace(obj, objId))
return true;
if (tryAttachWindowProxy(obj, objId))
return true;
if (tryAttachProxy(obj, objId))
return true;
if (nameOrSymbol) {
if (tryAttachObjectLength(obj, objId, id))
return true;
if (tryAttachNative(obj, objId, id))
return true;
if (tryAttachUnboxed(obj, objId, id))
return true;
if (tryAttachUnboxedExpando(obj, objId, id))
return true;
if (tryAttachTypedObject(obj, objId, id))
return true;
if (tryAttachModuleNamespace(obj, objId, id))
return true;
if (tryAttachWindowProxy(obj, objId, id))
return true;
if (tryAttachProxy(obj, objId, id))
return true;
}
return false;
}
if (tryAttachPrimitive(valId))
return true;
if (tryAttachStringLength(valId))
return true;
if (tryAttachMagicArguments(valId))
return true;
if (nameOrSymbol) {
if (tryAttachPrimitive(valId, id))
return true;
if (tryAttachStringLength(valId, id))
return true;
if (tryAttachMagicArguments(valId, id))
return true;
}
return false;
}
@ -98,7 +114,7 @@ IsCacheableNoProperty(JSContext* cx, JSObject* obj, JSObject* holder, Shape* sha
if (*pc == JSOP_GETXPROP)
return false;
return CheckHasNoSuchProperty(cx, obj, JSID_TO_ATOM(id)->asPropertyName());
return CheckHasNoSuchProperty(cx, obj, id);
}
enum NativeGetPropCacheability {
@ -301,20 +317,20 @@ EmitCallGetterResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
}
bool
GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId, HandleId id)
{
RootedShape shape(cx_);
RootedNativeObject holder(cx_);
RootedId id(cx_, NameToId(name_));
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, obj, id, &holder, &shape, pc_,
engine_, isTemporarilyUnoptimizable_);
switch (type) {
case CanAttachNone:
return false;
case CanAttachReadSlot:
maybeEmitIdGuard(id);
if (holder) {
EnsureTrackPropertyTypes(cx_, holder, NameToId(name_));
EnsureTrackPropertyTypes(cx_, holder, id);
if (obj == holder) {
// See the comment in StripPreliminaryObjectStubs.
if (IsPreliminaryObject(obj))
@ -327,6 +343,7 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId)
EmitReadSlotReturn(writer, obj, holder, shape);
return true;
case CanAttachCallGetter:
maybeEmitIdGuard(id);
EmitCallGetterResult(writer, obj, holder, shape, objId);
return true;
}
@ -335,7 +352,7 @@ GetPropIRGenerator::tryAttachNative(HandleObject obj, ObjOperandId objId)
}
bool
GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id)
{
// Attach a stub when the receiver is a WindowProxy and we are calling some
// kinds of JSNative getters on the Window object (the global object).
@ -354,7 +371,6 @@ GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId)
HandleObject windowObj = cx_->global();
RootedShape shape(cx_);
RootedNativeObject holder(cx_);
RootedId id(cx_, NameToId(name_));
NativeGetPropCacheability type = CanAttachNativeGetProp(cx_, windowObj, id, &holder, &shape, pc_,
engine_, isTemporarilyUnoptimizable_);
if (type != CanAttachCallGetter ||
@ -372,6 +388,7 @@ GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId)
// Guard the incoming object is a WindowProxy and inline a getter call based
// on the Window object.
maybeEmitIdGuard(id);
writer.guardClass(objId, GuardClassKind::WindowProxy);
ObjOperandId windowObjId = writer.loadObject(windowObj);
EmitCallGetterResult(writer, windowObj, holder, shape, windowObjId);
@ -379,7 +396,7 @@ GetPropIRGenerator::tryAttachWindowProxy(HandleObject obj, ObjOperandId objId)
}
bool
GetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id)
{
MOZ_ASSERT(obj->is<ProxyObject>());
@ -389,22 +406,32 @@ GetPropIRGenerator::tryAttachGenericProxy(HandleObject obj, ObjOperandId objId)
// the specialized stubs
writer.guardNotDOMProxy(objId);
writer.callProxyGetResult(objId, NameToId(name_));
if (cacheKind_ == CacheKind::GetProp) {
writer.callProxyGetResult(objId, id);
} else {
// We could call maybeEmitIdGuard here and then emit CallProxyGetResult,
// but for GetElem we prefer to attach a stub that can handle any Value
// so we don't attach a new stub for every id.
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
writer.callProxyGetByValueResult(objId, getElemKeyValueId());
}
writer.typeMonitorResult();
return true;
}
bool
GetPropIRGenerator::tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id)
{
MOZ_ASSERT(IsCacheableDOMProxy(obj));
maybeEmitIdGuard(id);
writer.guardShape(objId, obj->maybeShape());
// No need for more guards: we know this is a DOM proxy, since the shape
// guard enforces a given JSClass, so just go ahead and emit the call to
// ProxyGet.
writer.callProxyGetResult(objId, NameToId(name_));
writer.callProxyGetResult(objId, id);
writer.typeMonitorResult();
return true;
}
@ -444,7 +471,7 @@ CheckDOMProxyExpandoDoesNotShadow(CacheIRWriter& writer, JSObject* obj, jsid id,
}
bool
GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id)
{
MOZ_ASSERT(IsCacheableDOMProxy(obj));
@ -452,13 +479,13 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
RootedNativeObject holder(cx_);
RootedShape shape(cx_);
RootedId id(cx_, NameToId(name_));
NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape,
pc_, engine_,
isTemporarilyUnoptimizable_);
if (canCache == CanAttachNone)
return false;
maybeEmitIdGuard(id);
writer.guardShape(objId, obj->maybeShape());
// Guard that our expando object hasn't started shadowing this property.
@ -495,42 +522,42 @@ GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId o
}
bool
GetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<ProxyObject>())
return false;
// Skim off DOM proxies.
if (IsCacheableDOMProxy(obj)) {
RootedId id(cx_, NameToId(name_));
DOMProxyShadowsResult shadows = GetDOMProxyShadowsCheck()(cx_, obj, id);
if (shadows == ShadowCheckFailed) {
cx_->clearPendingException();
return false;
}
if (DOMProxyIsShadowing(shadows))
return tryAttachDOMProxyShadowed(obj, objId);
return tryAttachDOMProxyShadowed(obj, objId, id);
MOZ_ASSERT(shadows == DoesntShadow || shadows == DoesntShadowUnique);
return tryAttachDOMProxyUnshadowed(obj, objId);
return tryAttachDOMProxyUnshadowed(obj, objId, id);
}
return tryAttachGenericProxy(obj, objId);
return tryAttachGenericProxy(obj, objId, id);
}
bool
GetPropIRGenerator::tryAttachUnboxed(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachUnboxed(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<UnboxedPlainObject>())
return false;
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(name_);
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
if (!property)
return false;
if (!cx_->runtime()->jitSupportsFloatingPoint)
return false;
maybeEmitIdGuard(id);
writer.guardGroup(objId, obj->group());
writer.loadUnboxedPropertyResult(objId, property->type,
UnboxedPlainObject::offsetOfData() + property->offset);
@ -544,7 +571,7 @@ GetPropIRGenerator::tryAttachUnboxed(HandleObject obj, ObjOperandId objId)
}
bool
GetPropIRGenerator::tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<UnboxedPlainObject>())
return false;
@ -553,17 +580,18 @@ GetPropIRGenerator::tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId
if (!expando)
return false;
Shape* shape = expando->lookup(cx_, NameToId(name_));
Shape* shape = expando->lookup(cx_, id);
if (!shape || !shape->hasDefaultGetter() || !shape->hasSlot())
return false;
maybeEmitIdGuard(id);
EmitReadSlotResult(writer, obj, obj, shape, objId);
EmitReadSlotReturn(writer, obj, obj, shape);
return true;
}
bool
GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<TypedObject>() ||
!cx_->runtime()->jitSupportsFloatingPoint ||
@ -578,7 +606,7 @@ GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId)
StructTypeDescr* structDescr = &typedObj->typeDescr().as<StructTypeDescr>();
size_t fieldIndex;
if (!structDescr->fieldIndex(NameToId(name_), &fieldIndex))
if (!structDescr->fieldIndex(id, &fieldIndex))
return false;
TypeDescr* fieldDescr = &structDescr->fieldDescr(fieldIndex);
@ -591,6 +619,7 @@ GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId)
uint32_t fieldOffset = structDescr->fieldOffset(fieldIndex);
uint32_t typeDescr = SimpleTypeDescrKey(&fieldDescr->as<SimpleTypeDescr>());
maybeEmitIdGuard(id);
writer.guardNoDetachedTypedObjects();
writer.guardShape(objId, shape);
writer.loadTypedObjectResult(objId, fieldOffset, layout, typeDescr);
@ -614,9 +643,9 @@ GetPropIRGenerator::tryAttachTypedObject(HandleObject obj, ObjOperandId objId)
}
bool
GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (name_ != cx_->names().length)
if (!JSID_IS_ATOM(id, cx_->names().length))
return false;
if (obj->is<ArrayObject>()) {
@ -625,6 +654,7 @@ GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
if (obj->as<ArrayObject>().length() > INT32_MAX)
return false;
maybeEmitIdGuard(id);
writer.guardClass(objId, GuardClassKind::Array);
writer.loadInt32ArrayLengthResult(objId);
writer.returnFromIC();
@ -632,6 +662,7 @@ GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
}
if (obj->is<UnboxedArrayObject>()) {
maybeEmitIdGuard(id);
writer.guardClass(objId, GuardClassKind::UnboxedArray);
writer.loadUnboxedArrayLengthResult(objId);
writer.returnFromIC();
@ -639,6 +670,7 @@ GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
}
if (obj->is<ArgumentsObject>() && !obj->as<ArgumentsObject>().hasOverriddenLength()) {
maybeEmitIdGuard(id);
if (obj->is<MappedArgumentsObject>()) {
writer.guardClass(objId, GuardClassKind::MappedArguments);
} else {
@ -654,7 +686,7 @@ GetPropIRGenerator::tryAttachObjectLength(HandleObject obj, ObjOperandId objId)
}
bool
GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId)
GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, HandleId id)
{
if (!obj->is<ModuleNamespaceObject>())
return false;
@ -662,7 +694,7 @@ GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objI
Rooted<ModuleNamespaceObject*> ns(cx_, &obj->as<ModuleNamespaceObject>());
RootedModuleEnvironmentObject env(cx_);
RootedShape shape(cx_);
if (!ns->bindings().lookup(NameToId(name_), env.address(), shape.address()))
if (!ns->bindings().lookup(id, env.address(), shape.address()))
return false;
// Don't emit a stub until the target binding has been initialized.
@ -673,6 +705,7 @@ GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objI
EnsureTrackPropertyTypes(cx_, env, shape->propid());
// Check for the specific namespace object.
maybeEmitIdGuard(id);
writer.guardSpecificObject(objId, ns);
ObjOperandId envId = writer.loadObject(env);
@ -682,12 +715,12 @@ GetPropIRGenerator::tryAttachModuleNamespace(HandleObject obj, ObjOperandId objI
}
bool
GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId)
GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId, HandleId id)
{
JSValueType primitiveType;
RootedNativeObject proto(cx_);
if (val_.isString()) {
if (name_ == cx_->names().length) {
if (JSID_IS_ATOM(id, cx_->names().length)) {
// String length is special-cased, see js::GetProperty.
return false;
}
@ -710,7 +743,6 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId)
return false;
// Instantiate this property, for use during Ion compilation.
RootedId id(cx_, NameToId(name_));
if (IsIonEnabled(cx_))
EnsureTrackPropertyTypes(cx_, proto, id);
@ -720,6 +752,7 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId)
return false;
writer.guardType(valId, primitiveType);
maybeEmitIdGuard(id);
ObjOperandId protoId = writer.loadObject(proto);
writer.guardShape(protoId, proto->lastProperty());
@ -729,37 +762,61 @@ GetPropIRGenerator::tryAttachPrimitive(ValOperandId valId)
}
bool
GetPropIRGenerator::tryAttachStringLength(ValOperandId valId)
GetPropIRGenerator::tryAttachStringLength(ValOperandId valId, HandleId id)
{
if (!val_.isString() || name_ != cx_->names().length)
if (!val_.isString() || !JSID_IS_ATOM(id, cx_->names().length))
return false;
StringOperandId strId = writer.guardIsString(valId);
maybeEmitIdGuard(id);
writer.loadStringLengthResult(strId);
writer.returnFromIC();
return true;
}
bool
GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId)
GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
{
if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
return false;
if (name_ != cx_->names().length && name_ != cx_->names().callee)
if (!JSID_IS_ATOM(id, cx_->names().length) && !JSID_IS_ATOM(id, cx_->names().callee))
return false;
maybeEmitIdGuard(id);
writer.guardMagicValue(valId, JS_OPTIMIZED_ARGUMENTS);
writer.guardFrameHasNoArgumentsObject();
if (name_ == cx_->names().length) {
if (JSID_IS_ATOM(id, cx_->names().length)) {
writer.loadFrameNumActualArgsResult();
writer.returnFromIC();
} else {
MOZ_ASSERT(name_ == cx_->names().callee);
MOZ_ASSERT(JSID_IS_ATOM(id, cx_->names().callee));
writer.loadFrameCalleeResult();
writer.typeMonitorResult();
}
return true;
}
void
GetPropIRGenerator::maybeEmitIdGuard(jsid id)
{
if (cacheKind_ == CacheKind::GetProp) {
// Constant PropertyName, no guards necessary.
MOZ_ASSERT(&idVal_.toString()->asAtom() == JSID_TO_ATOM(id));
return;
}
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
ValOperandId valId = getElemKeyValueId();
if (JSID_IS_SYMBOL(id)) {
SymbolOperandId symId = writer.guardIsSymbol(valId);
writer.guardSpecificSymbol(symId, JSID_TO_SYMBOL(id));
} else {
MOZ_ASSERT(JSID_IS_ATOM(id));
StringOperandId strId = writer.guardIsString(valId);
writer.guardSpecificAtom(strId, JSID_TO_ATOM(id));
}
}

Просмотреть файл

@ -86,6 +86,13 @@ class StringOperandId : public OperandId
explicit StringOperandId(uint16_t id) : OperandId(id) {}
};
class SymbolOperandId : public OperandId
{
public:
SymbolOperandId() = default;
explicit SymbolOperandId(uint16_t id) : OperandId(id) {}
};
class TypedOperandId : public OperandId
{
JSValueType type_;
@ -97,13 +104,23 @@ class TypedOperandId : public OperandId
MOZ_IMPLICIT TypedOperandId(StringOperandId id)
: OperandId(id.id()), type_(JSVAL_TYPE_STRING)
{}
MOZ_IMPLICIT TypedOperandId(SymbolOperandId id)
: OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL)
{}
JSValueType type() const { return type_; }
};
enum class CacheKind : uint8_t
{
GetProp,
GetElem,
};
#define CACHE_IR_OPS(_) \
_(GuardIsObject) \
_(GuardIsString) \
_(GuardIsSymbol) \
_(GuardType) \
_(GuardShape) \
_(GuardGroup) \
@ -112,6 +129,8 @@ class TypedOperandId : public OperandId
_(GuardIsProxy) \
_(GuardNotDOMProxy) \
_(GuardSpecificObject) \
_(GuardSpecificAtom) \
_(GuardSpecificSymbol) \
_(GuardNoDetachedTypedObjects) \
_(GuardMagicValue) \
_(GuardFrameHasNoArgumentsObject) \
@ -138,6 +157,7 @@ class TypedOperandId : public OperandId
_(CallScriptedGetterResult) \
_(CallNativeGetterResult) \
_(CallProxyGetResult) \
_(CallProxyGetByValueResult) \
_(LoadUndefinedResult) \
\
_(TypeMonitorResult) \
@ -158,6 +178,8 @@ class StubField
Shape,
ObjectGroup,
JSObject,
Symbol,
String,
Id,
// These fields take up 64 bits on all platforms.
@ -342,6 +364,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOpWithOperandId(CacheOp::GuardIsString, val);
return StringOperandId(val.id());
}
SymbolOperandId guardIsSymbol(ValOperandId val) {
writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
return SymbolOperandId(val.id());
}
void guardType(ValOperandId val, JSValueType type) {
writeOpWithOperandId(CacheOp::GuardType, val);
static_assert(sizeof(type) == sizeof(uint8_t), "JSValueType should fit in a byte");
@ -375,6 +401,14 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOpWithOperandId(CacheOp::GuardSpecificObject, obj);
addStubField(uintptr_t(expected), StubField::Type::JSObject);
}
void guardSpecificAtom(StringOperandId str, JSAtom* expected) {
writeOpWithOperandId(CacheOp::GuardSpecificAtom, str);
addStubField(uintptr_t(expected), StubField::Type::String);
}
void guardSpecificSymbol(SymbolOperandId sym, JS::Symbol* expected) {
writeOpWithOperandId(CacheOp::GuardSpecificSymbol, sym);
addStubField(uintptr_t(expected), StubField::Type::Symbol);
}
void guardMagicValue(ValOperandId val, JSWhyMagic magic) {
writeOpWithOperandId(CacheOp::GuardMagicValue, val);
buffer_.writeByte(uint32_t(magic));
@ -485,6 +519,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOpWithOperandId(CacheOp::CallProxyGetResult, obj);
addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
}
void callProxyGetByValueResult(ObjOperandId obj, ValOperandId idVal) {
writeOpWithOperandId(CacheOp::CallProxyGetByValueResult, obj);
writeOperandId(idVal);
}
void typeMonitorResult() {
writeOp(CacheOp::TypeMonitorResult);
@ -522,6 +560,7 @@ class MOZ_RAII CacheIRReader
ValOperandId valOperandId() { return ValOperandId(buffer_.readByte()); }
ObjOperandId objOperandId() { return ObjOperandId(buffer_.readByte()); }
StringOperandId stringOperandId() { return StringOperandId(buffer_.readByte()); }
SymbolOperandId symbolOperandId() { return SymbolOperandId(buffer_.readByte()); }
uint32_t stubOffset() { return buffer_.readByte() * sizeof(uintptr_t); }
GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
@ -561,38 +600,48 @@ class MOZ_RAII GetPropIRGenerator
JSContext* cx_;
jsbytecode* pc_;
HandleValue val_;
HandlePropertyName name_;
HandleValue idVal_;
MutableHandleValue res_;
ICStubEngine engine_;
CacheKind cacheKind_;
bool* isTemporarilyUnoptimizable_;
enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
PreliminaryObjectAction preliminaryObjectAction_;
bool tryAttachNative(HandleObject obj, ObjOperandId objId);
bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId);
bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId);
bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId);
bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId);
bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId);
bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId);
bool tryAttachNative(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId);
bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId);
bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId);
bool tryAttachProxy(HandleObject obj, ObjOperandId objId);
bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachPrimitive(ValOperandId valId);
bool tryAttachStringLength(ValOperandId valId);
bool tryAttachMagicArguments(ValOperandId valId);
bool tryAttachPrimitive(ValOperandId valId, HandleId id);
bool tryAttachStringLength(ValOperandId valId, HandleId id);
bool tryAttachMagicArguments(ValOperandId valId, HandleId id);
ValOperandId getElemKeyValueId() const {
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
return ValOperandId(1);
}
// If this is a GetElem cache, emit instructions to guard the incoming Value
// matches |id|.
void maybeEmitIdGuard(jsid id);
GetPropIRGenerator(const GetPropIRGenerator&) = delete;
GetPropIRGenerator& operator=(const GetPropIRGenerator&) = delete;
public:
GetPropIRGenerator(JSContext* cx, jsbytecode* pc, ICStubEngine engine,
GetPropIRGenerator(JSContext* cx, jsbytecode* pc, ICStubEngine engine, CacheKind cacheKind,
bool* isTemporarilyUnoptimizable,
HandleValue val, HandlePropertyName name, MutableHandleValue res);
HandleValue val, HandleValue idVal, MutableHandleValue res);
bool tryAttachStub();
@ -602,14 +651,9 @@ class MOZ_RAII GetPropIRGenerator
bool shouldNotePreliminaryObjectStub() const {
return preliminaryObjectAction_ == PreliminaryObjectAction::NotePreliminary;
}
const CacheIRWriter& writerRef() const {
return writer;
}
};
enum class CacheKind : uint8_t
{
GetProp
const CacheIRWriter& writerRef() const { return writer; }
CacheKind cacheKind() const { return cacheKind_; }
};
} // namespace jit

Просмотреть файл

@ -1358,20 +1358,6 @@ CanAttachNativeGetProp(JSContext* cx, const GetPropCache& cache,
return GetPropertyIC::CanAttachNone;
}
static bool
EqualStringsHelper(JSString* str1, JSString* str2)
{
MOZ_ASSERT(str1->isAtom());
MOZ_ASSERT(!str2->isAtom());
MOZ_ASSERT(str1->length() == str2->length());
JSLinearString* str2Linear = str2->ensureLinear(nullptr);
if (!str2Linear)
return false;
return EqualChars(&str1->asLinear(), str2Linear);
}
static void
EmitIdGuard(MacroAssembler& masm, jsid id, TypedOrValueRegister idReg, Register objReg,
Register scratchReg, Label* failures)
@ -2144,8 +2130,9 @@ GetPropertyIC::tryAttachModuleNamespace(JSContext* cx, HandleScript outerScript,
JS::TrackedOutcome::ICGetPropStub_ReadSlot);
}
static bool
ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id, bool* nameOrSymbol)
bool
jit::ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
bool* nameOrSymbol)
{
*nameOrSymbol = false;

Просмотреть файл

@ -846,6 +846,9 @@ bool IsCacheableGetPropCallScripted(JSObject* obj, JSObject* holder, Shape* shap
bool* isTemporarilyUnoptimizable = nullptr);
bool IsCacheableGetPropCallNative(JSObject* obj, JSObject* holder, Shape* shape);
bool ValueToNameOrSymbolId(JSContext* cx, HandleValue idval, MutableHandleId id,
bool* nameOrSymbol);
} // namespace jit
} // namespace js

Просмотреть файл

@ -5439,8 +5439,7 @@ class MWasmTruncateToInt64
trapOffset_(trapOffset)
{
setResultType(MIRType::Int64);
setGuard(); // not removable because of possible side-effects.
setMovable();
setGuard(); // neither removable nor movable because of possible side-effects.
}
public:
@ -5472,8 +5471,7 @@ class MWasmTruncateToInt32
: MUnaryInstruction(def), isUnsigned_(isUnsigned), trapOffset_(trapOffset)
{
setResultType(MIRType::Int32);
setGuard(); // not removable because of possible side-effects.
setMovable();
setGuard(); // neither removable nor movable because of possible side-effects.
}
public:
@ -7032,8 +7030,10 @@ class MDiv : public MBinaryArithInstruction
div->unsigned_ = unsignd;
div->trapOnError_ = trapOnError;
div->trapOffset_ = trapOffset;
if (trapOnError)
if (trapOnError) {
div->setGuard(); // not removable because of possible side-effects.
div->setNotMovable();
}
div->setMustPreserveNaN(mustPreserveNaN);
if (type == MIRType::Int32)
div->setTruncateKind(Truncate);
@ -7166,8 +7166,10 @@ class MMod : public MBinaryArithInstruction
mod->unsigned_ = unsignd;
mod->trapOnError_ = trapOnError;
mod->trapOffset_ = trapOffset;
if (trapOnError)
if (trapOnError) {
mod->setGuard(); // not removable because of possible side-effects.
mod->setNotMovable();
}
if (type == MIRType::Int32)
mod->setTruncateKind(Truncate);
return mod;

Просмотреть файл

@ -175,15 +175,6 @@ ICStub::NonCacheIRStubMakesGCCalls(Kind kind)
case Call_ScriptedFunCall:
case Call_StringSplit:
case WarmUpCounter_Fallback:
case GetElem_NativeSlotName:
case GetElem_NativeSlotSymbol:
case GetElem_NativePrototypeSlotName:
case GetElem_NativePrototypeSlotSymbol:
case GetElem_NativePrototypeCallNativeName:
case GetElem_NativePrototypeCallNativeSymbol:
case GetElem_NativePrototypeCallScriptedName:
case GetElem_NativePrototypeCallScriptedSymbol:
case GetElem_UnboxedPropertyName:
case GetProp_CallNativeGlobal:
case GetProp_Generic:
case SetProp_CallScripted:
@ -272,63 +263,6 @@ ICStub::trace(JSTracer* trc)
TraceEdge(trc, &callStub->expectedStr(), "baseline-callstringsplit-str");
break;
}
case ICStub::GetElem_NativeSlotName:
case ICStub::GetElem_NativeSlotSymbol:
case ICStub::GetElem_UnboxedPropertyName: {
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
getElemStub->receiverGuard().trace(trc);
if (getElemStub->isSymbol()) {
ICGetElem_NativeSlot<JS::Symbol*>* typedGetElemStub = toGetElem_NativeSlotSymbol();
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-native-key");
} else {
ICGetElemNativeSlotStub<PropertyName*>* typedGetElemStub =
reinterpret_cast<ICGetElemNativeSlotStub<PropertyName*>*>(this);
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-native-key");
}
break;
}
case ICStub::GetElem_NativePrototypeSlotName:
case ICStub::GetElem_NativePrototypeSlotSymbol: {
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
getElemStub->receiverGuard().trace(trc);
if (getElemStub->isSymbol()) {
ICGetElem_NativePrototypeSlot<JS::Symbol*>* typedGetElemStub
= toGetElem_NativePrototypeSlotSymbol();
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-nativeproto-key");
TraceEdge(trc, &typedGetElemStub->holder(), "baseline-getelem-nativeproto-holder");
TraceEdge(trc, &typedGetElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
} else {
ICGetElem_NativePrototypeSlot<PropertyName*>* typedGetElemStub
= toGetElem_NativePrototypeSlotName();
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-nativeproto-key");
TraceEdge(trc, &typedGetElemStub->holder(), "baseline-getelem-nativeproto-holder");
TraceEdge(trc, &typedGetElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
}
break;
}
case ICStub::GetElem_NativePrototypeCallNativeName:
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
case ICStub::GetElem_NativePrototypeCallScriptedName:
case ICStub::GetElem_NativePrototypeCallScriptedSymbol: {
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
getElemStub->receiverGuard().trace(trc);
if (getElemStub->isSymbol()) {
ICGetElemNativePrototypeCallStub<JS::Symbol*>* callStub =
reinterpret_cast<ICGetElemNativePrototypeCallStub<JS::Symbol*>*>(this);
TraceEdge(trc, &callStub->key(), "baseline-getelem-nativeprotocall-key");
TraceEdge(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
TraceEdge(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
TraceEdge(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
} else {
ICGetElemNativePrototypeCallStub<PropertyName*>* callStub =
reinterpret_cast<ICGetElemNativePrototypeCallStub<PropertyName*>*>(this);
TraceEdge(trc, &callStub->key(), "baseline-getelem-nativeprotocall-key");
TraceEdge(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
TraceEdge(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
TraceEdge(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
}
break;
}
case ICStub::GetElem_Dense: {
ICGetElem_Dense* getElemStub = toGetElem_Dense();
TraceEdge(trc, &getElemStub->shape(), "baseline-getelem-dense-shape");
@ -2281,7 +2215,7 @@ UpdateExistingGetPropCallStubs(ICFallbackStub* fallbackStub,
}
bool
CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, jsid id,
JSObject** lastProto, size_t* protoChainDepthOut)
{
size_t depth = 0;
@ -2289,9 +2223,9 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
while (curObj) {
if (curObj->isNative()) {
// Don't handle proto chains with resolve hooks.
if (ClassMayResolveId(cx->names(), curObj->getClass(), NameToId(name), curObj))
if (ClassMayResolveId(cx->names(), curObj->getClass(), id, curObj))
return false;
if (curObj->as<NativeObject>().contains(cx, NameToId(name)))
if (curObj->as<NativeObject>().contains(cx, id))
return false;
if (curObj->getClass()->getGetProperty())
return false;
@ -2299,13 +2233,13 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
// Non-native objects are only handled as the original receiver.
return false;
} else if (curObj->is<UnboxedPlainObject>()) {
if (curObj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, NameToId(name)))
if (curObj->as<UnboxedPlainObject>().containsUnboxedOrExpandoProperty(cx, id))
return false;
} else if (curObj->is<UnboxedArrayObject>()) {
if (name == cx->names().length)
if (JSID_IS_ATOM(id, cx->names().length))
return false;
} else if (curObj->is<TypedObject>()) {
if (curObj->as<TypedObject>().typeDescr().hasProperty(cx->names(), NameToId(name)))
if (curObj->as<TypedObject>().typeDescr().hasProperty(cx->names(), id))
return false;
} else {
return false;
@ -2404,9 +2338,11 @@ DoGetPropFallback(JSContext* cx, void* payload, ICGetProp_Fallback* stub_,
}
if (!attached && !JitOptions.disableCacheIR) {
GetPropIRGenerator gen(cx, pc, engine, &isTemporarilyUnoptimizable, val, name, res);
RootedValue idVal(cx, StringValue(name));
GetPropIRGenerator gen(cx, pc, engine, CacheKind::GetProp, &isTemporarilyUnoptimizable,
val, idVal, res);
if (gen.tryAttachStub()) {
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), CacheKind::GetProp,
ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
engine, info.outerScript(cx), stub);
if (newStub) {
JitSpew(JitSpew_BaselineIC, " Attached CacheIR stub");

Просмотреть файл

@ -2238,7 +2238,7 @@ UpdateExistingGetPropCallStubs(ICFallbackStub* fallbackStub,
HandleObject receiver,
HandleFunction getter);
MOZ_MUST_USE bool
CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, jsid id,
JSObject** lastProto = nullptr, size_t* protoChainDepthOut = nullptr);
void

Просмотреть файл

@ -1362,5 +1362,31 @@ ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleVa
return Proxy::get(cx, proxy, receiver, id, vp);
}
bool
ProxyGetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal,
MutableHandleValue vp)
{
RootedId id(cx);
if (!ValueToId<CanGC>(cx, idVal, &id))
return false;
RootedValue receiver(cx, ObjectValue(*proxy));
return Proxy::get(cx, proxy, receiver, id, vp);
}
bool
EqualStringsHelper(JSString* str1, JSString* str2)
{
MOZ_ASSERT(str1->isAtom());
MOZ_ASSERT(!str2->isAtom());
MOZ_ASSERT(str1->length() == str2->length());
JSLinearString* str2Linear = str2->ensureLinear(nullptr);
if (!str2Linear)
return false;
return EqualChars(&str1->asLinear(), str2Linear);
}
} // namespace jit
} // namespace js

Просмотреть файл

@ -812,6 +812,13 @@ BaselineGetFunctionThis(JSContext* cx, BaselineFrame* frame, MutableHandleValue
MOZ_MUST_USE bool
ProxyGetProperty(JSContext* cx, HandleObject proxy, HandleId id, MutableHandleValue vp);
MOZ_MUST_USE bool
ProxyGetPropertyByValue(JSContext* cx, HandleObject proxy, HandleValue idVal,
MutableHandleValue vp);
MOZ_MUST_USE bool
EqualStringsHelper(JSString* str1, JSString* str2);
} // namespace jit
} // namespace js

Просмотреть файл

@ -692,7 +692,7 @@ CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register out
// 0/X (with X < 0) is bad because both of these values *should* be doubles,
// and the result should be -0.0, which cannot be represented in integers.
// X/0 is bad because it will give garbage (or abort), when it should give
// either \infty, -\infty or NAN.
// either \infty, -\infty or NaN.
// Prevent 0 / X (with X < 0) and X / 0
// testing X / Y. Compare Y with 0.
@ -704,19 +704,23 @@ CodeGeneratorARM::modICommon(MMod* mir, Register lhs, Register rhs, Register out
// If (Y > 0), we don't set EQ, and we don't trigger LT, so we don't take
// the bailout.
if (mir->canBeDivideByZero() || mir->canBeNegativeDividend()) {
if (mir->trapOnError()) {
// wasm allows negative lhs and return 0 in this case.
MOZ_ASSERT(mir->isTruncated());
masm.as_cmp(rhs, Imm8(0));
masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
return;
}
masm.as_cmp(rhs, Imm8(0));
masm.as_cmp(lhs, Imm8(0), Assembler::LessThan);
if (mir->isTruncated()) {
if (mir->trapOnError()) {
masm.ma_b(trap(mir, wasm::Trap::IntegerDivideByZero), Assembler::Equal);
} else {
// NaN|0 == 0 and (0 % -X)|0 == 0
Label skip;
masm.ma_b(&skip, Assembler::NotEqual);
masm.ma_mov(Imm32(0), output);
masm.ma_b(&done);
masm.bind(&skip);
}
// NaN|0 == 0 and (0 % -X)|0 == 0
Label skip;
masm.ma_b(&skip, Assembler::NotEqual);
masm.ma_mov(Imm32(0), output);
masm.ma_b(&done);
masm.bind(&skip);
} else {
MOZ_ASSERT(mir->fallible());
bailoutIf(Assembler::Equal, snapshot);

Просмотреть файл

@ -26,6 +26,7 @@
/* LegacyIntTypes.h is deliberately exempted from this requirement */
#include "js/MemoryMetrics.h"
#include "js/ProfilingStack.h"
#include "js/RefCounted.h"
#include "js/RequiredDefines.h"
#include "js/RootingAPI.h"
#include "js/SliceBudget.h"

Просмотреть файл

@ -14,7 +14,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Range.h"
#include "mozilla/RangedPtr.h"
#include "mozilla/RefCounted.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Variant.h"
@ -34,6 +33,7 @@
#include "js/Id.h"
#include "js/Principals.h"
#include "js/Realm.h"
#include "js/RefCounted.h"
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"
#include "js/Utility.h"
@ -6087,7 +6087,7 @@ SetBuildIdOp(JSContext* cx, BuildIdOp buildIdOp);
* by calling createObject().
*/
struct WasmModule : mozilla::external::AtomicRefCounted<WasmModule>
struct WasmModule : js::AtomicRefCounted<WasmModule>
{
MOZ_DECLARE_REFCOUNTED_TYPENAME(WasmModule)
virtual ~WasmModule() {}

Просмотреть файл

@ -133,6 +133,7 @@ EXPORTS.js += [
'../public/ProfilingStack.h',
'../public/Proxy.h',
'../public/Realm.h',
'../public/RefCounted.h',
'../public/RequiredDefines.h',
'../public/Result.h',
'../public/RootingAPI.h',

Просмотреть файл

@ -4293,20 +4293,20 @@ nsCSSFrameConstructor::GetAnonymousContent(nsIContent* aParent,
static
bool IsXULDisplayType(const nsStyleDisplay* aDisplay)
{
return (aDisplay->mDisplay == StyleDisplay::InlineBox ||
return (aDisplay->mDisplay == StyleDisplay::MozInlineBox ||
#ifdef MOZ_XUL
aDisplay->mDisplay == StyleDisplay::InlineXulGrid ||
aDisplay->mDisplay == StyleDisplay::InlineStack ||
aDisplay->mDisplay == StyleDisplay::MozInlineGrid ||
aDisplay->mDisplay == StyleDisplay::MozInlineStack ||
#endif
aDisplay->mDisplay == StyleDisplay::Box
aDisplay->mDisplay == StyleDisplay::MozBox
#ifdef MOZ_XUL
|| aDisplay->mDisplay == StyleDisplay::XulGrid ||
aDisplay->mDisplay == StyleDisplay::Stack ||
aDisplay->mDisplay == StyleDisplay::XulGridGroup ||
aDisplay->mDisplay == StyleDisplay::XulGridLine ||
aDisplay->mDisplay == StyleDisplay::Deck ||
aDisplay->mDisplay == StyleDisplay::Popup ||
aDisplay->mDisplay == StyleDisplay::Groupbox
|| aDisplay->mDisplay == StyleDisplay::MozGrid ||
aDisplay->mDisplay == StyleDisplay::MozStack ||
aDisplay->mDisplay == StyleDisplay::MozGridGroup ||
aDisplay->mDisplay == StyleDisplay::MozGridLine ||
aDisplay->mDisplay == StyleDisplay::MozDeck ||
aDisplay->mDisplay == StyleDisplay::MozPopup ||
aDisplay->mDisplay == StyleDisplay::MozGroupbox
#endif
);
}
@ -4485,7 +4485,7 @@ nsCSSFrameConstructor::FindXULListBoxBodyData(Element* aElement,
nsStyleContext* aStyleContext)
{
if (aStyleContext->StyleDisplay()->mDisplay !=
StyleDisplay::XulGridGroup) {
StyleDisplay::MozGridGroup) {
return nullptr;
}
@ -4499,7 +4499,7 @@ const nsCSSFrameConstructor::FrameConstructionData*
nsCSSFrameConstructor::FindXULListItemData(Element* aElement,
nsStyleContext* aStyleContext)
{
if (aStyleContext->StyleDisplay()->mDisplay != StyleDisplay::XulGridLine) {
if (aStyleContext->StyleDisplay()->mDisplay != StyleDisplay::MozGridLine) {
return nullptr;
}
@ -4517,36 +4517,36 @@ nsCSSFrameConstructor::FindXULDisplayData(const nsStyleDisplay* aDisplay,
nsStyleContext* aStyleContext)
{
static const FrameConstructionDataByDisplay sXULDisplayData[] = {
SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::Box,
SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozBox,
NS_NewBoxFrame),
SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::InlineBox,
SCROLLABLE_ABSPOS_CONTAINER_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineBox,
NS_NewBoxFrame),
#ifdef MOZ_XUL
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGrid, NS_NewGridBoxFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::InlineXulGrid, NS_NewGridBoxFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGridGroup,
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGrid, NS_NewGridBoxFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineGrid, NS_NewGridBoxFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridGroup,
NS_NewGridRowGroupFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::XulGridLine,
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGridLine,
NS_NewGridRowLeafFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::Stack, NS_NewStackFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::InlineStack, NS_NewStackFrame),
SIMPLE_XUL_DISPLAY_CREATE(StyleDisplay::Deck, NS_NewDeckFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::Groupbox, NS_NewGroupBoxFrame),
FCDATA_FOR_DISPLAY(StyleDisplay::Popup,
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozStack, NS_NewStackFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozInlineStack, NS_NewStackFrame),
SIMPLE_XUL_DISPLAY_CREATE(StyleDisplay::MozDeck, NS_NewDeckFrame),
SCROLLABLE_XUL_DISPLAY_CREATE(StyleDisplay::MozGroupbox, NS_NewGroupBoxFrame),
FCDATA_FOR_DISPLAY(StyleDisplay::MozPopup,
FCDATA_DECL(FCDATA_DISALLOW_OUT_OF_FLOW | FCDATA_IS_POPUP |
FCDATA_SKIP_ABSPOS_PUSH, NS_NewMenuPopupFrame))
#endif /* MOZ_XUL */
};
if (aDisplay->mDisplay < StyleDisplay::Box) {
if (aDisplay->mDisplay < StyleDisplay::MozBox) {
return nullptr;
}
MOZ_ASSERT(aDisplay->mDisplay <= StyleDisplay::Popup,
MOZ_ASSERT(aDisplay->mDisplay <= StyleDisplay::MozPopup,
"Someone added a new display value?");
const FrameConstructionDataByDisplay& data =
sXULDisplayData[size_t(aDisplay->mDisplay) - size_t(StyleDisplay::Box)];
sXULDisplayData[size_t(aDisplay->mDisplay) - size_t(StyleDisplay::MozBox)];
MOZ_ASSERT(aDisplay->mDisplay == data.mDisplay,
"Did someone mess with the order?");
@ -4576,8 +4576,8 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState,
const nsStyleDisplay* displayStyle = aContentStyle->StyleDisplay();
if (IsXULDisplayType(displayStyle)) {
gfxScrollFrame = NS_NewXULScrollFrame(mPresShell, contentStyle, aIsRoot,
displayStyle->mDisplay == StyleDisplay::Stack ||
displayStyle->mDisplay == StyleDisplay::InlineStack);
displayStyle->mDisplay == StyleDisplay::MozStack ||
displayStyle->mDisplay == StyleDisplay::MozInlineStack);
} else {
gfxScrollFrame = NS_NewHTMLScrollFrame(mPresShell, contentStyle, aIsRoot);
}
@ -6613,8 +6613,8 @@ nsCSSFrameConstructor::IsValidSibling(nsIFrame* aSibling,
}
if (nsGkAtoms::menuFrame == parentType) {
return
(StyleDisplay::Popup == aDisplay) ==
(StyleDisplay::Popup == siblingDisplay);
(StyleDisplay::MozPopup == aDisplay) ==
(StyleDisplay::MozPopup == siblingDisplay);
}
// To have decent performance we want to return false in cases in which
// reordering the two siblings has no effect on display. To ensure
@ -10902,7 +10902,7 @@ nsCSSFrameConstructor::ProcessChildren(nsFrameConstructorState& aState,
const char16_t* params[] = { parentTag.get(), kidTag.get() };
const nsStyleDisplay *display = frameStyleContext->StyleDisplay();
const char *message =
(display->mDisplay == StyleDisplay::InlineBox)
(display->mDisplay == StyleDisplay::MozInlineBox)
? "NeededToWrapXULInlineBox" : "NeededToWrapXUL";
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
NS_LITERAL_CSTRING("Layout: FrameConstructor"),

Просмотреть файл

@ -509,7 +509,7 @@ nsFrameIterator::IsPopupFrame(nsIFrame* aFrame)
}
return (aFrame &&
aFrame->StyleDisplay()->mDisplay == StyleDisplay::Popup);
aFrame->StyleDisplay()->mDisplay == StyleDisplay::MozPopup);
}
// nsVisualIterator implementation

Просмотреть файл

@ -1407,7 +1407,7 @@ nsLayoutUtils::GetChildListNameFor(nsIFrame* aChildFrame)
id = nsIFrame::kAbsoluteList;
}
#ifdef MOZ_XUL
} else if (StyleDisplay::Popup == disp->mDisplay) {
} else if (StyleDisplay::MozPopup == disp->mDisplay) {
// Out-of-flows that are DISPLAY_POPUP must be kids of the root popup set
#ifdef DEBUG
nsIFrame* parent = aChildFrame->GetParent();

Просмотреть файл

@ -838,7 +838,7 @@ ReflowInput::InitFrameType(nsIAtom* aFrameType)
else if (disp->IsFloating(mFrame)) {
frameType = NS_CSS_FRAME_TYPE_FLOATING;
} else {
NS_ASSERTION(disp->mDisplay == StyleDisplay::Popup,
NS_ASSERTION(disp->mDisplay == StyleDisplay::MozPopup,
"unknown out of flow frame type");
frameType = NS_CSS_FRAME_TYPE_UNKNOWN;
}
@ -859,9 +859,9 @@ ReflowInput::InitFrameType(nsIAtom* aFrameType)
case StyleDisplay::Inline:
case StyleDisplay::InlineBlock:
case StyleDisplay::InlineTable:
case StyleDisplay::InlineBox:
case StyleDisplay::InlineXulGrid:
case StyleDisplay::InlineStack:
case StyleDisplay::MozInlineBox:
case StyleDisplay::MozInlineGrid:
case StyleDisplay::MozInlineStack:
case StyleDisplay::InlineFlex:
case StyleDisplay::WebkitInlineBox:
case StyleDisplay::InlineGrid:

Просмотреть файл

@ -1302,18 +1302,18 @@ KTableEntry nsCSSProps::kDisplayKTable[] = {
{ eCSSKeyword_table_caption, StyleDisplay::TableCaption },
// Make sure this is kept in sync with the code in
// nsCSSFrameConstructor::ConstructXULFrame
{ eCSSKeyword__moz_box, StyleDisplay::Box },
{ eCSSKeyword__moz_inline_box, StyleDisplay::InlineBox },
{ eCSSKeyword__moz_box, StyleDisplay::MozBox },
{ eCSSKeyword__moz_inline_box, StyleDisplay::MozInlineBox },
#ifdef MOZ_XUL
{ eCSSKeyword__moz_grid, StyleDisplay::XulGrid },
{ eCSSKeyword__moz_inline_grid, StyleDisplay::InlineXulGrid },
{ eCSSKeyword__moz_grid_group, StyleDisplay::XulGridGroup },
{ eCSSKeyword__moz_grid_line, StyleDisplay::XulGridLine },
{ eCSSKeyword__moz_stack, StyleDisplay::Stack },
{ eCSSKeyword__moz_inline_stack, StyleDisplay::InlineStack },
{ eCSSKeyword__moz_deck, StyleDisplay::Deck },
{ eCSSKeyword__moz_popup, StyleDisplay::Popup },
{ eCSSKeyword__moz_groupbox, StyleDisplay::Groupbox },
{ eCSSKeyword__moz_grid, StyleDisplay::MozGrid },
{ eCSSKeyword__moz_inline_grid, StyleDisplay::MozInlineGrid },
{ eCSSKeyword__moz_grid_group, StyleDisplay::MozGridGroup },
{ eCSSKeyword__moz_grid_line, StyleDisplay::MozGridLine },
{ eCSSKeyword__moz_stack, StyleDisplay::MozStack },
{ eCSSKeyword__moz_inline_stack, StyleDisplay::MozInlineStack },
{ eCSSKeyword__moz_deck, StyleDisplay::MozDeck },
{ eCSSKeyword__moz_popup, StyleDisplay::MozPopup },
{ eCSSKeyword__moz_groupbox, StyleDisplay::MozGroupbox },
#endif
{ eCSSKeyword_flex, StyleDisplay::Flex },
{ eCSSKeyword_inline_flex, StyleDisplay::InlineFlex },

Просмотреть файл

@ -289,11 +289,11 @@ nsRuleNode::EnsureInlineDisplay(StyleDisplay& display)
case StyleDisplay::Grid:
display = StyleDisplay::InlineGrid;
break;
case StyleDisplay::Box:
display = StyleDisplay::InlineBox;
case StyleDisplay::MozBox:
display = StyleDisplay::MozInlineBox;
break;
case StyleDisplay::Stack:
display = StyleDisplay::InlineStack;
case StyleDisplay::MozStack:
display = StyleDisplay::MozInlineStack;
break;
default:
break; // Do nothing
@ -1445,7 +1445,7 @@ struct SetEnumValueHelper
DEFINE_ENUM_CLASS_SETTER(StyleWindowDragging, Default, NoDrag)
DEFINE_ENUM_CLASS_SETTER(StyleOrient, Inline, Vertical)
#ifdef MOZ_XUL
DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, Popup)
DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, MozPopup)
#else
DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, InlineBox)
#endif

Просмотреть файл

@ -514,18 +514,18 @@ enum class StyleDisplay : uint8_t {
Contents,
WebkitBox,
WebkitInlineBox,
Box,
InlineBox,
MozBox,
MozInlineBox,
#ifdef MOZ_XUL
XulGrid,
InlineXulGrid,
XulGridGroup,
XulGridLine,
Stack,
InlineStack,
Deck,
Groupbox,
Popup,
MozGrid,
MozInlineGrid,
MozGridGroup,
MozGridLine,
MozStack,
MozInlineStack,
MozDeck,
MozGroupbox,
MozPopup,
#endif
};

Просмотреть файл

@ -2800,7 +2800,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
// We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
// mBinding->mOriginPrincipal.
RefPtr<mozilla::css::URLValue> mBinding; // [reset]
mozilla::StyleDisplay mDisplay; // [reset] see nsStyleConsts.h SyleDisplay
mozilla::StyleDisplay mDisplay; // [reset] see nsStyleConsts.h StyleDisplay
mozilla::StyleDisplay mOriginalDisplay; // [reset] saved mDisplay for
// position:absolute/fixed
// and float:left/right;
@ -2904,12 +2904,12 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
return mozilla::StyleDisplay::Inline == aDisplay ||
mozilla::StyleDisplay::InlineBlock == aDisplay ||
mozilla::StyleDisplay::InlineTable == aDisplay ||
mozilla::StyleDisplay::InlineBox == aDisplay ||
mozilla::StyleDisplay::MozInlineBox == aDisplay ||
mozilla::StyleDisplay::InlineFlex == aDisplay ||
mozilla::StyleDisplay::WebkitInlineBox == aDisplay ||
mozilla::StyleDisplay::InlineGrid == aDisplay ||
mozilla::StyleDisplay::InlineXulGrid == aDisplay ||
mozilla::StyleDisplay::InlineStack == aDisplay ||
mozilla::StyleDisplay::MozInlineGrid == aDisplay ||
mozilla::StyleDisplay::MozInlineStack == aDisplay ||
mozilla::StyleDisplay::Ruby == aDisplay ||
mozilla::StyleDisplay::RubyBase == aDisplay ||
mozilla::StyleDisplay::RubyBaseContainer == aDisplay ||

Просмотреть файл

@ -1237,7 +1237,7 @@ nsBoxFrame::AttributeChanged(int32_t aNameSpaceID,
// kPopupList and XULRelayoutChildAtOrdinal() only handles
// principal children.
if (parent && !(GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
StyleDisplay()->mDisplay != mozilla::StyleDisplay::Popup) {
StyleDisplay()->mDisplay != mozilla::StyleDisplay::MozPopup) {
parent->XULRelayoutChildAtOrdinal(this);
// XXXldb Should this instead be a tree change on the child or parent?
PresContext()->PresShell()->

Просмотреть файл

@ -16,6 +16,7 @@
#include "mozilla/Move.h"
#include "mozilla/RefCountType.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/UniquePtr.h"
#if defined(MOZILLA_INTERNAL_API)
#include "nsXPCOM.h"
@ -86,7 +87,7 @@ enum RefCountAtomicity
NonAtomicRefCount
};
template<typename T, RefCountAtomicity Atomicity>
template<typename T, RefCountAtomicity Atomicity, typename D>
class RefCounted
{
protected:
@ -132,7 +133,7 @@ public:
#ifdef DEBUG
mRefCnt = detail::DEAD;
#endif
delete static_cast<const T*>(this);
D()(const_cast<T*>(static_cast<const T*>(this)));
}
}
@ -171,8 +172,8 @@ private:
} // namespace detail
template<typename T>
class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount>
template<typename T, class D = DefaultDelete<T>>
class RefCounted : public detail::RefCounted<T, detail::NonAtomicRefCount, D>
{
public:
~RefCounted()
@ -191,9 +192,9 @@ namespace external {
* NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
* instead.
*/
template<typename T>
template<typename T, typename D = DefaultDelete<T>>
class AtomicRefCounted :
public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount, D>
{
public:
~AtomicRefCounted()

Просмотреть файл

@ -81,9 +81,9 @@ class LibHandle;
namespace mozilla {
namespace detail {
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const;
template <> inline void RefCounted<LibHandle, AtomicRefCount, DefaultDelete<LibHandle>>::Release() const;
template <> inline RefCounted<LibHandle, AtomicRefCount>::~RefCounted()
template <> inline RefCounted<LibHandle, AtomicRefCount, DefaultDelete<LibHandle>>::~RefCounted()
{
MOZ_ASSERT(mRefCnt == 0x7fffdead);
}
@ -249,7 +249,7 @@ private:
namespace mozilla {
namespace detail {
template <> inline void RefCounted<LibHandle, AtomicRefCount>::Release() const {
template <> inline void RefCounted<LibHandle, AtomicRefCount, DefaultDelete<LibHandle>>::Release() const {
#ifdef DEBUG
if (mRefCnt > 0x7fff0000)
MOZ_ASSERT(mRefCnt > 0x7fffdead);

Просмотреть файл

@ -800,6 +800,19 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
// The mConnectionBased flag is set later for the newly received challenge,
// so here it reflects the previous 401/7 response schema.
mAuthChannel->CloseStickyConnection();
if (!proxyAuth) {
// We must clear proxy ident in the following scenario + explanation:
// - we are authenticating to an NTLM proxy and an NTLM server
// - we successfully authenticated to the proxy, mProxyIdent keeps
// the user name/domain and password, the identity has also been cached
// - we just threw away the connection because we are now asking for
// creds for the server (WWW auth)
// - hence, we will have to auth to the proxy again as well
// - if we didn't clear the proxy identity, it would be considered
// as non-valid and we would ask the user again ; clearing it forces
// use of the cached identity and not asking the user again
mProxyIdent.Clear();
}
mConnectionBased = false;
}