LCOV - code coverage report
Current view: top level - js/src/jit/x64 - MacroAssembler-x64.h (source / functions) Hit Total Coverage
Test: output.info Lines: 447 565 79.1 %
Date: 2017-07-14 16:53:18 Functions: 118 158 74.7 %
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_x64_MacroAssembler_x64_h
       8             : #define jit_x64_MacroAssembler_x64_h
       9             : 
      10             : #include "jit/JitFrames.h"
      11             : #include "jit/MoveResolver.h"
      12             : #include "jit/x86-shared/MacroAssembler-x86-shared.h"
      13             : 
      14             : namespace js {
      15             : namespace jit {
      16             : 
      17             : struct ImmShiftedTag : public ImmWord
      18             : {
      19         394 :     explicit ImmShiftedTag(JSValueShiftedTag shtag)
      20         394 :       : ImmWord((uintptr_t)shtag)
      21         394 :     { }
      22             : 
      23         898 :     explicit ImmShiftedTag(JSValueType type)
      24         898 :       : ImmWord(uintptr_t(JSValueShiftedTag(JSVAL_TYPE_TO_SHIFTED_TAG(type))))
      25         898 :     { }
      26             : };
      27             : 
      28             : struct ImmTag : public Imm32
      29             : {
      30        5121 :     explicit ImmTag(JSValueTag tag)
      31        5121 :       : Imm32(tag)
      32        5121 :     { }
      33             : };
      34             : 
      35        4503 : class MacroAssemblerX64 : public MacroAssemblerX86Shared
      36             : {
      37             :   private:
      38             :     // Perform a downcast. Should be removed by Bug 996602.
      39             :     MacroAssembler& asMasm();
      40             :     const MacroAssembler& asMasm() const;
      41             : 
      42             :     void bindOffsets(const MacroAssemblerX86Shared::UsesVector&);
      43             : 
      44             :   public:
      45             :     using MacroAssemblerX86Shared::load32;
      46             :     using MacroAssemblerX86Shared::store32;
      47             :     using MacroAssemblerX86Shared::store16;
      48             : 
      49        4503 :     MacroAssemblerX64()
      50        4503 :     {
      51        4503 :     }
      52             : 
      53             :     // The buffer is about to be linked, make sure any constant pools or excess
      54             :     // bookkeeping has been flushed to the instruction stream.
      55             :     void finish();
      56             : 
      57             :     /////////////////////////////////////////////////////////////////
      58             :     // X64 helpers.
      59             :     /////////////////////////////////////////////////////////////////
      60        4790 :     void writeDataRelocation(const Value& val) {
      61        4790 :         if (val.isGCThing()) {
      62        1415 :             gc::Cell* cell = val.toGCThing();
      63        1415 :             if (cell && gc::IsInsideNursery(cell))
      64           0 :                 embedsNurseryPointers_ = true;
      65        1415 :             dataRelocations_.writeUnsigned(masm.currentOffset());
      66             :         }
      67        4790 :     }
      68             : 
      69             :     // Refers to the upper 32 bits of a 64-bit Value operand.
      70             :     // On x86_64, the upper 32 bits do not necessarily only contain the type.
      71           9 :     Operand ToUpper32(Operand base) {
      72           9 :         switch (base.kind()) {
      73             :           case Operand::MEM_REG_DISP:
      74           9 :             return Operand(Register::FromCode(base.base()), base.disp() + 4);
      75             : 
      76             :           case Operand::MEM_SCALE:
      77           0 :             return Operand(Register::FromCode(base.base()), Register::FromCode(base.index()),
      78           0 :                            base.scale(), base.disp() + 4);
      79             : 
      80             :           default:
      81           0 :             MOZ_CRASH("unexpected operand kind");
      82             :         }
      83             :     }
      84          36 :     static inline Operand ToUpper32(const Address& address) {
      85          36 :         return Operand(address.base, address.offset + 4);
      86             :     }
      87             :     static inline Operand ToUpper32(const BaseIndex& address) {
      88             :         return Operand(address.base, address.index, address.scale, address.offset + 4);
      89             :     }
      90             : 
      91          45 :     uint32_t Upper32Of(JSValueShiftedTag tag) {
      92             :         union { // Implemented in this way to appease MSVC++.
      93             :             uint64_t tag;
      94             :             struct {
      95             :                 uint32_t lo32;
      96             :                 uint32_t hi32;
      97             :             } s;
      98             :         } e;
      99          45 :         e.tag = tag;
     100          45 :         return e.s.hi32;
     101             :     }
     102             : 
     103          45 :     JSValueShiftedTag GetShiftedTag(JSValueType type) {
     104          45 :         return (JSValueShiftedTag)JSVAL_TYPE_TO_SHIFTED_TAG(type);
     105             :     }
     106             : 
     107             :     /////////////////////////////////////////////////////////////////
     108             :     // X86/X64-common interface.
     109             :     /////////////////////////////////////////////////////////////////
     110           0 :     Address ToPayload(Address value) {
     111           0 :         return value;
     112             :     }
     113             : 
     114        3414 :     void storeValue(ValueOperand val, Operand dest) {
     115        3414 :         movq(val.valueReg(), dest);
     116        3414 :     }
     117        3352 :     void storeValue(ValueOperand val, const Address& dest) {
     118        3352 :         storeValue(val, Operand(dest));
     119        3352 :     }
     120             :     template <typename T>
     121          68 :     void storeValue(JSValueType type, Register reg, const T& dest) {
     122             :         // Value types with 32-bit payloads can be emitted as two 32-bit moves.
     123          68 :         if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
     124           9 :             movl(reg, Operand(dest));
     125           9 :             movl(Imm32(Upper32Of(GetShiftedTag(type))), ToUpper32(Operand(dest)));
     126             :         } else {
     127         118 :             ScratchRegisterScope scratch(asMasm());
     128          59 :             boxValue(type, reg, scratch);
     129          59 :             movq(scratch, Operand(dest));
     130             :         }
     131          68 :     }
     132             :     template <typename T>
     133        1087 :     void storeValue(const Value& val, const T& dest) {
     134        2174 :         ScratchRegisterScope scratch(asMasm());
     135        1087 :         if (val.isGCThing()) {
     136          31 :             movWithPatch(ImmWord(val.asRawBits()), scratch);
     137          31 :             writeDataRelocation(val);
     138             :         } else {
     139        1056 :             mov(ImmWord(val.asRawBits()), scratch);
     140             :         }
     141        1087 :         movq(scratch, Operand(dest));
     142        1087 :     }
     143          54 :     void storeValue(ValueOperand val, BaseIndex dest) {
     144          54 :         storeValue(val, Operand(dest));
     145          54 :     }
     146           0 :     void storeValue(const Address& src, const Address& dest, Register temp) {
     147           0 :         loadPtr(src, temp);
     148           0 :         storePtr(temp, dest);
     149           0 :     }
     150       11884 :     void loadValue(Operand src, ValueOperand val) {
     151       11884 :         movq(src, val.valueReg());
     152       11884 :     }
     153       11613 :     void loadValue(Address src, ValueOperand val) {
     154       11613 :         loadValue(Operand(src), val);
     155       11613 :     }
     156         271 :     void loadValue(const BaseIndex& src, ValueOperand val) {
     157         271 :         loadValue(Operand(src), val);
     158         271 :     }
     159         898 :     void tagValue(JSValueType type, Register payload, ValueOperand dest) {
     160        1796 :         ScratchRegisterScope scratch(asMasm());
     161         898 :         MOZ_ASSERT(dest.valueReg() != scratch);
     162         898 :         if (payload != dest.valueReg())
     163         443 :             movq(payload, dest.valueReg());
     164         898 :         mov(ImmShiftedTag(type), scratch);
     165         898 :         orq(scratch, dest.valueReg());
     166         898 :     }
     167       16961 :     void pushValue(ValueOperand val) {
     168       16961 :         push(val.valueReg());
     169       16961 :     }
     170        5441 :     void popValue(ValueOperand val) {
     171        5441 :         pop(val.valueReg());
     172        5441 :     }
     173        4332 :     void pushValue(const Value& val) {
     174        4332 :         if (val.isGCThing()) {
     175        1424 :             ScratchRegisterScope scratch(asMasm());
     176         712 :             movWithPatch(ImmWord(val.asRawBits()), scratch);
     177         712 :             writeDataRelocation(val);
     178         712 :             push(scratch);
     179             :         } else {
     180        3620 :             push(ImmWord(val.asRawBits()));
     181             :         }
     182        4332 :     }
     183          99 :     void pushValue(JSValueType type, Register reg) {
     184         198 :         ScratchRegisterScope scratch(asMasm());
     185          99 :         boxValue(type, reg, scratch);
     186          99 :         push(scratch);
     187          99 :     }
     188        3625 :     void pushValue(const Address& addr) {
     189        3625 :         push(Operand(addr));
     190        3625 :     }
     191             : 
     192        4047 :     void moveValue(const Value& val, Register dest) {
     193        4047 :         movWithPatch(ImmWord(val.asRawBits()), dest);
     194        4047 :         writeDataRelocation(val);
     195        4047 :     }
     196        3870 :     void moveValue(const Value& src, const ValueOperand& dest) {
     197        3870 :         moveValue(src, dest.valueReg());
     198        3870 :     }
     199       12941 :     void moveValue(const ValueOperand& src, const ValueOperand& dest) {
     200       12941 :         if (src.valueReg() != dest.valueReg())
     201        4872 :             movq(src.valueReg(), dest.valueReg());
     202       12941 :     }
     203             :     void boxValue(JSValueType type, Register src, Register dest);
     204             : 
     205         444 :     Condition testUndefined(Condition cond, Register tag) {
     206         444 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     207         444 :         cmp32(tag, ImmTag(JSVAL_TAG_UNDEFINED));
     208         444 :         return cond;
     209             :     }
     210         606 :     Condition testInt32(Condition cond, Register tag) {
     211         606 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     212         606 :         cmp32(tag, ImmTag(JSVAL_TAG_INT32));
     213         606 :         return cond;
     214             :     }
     215        1679 :     Condition testBoolean(Condition cond, Register tag) {
     216        1679 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     217        1679 :         cmp32(tag, ImmTag(JSVAL_TAG_BOOLEAN));
     218        1679 :         return cond;
     219             :     }
     220         246 :     Condition testNull(Condition cond, Register tag) {
     221         246 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     222         246 :         cmp32(tag, ImmTag(JSVAL_TAG_NULL));
     223         246 :         return cond;
     224             :     }
     225         358 :     Condition testString(Condition cond, Register tag) {
     226         358 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     227         358 :         cmp32(tag, ImmTag(JSVAL_TAG_STRING));
     228         358 :         return cond;
     229             :     }
     230          21 :     Condition testSymbol(Condition cond, Register tag) {
     231          21 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     232          21 :         cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
     233          21 :         return cond;
     234             :     }
     235        1702 :     Condition testObject(Condition cond, Register tag) {
     236        1702 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     237        1702 :         cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
     238        1702 :         return cond;
     239             :     }
     240          51 :     Condition testDouble(Condition cond, Register tag) {
     241          51 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     242          51 :         cmp32(tag, Imm32(JSVAL_TAG_MAX_DOUBLE));
     243          51 :         return cond == Equal ? BelowOrEqual : Above;
     244             :     }
     245         174 :     Condition testNumber(Condition cond, Register tag) {
     246         174 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     247         174 :         cmp32(tag, Imm32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
     248         174 :         return cond == Equal ? BelowOrEqual : Above;
     249             :     }
     250         207 :     Condition testGCThing(Condition cond, Register tag) {
     251         207 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     252         207 :         cmp32(tag, Imm32(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
     253         207 :         return cond == Equal ? AboveOrEqual : Below;
     254             :     }
     255             : 
     256          61 :     Condition testMagic(Condition cond, Register tag) {
     257          61 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     258          61 :         cmp32(tag, ImmTag(JSVAL_TAG_MAGIC));
     259          61 :         return cond;
     260             :     }
     261             :     Condition testError(Condition cond, Register tag) {
     262             :         return testMagic(cond, tag);
     263             :     }
     264           4 :     Condition testPrimitive(Condition cond, Register tag) {
     265           4 :         MOZ_ASSERT(cond == Equal || cond == NotEqual);
     266           4 :         cmp32(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
     267           4 :         return cond == Equal ? Below : AboveOrEqual;
     268             :     }
     269             : 
     270         339 :     Condition testUndefined(Condition cond, const ValueOperand& src) {
     271         678 :         ScratchRegisterScope scratch(asMasm());
     272         339 :         splitTag(src, scratch);
     273         678 :         return testUndefined(cond, scratch);
     274             :     }
     275         572 :     Condition testInt32(Condition cond, const ValueOperand& src) {
     276        1144 :         ScratchRegisterScope scratch(asMasm());
     277         572 :         splitTag(src, scratch);
     278        1144 :         return testInt32(cond, scratch);
     279             :     }
     280        1627 :     Condition testBoolean(Condition cond, const ValueOperand& src) {
     281        3254 :         ScratchRegisterScope scratch(asMasm());
     282        1627 :         splitTag(src, scratch);
     283        3254 :         return testBoolean(cond, scratch);
     284             :     }
     285          27 :     Condition testDouble(Condition cond, const ValueOperand& src) {
     286          54 :         ScratchRegisterScope scratch(asMasm());
     287          27 :         splitTag(src, scratch);
     288          54 :         return testDouble(cond, scratch);
     289             :     }
     290         173 :     Condition testNumber(Condition cond, const ValueOperand& src) {
     291         346 :         ScratchRegisterScope scratch(asMasm());
     292         173 :         splitTag(src, scratch);
     293         346 :         return testNumber(cond, scratch);
     294             :     }
     295         243 :     Condition testNull(Condition cond, const ValueOperand& src) {
     296         486 :         ScratchRegisterScope scratch(asMasm());
     297         243 :         splitTag(src, scratch);
     298         486 :         return testNull(cond, scratch);
     299             :     }
     300         333 :     Condition testString(Condition cond, const ValueOperand& src) {
     301         666 :         ScratchRegisterScope scratch(asMasm());
     302         333 :         splitTag(src, scratch);
     303         666 :         return testString(cond, scratch);
     304             :     }
     305          21 :     Condition testSymbol(Condition cond, const ValueOperand& src) {
     306          42 :         ScratchRegisterScope scratch(asMasm());
     307          21 :         splitTag(src, scratch);
     308          42 :         return testSymbol(cond, scratch);
     309             :     }
     310        1638 :     Condition testObject(Condition cond, const ValueOperand& src) {
     311        3276 :         ScratchRegisterScope scratch(asMasm());
     312        1638 :         splitTag(src, scratch);
     313        3276 :         return testObject(cond, scratch);
     314             :     }
     315             :     Condition testGCThing(Condition cond, const ValueOperand& src) {
     316             :         ScratchRegisterScope scratch(asMasm());
     317             :         splitTag(src, scratch);
     318             :         return testGCThing(cond, scratch);
     319             :     }
     320           4 :     Condition testPrimitive(Condition cond, const ValueOperand& src) {
     321           8 :         ScratchRegisterScope scratch(asMasm());
     322           4 :         splitTag(src, scratch);
     323           8 :         return testPrimitive(cond, scratch);
     324             :     }
     325             : 
     326             : 
     327           0 :     Condition testUndefined(Condition cond, const Address& src) {
     328           0 :         cmp32(ToUpper32(src), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_UNDEFINED))));
     329           0 :         return cond;
     330             :     }
     331          32 :     Condition testInt32(Condition cond, const Address& src) {
     332          32 :         cmp32(ToUpper32(src), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_INT32))));
     333          32 :         return cond;
     334             :     }
     335           0 :     Condition testBoolean(Condition cond, const Address& src) {
     336           0 :         cmp32(ToUpper32(src), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
     337           0 :         return cond;
     338             :     }
     339           0 :     Condition testDouble(Condition cond, const Address& src) {
     340           0 :         ScratchRegisterScope scratch(asMasm());
     341           0 :         splitTag(src, scratch);
     342           0 :         return testDouble(cond, scratch);
     343             :     }
     344             :     Condition testNumber(Condition cond, const Address& src) {
     345             :         ScratchRegisterScope scratch(asMasm());
     346             :         splitTag(src, scratch);
     347             :         return testNumber(cond, scratch);
     348             :     }
     349           4 :     Condition testNull(Condition cond, const Address& src) {
     350           4 :         cmp32(ToUpper32(src), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
     351           4 :         return cond;
     352             :     }
     353             :     Condition testString(Condition cond, const Address& src) {
     354             :         ScratchRegisterScope scratch(asMasm());
     355             :         splitTag(src, scratch);
     356             :         return testString(cond, scratch);
     357             :     }
     358             :     Condition testSymbol(Condition cond, const Address& src) {
     359             :         ScratchRegisterScope scratch(asMasm());
     360             :         splitTag(src, scratch);
     361             :         return testSymbol(cond, scratch);
     362             :     }
     363          24 :     Condition testObject(Condition cond, const Address& src) {
     364          48 :         ScratchRegisterScope scratch(asMasm());
     365          24 :         splitTag(src, scratch);
     366          48 :         return testObject(cond, scratch);
     367             :     }
     368             :     Condition testPrimitive(Condition cond, const Address& src) {
     369             :         ScratchRegisterScope scratch(asMasm());
     370             :         splitTag(src, scratch);
     371             :         return testPrimitive(cond, scratch);
     372             :     }
     373         190 :     Condition testGCThing(Condition cond, const Address& src) {
     374         380 :         ScratchRegisterScope scratch(asMasm());
     375         190 :         splitTag(src, scratch);
     376         380 :         return testGCThing(cond, scratch);
     377             :     }
     378          28 :     Condition testMagic(Condition cond, const Address& src) {
     379          56 :         ScratchRegisterScope scratch(asMasm());
     380          28 :         splitTag(src, scratch);
     381          56 :         return testMagic(cond, scratch);
     382             :     }
     383             : 
     384             : 
     385             :     Condition testUndefined(Condition cond, const BaseIndex& src) {
     386             :         ScratchRegisterScope scratch(asMasm());
     387             :         splitTag(src, scratch);
     388             :         return testUndefined(cond, scratch);
     389             :     }
     390             :     Condition testNull(Condition cond, const BaseIndex& src) {
     391             :         ScratchRegisterScope scratch(asMasm());
     392             :         splitTag(src, scratch);
     393             :         return testNull(cond, scratch);
     394             :     }
     395             :     Condition testBoolean(Condition cond, const BaseIndex& src) {
     396             :         ScratchRegisterScope scratch(asMasm());
     397             :         splitTag(src, scratch);
     398             :         return testBoolean(cond, scratch);
     399             :     }
     400             :     Condition testString(Condition cond, const BaseIndex& src) {
     401             :         ScratchRegisterScope scratch(asMasm());
     402             :         splitTag(src, scratch);
     403             :         return testString(cond, scratch);
     404             :     }
     405             :     Condition testSymbol(Condition cond, const BaseIndex& src) {
     406             :         ScratchRegisterScope scratch(asMasm());
     407             :         splitTag(src, scratch);
     408             :         return testSymbol(cond, scratch);
     409             :     }
     410           0 :     Condition testInt32(Condition cond, const BaseIndex& src) {
     411           0 :         ScratchRegisterScope scratch(asMasm());
     412           0 :         splitTag(src, scratch);
     413           0 :         return testInt32(cond, scratch);
     414             :     }
     415           2 :     Condition testObject(Condition cond, const BaseIndex& src) {
     416           4 :         ScratchRegisterScope scratch(asMasm());
     417           2 :         splitTag(src, scratch);
     418           4 :         return testObject(cond, scratch);
     419             :     }
     420             :     Condition testDouble(Condition cond, const BaseIndex& src) {
     421             :         ScratchRegisterScope scratch(asMasm());
     422             :         splitTag(src, scratch);
     423             :         return testDouble(cond, scratch);
     424             :     }
     425          21 :     Condition testMagic(Condition cond, const BaseIndex& src) {
     426          42 :         ScratchRegisterScope scratch(asMasm());
     427          21 :         splitTag(src, scratch);
     428          42 :         return testMagic(cond, scratch);
     429             :     }
     430          17 :     Condition testGCThing(Condition cond, const BaseIndex& src) {
     431          34 :         ScratchRegisterScope scratch(asMasm());
     432          17 :         splitTag(src, scratch);
     433          34 :         return testGCThing(cond, scratch);
     434             :     }
     435             : 
     436             :     Condition isMagic(Condition cond, const ValueOperand& src, JSWhyMagic why) {
     437             :         uint64_t magic = MagicValue(why).asRawBits();
     438             :         cmpPtr(src.valueReg(), ImmWord(magic));
     439             :         return cond;
     440             :     }
     441             : 
     442           0 :     void cmpPtr(Register lhs, const ImmWord rhs) {
     443           0 :         ScratchRegisterScope scratch(asMasm());
     444           0 :         MOZ_ASSERT(lhs != scratch);
     445           0 :         if (intptr_t(rhs.value) <= INT32_MAX && intptr_t(rhs.value) >= INT32_MIN) {
     446           0 :             cmpPtr(lhs, Imm32(int32_t(rhs.value)));
     447             :         } else {
     448           0 :             movePtr(rhs, scratch);
     449           0 :             cmpPtr(lhs, scratch);
     450             :         }
     451           0 :     }
     452           0 :     void cmpPtr(Register lhs, const ImmPtr rhs) {
     453           0 :         cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
     454           0 :     }
     455             :     void cmpPtr(Register lhs, const ImmGCPtr rhs) {
     456             :         ScratchRegisterScope scratch(asMasm());
     457             :         MOZ_ASSERT(lhs != scratch);
     458             :         movePtr(rhs, scratch);
     459             :         cmpPtr(lhs, scratch);
     460             :     }
     461           0 :     void cmpPtr(Register lhs, const Imm32 rhs) {
     462           0 :         cmpq(rhs, lhs);
     463           0 :     }
     464         134 :     void cmpPtr(const Operand& lhs, const ImmGCPtr rhs) {
     465         268 :         ScratchRegisterScope scratch(asMasm());
     466         134 :         MOZ_ASSERT(!lhs.containsReg(scratch));
     467         134 :         movePtr(rhs, scratch);
     468         134 :         cmpPtr(lhs, scratch);
     469         134 :     }
     470        1503 :     void cmpPtr(const Operand& lhs, const ImmWord rhs) {
     471        1503 :         if ((intptr_t)rhs.value <= INT32_MAX && (intptr_t)rhs.value >= INT32_MIN) {
     472        1419 :             cmpPtr(lhs, Imm32((int32_t)rhs.value));
     473             :         } else {
     474         168 :             ScratchRegisterScope scratch(asMasm());
     475          84 :             movePtr(rhs, scratch);
     476          84 :             cmpPtr(lhs, scratch);
     477             :         }
     478        1503 :     }
     479        1015 :     void cmpPtr(const Operand& lhs, const ImmPtr rhs) {
     480        1015 :         cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
     481        1015 :     }
     482             :     void cmpPtr(const Address& lhs, const ImmGCPtr rhs) {
     483             :         cmpPtr(Operand(lhs), rhs);
     484             :     }
     485           0 :     void cmpPtr(const Address& lhs, const ImmWord rhs) {
     486           0 :         cmpPtr(Operand(lhs), rhs);
     487           0 :     }
     488           0 :     void cmpPtr(const Address& lhs, const ImmPtr rhs) {
     489           0 :         cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
     490           0 :     }
     491        1946 :     void cmpPtr(const Operand& lhs, Register rhs) {
     492        1946 :         cmpq(rhs, lhs);
     493        1946 :     }
     494           0 :     void cmpPtr(Register lhs, const Operand& rhs) {
     495           0 :         cmpq(rhs, lhs);
     496           0 :     }
     497        2748 :     void cmpPtr(const Operand& lhs, const Imm32 rhs) {
     498        2748 :         cmpq(rhs, lhs);
     499        2748 :     }
     500             :     void cmpPtr(const Address& lhs, Register rhs) {
     501             :         cmpPtr(Operand(lhs), rhs);
     502             :     }
     503         413 :     void cmpPtr(Register lhs, Register rhs) {
     504         413 :         cmpq(rhs, lhs);
     505         413 :     }
     506         357 :     void testPtr(Register lhs, Register rhs) {
     507         357 :         testq(rhs, lhs);
     508         357 :     }
     509       13390 :     void testPtr(Register lhs, Imm32 rhs) {
     510       13390 :         testq(rhs, lhs);
     511       13390 :     }
     512          57 :     void testPtr(const Operand& lhs, Imm32 rhs) {
     513          57 :         testq(rhs, lhs);
     514          57 :     }
     515             : 
     516             :     /////////////////////////////////////////////////////////////////
     517             :     // Common interface.
     518             :     /////////////////////////////////////////////////////////////////
     519             : 
     520          21 :     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Label* documentation = nullptr) {
     521          21 :         JmpSrc src = jmpSrc(label);
     522          21 :         return CodeOffsetJump(size(), addPatchableJump(src, Relocation::HARDCODED));
     523             :     }
     524             : 
     525           0 :     CodeOffsetJump jumpWithPatch(RepatchLabel* label, Condition cond,
     526             :                                  Label* documentation = nullptr)
     527             :     {
     528           0 :         JmpSrc src = jSrc(cond, label);
     529           0 :         return CodeOffsetJump(size(), addPatchableJump(src, Relocation::HARDCODED));
     530             :     }
     531             : 
     532           0 :     CodeOffsetJump backedgeJump(RepatchLabel* label, Label* documentation = nullptr) {
     533           0 :         return jumpWithPatch(label);
     534             :     }
     535             : 
     536        5583 :     void movePtr(Register src, Register dest) {
     537        5583 :         movq(src, dest);
     538        5583 :     }
     539             :     void movePtr(Register src, const Operand& dest) {
     540             :         movq(src, dest);
     541             :     }
     542         643 :     void movePtr(ImmWord imm, Register dest) {
     543         643 :         mov(imm, dest);
     544         643 :     }
     545        8876 :     void movePtr(ImmPtr imm, Register dest) {
     546        8876 :         mov(imm, dest);
     547        8876 :     }
     548             :     void movePtr(wasm::SymbolicAddress imm, Register dest) {
     549             :         mov(imm, dest);
     550             :     }
     551        3503 :     void movePtr(ImmGCPtr imm, Register dest) {
     552        3503 :         movq(imm, dest);
     553        3503 :     }
     554        5113 :     void loadPtr(AbsoluteAddress address, Register dest) {
     555        5113 :         if (X86Encoding::IsAddressImmediate(address.addr)) {
     556           0 :             movq(Operand(address), dest);
     557             :         } else {
     558       10226 :             ScratchRegisterScope scratch(asMasm());
     559        5113 :             mov(ImmPtr(address.addr), scratch);
     560        5113 :             loadPtr(Address(scratch, 0x0), dest);
     561             :         }
     562        5113 :     }
     563       39230 :     void loadPtr(const Address& address, Register dest) {
     564       39230 :         movq(Operand(address), dest);
     565       39230 :     }
     566             :     void load64(const Address& address, Register dest) {
     567             :         movq(Operand(address), dest);
     568             :     }
     569             :     void loadPtr(const Operand& src, Register dest) {
     570             :         movq(src, dest);
     571             :     }
     572          31 :     void loadPtr(const BaseIndex& src, Register dest) {
     573          31 :         movq(Operand(src), dest);
     574          31 :     }
     575           0 :     void loadPrivate(const Address& src, Register dest) {
     576           0 :         loadPtr(src, dest);
     577           0 :         shlq(Imm32(1), dest);
     578           0 :     }
     579         181 :     void load32(AbsoluteAddress address, Register dest) {
     580         181 :         if (X86Encoding::IsAddressImmediate(address.addr)) {
     581           0 :             movl(Operand(address), dest);
     582             :         } else {
     583         362 :             ScratchRegisterScope scratch(asMasm());
     584         181 :             mov(ImmPtr(address.addr), scratch);
     585         181 :             load32(Address(scratch, 0x0), dest);
     586             :         }
     587         181 :     }
     588           0 :     void load64(const Address& address, Register64 dest) {
     589           0 :         movq(Operand(address), dest.reg);
     590           0 :     }
     591             :     template <typename T>
     592        1452 :     void storePtr(ImmWord imm, T address) {
     593        1452 :         if ((intptr_t)imm.value <= INT32_MAX && (intptr_t)imm.value >= INT32_MIN) {
     594        1381 :             movq(Imm32((int32_t)imm.value), Operand(address));
     595             :         } else {
     596         142 :             ScratchRegisterScope scratch(asMasm());
     597          71 :             mov(imm, scratch);
     598          71 :             movq(scratch, Operand(address));
     599             :         }
     600        1452 :     }
     601             :     template <typename T>
     602        1401 :     void storePtr(ImmPtr imm, T address) {
     603        1401 :         storePtr(ImmWord(uintptr_t(imm.value)), address);
     604        1401 :     }
     605             :     template <typename T>
     606         196 :     void storePtr(ImmGCPtr imm, T address) {
     607         392 :         ScratchRegisterScope scratch(asMasm());
     608         196 :         movq(imm, scratch);
     609         196 :         movq(scratch, Operand(address));
     610         196 :     }
     611        4279 :     void storePtr(Register src, const Address& address) {
     612        4279 :         movq(src, Operand(address));
     613        4279 :     }
     614             :     void store64(Register src, const Address& address) {
     615             :         movq(src, Operand(address));
     616             :     }
     617           8 :     void storePtr(Register src, const BaseIndex& address) {
     618           8 :         movq(src, Operand(address));
     619           8 :     }
     620             :     void storePtr(Register src, const Operand& dest) {
     621             :         movq(src, dest);
     622             :     }
     623          95 :     void storePtr(Register src, AbsoluteAddress address) {
     624          95 :         if (X86Encoding::IsAddressImmediate(address.addr)) {
     625           0 :             movq(src, Operand(address));
     626             :         } else {
     627         190 :             ScratchRegisterScope scratch(asMasm());
     628          95 :             mov(ImmPtr(address.addr), scratch);
     629          95 :             storePtr(src, Address(scratch, 0x0));
     630             :         }
     631          95 :     }
     632         181 :     void store32(Register src, AbsoluteAddress address) {
     633         181 :         if (X86Encoding::IsAddressImmediate(address.addr)) {
     634           0 :             movl(src, Operand(address));
     635             :         } else {
     636         362 :             ScratchRegisterScope scratch(asMasm());
     637         181 :             mov(ImmPtr(address.addr), scratch);
     638         181 :             store32(src, Address(scratch, 0x0));
     639             :         }
     640         181 :     }
     641             :     void store16(Register src, AbsoluteAddress address) {
     642             :         if (X86Encoding::IsAddressImmediate(address.addr)) {
     643             :             movw(src, Operand(address));
     644             :         } else {
     645             :             ScratchRegisterScope scratch(asMasm());
     646             :             mov(ImmPtr(address.addr), scratch);
     647             :             store16(src, Address(scratch, 0x0));
     648             :         }
     649             :     }
     650           0 :     void store64(Register64 src, Address address) {
     651           0 :         storePtr(src.reg, address);
     652           0 :     }
     653           0 :     void store64(Imm64 imm, Address address) {
     654           0 :         storePtr(ImmWord(imm.value), address);
     655           0 :     }
     656             : 
     657        5228 :     void splitTag(Register src, Register dest) {
     658        5228 :         if (src != dest)
     659        5180 :             movq(src, dest);
     660        5228 :         shrq(Imm32(JSVAL_TAG_SHIFT), dest);
     661        5228 :     }
     662        5180 :     void splitTag(const ValueOperand& operand, Register dest) {
     663        5180 :         splitTag(operand.valueReg(), dest);
     664        5180 :     }
     665         282 :     void splitTag(const Operand& operand, Register dest) {
     666         282 :         movq(operand, dest);
     667         282 :         shrq(Imm32(JSVAL_TAG_SHIFT), dest);
     668         282 :     }
     669         242 :     void splitTag(const Address& operand, Register dest) {
     670         242 :         splitTag(Operand(operand), dest);
     671         242 :     }
     672          40 :     void splitTag(const BaseIndex& operand, Register dest) {
     673          40 :         splitTag(Operand(operand), dest);
     674          40 :     }
     675             : 
     676             :     // Extracts the tag of a value and places it in ScratchReg.
     677          61 :     Register splitTagForTest(const ValueOperand& value) {
     678          61 :         splitTag(value, ScratchReg);
     679          61 :         return ScratchReg;
     680             :     }
     681             :     void cmpTag(const ValueOperand& operand, ImmTag tag) {
     682             :         Register reg = splitTagForTest(operand);
     683             :         cmp32(reg, tag);
     684             :     }
     685             : 
     686          12 :     Condition testMagic(Condition cond, const ValueOperand& src) {
     687          24 :         ScratchRegisterScope scratch(asMasm());
     688          12 :         splitTag(src, scratch);
     689          24 :         return testMagic(cond, scratch);
     690             :     }
     691             :     Condition testError(Condition cond, const ValueOperand& src) {
     692             :         return testMagic(cond, src);
     693             :     }
     694             : 
     695           0 :     void testNullSet(Condition cond, const ValueOperand& value, Register dest) {
     696           0 :         cond = testNull(cond, value);
     697           0 :         emitSet(cond, dest);
     698           0 :     }
     699             : 
     700           0 :     void testObjectSet(Condition cond, const ValueOperand& value, Register dest) {
     701           0 :         cond = testObject(cond, value);
     702           0 :         emitSet(cond, dest);
     703           0 :     }
     704             : 
     705           0 :     void testUndefinedSet(Condition cond, const ValueOperand& value, Register dest) {
     706           0 :         cond = testUndefined(cond, value);
     707           0 :         emitSet(cond, dest);
     708           0 :     }
     709             : 
     710           8 :     void boxDouble(FloatRegister src, const ValueOperand& dest) {
     711           8 :         vmovq(src, dest.valueReg());
     712           8 :     }
     713          15 :     void boxNonDouble(JSValueType type, Register src, const ValueOperand& dest) {
     714          15 :         MOZ_ASSERT(src != dest.valueReg());
     715          15 :         boxValue(type, src, dest.valueReg());
     716          15 :     }
     717             : 
     718             :     // Note that the |dest| register here may be ScratchReg, so we shouldn't
     719             :     // use it.
     720         141 :     void unboxInt32(const ValueOperand& src, Register dest) {
     721         141 :         movl(src.valueReg(), dest);
     722         141 :     }
     723          27 :     void unboxInt32(const Operand& src, Register dest) {
     724          27 :         movl(src, dest);
     725          27 :     }
     726           5 :     void unboxInt32(const Address& src, Register dest) {
     727           5 :         unboxInt32(Operand(src), dest);
     728           5 :     }
     729           0 :     void unboxDouble(const Address& src, FloatRegister dest) {
     730           0 :         loadDouble(Operand(src), dest);
     731           0 :     }
     732             : 
     733             :     void unboxArgObjMagic(const ValueOperand& src, Register dest) {
     734             :         unboxArgObjMagic(Operand(src.valueReg()), dest);
     735             :     }
     736             :     void unboxArgObjMagic(const Operand& src, Register dest) {
     737             :         mov(ImmWord(0), dest);
     738             :     }
     739             :     void unboxArgObjMagic(const Address& src, Register dest) {
     740             :         unboxArgObjMagic(Operand(src), dest);
     741             :     }
     742             : 
     743           2 :     void unboxBoolean(const ValueOperand& src, Register dest) {
     744           2 :         movl(src.valueReg(), dest);
     745           2 :     }
     746          24 :     void unboxBoolean(const Operand& src, Register dest) {
     747          24 :         movl(src, dest);
     748          24 :     }
     749             :     void unboxBoolean(const Address& src, Register dest) {
     750             :         unboxBoolean(Operand(src), dest);
     751             :     }
     752             : 
     753             :     void unboxMagic(const ValueOperand& src, Register dest) {
     754             :         movl(src.valueReg(), dest);
     755             :     }
     756             : 
     757          52 :     void unboxDouble(const ValueOperand& src, FloatRegister dest) {
     758          52 :         vmovq(src.valueReg(), dest);
     759          52 :     }
     760             :     void unboxPrivate(const ValueOperand& src, const Register dest) {
     761             :         movq(src.valueReg(), dest);
     762             :         shlq(Imm32(1), dest);
     763             :     }
     764             : 
     765         473 :     void notBoolean(const ValueOperand& val) {
     766         473 :         xorq(Imm32(1), val.valueReg());
     767         473 :     }
     768             : 
     769             :     // Unbox any non-double value into dest. Prefer unboxInt32 or unboxBoolean
     770             :     // instead if the source type is known.
     771        1109 :     void unboxNonDouble(const ValueOperand& src, Register dest) {
     772        1109 :         if (src.valueReg() == dest) {
     773         704 :             ScratchRegisterScope scratch(asMasm());
     774         352 :             mov(ImmWord(JSVAL_PAYLOAD_MASK), scratch);
     775         352 :             andq(scratch, dest);
     776             :         } else {
     777         757 :             mov(ImmWord(JSVAL_PAYLOAD_MASK), dest);
     778         757 :             andq(src.valueReg(), dest);
     779             :         }
     780        1109 :     }
     781         531 :     void unboxNonDouble(const Operand& src, Register dest) {
     782             :         // Explicitly permits |dest| to be used in |src|.
     783        1062 :         ScratchRegisterScope scratch(asMasm());
     784         531 :         MOZ_ASSERT(dest != scratch);
     785         531 :         if (src.containsReg(dest)) {
     786         335 :             mov(ImmWord(JSVAL_PAYLOAD_MASK), scratch);
     787             :             // If src is already a register, then src and dest are the same
     788             :             // thing and we don't need to move anything into dest.
     789         335 :             if (src.kind() != Operand::REG)
     790         314 :                 movq(src, dest);
     791         335 :             andq(scratch, dest);
     792             :         } else {
     793         196 :             mov(ImmWord(JSVAL_PAYLOAD_MASK), dest);
     794         196 :             andq(src, dest);
     795             :         }
     796         531 :     }
     797           0 :     void unboxNonDouble(const Address& src, Register dest) {
     798           0 :         unboxNonDouble(Operand(src), dest);
     799           0 :     }
     800             : 
     801          49 :     void unboxString(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
     802          24 :     void unboxString(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
     803             : 
     804             :     void unboxSymbol(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
     805           0 :     void unboxSymbol(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
     806             : 
     807        1046 :     void unboxObject(const ValueOperand& src, Register dest) { unboxNonDouble(src, dest); }
     808          47 :     void unboxObject(const Operand& src, Register dest) { unboxNonDouble(src, dest); }
     809         450 :     void unboxObject(const Address& src, Register dest) { unboxNonDouble(Operand(src), dest); }
     810           2 :     void unboxObject(const BaseIndex& src, Register dest) { unboxNonDouble(Operand(src), dest); }
     811             : 
     812             :     // Extended unboxing API. If the payload is already in a register, returns
     813             :     // that register. Otherwise, provides a move to the given scratch register,
     814             :     // and returns that.
     815         398 :     Register extractObject(const Address& address, Register scratch) {
     816         398 :         MOZ_ASSERT(scratch != ScratchReg);
     817         398 :         unboxObject(address, scratch);
     818         398 :         return scratch;
     819             :     }
     820         704 :     Register extractObject(const ValueOperand& value, Register scratch) {
     821         704 :         MOZ_ASSERT(scratch != ScratchReg);
     822         704 :         unboxObject(value, scratch);
     823         704 :         return scratch;
     824             :     }
     825          37 :     Register extractInt32(const ValueOperand& value, Register scratch) {
     826          37 :         MOZ_ASSERT(scratch != ScratchReg);
     827          37 :         unboxInt32(value, scratch);
     828          37 :         return scratch;
     829             :     }
     830           2 :     Register extractBoolean(const ValueOperand& value, Register scratch) {
     831           2 :         MOZ_ASSERT(scratch != ScratchReg);
     832           2 :         unboxBoolean(value, scratch);
     833           2 :         return scratch;
     834             :     }
     835          48 :     Register extractTag(const Address& address, Register scratch) {
     836          48 :         MOZ_ASSERT(scratch != ScratchReg);
     837          48 :         loadPtr(address, scratch);
     838          48 :         splitTag(scratch, scratch);
     839          48 :         return scratch;
     840             :     }
     841         130 :     Register extractTag(const ValueOperand& value, Register scratch) {
     842         130 :         MOZ_ASSERT(scratch != ScratchReg);
     843         130 :         splitTag(value, scratch);
     844         130 :         return scratch;
     845             :     }
     846             : 
     847             :     inline void unboxValue(const ValueOperand& src, AnyRegister dest);
     848             : 
     849             :     // These two functions use the low 32-bits of the full value register.
     850           0 :     void boolValueToDouble(const ValueOperand& operand, FloatRegister dest) {
     851           0 :         convertInt32ToDouble(operand.valueReg(), dest);
     852           0 :     }
     853           0 :     void int32ValueToDouble(const ValueOperand& operand, FloatRegister dest) {
     854           0 :         convertInt32ToDouble(operand.valueReg(), dest);
     855           0 :     }
     856             : 
     857           0 :     void boolValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
     858           0 :         convertInt32ToFloat32(operand.valueReg(), dest);
     859           0 :     }
     860           0 :     void int32ValueToFloat32(const ValueOperand& operand, FloatRegister dest) {
     861           0 :         convertInt32ToFloat32(operand.valueReg(), dest);
     862           0 :     }
     863             : 
     864             :     void loadConstantDouble(double d, FloatRegister dest);
     865             :     void loadConstantFloat32(float f, FloatRegister dest);
     866             : 
     867             :     void loadConstantSimd128Int(const SimdConstant& v, FloatRegister dest);
     868             :     void loadConstantSimd128Float(const SimdConstant& v, FloatRegister dest);
     869             : 
     870             :     void convertInt64ToDouble(Register64 input, FloatRegister output);
     871             :     void convertInt64ToFloat32(Register64 input, FloatRegister output);
     872             :     static bool convertUInt64ToDoubleNeedsTemp();
     873             :     void convertUInt64ToDouble(Register64 input, FloatRegister output, Register temp);
     874             :     void convertUInt64ToFloat32(Register64 input, FloatRegister output, Register temp);
     875             : 
     876             :     void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output, Label* oolEntry,
     877             :                                    Label* oolRejoin, FloatRegister tempDouble);
     878             :     void wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output, Label* oolEntry,
     879             :                                     Label* oolRejoin, FloatRegister tempDouble);
     880             : 
     881             :     void wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output, Label* oolEntry,
     882             :                                     Label* oolRejoin, FloatRegister tempDouble);
     883             :     void wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output, Label* oolEntry,
     884             :                                      Label* oolRejoin, FloatRegister tempDouble);
     885             : 
     886           0 :     void loadWasmGlobalPtr(uint32_t globalDataOffset, Register dest) {
     887           0 :         loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, globalArea) + globalDataOffset), dest);
     888           0 :     }
     889           0 :     void loadWasmPinnedRegsFromTls() {
     890           0 :         loadPtr(Address(WasmTlsReg, offsetof(wasm::TlsData, memoryBase)), HeapReg);
     891           0 :     }
     892             : 
     893             :   public:
     894          11 :     Condition testInt32Truthy(bool truthy, const ValueOperand& operand) {
     895          11 :         test32(operand.valueReg(), operand.valueReg());
     896          11 :         return truthy ? NonZero : Zero;
     897             :     }
     898          21 :     Condition testStringTruthy(bool truthy, const ValueOperand& value) {
     899          42 :         ScratchRegisterScope scratch(asMasm());
     900          21 :         unboxString(value, scratch);
     901          21 :         cmp32(Operand(scratch, JSString::offsetOfLength()), Imm32(0));
     902          42 :         return truthy ? Assembler::NotEqual : Assembler::Equal;
     903             :     }
     904             : 
     905             :     template <typename T>
     906             :     inline void loadInt32OrDouble(const T& src, FloatRegister dest);
     907             : 
     908             :     template <typename T>
     909          14 :     void loadUnboxedValue(const T& src, MIRType type, AnyRegister dest) {
     910          14 :         if (dest.isFloat())
     911           0 :             loadInt32OrDouble(src, dest.fpu());
     912          14 :         else if (type == MIRType::Int32 || type == MIRType::Boolean)
     913           6 :             movl(Operand(src), dest.gpr());
     914             :         else
     915           8 :             unboxNonDouble(Operand(src), dest.gpr());
     916          14 :     }
     917             : 
     918             :     template <typename T>
     919          10 :     void storeUnboxedPayload(ValueOperand value, T address, size_t nbytes) {
     920          10 :         switch (nbytes) {
     921             :           case 8: {
     922          14 :             ScratchRegisterScope scratch(asMasm());
     923           7 :             unboxNonDouble(value, scratch);
     924           7 :             storePtr(scratch, address);
     925           7 :             return;
     926             :           }
     927             :           case 4:
     928           0 :             store32(value.valueReg(), address);
     929           0 :             return;
     930             :           case 1:
     931           3 :             store8(value.valueReg(), address);
     932           3 :             return;
     933           0 :           default: MOZ_CRASH("Bad payload width");
     934             :         }
     935             :     }
     936             : 
     937             :     void loadInstructionPointerAfterCall(Register dest) {
     938             :         loadPtr(Address(StackPointer, 0x0), dest);
     939             :     }
     940             : 
     941           0 :     void convertUInt32ToDouble(Register src, FloatRegister dest) {
     942             :         // Zero the output register to break dependencies, see convertInt32ToDouble.
     943           0 :         zeroDouble(dest);
     944             : 
     945           0 :         vcvtsq2sd(src, dest, dest);
     946           0 :     }
     947             : 
     948           0 :     void convertUInt32ToFloat32(Register src, FloatRegister dest) {
     949             :         // Zero the output register to break dependencies, see convertInt32ToDouble.
     950           0 :         zeroDouble(dest);
     951             : 
     952           0 :         vcvtsq2ss(src, dest, dest);
     953           0 :     }
     954             : 
     955             :     inline void incrementInt32Value(const Address& addr);
     956             : 
     957             :     inline void ensureDouble(const ValueOperand& source, FloatRegister dest, Label* failure);
     958             : 
     959             :   public:
     960             :     void handleFailureWithHandlerTail(void* handler);
     961             : 
     962             :     // Instrumentation for entering and leaving the profiler.
     963             :     void profilerEnterFrame(Register framePtr, Register scratch);
     964             :     void profilerExitFrame();
     965             : };
     966             : 
     967             : typedef MacroAssemblerX64 MacroAssemblerSpecific;
     968             : 
     969             : } // namespace jit
     970             : } // namespace js
     971             : 
     972             : #endif /* jit_x64_MacroAssembler_x64_h */

Generated by: LCOV version 1.13