From d8d6e3aa8a8bae2738269612244b01d006ad3a13 Mon Sep 17 00:00:00 2001 From: win7-7 Date: Sun, 11 Jan 2026 00:19:59 +0200 Subject: [PATCH] CacheIR nursery changes. CacheIR nursery changes. --- js/src/jit/BaselineCacheIRCompiler.cpp | 3 +- js/src/jit/BaselineCompiler.cpp | 157 +++++++++++++++++++++++++ js/src/jit/CacheIRCompiler.cpp | 13 +- 3 files changed, 166 insertions(+), 7 deletions(-) diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp index 256f88cb93..7021433c3c 100644 --- a/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -1175,8 +1175,7 @@ BaselineCacheIRCompiler::emitStoreTypedObjectReferenceProperty() emitStoreTypedObjectReferenceProp(val, type, dest, scratch2); - if (type != ReferenceTypeDescr::TYPE_STRING) - emitPostBarrierSlot(obj, val, scratch1); + emitPostBarrierSlot(obj, val, scratch1); return true; } diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 6b4d62aa0d..b7c65129a4 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -4738,6 +4738,163 @@ BaselineCompiler::emit_JSOP_JUMPTARGET() return true; } +typedef bool (*CheckClassHeritageOperationFn)(JSContext*, HandleValue); +static const VMFunction CheckClassHeritageOperationInfo = + FunctionInfo(js::CheckClassHeritageOperation, + "CheckClassHeritageOperation"); + +bool +BaselineCompiler::emit_JSOP_CHECKCLASSHERITAGE() +{ + frame.syncStack(0); + + // Leave the heritage value on the stack. + masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0); + + prepareVMCall(); + pushArg(R0); + return callVM(CheckClassHeritageOperationInfo); +} + +bool +BaselineCompiler::emit_JSOP_INITHOMEOBJECT() +{ + frame.syncStack(0); + + // Load HomeObject off stack + unsigned skipOver = GET_UINT8(pc); + MOZ_ASSERT(frame.stackDepth() >= skipOver + 2); + masm.loadValue(frame.addressOfStackValue(frame.peek(-2 - skipOver)), R0); + + // Load function off stack + Register func = R2.scratchReg(); + masm.unboxObject(frame.addressOfStackValue(frame.peek(-1)), func); + + // Set HOMEOBJECT_SLOT + Address addr(func, FunctionExtended::offsetOfMethodHomeObjectSlot()); +#ifdef DEBUG + Label isUndefined; + masm.branchTestUndefined(Assembler::Equal, addr, &isUndefined); + masm.assumeUnreachable("INITHOMEOBJECT expects undefined slot"); + masm.bind(&isUndefined); +#endif + masm.storeValue(R0, addr); + + Register temp = R1.scratchReg(); + Label skipBarrier; + masm.branchPtrInNurseryChunk(Assembler::Equal, func, temp, &skipBarrier); + masm.branchValueIsNurseryCell(Assembler::NotEqual, R0, temp, &skipBarrier); + masm.call(&postBarrierSlot_); + masm.bind(&skipBarrier); + + return true; +} + +bool +BaselineCompiler::emit_JSOP_BUILTINPROTO() +{ + // The builtin prototype is a constant for a given global. + RootedObject builtin(cx); + JSProtoKey key = static_cast(GET_UINT8(pc)); + MOZ_ASSERT(key < JSProto_LIMIT); + if (!GetBuiltinPrototype(cx, key, &builtin)) + return false; + frame.push(ObjectValue(*builtin)); + return true; +} + +typedef JSObject* (*ObjectWithProtoOperationFn)(JSContext*, HandleValue); +static const VMFunction ObjectWithProtoOperationInfo = + FunctionInfo(js::ObjectWithProtoOperation, + "ObjectWithProtoOperationInfo"); + +bool +BaselineCompiler::emit_JSOP_OBJWITHPROTO() +{ + frame.syncStack(0); + + // Leave the proto value on the stack for the decompiler + masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0); + + prepareVMCall(); + pushArg(R0); + if (!callVM(ObjectWithProtoOperationInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + frame.pop(); + frame.push(R0); + return true; +} + + +typedef JSObject* (*FunWithProtoFn)(JSContext*, HandleFunction, HandleObject, HandleObject); +static const VMFunction FunWithProtoInfo = + FunctionInfo(js::FunWithProtoOperation, "FunWithProtoOperation"); + +bool +BaselineCompiler::emit_JSOP_FUNWITHPROTO() +{ + frame.popRegsAndSync(1); + + masm.unboxObject(R0, R0.scratchReg()); + masm.loadPtr(frame.addressOfEnvironmentChain(), R1.scratchReg()); + + prepareVMCall(); + pushArg(R0.scratchReg()); + pushArg(R1.scratchReg()); + pushArg(ImmGCPtr(script->getFunction(GET_UINT32_INDEX(pc)))); + if (!callVM(FunWithProtoInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + frame.push(R0); + return true; +} + +typedef JSFunction* (*MakeDefaultConstructorFn)(JSContext*, HandleScript, + jsbytecode*, HandleObject); +static const VMFunction MakeDefaultConstructorInfo = + FunctionInfo(js::MakeDefaultConstructor, + "MakeDefaultConstructor"); + +bool +BaselineCompiler::emit_JSOP_CLASSCONSTRUCTOR() +{ + frame.syncStack(0); + + // Pass nullptr as prototype to MakeDefaultConstructor + prepareVMCall(); + pushArg(ImmPtr(nullptr)); + pushArg(ImmPtr(pc)); + pushArg(ImmGCPtr(script)); + if (!callVM(MakeDefaultConstructorInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + frame.push(R0); + return true; +} + +bool +BaselineCompiler::emit_JSOP_DERIVEDCONSTRUCTOR() +{ + frame.popRegsAndSync(1); + + masm.unboxObject(R0, R0.scratchReg()); + + prepareVMCall(); + pushArg(R0.scratchReg()); + pushArg(ImmPtr(pc)); + pushArg(ImmGCPtr(script)); + if (!callVM(MakeDefaultConstructorInfo)) + return false; + + masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0); + frame.push(R0); + return true; +} + typedef JSObject* (*GetOrCreateModuleMetaObjectFn)(JSContext*, HandleObject); static const VMFunction GetOrCreateModuleMetaObjectInfo = FunctionInfo(js::GetOrCreateModuleMetaObject, diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index 8b298c9726..aa2f0c296c 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -2238,6 +2238,8 @@ void CacheIRCompiler::emitStoreTypedObjectReferenceProp(ValueOperand val, ReferenceTypeDescr::Type type, const Address& dest, Register scratch) { + // Callers will post-barrier this store. + switch (type) { case ReferenceTypeDescr::TYPE_ANY: EmitPreBarrier(masm, dest, MIRType::Value); @@ -2273,18 +2275,19 @@ CacheIRCompiler::emitPostBarrierShared(Register obj, const ConstantOrRegister& v return; if (val.constant()) { - MOZ_ASSERT_IF(val.value().isObject(), !IsInsideNursery(&val.value().toObject())); + MOZ_ASSERT_IF(val.value().isGCThing(), !IsInsideNursery(val.value().toGCThing())); return; } TypedOrValueRegister reg = val.reg(); - if (reg.hasTyped() && reg.type() != MIRType::Object) - return; + if (reg.hasTyped()) { + if (reg.type() != MIRType::Object && reg.type() != MIRType::String) + return; + } Label skipBarrier; if (reg.hasValue()) { - masm.branchValueIsNurseryObject(Assembler::NotEqual, reg.valueReg(), scratch, - &skipBarrier); + masm.branchValueIsNurseryCell(Assembler::NotEqual, reg.valueReg(), scratch, &skipBarrier); } else { masm.branchPtrInNurseryChunk(Assembler::NotEqual, reg.typedReg().gpr(), scratch, &skipBarrier);