diff --git a/js/src/jit/BaselineCacheIRCompiler.cpp b/js/src/jit/BaselineCacheIRCompiler.cpp index 03fa062d926f..92169d318057 100644 --- a/js/src/jit/BaselineCacheIRCompiler.cpp +++ b/js/src/jit/BaselineCacheIRCompiler.cpp @@ -523,9 +523,7 @@ BaselineCacheIRCompiler::emitMegamorphicLoadSlotResult() return false; // The object must be Native. - masm.loadObjClass(obj, scratch3); - masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()), - Imm32(Class::NON_NATIVE), failure->label()); + masm.branchIfNonNativeObj(obj, scratch3, failure->label()); masm.Push(UndefinedValue()); masm.moveStackPtrTo(scratch3.get()); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 50d7e7a53618..b34183a6d38d 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -3429,11 +3429,9 @@ ICCall_ClassHook::Compiler::generateStubCode(MacroAssembler& masm) // Ensure the callee's class matches the one in this stub. Register callee = masm.extractObject(R1, ExtractTemp0); Register scratch = regs.takeAny(); - masm.loadObjClass(callee, scratch); - masm.branchPtr(Assembler::NotEqual, - Address(ICStubReg, ICCall_ClassHook::offsetOfClass()), - scratch, &failure); - + masm.branchTestObjClass(Assembler::NotEqual, callee, scratch, + Address(ICStubReg, ICCall_ClassHook::offsetOfClass()), + &failure); regs.add(R1); regs.takeUnchecked(callee); diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index 505813d84a9a..98d2dcbf1b23 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -1472,9 +1472,7 @@ CacheIRCompiler::emitGuardIsNativeObject() if (!addFailurePath(&failure)) return false; - masm.loadObjClass(obj, scratch); - masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()), - Imm32(Class::NON_NATIVE), failure->label()); + masm.branchIfNonNativeObj(obj, scratch, failure->label()); return true; } @@ -2668,9 +2666,7 @@ CacheIRCompiler::emitMegamorphicLoadSlotByValueResult() return false; // The object must be Native. - masm.loadObjClass(obj, scratch); - masm.branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()), - Imm32(Class::NON_NATIVE), failure->label()); + masm.branchIfNonNativeObj(obj, scratch, failure->label()); // idVal will be in vp[0], result will be stored in vp[1]. masm.reserveStack(sizeof(Value)); diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 99b0336640b7..7ee90bf89073 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -3713,11 +3713,8 @@ CodeGenerator::visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite* lir) OutOfLineCode* ool = oolCallVM(CopyElementsForWriteInfo, lir, ArgList(object), StoreNothing()); - if (lir->mir()->checkNative()) { - masm.loadObjClass(object, temp); - masm.branchTest32(Assembler::NonZero, Address(temp, Class::offsetOfFlags()), - Imm32(Class::NON_NATIVE), ool->rejoin()); - } + if (lir->mir()->checkNative()) + masm.branchIfNonNativeObj(object, temp, ool->rejoin()); masm.loadPtr(Address(object, NativeObject::offsetOfElements()), temp); masm.branchTest32(Assembler::NonZero, @@ -4876,10 +4873,10 @@ CodeGenerator::emitApplyGeneric(T* apply) // Unless already known, guard that calleereg is actually a function object. if (!apply->hasSingleTarget()) { - masm.loadObjClass(calleereg, objreg); - - ImmPtr ptr = ImmPtr(&JSFunction::class_); - bailoutCmpPtr(Assembler::NotEqual, objreg, ptr, apply->snapshot()); + Label bail; + masm.branchTestObjClass(Assembler::NotEqual, calleereg, objreg, &JSFunction::class_, + &bail); + bailoutFrom(&bail, apply->snapshot()); } // Copy the arguments of the current function. @@ -7065,9 +7062,7 @@ CodeGenerator::visitTypedObjectElements(LTypedObjectElements* lir) masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out); } else { Label inlineObject, done; - masm.loadObjClass(obj, out); - masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject); - masm.branchPtr(Assembler::Equal, out, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject); + masm.branchIfInlineTypedObject(obj, out, &inlineObject); masm.loadPtr(Address(obj, OutlineTypedObject::offsetOfData()), out); masm.jump(&done); @@ -7090,9 +7085,7 @@ CodeGenerator::visitSetTypedObjectOffset(LSetTypedObjectOffset* lir) masm.loadPtr(Address(object, OutlineTypedObject::offsetOfOwner()), temp0); Label inlineObject, done; - masm.loadObjClass(temp0, temp1); - masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineOpaqueTypedObject::class_), &inlineObject); - masm.branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineTransparentTypedObject::class_), &inlineObject); + masm.branchIfInlineTypedObject(temp0, temp1, &inlineObject); masm.loadPrivate(Address(temp0, ArrayBufferObject::offsetOfDataSlot()), temp0); masm.jump(&done); @@ -12093,7 +12086,7 @@ void CodeGenerator::emitIsCallableOrConstructor(Register object, Register output, Label* failure) { Label notFunction, hasCOps, done; - masm.loadObjClass(object, output); + masm.loadObjClassUnsafe(object, output); // Just skim proxies off. Their notion of isCallable()/isConstructor() is // more complicated. @@ -12272,7 +12265,7 @@ static void EmitObjectIsArray(MacroAssembler& masm, OutOfLineCode* ool, Register obj, Register output, Label* notArray = nullptr) { - masm.loadObjClass(obj, output); + masm.loadObjClassUnsafe(obj, output); Label isArray; masm.branchPtr(Assembler::Equal, output, ImmPtr(&ArrayObject::class_), &isArray); @@ -12333,7 +12326,7 @@ CodeGenerator::visitIsTypedArray(LIsTypedArray* lir) const Class* firstTypedArrayClass = TypedArrayObject::classForType(Scalar::Int8); const Class* lastTypedArrayClass = TypedArrayObject::classForType(Scalar::Uint8Clamped); - masm.loadObjClass(object, output); + masm.loadObjClassUnsafe(object, output); masm.branchPtr(Assembler::Below, output, ImmPtr(firstTypedArrayClass), ¬TypedArray); masm.branchPtr(Assembler::Above, output, ImmPtr(lastTypedArrayClass), ¬TypedArray); @@ -12387,7 +12380,7 @@ CodeGenerator::visitHasClass(LHasClass* ins) Register lhs = ToRegister(ins->lhs()); Register output = ToRegister(ins->output()); - masm.loadObjClass(lhs, output); + masm.loadObjClassUnsafe(lhs, output); masm.cmpPtrSet(Assembler::Equal, output, ImmPtr(ins->mir()->getClass()), output); } diff --git a/js/src/jit/IonCacheIRCompiler.cpp b/js/src/jit/IonCacheIRCompiler.cpp index ef92ae1f0524..71cd702f8580 100644 --- a/js/src/jit/IonCacheIRCompiler.cpp +++ b/js/src/jit/IonCacheIRCompiler.cpp @@ -934,9 +934,7 @@ IonCacheIRCompiler::emitMegamorphicLoadSlotResult() return false; // The object must be Native. - masm.loadObjClass(obj, scratch3); - masm.branchTest32(Assembler::NonZero, Address(scratch3, Class::offsetOfFlags()), - Imm32(Class::NON_NATIVE), failure->label()); + masm.branchIfNonNativeObj(obj, scratch3, failure->label()); masm.Push(UndefinedValue()); masm.moveStackPtrTo(scratch3.get()); diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index 59d4d20db4b2..37ba31c0e2af 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -467,7 +467,7 @@ MacroAssembler::branchIfObjectEmulatesUndefined(Register objReg, Register scratc { // The branches to out-of-line code here implement a conservative version // of the JSObject::isWrapper test performed in EmulatesUndefined. - loadObjClass(objReg, scratch); + loadObjClassUnsafe(objReg, scratch); branchTestClassIsProxy(true, scratch, slowCheck); @@ -544,7 +544,7 @@ MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label) void MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label) { - loadObjClass(object, scratch); + loadObjClassUnsafe(object, scratch); branchTestClassIsProxy(proxy, scratch, label); } diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index fbcc4f579720..d7e96f9954be 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -1751,7 +1751,7 @@ void MacroAssembler::typeOfObject(Register obj, Register scratch, Label* slow, Label* isObject, Label* isCallable, Label* isUndefined) { - loadObjClass(obj, scratch); + loadObjClassUnsafe(obj, scratch); // Proxies can emulate undefined and have complex isCallable behavior. branchTestClassIsProxy(true, scratch, slow); @@ -3250,6 +3250,22 @@ MacroAssembler::branchIfPretenuredGroup(const ObjectGroup* group, Register scrat Imm32(OBJECT_FLAG_PRE_TENURE), label); } +void +MacroAssembler::branchIfNonNativeObj(Register obj, Register scratch, Label* label) +{ + loadObjClassUnsafe(obj, scratch); + branchTest32(Assembler::NonZero, Address(scratch, Class::offsetOfFlags()), + Imm32(Class::NON_NATIVE), label); +} + +void +MacroAssembler::branchIfInlineTypedObject(Register obj, Register scratch, Label* label) +{ + loadObjClassUnsafe(obj, scratch); + branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineOpaqueTypedObject::class_), label); + branchPtr(Assembler::Equal, temp1, ImmPtr(&InlineTransparentTypedObject::class_), label); +} + void MacroAssembler::branchIfNotSimdObject(Register obj, Register scratch, SimdType simdType, Label* label) diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 273d993eec58..752a74aea593 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -1197,6 +1197,10 @@ class MacroAssembler : public MacroAssemblerSpecific void branchIfObjGroupHasNoAddendum(Register obj, Register scratch, Label* label); void branchIfPretenuredGroup(const ObjectGroup* group, Register scratch, Label* label); + void branchIfNonNativeObj(Register obj, Register scratch, Label* label); + + void branchIfInlineTypedObject(Register obj, Register scratch, Label* label); + void branchIfNotSimdObject(Register obj, Register scratch, SimdType simdType, Label* label); inline void branchTestClassIsProxy(bool proxy, Register clasp, Label* label); @@ -1976,6 +1980,10 @@ class MacroAssembler : public MacroAssemblerSpecific void loadObjGroupUnsafe(Register obj, Register dest) { loadPtr(Address(obj, JSObject::offsetOfGroup()), dest); } + void loadObjClassUnsafe(Register obj, Register dest) { + loadPtr(Address(obj, JSObject::offsetOfGroup()), dest); + loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), dest); + } template inline void storeObjGroup(Register group, Register obj, EmitPreBarrier emitPreBarrier); @@ -1986,11 +1994,6 @@ class MacroAssembler : public MacroAssemblerSpecific template inline void storeObjShape(Shape* shape, Register obj, EmitPreBarrier emitPreBarrier); - void loadObjClass(Register obj, Register dest) { - loadPtr(Address(obj, JSObject::offsetOfGroup()), dest); - loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), dest); - } - void loadObjPrivate(Register obj, uint32_t nfixed, Register dest) { loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest); }