diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h index 2eb7447a64f..f02ce4c6054 100644 --- a/js/src/jit/MacroAssembler-inl.h +++ b/js/src/jit/MacroAssembler-inl.h @@ -317,8 +317,8 @@ MacroAssembler::addPtr(ImmPtr imm, Register dest) addPtr(ImmWord(uintptr_t(imm.value)), dest); } +//}}} check_macroassembler_style // =============================================================== -// Branch functions template void @@ -381,6 +381,46 @@ MacroAssembler::branchIfInterpreted(Register fun, Label* label) branchTest32(Assembler::NonZero, address, Imm32(bit), label); } +void +MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label) +{ + MOZ_ASSERT(cond == Zero || cond == NonZero); + CompileZone* zone = GetJitContext()->compartment->zone(); + AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier()); + branchTest32(cond, needsBarrierAddr, Imm32(0x1), label); +} + +void +MacroAssembler::branchTestObjectTruthy(bool truthy, Register objReg, Register scratch, + Label* slowCheck, Label* checked) +{ + // The branches to out-of-line code here implement a conservative version + // of the JSObject::isWrapper test performed in EmulatesUndefined. If none + // of the branches are taken, we can check class flags directly. + loadObjClass(objReg, scratch); + Address flags(scratch, Class::offsetOfFlags()); + + branchTestClassIsProxy(true, scratch, slowCheck); + + Condition cond = truthy ? Assembler::Zero : Assembler::NonZero; + branchTest32(cond, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), checked); +} + +void +MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label) +{ + branchTest32(proxy ? Assembler::NonZero : Assembler::Zero, + Address(clasp, Class::offsetOfFlags()), + Imm32(JSCLASS_IS_PROXY), label); +} + +void +MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label) +{ + loadObjClass(object, scratch); + branchTestClassIsProxy(proxy, scratch, label); +} + void MacroAssembler::branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun, Register scratch, Label* label) @@ -429,37 +469,6 @@ MacroAssembler::branchTestObjGroup(Condition cond, Register obj, Register group, branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), group, label); } -void -MacroAssembler::branchTestObjectTruthy(bool truthy, Register objReg, Register scratch, - Label* slowCheck, Label* checked) -{ - // The branches to out-of-line code here implement a conservative version - // of the JSObject::isWrapper test performed in EmulatesUndefined. If none - // of the branches are taken, we can check class flags directly. - loadObjClass(objReg, scratch); - Address flags(scratch, Class::offsetOfFlags()); - - branchTestClassIsProxy(true, scratch, slowCheck); - - Condition cond = truthy ? Assembler::Zero : Assembler::NonZero; - branchTest32(cond, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), checked); -} - -void -MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label) -{ - branchTest32(proxy ? Assembler::NonZero : Assembler::Zero, - Address(clasp, Class::offsetOfFlags()), - Imm32(JSCLASS_IS_PROXY), label); -} - -void -MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label) -{ - loadObjClass(object, scratch); - branchTestClassIsProxy(proxy, scratch, label); -} - void MacroAssembler::branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch, const void* handlerp, Label* label) @@ -470,49 +479,6 @@ MacroAssembler::branchTestProxyHandlerFamily(Condition cond, Register proxy, Reg branchPtr(cond, familyAddr, ImmPtr(handlerp), label); } -template -void -MacroAssembler::branchTestMIRType(Condition cond, const Value& val, MIRType type, Label* label) -{ - switch (type) { - case MIRType_Null: return branchTestNull(cond, val, label); - case MIRType_Undefined: return branchTestUndefined(cond, val, label); - case MIRType_Boolean: return branchTestBoolean(cond, val, label); - case MIRType_Int32: return branchTestInt32(cond, val, label); - case MIRType_String: return branchTestString(cond, val, label); - case MIRType_Symbol: return branchTestSymbol(cond, val, label); - case MIRType_Object: return branchTestObject(cond, val, label); - case MIRType_Double: return branchTestDouble(cond, val, label); - case MIRType_MagicOptimizedArguments: // Fall through. - case MIRType_MagicIsConstructing: - case MIRType_MagicHole: return branchTestMagic(cond, val, label); - default: - MOZ_CRASH("Bad MIRType"); - } -} - -template -void -MacroAssembler::branchKey(Condition cond, const T& length, const Int32Key& key, Label* label) -{ - if (key.isRegister()) - branch32(cond, length, key.reg(), label); - else - branch32(cond, length, Imm32(key.constant()), label); -} - -void -MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label) -{ - MOZ_ASSERT(cond == Zero || cond == NonZero); - CompileZone* zone = GetJitContext()->compartment->zone(); - AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier()); - branchTest32(cond, needsBarrierAddr, Imm32(0x1), label); -} - -//}}} check_macroassembler_style -// =============================================================== - #ifndef JS_CODEGEN_ARM64 template diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp index 38400c151e2..0697efcaf36 100644 --- a/js/src/jit/MacroAssembler.cpp +++ b/js/src/jit/MacroAssembler.cpp @@ -2024,6 +2024,57 @@ MacroAssembler::link(JitCode* code) linkProfilerCallSites(code); } +void +MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch, Label* label) +{ + // 16-bit loads are slow and unaligned 32-bit loads may be too so + // perform an aligned 32-bit load and adjust the bitmask accordingly. + MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0); + MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2); + + // First, ensure it's a scripted function. + load32(Address(fun, JSFunction::offsetOfNargs()), scratch); + int32_t bits = IMM32_16ADJ(JSFunction::INTERPRETED); + branchTest32(Assembler::Zero, scratch, Imm32(bits), label); + + // Check if the CONSTRUCTOR bit is set. + bits = IMM32_16ADJ(JSFunction::CONSTRUCTOR); + branchTest32(Assembler::Zero, scratch, Imm32(bits), label); +} + +void +MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition* maybeDef, Register tag, + Label* label) +{ + if (!maybeDef || maybeDef->mightBeType(type)) { + switch (type) { + case MIRType_Null: + branchTestNull(Equal, tag, label); + break; + case MIRType_Boolean: + branchTestBoolean(Equal, tag, label); + break; + case MIRType_Int32: + branchTestInt32(Equal, tag, label); + break; + case MIRType_Double: + branchTestDouble(Equal, tag, label); + break; + case MIRType_String: + branchTestString(Equal, tag, label); + break; + case MIRType_Symbol: + branchTestSymbol(Equal, tag, label); + break; + case MIRType_Object: + branchTestObject(Equal, tag, label); + break; + default: + MOZ_CRASH("Unsupported type"); + } + } +} + MacroAssembler::AutoProfilerCallInstrumentation::AutoProfilerCallInstrumentation( MacroAssembler& masm MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL) @@ -2485,85 +2536,8 @@ MacroAssembler::linkSelfReference(JitCode* code) } } -// =============================================================== -// Branch functions - -void -MacroAssembler::branchIfNotInterpretedConstructor(Register fun, Register scratch, Label* label) -{ - // 16-bit loads are slow and unaligned 32-bit loads may be too so - // perform an aligned 32-bit load and adjust the bitmask accordingly. - MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0); - MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2); - - // First, ensure it's a scripted function. - load32(Address(fun, JSFunction::offsetOfNargs()), scratch); - int32_t bits = IMM32_16ADJ(JSFunction::INTERPRETED); - branchTest32(Assembler::Zero, scratch, Imm32(bits), label); - - // Check if the CONSTRUCTOR bit is set. - bits = IMM32_16ADJ(JSFunction::CONSTRUCTOR); - branchTest32(Assembler::Zero, scratch, Imm32(bits), label); -} - -void -MacroAssembler::branchEqualTypeIfNeeded(MIRType type, MDefinition* maybeDef, Register tag, - Label* label) -{ - if (!maybeDef || maybeDef->mightBeType(type)) { - switch (type) { - case MIRType_Null: - branchTestNull(Equal, tag, label); - break; - case MIRType_Boolean: - branchTestBoolean(Equal, tag, label); - break; - case MIRType_Int32: - branchTestInt32(Equal, tag, label); - break; - case MIRType_Double: - branchTestDouble(Equal, tag, label); - break; - case MIRType_String: - branchTestString(Equal, tag, label); - break; - case MIRType_Symbol: - branchTestSymbol(Equal, tag, label); - break; - case MIRType_Object: - branchTestObject(Equal, tag, label); - break; - default: - MOZ_CRASH("Unsupported type"); - } - } -} - //}}} check_macroassembler_style -void -MacroAssembler::BranchType::emit(MacroAssembler& masm) -{ - MOZ_ASSERT(isInitialized()); - MIRType mirType = MIRType_None; - - if (type_.isPrimitive()) { - if (type_.isMagicArguments()) - mirType = MIRType_MagicOptimizedArguments; - else - mirType = MIRTypeFromValueType(type_.primitive()); - } else if (type_.isAnyObject()) { - mirType = MIRType_Object; - } else { - MOZ_CRASH("Unknown conversion to mirtype"); - } - - if (mirType == MIRType_Double) - masm.branchTestNumber(cond(), reg(), jump()); - else - masm.branchTestMIRType(cond(), reg(), mirType, jump()); -} - void MacroAssembler::BranchGCPtr::emit(MacroAssembler& masm) { diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index b9b24099df4..4b8e0919af1 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -284,7 +284,27 @@ class MacroAssembler : public MacroAssemblerSpecific type_(type) { } - void emit(MacroAssembler& masm); + void emit(MacroAssembler& masm) { + MOZ_ASSERT(isInitialized()); + MIRType mirType = MIRType_None; + + if (type_.isPrimitive()) { + if (type_.isMagicArguments()) + mirType = MIRType_MagicOptimizedArguments; + else + mirType = MIRTypeFromValueType(type_.primitive()); + } else if (type_.isAnyObject()) { + mirType = MIRType_Object; + } else { + MOZ_CRASH("Unknown conversion to mirtype"); + } + + if (mirType == MIRType_Double) + masm.branchTestNumber(cond(), reg(), jump()); + else + masm.branchTestMIRType(cond(), reg(), mirType, jump()); + } + }; /* @@ -846,55 +866,6 @@ class MacroAssembler : public MacroAssemblerSpecific inline void branchTest64(Condition cond, Register64 lhs, Register64 rhs, Register temp, Label* label) PER_ARCH; - // Branches to |label| if |reg| is false. |reg| should be a C++ bool. - template - inline void branchIfFalseBool(Register reg, L label); - - // Branches to |label| if |reg| is true. |reg| should be a C++ bool. - inline void branchIfTrueBool(Register reg, Label* label); - - inline void branchIfRope(Register str, Label* label); - - inline void branchLatin1String(Register string, Label* label); - inline void branchTwoByteString(Register string, Label* label); - - inline void branchIfFunctionHasNoScript(Register fun, Label* label); - inline void branchIfInterpreted(Register fun, Label* label); - - inline void branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun, - Register scratch, Label* label); - - void branchIfNotInterpretedConstructor(Register fun, Register scratch, Label* label); - - inline void branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp, - Label* label); - inline void branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label); - inline void branchTestObjShape(Condition cond, Register obj, Register shape, Label* label); - inline void branchTestObjGroup(Condition cond, Register obj, ObjectGroup* group, Label* label); - inline void branchTestObjGroup(Condition cond, Register obj, Register group, Label* label); - - inline void branchTestObjectTruthy(bool truthy, Register objReg, Register scratch, - Label* slowCheck, Label* checked); - - inline void branchTestClassIsProxy(bool proxy, Register clasp, Label* label); - - inline void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label); - - inline void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch, - const void* handlerp, Label* label); - - template - inline void branchTestMIRType(Condition cond, const Value& val, MIRType type, Label* label); - - // Emit type case branch on tag matching if the type tag in the definition - // might actually be that type. - void branchEqualTypeIfNeeded(MIRType type, MDefinition* maybeDef, Register tag, Label* label); - - template - inline void branchKey(Condition cond, const T& length, const Int32Key& key, Label* label); - - inline void branchTestNeedsIncrementalBarrier(Condition cond, Label* label); - //}}} check_macroassembler_style public: @@ -922,6 +893,40 @@ class MacroAssembler : public MacroAssemblerSpecific loadObjGroup(objReg, dest); loadPtr(Address(dest, ObjectGroup::offsetOfClasp()), dest); } + inline void branchTestObjClass(Condition cond, Register obj, Register scratch, const js::Class* clasp, + Label* label); + inline void branchTestObjShape(Condition cond, Register obj, const Shape* shape, Label* label); + inline void branchTestObjShape(Condition cond, Register obj, Register shape, Label* label); + inline void branchTestObjGroup(Condition cond, Register obj, ObjectGroup* group, Label* label); + inline void branchTestObjGroup(Condition cond, Register obj, Register group, Label* label); + inline void branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch, + const void* handlerp, Label* label); + + template + void branchTestMIRType(Condition cond, const Value& val, MIRType type, Label* label) { + switch (type) { + case MIRType_Null: return branchTestNull(cond, val, label); + case MIRType_Undefined: return branchTestUndefined(cond, val, label); + case MIRType_Boolean: return branchTestBoolean(cond, val, label); + case MIRType_Int32: return branchTestInt32(cond, val, label); + case MIRType_String: return branchTestString(cond, val, label); + case MIRType_Symbol: return branchTestSymbol(cond, val, label); + case MIRType_Object: return branchTestObject(cond, val, label); + case MIRType_Double: return branchTestDouble(cond, val, label); + case MIRType_MagicOptimizedArguments: // Fall through. + case MIRType_MagicIsConstructing: + case MIRType_MagicHole: return branchTestMagic(cond, val, label); + default: + MOZ_CRASH("Bad MIRType"); + } + } + + // Branches to |label| if |reg| is false. |reg| should be a C++ bool. + template + inline void branchIfFalseBool(Register reg, L label); + + // Branches to |label| if |reg| is true. |reg| should be a C++ bool. + inline void branchIfTrueBool(Register reg, Label* label); void loadObjPrivate(Register obj, uint32_t nfixed, Register dest) { loadPtr(Address(obj, NativeObject::getPrivateDataOffset(nfixed)), dest); @@ -939,6 +944,11 @@ class MacroAssembler : public MacroAssemblerSpecific void loadStringChars(Register str, Register dest); void loadStringChar(Register str, Register index, Register output); + inline void branchIfRope(Register str, Label* label); + + inline void branchLatin1String(Register string, Label* label); + inline void branchTwoByteString(Register string, Label* label); + void loadJSContext(Register dest) { loadPtr(AbsoluteAddress(GetJitContext()->runtime->addressOfJSContext()), dest); } @@ -1056,6 +1066,11 @@ class MacroAssembler : public MacroAssemblerSpecific return extractObject(source, scratch); } + inline void branchIfFunctionHasNoScript(Register fun, Label* label); + inline void branchIfInterpreted(Register fun, Label* label); + + void branchIfNotInterpretedConstructor(Register fun, Register scratch, Label* label); + inline void bumpKey(Int32Key* key, int diff); void storeKey(const Int32Key& key, const Address& dest) { @@ -1065,6 +1080,16 @@ class MacroAssembler : public MacroAssemblerSpecific store32(Imm32(key.constant()), dest); } + template + void branchKey(Condition cond, const T& length, const Int32Key& key, Label* label) { + if (key.isRegister()) + branch32(cond, length, key.reg(), label); + else + branch32(cond, length, Imm32(key.constant()), label); + } + + inline void branchTestNeedsIncrementalBarrier(Condition cond, Label* label); + template void callPreBarrier(const T& address, MIRType type) { Label done; @@ -1196,6 +1221,10 @@ class MacroAssembler : public MacroAssemblerSpecific bind(&done); } + // Emit type case branch on tag matching if the type tag in the definition + // might actually be that type. + void branchEqualTypeIfNeeded(MIRType type, MDefinition* maybeDef, Register tag, Label* label); + // Inline allocation. private: void checkAllocatorState(Label* fail); @@ -1238,6 +1267,16 @@ class MacroAssembler : public MacroAssemblerSpecific // Generates code used to complete a bailout. void generateBailoutTail(Register scratch, Register bailoutInfo); + inline void branchTestObjectTruthy(bool truthy, Register objReg, Register scratch, + Label* slowCheck, Label* checked); + + inline void branchTestClassIsProxy(bool proxy, Register clasp, Label* label); + + inline void branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label); + + inline void branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun, + Register scratch, Label* label); + public: #ifndef JS_CODEGEN_ARM64 // StackPointer manipulation functions.