Bug 1885774: Make loadWrapperTarget fallible r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D205654
This commit is contained in:
Iain Ireland 2024-03-27 19:20:30 +00:00
parent d274938a4e
commit c37e2efc87
11 changed files with 93 additions and 16 deletions

View File

@ -0,0 +1,25 @@
// |jit-test| --no-threads; --fast-warmup
var {proxy, revoke} = Proxy.revocable({x:1}, {});
function foo(o) {
var res = 0;
for (var i = 0; i < 2; i++) {
res += o.x;
}
return res;
}
with ({}) {}
for (var i = 0; i < 100; i++) {
assertEq(foo(proxy), 2);
}
revoke();
var caught = false;
try {
foo(proxy);
} catch {
caught = true;
}
assertEq(caught, true);

View File

@ -1199,7 +1199,8 @@ static ObjOperandId GuardAndLoadWindowProxyWindow(CacheIRWriter& writer,
ObjOperandId objId,
GlobalObject* windowObj) {
writer.guardClass(objId, GuardClassKind::WindowProxy);
ObjOperandId windowObjId = writer.loadWrapperTarget(objId);
ObjOperandId windowObjId = writer.loadWrapperTarget(objId,
/*fallible = */ false);
writer.guardSpecificObject(windowObjId, windowObj);
return windowObjId;
}
@ -1357,7 +1358,8 @@ AttachDecision GetPropIRGenerator::tryAttachCrossCompartmentWrapper(
writer.guardHasProxyHandler(objId, Wrapper::wrapperHandler(obj));
// Load the object wrapped by the CCW
ObjOperandId wrapperTargetId = writer.loadWrapperTarget(objId);
ObjOperandId wrapperTargetId =
writer.loadWrapperTarget(objId, /*fallible = */ false);
// If the compartment of the wrapped object is different we should fail.
writer.guardCompartment(wrapperTargetId, wrappedTargetGlobal,
@ -1468,7 +1470,8 @@ AttachDecision GetPropIRGenerator::tryAttachXrayCrossCompartmentWrapper(
writer.guardHasProxyHandler(objId, GetProxyHandler(obj));
// Load the object wrapped by the CCW
ObjOperandId wrapperTargetId = writer.loadWrapperTarget(objId);
ObjOperandId wrapperTargetId =
writer.loadWrapperTarget(objId, /*fallible = */ false);
// Test the wrapped object's class. The properties held by xrays or their
// prototypes will be invariant for objects of a given class, except for
@ -1580,7 +1583,8 @@ AttachDecision GetPropIRGenerator::tryAttachScriptedProxy(
writer.guardHasProxyHandler(objId, &ScriptedProxyHandler::singleton);
ValOperandId handlerValId = writer.loadScriptedProxyHandler(objId);
ObjOperandId handlerObjId = writer.guardToObject(handlerValId);
ObjOperandId targetObjId = writer.loadWrapperTarget(objId);
ObjOperandId targetObjId =
writer.loadWrapperTarget(objId, /*fallible =*/true);
writer.guardIsNativeObject(targetObjId);

View File

@ -2934,14 +2934,27 @@ bool CacheIRCompiler::emitLoadEnclosingEnvironment(ObjOperandId objId,
}
bool CacheIRCompiler::emitLoadWrapperTarget(ObjOperandId objId,
ObjOperandId resultId) {
ObjOperandId resultId,
bool fallible) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Register obj = allocator.useRegister(masm, objId);
Register reg = allocator.defineRegister(masm, resultId);
FailurePath* failure;
if (fallible && !addFailurePath(&failure)) {
return false;
}
masm.loadPtr(Address(obj, ProxyObject::offsetOfReservedSlots()), reg);
masm.unboxObject(
Address(reg, js::detail::ProxyReservedSlots::offsetOfPrivateSlot()), reg);
Address targetAddr(reg,
js::detail::ProxyReservedSlots::offsetOfPrivateSlot());
if (fallible) {
masm.fallibleUnboxObject(targetAddr, reg, failure->label());
} else {
masm.unboxObject(targetAddr, reg);
}
return true;
}

View File

@ -837,6 +837,7 @@
args:
obj: ObjId
result: ObjId
fallible: BoolImm
- name: LoadValueTag
shared: true

View File

@ -19881,9 +19881,17 @@ void CodeGenerator::visitLoadWrapperTarget(LLoadWrapperTarget* lir) {
Register output = ToRegister(lir->output());
masm.loadPtr(Address(object, ProxyObject::offsetOfReservedSlots()), output);
masm.unboxObject(
Address(output, js::detail::ProxyReservedSlots::offsetOfPrivateSlot()),
output);
// Bail for revoked proxies.
Label bail;
Address targetAddr(output,
js::detail::ProxyReservedSlots::offsetOfPrivateSlot());
if (lir->mir()->fallible()) {
masm.fallibleUnboxObject(targetAddr, output, &bail);
bailoutFrom(&bail, lir->snapshot());
} else {
masm.unboxObject(targetAddr, output);
}
}
void CodeGenerator::visitGuardHasGetterSetter(LGuardHasGetterSetter* lir) {

View File

@ -3694,6 +3694,7 @@
result_type: WordSized
operands:
object: WordSized
mir_op: true
- name: GuardHasGetterSetter
operands:

View File

@ -6752,7 +6752,11 @@ void LIRGenerator::visitLoadWrapperTarget(MLoadWrapperTarget* ins) {
MDefinition* object = ins->object();
MOZ_ASSERT(object->type() == MIRType::Object);
define(new (alloc()) LLoadWrapperTarget(useRegisterAtStart(object)), ins);
auto* lir = new (alloc()) LLoadWrapperTarget(useRegisterAtStart(object));
if (ins->fallible()) {
assignSnapshot(lir, ins->bailoutKind());
}
define(lir, ins);
}
void LIRGenerator::visitGuardHasGetterSetter(MGuardHasGetterSetter* ins) {

View File

@ -7242,6 +7242,16 @@ AliasSet MLoadWrapperTarget::getAliasSet() const {
return AliasSet::Load(AliasSet::Any);
}
bool MLoadWrapperTarget::congruentTo(const MDefinition* ins) const {
if (!ins->isLoadWrapperTarget()) {
return false;
}
if (ins->toLoadWrapperTarget()->fallible() != fallible()) {
return false;
}
return congruentIfOperandsEqual(ins);
}
AliasSet MGuardHasGetterSetter::getAliasSet() const {
return AliasSet::Load(AliasSet::ObjectFields);
}

View File

@ -2810,13 +2810,16 @@
alias_set: none
# Load the target object from a proxy wrapper. The target is stored in the
# proxy object's private slot.
# proxy object's private slot. This operation is fallible if the proxy can
# be revoked.
- name: LoadWrapperTarget
operands:
object: Object
arguments:
fallible: bool
result_type: Object
movable: true
congruent_to: if_operands_equal
congruent_to: custom
# Can't use |AliasSet::None| because the target changes on navigation.
# TODO: Investigate using a narrower or a custom alias set.
alias_set: custom

View File

@ -5216,10 +5216,14 @@ bool WarpCacheIRTranspiler::emitLoadOperandResult(ValOperandId inputId) {
}
bool WarpCacheIRTranspiler::emitLoadWrapperTarget(ObjOperandId objId,
ObjOperandId resultId) {
ObjOperandId resultId,
bool fallible) {
MDefinition* obj = getOperand(objId);
auto* ins = MLoadWrapperTarget::New(alloc(), obj);
auto* ins = MLoadWrapperTarget::New(alloc(), obj, fallible);
if (fallible) {
ins->setGuard();
}
add(ins);
return defineOperand(resultId, ins);

View File

@ -1373,9 +1373,13 @@ ICInterpretOps(BaselineFrame* frame, VMFrameManager& frameMgr, State& state,
CACHEOP_CASE(LoadWrapperTarget) {
ObjOperandId objId = icregs.cacheIRReader.objOperandId();
ObjOperandId resultId = icregs.cacheIRReader.objOperandId();
bool fallible = icregs.cacheIRReader.readBool();
BOUNDSCHECK(resultId);
JSObject* obj = reinterpret_cast<JSObject*>(icregs.icVals[objId.id()]);
JSObject* target = &obj->as<ProxyObject>().private_().toObject();
JSObject* target = obj->as<ProxyObject>().private_().toObjectOrNull();
if (fallible && !target) {
return ICInterpretOpResult::NextIC;
}
icregs.icVals[resultId.id()] = reinterpret_cast<uintptr_t>(target);
DISPATCH_CACHEOP();
}