diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index c8d2d7f13add..be0d224a4d9f 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -5195,6 +5195,34 @@ AttachDecision CallIRGenerator::tryAttachIsCallable(HandleFunction callee) { return AttachDecision::Attach; } +AttachDecision CallIRGenerator::tryAttachIsConstructor(HandleFunction callee) { + // Need a single object argument. + if (argc_ != 1 || !args_[0].isObject()) { + return AttachDecision::NoAction; + } + + // Initialize the input operand. + Int32OperandId argcId(writer.setInputOperandId(0)); + + // Guard callee is the 'IsConstructor' intrinsic native function. + emitNativeCalleeGuard(callee); + + // Guard that the argument is an object. + ValOperandId argId = writer.loadArgumentFixedSlot(ArgumentKind::Arg0, argc_); + ObjOperandId objId = writer.guardToObject(argId); + + // Check if the argument is a constructor and return result. + writer.isConstructorResult(objId); + + // This stub does not need to be monitored, because it always + // returns a boolean. + writer.returnFromIC(); + cacheIRStubKind_ = BaselineCacheIRStubKind::Regular; + + trackAttached("IsConstructor"); + return AttachDecision::Attach; +} + AttachDecision CallIRGenerator::tryAttachStringChar(HandleFunction callee, StringChar kind) { // Need one argument. @@ -5635,6 +5663,8 @@ AttachDecision CallIRGenerator::tryAttachInlinableNative( return tryAttachIsObject(callee); case InlinableNative::IntrinsicIsCallable: return tryAttachIsCallable(callee); + case InlinableNative::IntrinsicIsConstructor: + return tryAttachIsConstructor(callee); // String natives. case InlinableNative::StringCharCodeAt: diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h index 3f574b026477..6674e818b959 100644 --- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -1527,6 +1527,7 @@ class MOZ_RAII CallIRGenerator : public IRGenerator { AttachDecision tryAttachToInteger(HandleFunction callee); AttachDecision tryAttachIsObject(HandleFunction callee); AttachDecision tryAttachIsCallable(HandleFunction callee); + AttachDecision tryAttachIsConstructor(HandleFunction callee); AttachDecision tryAttachStringChar(HandleFunction callee, StringChar kind); AttachDecision tryAttachStringCharCodeAt(HandleFunction callee); AttachDecision tryAttachStringCharAt(HandleFunction callee); diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index cafef6b10794..375856d1dc94 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -3751,6 +3751,39 @@ bool CacheIRCompiler::emitIsCallableResult(ValOperandId inputId) { return true; } +bool CacheIRCompiler::emitIsConstructorResult(ObjOperandId objId) { + JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); + + AutoOutputRegister output(*this); + AutoScratchRegisterMaybeOutput scratch(allocator, masm, output); + + Register obj = allocator.useRegister(masm, objId); + + Label isProxy, done; + masm.isConstructor(obj, scratch, &isProxy); + masm.jump(&done); + + masm.bind(&isProxy); + { + LiveRegisterSet volatileRegs(GeneralRegisterSet::Volatile(), + liveVolatileFloatRegs()); + masm.PushRegsInMask(volatileRegs); + + masm.setupUnalignedABICall(scratch); + masm.passABIArg(obj); + masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, ObjectIsConstructor)); + masm.storeCallBoolResult(scratch); + + LiveRegisterSet ignore; + ignore.add(scratch); + masm.PopRegsInMaskIgnore(volatileRegs, ignore); + } + + masm.bind(&done); + EmitStoreResult(masm, scratch, JSVAL_TYPE_BOOLEAN, output); + return true; +} + bool CacheIRCompiler::emitMathAbsInt32Result(Int32OperandId inputId) { JitSpew(JitSpew_Codegen, "%s", __FUNCTION__); diff --git a/js/src/jit/CacheIROps.yaml b/js/src/jit/CacheIROps.yaml index 8c3d00a93707..1b2c820c84b4 100644 --- a/js/src/jit/CacheIROps.yaml +++ b/js/src/jit/CacheIROps.yaml @@ -685,6 +685,12 @@ args: input: ValId +- name: IsConstructorResult + shared: true + transpile: false + args: + obj: ObjId + - name: MathAbsInt32Result shared: true transpile: true