LCOV - code coverage report
Current view: top level - js/src/jit - MacroAssembler-inl.h (source / functions) Hit Total Coverage
Test: output.info Lines: 125 312 40.1 %
Date: 2018-08-07 16:42:27 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_MacroAssembler_inl_h
       8             : #define jit_MacroAssembler_inl_h
       9             : 
      10             : #include "jit/MacroAssembler.h"
      11             : 
      12             : #include "mozilla/FloatingPoint.h"
      13             : #include "mozilla/MathAlgorithms.h"
      14             : 
      15             : #if defined(JS_CODEGEN_X86)
      16             : # include "jit/x86/MacroAssembler-x86-inl.h"
      17             : #elif defined(JS_CODEGEN_X64)
      18             : # include "jit/x64/MacroAssembler-x64-inl.h"
      19             : #elif defined(JS_CODEGEN_ARM)
      20             : # include "jit/arm/MacroAssembler-arm-inl.h"
      21             : #elif defined(JS_CODEGEN_ARM64)
      22             : # include "jit/arm64/MacroAssembler-arm64-inl.h"
      23             : #elif defined(JS_CODEGEN_MIPS32)
      24             : # include "jit/mips32/MacroAssembler-mips32-inl.h"
      25             : #elif defined(JS_CODEGEN_MIPS64)
      26             : # include "jit/mips64/MacroAssembler-mips64-inl.h"
      27             : #elif !defined(JS_CODEGEN_NONE)
      28             : # error "Unknown architecture!"
      29             : #endif
      30             : 
      31             : #include "wasm/WasmBuiltins.h"
      32             : 
      33             : namespace js {
      34             : namespace jit {
      35             : 
      36             : //{{{ check_macroassembler_style
      37             : // ===============================================================
      38             : // Stack manipulation functions.
      39             : 
      40             : CodeOffset
      41             : MacroAssembler::PushWithPatch(ImmWord word)
      42             : {
      43           0 :     framePushed_ += sizeof(word.value);
      44         474 :     return pushWithPatch(word);
      45             : }
      46             : 
      47             : CodeOffset
      48             : MacroAssembler::PushWithPatch(ImmPtr imm)
      49             : {
      50         170 :     return PushWithPatch(ImmWord(uintptr_t(imm.value)));
      51             : }
      52             : 
      53             : // ===============================================================
      54             : // Simple call functions.
      55             : 
      56             : void
      57          48 : MacroAssembler::call(TrampolinePtr code)
      58             : {
      59           0 :     call(ImmPtr(code.value));
      60          48 : }
      61             : 
      62             : void
      63             : MacroAssembler::call(const wasm::CallSiteDesc& desc, const Register reg)
      64             : {
      65           0 :     CodeOffset l = call(reg);
      66           0 :     append(desc, l);
      67             : }
      68             : 
      69             : void
      70             : MacroAssembler::call(const wasm::CallSiteDesc& desc, uint32_t funcIndex)
      71             : {
      72           0 :     CodeOffset l = callWithPatch();
      73           0 :     append(desc, l, funcIndex);
      74             : }
      75             : 
      76             : void
      77             : MacroAssembler::call(const wasm::CallSiteDesc& desc, wasm::Trap trap)
      78             : {
      79             :     CodeOffset l = callWithPatch();
      80             :     append(desc, l, trap);
      81             : }
      82             : 
      83             : void
      84           0 : MacroAssembler::call(const wasm::CallSiteDesc& desc, wasm::SymbolicAddress imm)
      85             : {
      86           0 :     MOZ_ASSERT(wasm::NeedsBuiltinThunk(imm), "only for functions which may appear in profiler");
      87           0 :     call(imm);
      88           0 :     append(desc, CodeOffset(currentOffset()));
      89           0 : }
      90             : 
      91             : // ===============================================================
      92             : // ABI function calls.
      93             : 
      94             : void
      95             : MacroAssembler::passABIArg(Register reg)
      96             : {
      97       31132 :     passABIArg(MoveOperand(reg), MoveOp::GENERAL);
      98             : }
      99             : 
     100             : void
     101           1 : MacroAssembler::passABIArg(FloatRegister reg, MoveOp::Type type)
     102             : {
     103           0 :     passABIArg(MoveOperand(reg), type);
     104           1 : }
     105             : 
     106             : void
     107       25309 : MacroAssembler::callWithABI(void* fun, MoveOp::Type result, CheckUnsafeCallWithABI check)
     108             : {
     109           0 :     AutoProfilerCallInstrumentation profiler(*this);
     110           0 :     callWithABINoProfiler(fun, result, check);
     111       25309 : }
     112             : 
     113             : void
     114           3 : MacroAssembler::callWithABI(Register fun, MoveOp::Type result)
     115             : {
     116           0 :     AutoProfilerCallInstrumentation profiler(*this);
     117           0 :     callWithABINoProfiler(fun, result);
     118           3 : }
     119             : 
     120             : void
     121          25 : MacroAssembler::callWithABI(const Address& fun, MoveOp::Type result)
     122             : {
     123           0 :     AutoProfilerCallInstrumentation profiler(*this);
     124           0 :     callWithABINoProfiler(fun, result);
     125          25 : }
     126             : 
     127             : void
     128             : MacroAssembler::appendSignatureType(MoveOp::Type type)
     129             : {
     130             : #ifdef JS_SIMULATOR
     131             :     signature_ <<= ArgType_Shift;
     132             :     switch (type) {
     133             :       case MoveOp::GENERAL: signature_ |= ArgType_General; break;
     134             :       case MoveOp::DOUBLE:  signature_ |= ArgType_Double;  break;
     135             :       case MoveOp::FLOAT32: signature_ |= ArgType_Float32; break;
     136             :       default: MOZ_CRASH("Invalid argument type");
     137             :     }
     138             : #endif
     139             : }
     140             : 
     141             : ABIFunctionType
     142             : MacroAssembler::signature() const
     143             : {
     144             : #ifdef JS_SIMULATOR
     145             : #ifdef DEBUG
     146             :     switch (signature_) {
     147             :       case Args_General0:
     148             :       case Args_General1:
     149             :       case Args_General2:
     150             :       case Args_General3:
     151             :       case Args_General4:
     152             :       case Args_General5:
     153             :       case Args_General6:
     154             :       case Args_General7:
     155             :       case Args_General8:
     156             :       case Args_Double_None:
     157             :       case Args_Int_Double:
     158             :       case Args_Float32_Float32:
     159             :       case Args_Double_Double:
     160             :       case Args_Double_Int:
     161             :       case Args_Double_DoubleInt:
     162             :       case Args_Double_DoubleDouble:
     163             :       case Args_Double_IntDouble:
     164             :       case Args_Int_IntDouble:
     165             :       case Args_Int_DoubleIntInt:
     166             :       case Args_Int_IntDoubleIntInt:
     167             :       case Args_Double_DoubleDoubleDouble:
     168             :       case Args_Double_DoubleDoubleDoubleDouble:
     169             :         break;
     170             :       default:
     171             :         MOZ_CRASH("Unexpected type");
     172             :     }
     173             : #endif // DEBUG
     174             : 
     175             :     return ABIFunctionType(signature_);
     176             : #else
     177             :     // No simulator enabled.
     178             :     MOZ_CRASH("Only available for making calls within a simulator.");
     179             : #endif
     180             : }
     181             : 
     182             : // ===============================================================
     183             : // Jit Frames.
     184             : 
     185             : uint32_t
     186           4 : MacroAssembler::callJitNoProfiler(Register callee)
     187             : {
     188             : #ifdef JS_USE_LINK_REGISTER
     189             :     // The return address is pushed by the callee.
     190             :     call(callee);
     191             : #else
     192         219 :     callAndPushReturnAddress(callee);
     193             : #endif
     194         438 :     return currentOffset();
     195             : }
     196             : 
     197             : uint32_t
     198         211 : MacroAssembler::callJit(Register callee)
     199             : {
     200           0 :     AutoProfilerCallInstrumentation profiler(*this);
     201           0 :     uint32_t ret = callJitNoProfiler(callee);
     202         422 :     return ret;
     203             : }
     204             : 
     205             : uint32_t
     206             : MacroAssembler::callJit(JitCode* callee)
     207             : {
     208             :     AutoProfilerCallInstrumentation profiler(*this);
     209             :     call(callee);
     210             :     return currentOffset();
     211             : }
     212             : 
     213             : uint32_t
     214        1078 : MacroAssembler::callJit(TrampolinePtr code)
     215             : {
     216           0 :     AutoProfilerCallInstrumentation profiler(*this);
     217           0 :     call(code);
     218        3234 :     return currentOffset();
     219             : }
     220             : 
     221             : void
     222         704 : MacroAssembler::makeFrameDescriptor(Register frameSizeReg, FrameType type, uint32_t headerSize)
     223             : {
     224             :     // See JitFrames.h for a description of the frame descriptor format.
     225             :     // The saved-frame bit is zero for new frames. See js::SavedStacks.
     226             : 
     227         704 :     lshiftPtr(Imm32(FRAMESIZE_SHIFT), frameSizeReg);
     228             : 
     229           0 :     headerSize = EncodeFrameHeaderSize(headerSize);
     230           0 :     orPtr(Imm32((headerSize << FRAME_HEADER_SIZE_SHIFT) | type), frameSizeReg);
     231         704 : }
     232             : 
     233             : void
     234        1151 : MacroAssembler::pushStaticFrameDescriptor(FrameType type, uint32_t headerSize)
     235             : {
     236           0 :     uint32_t descriptor = MakeFrameDescriptor(framePushed(), type, headerSize);
     237           0 :     Push(Imm32(descriptor));
     238        1151 : }
     239             : 
     240             : void
     241         159 : MacroAssembler::PushCalleeToken(Register callee, bool constructing)
     242             : {
     243           0 :     if (constructing) {
     244           0 :         orPtr(Imm32(CalleeToken_FunctionConstructing), callee);
     245           0 :         Push(callee);
     246           5 :         andPtr(Imm32(uint32_t(CalleeTokenMask)), callee);
     247             :     } else {
     248             :         static_assert(CalleeToken_Function == 0, "Non-constructing call requires no tagging");
     249         154 :         Push(callee);
     250             :     }
     251         159 : }
     252             : 
     253             : void
     254         882 : MacroAssembler::loadFunctionFromCalleeToken(Address token, Register dest)
     255             : {
     256             : #ifdef DEBUG
     257           0 :     Label ok;
     258           0 :     loadPtr(token, dest);
     259           0 :     andPtr(Imm32(uint32_t(~CalleeTokenMask)), dest);
     260           0 :     branchPtr(Assembler::Equal, dest, Imm32(CalleeToken_Function), &ok);
     261           0 :     branchPtr(Assembler::Equal, dest, Imm32(CalleeToken_FunctionConstructing), &ok);
     262           0 :     assumeUnreachable("Unexpected CalleeToken tag");
     263         882 :     bind(&ok);
     264             : #endif
     265           0 :     loadPtr(token, dest);
     266           0 :     andPtr(Imm32(uint32_t(CalleeTokenMask)), dest);
     267         882 : }
     268             : 
     269             : uint32_t
     270          81 : MacroAssembler::buildFakeExitFrame(Register scratch)
     271             : {
     272         243 :     mozilla::DebugOnly<uint32_t> initialDepth = framePushed();
     273             : 
     274           0 :     pushStaticFrameDescriptor(JitFrame_IonJS, ExitFrameLayout::Size());
     275          81 :     uint32_t retAddr = pushFakeReturnAddress(scratch);
     276             : 
     277           0 :     MOZ_ASSERT(framePushed() == initialDepth + ExitFrameLayout::Size());
     278         162 :     return retAddr;
     279             : }
     280             : 
     281             : // ===============================================================
     282             : // Exit frame footer.
     283             : 
     284             : void
     285         908 : MacroAssembler::enterExitFrame(Register cxreg, Register scratch, const VMFunction* f)
     286             : {
     287           0 :     MOZ_ASSERT(f);
     288         908 :     linkExitFrame(cxreg, scratch);
     289             :     // Push VMFunction pointer, to mark arguments.
     290           0 :     Push(ImmPtr(f));
     291         908 : }
     292             : 
     293             : void
     294             : MacroAssembler::enterFakeExitFrame(Register cxreg, Register scratch, ExitFrameType type)
     295             : {
     296           0 :     linkExitFrame(cxreg, scratch);
     297         332 :     Push(Imm32(int32_t(type)));
     298             : }
     299             : 
     300             : void
     301         106 : MacroAssembler::enterFakeExitFrameForNative(Register cxreg, Register scratch, bool isConstructing)
     302             : {
     303           0 :     enterFakeExitFrame(cxreg, scratch, isConstructing ? ExitFrameType::ConstructNative
     304           0 :                                                       : ExitFrameType::CallNative);
     305         106 : }
     306             : 
     307             : void
     308             : MacroAssembler::leaveExitFrame(size_t extraFrame)
     309             : {
     310         916 :     freeStack(ExitFooterFrame::Size() + extraFrame);
     311             : }
     312             : 
     313             : // ===============================================================
     314             : // Move instructions
     315             : 
     316             : void
     317           0 : MacroAssembler::moveValue(const ConstantOrRegister& src, const ValueOperand& dest)
     318             : {
     319           0 :     if (src.constant()) {
     320           0 :         moveValue(src.value(), dest);
     321           0 :         return;
     322             :     }
     323             : 
     324           0 :     moveValue(src.reg(), dest);
     325             : }
     326             : 
     327             : // ===============================================================
     328             : // Arithmetic functions
     329             : 
     330             : void
     331             : MacroAssembler::addPtr(ImmPtr imm, Register dest)
     332             : {
     333             :     addPtr(ImmWord(uintptr_t(imm.value)), dest);
     334             : }
     335             : 
     336             : // ===============================================================
     337             : // Branch functions
     338             : 
     339             : template <class L>
     340             : void
     341             : MacroAssembler::branchIfFalseBool(Register reg, L label)
     342             : {
     343             :     // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
     344         501 :     branchTest32(Assembler::Zero, reg, Imm32(0xFF), label);
     345             : }
     346             : 
     347             : void
     348             : MacroAssembler::branchIfTrueBool(Register reg, Label* label)
     349             : {
     350             :     // Note that C++ bool is only 1 byte, so ignore the higher-order bits.
     351          87 :     branchTest32(Assembler::NonZero, reg, Imm32(0xFF), label);
     352             : }
     353             : 
     354             : void
     355             : MacroAssembler::branchIfRope(Register str, Label* label)
     356             : {
     357           0 :     Address flags(str, JSString::offsetOfFlags());
     358           6 :     branchTest32(Assembler::Zero, flags, Imm32(JSString::LINEAR_BIT), label);
     359             : }
     360             : 
     361             : void
     362           6 : MacroAssembler::branchIfRopeOrExternal(Register str, Register temp, Label* label)
     363             : {
     364           0 :     Address flags(str, JSString::offsetOfFlags());
     365           0 :     move32(Imm32(JSString::TYPE_FLAGS_MASK), temp);
     366           6 :     and32(flags, temp);
     367             : 
     368           0 :     branchTest32(Assembler::Zero, temp, Imm32(JSString::LINEAR_BIT), label);
     369           0 :     branch32(Assembler::Equal, temp, Imm32(JSString::EXTERNAL_FLAGS), label);
     370           6 : }
     371             : 
     372             : void
     373             : MacroAssembler::branchIfNotRope(Register str, Label* label)
     374             : {
     375           0 :     Address flags(str, JSString::offsetOfFlags());
     376           2 :     branchTest32(Assembler::NonZero, flags, Imm32(JSString::LINEAR_BIT), label);
     377             : }
     378             : 
     379             : void
     380             : MacroAssembler::branchLatin1String(Register string, Label* label)
     381             : {
     382           0 :     branchTest32(Assembler::NonZero, Address(string, JSString::offsetOfFlags()),
     383          17 :                  Imm32(JSString::LATIN1_CHARS_BIT), label);
     384             : }
     385             : 
     386             : void
     387             : MacroAssembler::branchTwoByteString(Register string, Label* label)
     388             : {
     389             :     branchTest32(Assembler::Zero, Address(string, JSString::offsetOfFlags()),
     390             :                  Imm32(JSString::LATIN1_CHARS_BIT), label);
     391             : }
     392             : 
     393             : void
     394             : MacroAssembler::branchIfFunctionHasNoJitEntry(Register fun, bool isConstructing, Label* label)
     395             : {
     396             :     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     397             :     // perform an aligned 32-bit load and adjust the bitmask accordingly.
     398             : 
     399             :     static_assert(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0,
     400             :                   "The code in this function and the ones below must change");
     401             :     static_assert(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2,
     402             :                   "The code in this function and the ones below must change");
     403             : 
     404           0 :     Address address(fun, JSFunction::offsetOfNargs());
     405           0 :     int32_t bit = JSFunction::INTERPRETED;
     406           0 :     if (!isConstructing)
     407           0 :         bit |= JSFunction::WASM_OPTIMIZED;
     408           0 :     bit = IMM32_16ADJ(bit);
     409         344 :     branchTest32(Assembler::Zero, address, Imm32(bit), label);
     410             : }
     411             : 
     412             : void
     413             : MacroAssembler::branchIfInterpreted(Register fun, Label* label)
     414             : {
     415             :     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     416             :     // perform an aligned 32-bit load and adjust the bitmask accordingly.
     417             :     Address address(fun, JSFunction::offsetOfNargs());
     418             :     int32_t bit = IMM32_16ADJ(JSFunction::INTERPRETED);
     419             :     branchTest32(Assembler::NonZero, address, Imm32(bit), label);
     420             : }
     421             : 
     422             : void
     423          29 : MacroAssembler::branchIfObjectEmulatesUndefined(Register objReg, Register scratch,
     424             :                                                 Label* slowCheck, Label* label)
     425             : {
     426             :     // The branches to out-of-line code here implement a conservative version
     427             :     // of the JSObject::isWrapper test performed in EmulatesUndefined.
     428          29 :     loadObjClassUnsafe(objReg, scratch);
     429             : 
     430          29 :     branchTestClassIsProxy(true, scratch, slowCheck);
     431             : 
     432           0 :     Address flags(scratch, Class::offsetOfFlags());
     433           0 :     branchTest32(Assembler::NonZero, flags, Imm32(JSCLASS_EMULATES_UNDEFINED), label);
     434          29 : }
     435             : 
     436             : void
     437         120 : MacroAssembler::branchFunctionKind(Condition cond, JSFunction::FunctionKind kind, Register fun,
     438             :                                    Register scratch, Label* label)
     439             : {
     440             :     // 16-bit loads are slow and unaligned 32-bit loads may be too so
     441             :     // perform an aligned 32-bit load and adjust the bitmask accordingly.
     442             :     MOZ_ASSERT(JSFunction::offsetOfNargs() % sizeof(uint32_t) == 0);
     443             :     MOZ_ASSERT(JSFunction::offsetOfFlags() == JSFunction::offsetOfNargs() + 2);
     444           0 :     Address address(fun, JSFunction::offsetOfNargs());
     445           0 :     int32_t mask = IMM32_16ADJ(JSFunction::FUNCTION_KIND_MASK);
     446           0 :     int32_t bit = IMM32_16ADJ(kind << JSFunction::FUNCTION_KIND_SHIFT);
     447           0 :     load32(address, scratch);
     448           0 :     and32(Imm32(mask), scratch);
     449           0 :     branch32(cond, scratch, Imm32(bit), label);
     450         120 : }
     451             : 
     452             : void
     453         210 : MacroAssembler::branchTestObjClass(Condition cond, Register obj, const js::Class* clasp,
     454             :                                    Register scratch, Register spectreRegToZero, Label* label)
     455             : {
     456           0 :     MOZ_ASSERT(obj != scratch);
     457         210 :     MOZ_ASSERT(scratch != spectreRegToZero);
     458             : 
     459           0 :     loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
     460         630 :     branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp), label);
     461             : 
     462           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     463           0 :         spectreZeroRegister(cond, scratch, spectreRegToZero);
     464         210 : }
     465             : 
     466             : void
     467          12 : MacroAssembler::branchTestObjClassNoSpectreMitigations(Condition cond, Register obj,
     468             :                                                        const js::Class* clasp,
     469             :                                                        Register scratch, Label* label)
     470             : {
     471           0 :     loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
     472           0 :     branchPtr(cond, Address(scratch, ObjectGroup::offsetOfClasp()), ImmPtr(clasp), label);
     473          12 : }
     474             : 
     475             : void
     476           5 : MacroAssembler::branchTestObjClass(Condition cond, Register obj, const Address& clasp,
     477             :                                    Register scratch, Register spectreRegToZero, Label* label)
     478             : {
     479           0 :     MOZ_ASSERT(obj != scratch);
     480           5 :     MOZ_ASSERT(scratch != spectreRegToZero);
     481             : 
     482           0 :     loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
     483           0 :     loadPtr(Address(scratch, ObjectGroup::offsetOfClasp()), scratch);
     484           5 :     branchPtr(cond, clasp, scratch, label);
     485             : 
     486           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     487           0 :         spectreZeroRegister(cond, scratch, spectreRegToZero);
     488           5 : }
     489             : 
     490             : void
     491           0 : MacroAssembler::branchTestObjClassNoSpectreMitigations(Condition cond, Register obj,
     492             :                                                        const Address& clasp, Register scratch,
     493             :                                                        Label* label)
     494             : {
     495           0 :     MOZ_ASSERT(obj != scratch);
     496           0 :     loadPtr(Address(obj, JSObject::offsetOfGroup()), scratch);
     497           0 :     loadPtr(Address(scratch, ObjectGroup::offsetOfClasp()), scratch);
     498           0 :     branchPtr(cond, clasp, scratch, label);
     499           0 : }
     500             : 
     501             : void
     502         488 : MacroAssembler::branchTestObjShape(Condition cond, Register obj, const Shape* shape, Register scratch,
     503             :                                    Register spectreRegToZero, Label* label)
     504             : {
     505           0 :     MOZ_ASSERT(obj != scratch);
     506         488 :     MOZ_ASSERT(spectreRegToZero != scratch);
     507             : 
     508           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     509         976 :         move32(Imm32(0), scratch);
     510             : 
     511        1464 :     branchPtr(cond, Address(obj, ShapedObject::offsetOfShape()), ImmGCPtr(shape), label);
     512             : 
     513           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     514           0 :         spectreMovePtr(cond, scratch, spectreRegToZero);
     515         488 : }
     516             : 
     517             : void
     518         169 : MacroAssembler::branchTestObjShapeNoSpectreMitigations(Condition cond, Register obj,
     519             :                                                        const Shape* shape, Label* label)
     520             : {
     521           0 :     branchPtr(cond, Address(obj, ShapedObject::offsetOfShape()), ImmGCPtr(shape), label);
     522         169 : }
     523             : 
     524             : void
     525         329 : MacroAssembler::branchTestObjShape(Condition cond, Register obj, Register shape, Register scratch,
     526             :                                    Register spectreRegToZero, Label* label)
     527             : {
     528           0 :     MOZ_ASSERT(obj != scratch);
     529           0 :     MOZ_ASSERT(obj != shape);
     530         329 :     MOZ_ASSERT(spectreRegToZero != scratch);
     531             : 
     532           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     533         658 :         move32(Imm32(0), scratch);
     534             : 
     535         658 :     branchPtr(cond, Address(obj, ShapedObject::offsetOfShape()), shape, label);
     536             : 
     537           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     538           0 :         spectreMovePtr(cond, scratch, spectreRegToZero);
     539         329 : }
     540             : 
     541             : void
     542             : MacroAssembler::branchTestObjShapeNoSpectreMitigations(Condition cond, Register obj, Register shape,
     543             :                                                        Label* label)
     544             : {
     545         236 :     branchPtr(cond, Address(obj, ShapedObject::offsetOfShape()), shape, label);
     546             : }
     547             : 
     548             : void
     549             : MacroAssembler::branchTestObjShapeUnsafe(Condition cond, Register obj, Register shape,
     550             :                                          Label* label)
     551             : {
     552           0 :     branchTestObjShapeNoSpectreMitigations(cond, obj, shape, label);
     553             : }
     554             : 
     555             : void
     556         116 : MacroAssembler::branchTestObjGroup(Condition cond, Register obj, const ObjectGroup* group,
     557             :                                    Register scratch, Register spectreRegToZero, Label* label)
     558             : {
     559           0 :     MOZ_ASSERT(obj != scratch);
     560         116 :     MOZ_ASSERT(spectreRegToZero != scratch);
     561             : 
     562           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     563         232 :         move32(Imm32(0), scratch);
     564             : 
     565         348 :     branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), ImmGCPtr(group), label);
     566             : 
     567           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     568           0 :         spectreMovePtr(cond, scratch, spectreRegToZero);
     569         116 : }
     570             : 
     571             : void
     572           4 : MacroAssembler::branchTestObjGroupNoSpectreMitigations(Condition cond, Register obj,
     573             :                                                        const ObjectGroup* group, Label* label)
     574             : {
     575           0 :     branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), ImmGCPtr(group), label);
     576           4 : }
     577             : 
     578             : void
     579             : MacroAssembler::branchTestObjGroupUnsafe(Condition cond, Register obj, const ObjectGroup* group,
     580             :                                          Label* label)
     581             : {
     582           0 :     branchTestObjGroupNoSpectreMitigations(cond, obj, group, label);
     583             : }
     584             : 
     585             : void
     586         100 : MacroAssembler::branchTestObjGroup(Condition cond, Register obj, Register group, Register scratch,
     587             :                                    Register spectreRegToZero, Label* label)
     588             : {
     589           0 :     MOZ_ASSERT(obj != scratch);
     590           0 :     MOZ_ASSERT(obj != group);
     591         100 :     MOZ_ASSERT(spectreRegToZero != scratch);
     592             : 
     593           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     594         200 :         move32(Imm32(0), scratch);
     595             : 
     596         200 :     branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), group, label);
     597             : 
     598           0 :     if (JitOptions.spectreObjectMitigationsMisc)
     599           0 :         spectreMovePtr(cond, scratch, spectreRegToZero);
     600         100 : }
     601             : 
     602             : void
     603           5 : MacroAssembler::branchTestObjGroupNoSpectreMitigations(Condition cond, Register obj, Register group,
     604             :                                                        Label* label)
     605             : {
     606           0 :     MOZ_ASSERT(obj != group);
     607           0 :     branchPtr(cond, Address(obj, JSObject::offsetOfGroup()), group, label);
     608           5 : }
     609             : 
     610             : void
     611             : MacroAssembler::branchTestClassIsProxy(bool proxy, Register clasp, Label* label)
     612             : {
     613           0 :     branchTest32(proxy ? Assembler::NonZero : Assembler::Zero,
     614           0 :                  Address(clasp, Class::offsetOfFlags()),
     615         160 :                  Imm32(JSCLASS_IS_PROXY), label);
     616             : }
     617             : 
     618             : void
     619         104 : MacroAssembler::branchTestObjectIsProxy(bool proxy, Register object, Register scratch, Label* label)
     620             : {
     621           0 :     loadObjClassUnsafe(object, scratch);
     622           0 :     branchTestClassIsProxy(proxy, scratch, label);
     623         104 : }
     624             : 
     625             : void
     626          46 : MacroAssembler::branchTestProxyHandlerFamily(Condition cond, Register proxy, Register scratch,
     627             :                                              const void* handlerp, Label* label)
     628             : {
     629           0 :     Address handlerAddr(proxy, ProxyObject::offsetOfHandler());
     630           0 :     loadPtr(handlerAddr, scratch);
     631           0 :     Address familyAddr(scratch, BaseProxyHandler::offsetOfFamily());
     632           0 :     branchPtr(cond, familyAddr, ImmPtr(handlerp), label);
     633          46 : }
     634             : 
     635             : void
     636         957 : MacroAssembler::branchTestNeedsIncrementalBarrier(Condition cond, Label* label)
     637             : {
     638           0 :     MOZ_ASSERT(cond == Zero || cond == NonZero);
     639           0 :     CompileZone* zone = GetJitContext()->realm->zone();
     640           0 :     AbsoluteAddress needsBarrierAddr(zone->addressOfNeedsIncrementalBarrier());
     641           0 :     branchTest32(cond, needsBarrierAddr, Imm32(0x1), label);
     642         957 : }
     643             : 
     644             : void
     645         153 : MacroAssembler::branchTestMagicValue(Condition cond, const ValueOperand& val, JSWhyMagic why,
     646             :                                      Label* label)
     647             : {
     648           0 :     MOZ_ASSERT(cond == Equal || cond == NotEqual);
     649           0 :     branchTestValue(cond, val, MagicValue(why), label);
     650         153 : }
     651             : 
     652             : void
     653             : MacroAssembler::branchDoubleNotInInt64Range(Address src, Register temp, Label* fail)
     654             : {
     655             :     using mozilla::FloatingPoint;
     656             : 
     657             :     // Tests if double is in [INT64_MIN; INT64_MAX] range
     658             :     uint32_t EXPONENT_MASK = 0x7ff00000;
     659             :     uint32_t EXPONENT_SHIFT = FloatingPoint<double>::kExponentShift - 32;
     660             :     uint32_t TOO_BIG_EXPONENT = (FloatingPoint<double>::kExponentBias + 63) << EXPONENT_SHIFT;
     661             : 
     662             :     load32(Address(src.base, src.offset + sizeof(int32_t)), temp);
     663             :     and32(Imm32(EXPONENT_MASK), temp);
     664             :     branch32(Assembler::GreaterThanOrEqual, temp, Imm32(TOO_BIG_EXPONENT), fail);
     665             : }
     666             : 
     667             : void
     668             : MacroAssembler::branchDoubleNotInUInt64Range(Address src, Register temp, Label* fail)
     669             : {
     670             :     using mozilla::FloatingPoint;
     671             : 
     672             :     // Note: returns failure on -0.0
     673             :     // Tests if double is in [0; UINT64_MAX] range
     674             :     // Take the sign also in the equation. That way we can compare in one test?
     675             :     uint32_t EXPONENT_MASK = 0xfff00000;
     676             :     uint32_t EXPONENT_SHIFT = FloatingPoint<double>::kExponentShift - 32;
     677             :     uint32_t TOO_BIG_EXPONENT = (FloatingPoint<double>::kExponentBias + 64) << EXPONENT_SHIFT;
     678             : 
     679             :     load32(Address(src.base, src.offset + sizeof(int32_t)), temp);
     680             :     and32(Imm32(EXPONENT_MASK), temp);
     681             :     branch32(Assembler::AboveOrEqual, temp, Imm32(TOO_BIG_EXPONENT), fail);
     682             : }
     683             : 
     684             : void
     685             : MacroAssembler::branchFloat32NotInInt64Range(Address src, Register temp, Label* fail)
     686             : {
     687             :     using mozilla::FloatingPoint;
     688             : 
     689             :     // Tests if float is in [INT64_MIN; INT64_MAX] range
     690             :     uint32_t EXPONENT_MASK = 0x7f800000;
     691             :     uint32_t EXPONENT_SHIFT = FloatingPoint<float>::kExponentShift;
     692             :     uint32_t TOO_BIG_EXPONENT = (FloatingPoint<float>::kExponentBias + 63) << EXPONENT_SHIFT;
     693             : 
     694             :     load32(src, temp);
     695             :     and32(Imm32(EXPONENT_MASK), temp);
     696             :     branch32(Assembler::GreaterThanOrEqual, temp, Imm32(TOO_BIG_EXPONENT), fail);
     697             : }
     698             : 
     699             : void
     700             : MacroAssembler::branchFloat32NotInUInt64Range(Address src, Register temp, Label* fail)
     701             : {
     702             :     using mozilla::FloatingPoint;
     703             : 
     704             :     // Note: returns failure on -0.0
     705             :     // Tests if float is in [0; UINT64_MAX] range
     706             :     // Take the sign also in the equation. That way we can compare in one test?
     707             :     uint32_t EXPONENT_MASK = 0xff800000;
     708             :     uint32_t EXPONENT_SHIFT = FloatingPoint<float>::kExponentShift;
     709             :     uint32_t TOO_BIG_EXPONENT = (FloatingPoint<float>::kExponentBias + 64) << EXPONENT_SHIFT;
     710             : 
     711             :     load32(src, temp);
     712             :     and32(Imm32(EXPONENT_MASK), temp);
     713             :     branch32(Assembler::AboveOrEqual, temp, Imm32(TOO_BIG_EXPONENT), fail);
     714             : }
     715             : 
     716             : // ========================================================================
     717             : // Canonicalization primitives.
     718             : void
     719           0 : MacroAssembler::canonicalizeFloat(FloatRegister reg)
     720             : {
     721           0 :     Label notNaN;
     722           0 :     branchFloat(DoubleOrdered, reg, reg, &notNaN);
     723           0 :     loadConstantFloat32(float(JS::GenericNaN()), reg);
     724           0 :     bind(&notNaN);
     725           0 : }
     726             : 
     727             : void
     728             : MacroAssembler::canonicalizeFloatIfDeterministic(FloatRegister reg)
     729             : {
     730             : #ifdef JS_MORE_DETERMINISTIC
     731             :     // See the comment in TypedArrayObjectTemplate::getIndexValue.
     732             :     canonicalizeFloat(reg);
     733             : #endif // JS_MORE_DETERMINISTIC
     734             : }
     735             : 
     736             : void
     737           0 : MacroAssembler::canonicalizeDouble(FloatRegister reg)
     738             : {
     739           0 :     Label notNaN;
     740           0 :     branchDouble(DoubleOrdered, reg, reg, &notNaN);
     741           0 :     loadConstantDouble(JS::GenericNaN(), reg);
     742           0 :     bind(&notNaN);
     743           0 : }
     744             : 
     745             : void
     746             : MacroAssembler::canonicalizeDoubleIfDeterministic(FloatRegister reg)
     747             : {
     748             : #ifdef JS_MORE_DETERMINISTIC
     749             :     // See the comment in TypedArrayObjectTemplate::getIndexValue.
     750             :     canonicalizeDouble(reg);
     751             : #endif // JS_MORE_DETERMINISTIC
     752             : }
     753             : 
     754             : // ========================================================================
     755             : // Memory access primitives.
     756             : template<class T> void
     757           0 : MacroAssembler::storeDouble(FloatRegister src, const T& dest)
     758             : {
     759         218 :     canonicalizeDoubleIfDeterministic(src);
     760           0 :     storeUncanonicalizedDouble(src, dest);
     761           0 : }
     762             : 
     763             : template void MacroAssembler::storeDouble(FloatRegister src, const Address& dest);
     764             : template void MacroAssembler::storeDouble(FloatRegister src, const BaseIndex& dest);
     765             : 
     766             : void
     767             : MacroAssembler::boxDouble(FloatRegister src, const Address& dest)
     768             : {
     769           0 :     storeDouble(src, dest);
     770             : }
     771             : 
     772             : template<class T> void
     773           0 : MacroAssembler::storeFloat32(FloatRegister src, const T& dest)
     774             : {
     775           0 :     canonicalizeFloatIfDeterministic(src);
     776           0 :     storeUncanonicalizedFloat32(src, dest);
     777           0 : }
     778             : 
     779             : template void MacroAssembler::storeFloat32(FloatRegister src, const Address& dest);
     780             : template void MacroAssembler::storeFloat32(FloatRegister src, const BaseIndex& dest);
     781             : 
     782             : //}}} check_macroassembler_style
     783             : // ===============================================================
     784             : 
     785             : #ifndef JS_CODEGEN_ARM64
     786             : 
     787             : template <typename T>
     788             : void
     789           0 : MacroAssembler::branchTestStackPtr(Condition cond, T t, Label* label)
     790             : {
     791       51276 :     branchTestPtr(cond, getStackPointer(), t, label);
     792       25638 : }
     793             : 
     794             : template <typename T>
     795             : void
     796             : MacroAssembler::branchStackPtr(Condition cond, T rhs, Label* label)
     797             : {
     798          12 :     branchPtr(cond, getStackPointer(), rhs, label);
     799             : }
     800             : 
     801             : template <typename T>
     802             : void
     803             : MacroAssembler::branchStackPtrRhs(Condition cond, T lhs, Label* label)
     804             : {
     805         193 :     branchPtr(cond, lhs, getStackPointer(), label);
     806             : }
     807             : 
     808             : template <typename T> void
     809             : MacroAssembler::addToStackPtr(T t)
     810             : {
     811       62477 :     addPtr(t, getStackPointer());
     812             : }
     813             : 
     814             : template <typename T> void
     815             : MacroAssembler::addStackPtrTo(T t)
     816             : {
     817           6 :     addPtr(getStackPointer(), t);
     818             : }
     819             : 
     820             : void
     821             : MacroAssembler::reserveStack(uint32_t amount)
     822             : {
     823           0 :     subFromStackPtr(Imm32(amount));
     824           0 :     adjustFrame(amount);
     825             : }
     826             : #endif // !JS_CODEGEN_ARM64
     827             : 
     828             : template <typename EmitPreBarrier>
     829             : void
     830           3 : MacroAssembler::storeObjGroup(Register group, Register obj, EmitPreBarrier emitPreBarrier)
     831             : {
     832           3 :     MOZ_ASSERT(group != obj);
     833           0 :     Address groupAddr(obj, JSObject::offsetOfGroup());
     834           0 :     emitPreBarrier(*this, groupAddr);
     835           0 :     storePtr(group, groupAddr);
     836           0 : }
     837             : 
     838             : template <typename EmitPreBarrier>
     839             : void
     840           0 : MacroAssembler::storeObjGroup(ObjectGroup* group, Register obj, EmitPreBarrier emitPreBarrier)
     841             : {
     842           0 :     Address groupAddr(obj, JSObject::offsetOfGroup());
     843           0 :     emitPreBarrier(*this, groupAddr);
     844           0 :     storePtr(ImmGCPtr(group), groupAddr);
     845           0 : }
     846             : 
     847             : template <typename EmitPreBarrier>
     848             : void
     849          43 : MacroAssembler::storeObjShape(Register shape, Register obj, EmitPreBarrier emitPreBarrier)
     850             : {
     851          43 :     MOZ_ASSERT(shape != obj);
     852           0 :     Address shapeAddr(obj, ShapedObject::offsetOfShape());
     853           0 :     emitPreBarrier(*this, shapeAddr);
     854           0 :     storePtr(shape, shapeAddr);
     855           0 : }
     856             : 
     857             : template <typename EmitPreBarrier>
     858             : void
     859           0 : MacroAssembler::storeObjShape(Shape* shape, Register obj, EmitPreBarrier emitPreBarrier)
     860             : {
     861           0 :     Address shapeAddr(obj, ShapedObject::offsetOfShape());
     862           0 :     emitPreBarrier(*this, shapeAddr);
     863           0 :     storePtr(ImmGCPtr(shape), shapeAddr);
     864           0 : }
     865             : 
     866             : template <typename T>
     867             : void
     868           0 : MacroAssembler::storeObjectOrNull(Register src, const T& dest)
     869             : {
     870           0 :     Label notNull, done;
     871           0 :     branchTestPtr(Assembler::NonZero, src, src, &notNull);
     872           0 :     storeValue(NullValue(), dest);
     873           0 :     jump(&done);
     874           0 :     bind(&notNull);
     875           0 :     storeValue(JSVAL_TYPE_OBJECT, src, dest);
     876           0 :     bind(&done);
     877           0 : }
     878             : 
     879             : void
     880           1 : MacroAssembler::assertStackAlignment(uint32_t alignment, int32_t offset /* = 0 */)
     881             : {
     882             : #ifdef DEBUG
     883           0 :     Label ok, bad;
     884           0 :     MOZ_ASSERT(mozilla::IsPowerOfTwo(alignment));
     885             : 
     886             :     // Wrap around the offset to be a non-negative number.
     887           0 :     offset %= alignment;
     888       25544 :     if (offset < 0)
     889           0 :         offset += alignment;
     890             : 
     891             :     // Test if each bit from offset is set.
     892       25544 :     uint32_t off = offset;
     893           0 :     while (off) {
     894           0 :         uint32_t lowestBit = 1 << mozilla::CountTrailingZeroes32(off);
     895           0 :         branchTestStackPtr(Assembler::Zero, Imm32(lowestBit), &bad);
     896          51 :         off ^= lowestBit;
     897             :     }
     898             : 
     899             :     // Check that all remaining bits are zero.
     900           0 :     branchTestStackPtr(Assembler::Zero, Imm32((alignment - 1) ^ offset), &ok);
     901             : 
     902           0 :     bind(&bad);
     903           0 :     breakpoint();
     904       25544 :     bind(&ok);
     905             : #endif
     906           0 : }
     907             : 
     908             : void
     909         172 : MacroAssembler::storeCallBoolResult(Register reg)
     910             : {
     911         172 :     if (reg != ReturnReg)
     912         156 :         mov(ReturnReg, reg);
     913             :     // C++ compilers like to only use the bottom byte for bools, but we
     914             :     // need to maintain the entire register.
     915         172 :     and32(Imm32(0xFF), reg);
     916           0 : }
     917             : 
     918             : void
     919             : MacroAssembler::storeCallInt32Result(Register reg)
     920             : {
     921             : #if JS_BITS_PER_WORD == 32
     922             :     storeCallPointerResult(reg);
     923             : #else
     924             :     // Ensure the upper 32 bits are cleared.
     925           2 :     move32(ReturnReg, reg);
     926             : #endif
     927             : }
     928             : 
     929             : void
     930             : MacroAssembler::storeCallResultValue(AnyRegister dest, JSValueType type)
     931             : {
     932           0 :     unboxValue(JSReturnOperand, dest, type);
     933             : }
     934             : 
     935             : void
     936             : MacroAssembler::storeCallResultValue(TypedOrValueRegister dest)
     937             : {
     938             :     if (dest.hasValue())
     939             :         storeCallResultValue(dest.valueReg());
     940             :     else
     941             :         storeCallResultValue(dest.typedReg(), ValueTypeFromMIRType(dest.type()));
     942             : }
     943             : 
     944             : } // namespace jit
     945             : } // namespace js
     946             : 
     947             : #endif /* jit_MacroAssembler_inl_h */

Generated by: LCOV version 1.13-14-ga5dd952