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

Generated by: LCOV version 1.13