tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CodeGenerator-shared-inl.h (10884B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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_shared_CodeGenerator_shared_inl_h
      8 #define jit_shared_CodeGenerator_shared_inl_h
      9 
     10 #include "jit/shared/CodeGenerator-shared.h"
     11 
     12 #include "jit/JitFrames.h"
     13 #include "jit/ScalarTypeUtils.h"
     14 
     15 #include "jit/MacroAssembler-inl.h"
     16 
     17 namespace js {
     18 namespace jit {
     19 
     20 static inline bool IsConstant(const LInt64Allocation& a) {
     21 #if JS_BITS_PER_WORD == 32
     22  if (a.high().isConstantValue()) {
     23    return true;
     24  }
     25  if (a.high().isConstantIndex()) {
     26    return true;
     27  }
     28 #else
     29  if (a.value().isConstantValue()) {
     30    return true;
     31  }
     32  if (a.value().isConstantIndex()) {
     33    return true;
     34  }
     35 #endif
     36  return false;
     37 }
     38 
     39 static inline int32_t ToInt32(const LAllocation* a) {
     40  if (a->isConstantValue()) {
     41    const MConstant* cst = a->toConstant();
     42    if (cst->type() == MIRType::Int32) {
     43      return cst->toInt32();
     44    }
     45    intptr_t val = cst->toIntPtr();
     46    MOZ_ASSERT(INT32_MIN <= val && val <= INT32_MAX);
     47    return int32_t(val);
     48  }
     49  if (a->isConstantIndex()) {
     50    return a->toConstantIndex()->index();
     51  }
     52  MOZ_CRASH("this is not a constant!");
     53 }
     54 
     55 static inline intptr_t ToIntPtr(const LAllocation* a) {
     56  if (a->isConstantValue()) {
     57    const MConstant* cst = a->toConstant();
     58    if (cst->type() == MIRType::Int32) {
     59      return cst->toInt32();
     60    }
     61    return cst->toIntPtr();
     62  }
     63  if (a->isConstantIndex()) {
     64    return a->toConstantIndex()->index();
     65  }
     66  MOZ_CRASH("this is not a constant!");
     67 }
     68 
     69 static inline int64_t ToInt64(const LAllocation* a) {
     70  if (a->isConstantValue()) {
     71    return a->toConstant()->toInt64();
     72  }
     73  if (a->isConstantIndex()) {
     74    return a->toConstantIndex()->index();
     75  }
     76  MOZ_CRASH("this is not a constant!");
     77 }
     78 
     79 static inline int64_t ToInt64(const LInt64Allocation& a) {
     80 #if JS_BITS_PER_WORD == 32
     81  if (a.high().isConstantValue()) {
     82    return a.high().toConstant()->toInt64();
     83  }
     84  if (a.high().isConstantIndex()) {
     85    return a.high().toConstantIndex()->index();
     86  }
     87 #else
     88  if (a.value().isConstantValue()) {
     89    return a.value().toConstant()->toInt64();
     90  }
     91  if (a.value().isConstantIndex()) {
     92    return a.value().toConstantIndex()->index();
     93  }
     94 #endif
     95  MOZ_CRASH("this is not a constant!");
     96 }
     97 
     98 static inline double ToDouble(const LAllocation* a) {
     99  return a->toConstant()->numberToDouble();
    100 }
    101 
    102 static inline bool ToBoolean(const LAllocation* a) {
    103  return a->toConstant()->toBoolean();
    104 }
    105 
    106 static inline Register ToRegister(const LAllocation& a) {
    107  MOZ_ASSERT(a.isGeneralReg());
    108  return a.toGeneralReg()->reg();
    109 }
    110 
    111 static inline Register ToRegister(const LAllocation* a) {
    112  return ToRegister(*a);
    113 }
    114 
    115 static inline Register ToRegister(const LDefinition* def) {
    116  return ToRegister(*def->output());
    117 }
    118 
    119 static inline Register64 ToOutRegister64(LInstruction* ins) {
    120 #if JS_BITS_PER_WORD == 32
    121  Register loReg = ToRegister(ins->getDef(INT64LOW_INDEX));
    122  Register hiReg = ToRegister(ins->getDef(INT64HIGH_INDEX));
    123  return Register64(hiReg, loReg);
    124 #else
    125  return Register64(ToRegister(ins->getDef(0)));
    126 #endif
    127 }
    128 
    129 static inline bool IsRegister64(const LInt64Allocation& a) {
    130 #if JS_BITS_PER_WORD == 32
    131  MOZ_ASSERT(a.low().isGeneralReg() == a.high().isGeneralReg());
    132  return a.low().isGeneralReg();
    133 #else
    134  return a.value().isGeneralReg();
    135 #endif
    136 }
    137 
    138 static inline Register64 ToRegister64(const LInt64Allocation& a) {
    139 #if JS_BITS_PER_WORD == 32
    140  return Register64(ToRegister(a.high()), ToRegister(a.low()));
    141 #else
    142  return Register64(ToRegister(a.value()));
    143 #endif
    144 }
    145 
    146 static inline Register64 ToRegister64(const LInt64Definition& a) {
    147 #if JS_BITS_PER_WORD == 32
    148  return Register64(ToRegister(a.pointerHigh()), ToRegister(a.pointerLow()));
    149 #else
    150  return Register64(ToRegister(a.pointer()));
    151 #endif
    152 }
    153 
    154 static inline Register ToTempRegisterOrInvalid(const LDefinition* def) {
    155  if (def->isBogusTemp()) {
    156    return InvalidReg;
    157  }
    158  return ToRegister(def);
    159 }
    160 
    161 static inline Register64 ToTempRegister64OrInvalid(
    162    const LInt64Definition& def) {
    163  if (def.isBogusTemp()) {
    164    return Register64::Invalid();
    165  }
    166  return ToRegister64(def);
    167 }
    168 
    169 static inline Register ToTempUnboxRegister(const LDefinition* def) {
    170  return ToTempRegisterOrInvalid(def);
    171 }
    172 
    173 static inline FloatRegister ToFloatRegister(const LAllocation& a) {
    174  MOZ_ASSERT(a.isFloatReg());
    175  return a.toFloatReg()->reg();
    176 }
    177 
    178 static inline FloatRegister ToFloatRegister(const LAllocation* a) {
    179  return ToFloatRegister(*a);
    180 }
    181 
    182 static inline FloatRegister ToFloatRegister(const LDefinition* def) {
    183  return ToFloatRegister(*def->output());
    184 }
    185 
    186 static inline FloatRegister ToTempFloatRegisterOrInvalid(
    187    const LDefinition* def) {
    188  if (def->isBogusTemp()) {
    189    return InvalidFloatReg;
    190  }
    191  return ToFloatRegister(def);
    192 }
    193 
    194 static inline AnyRegister ToAnyRegister(const LAllocation& a) {
    195  MOZ_ASSERT(a.isGeneralReg() || a.isFloatReg());
    196  if (a.isGeneralReg()) {
    197    return AnyRegister(ToRegister(a));
    198  }
    199  return AnyRegister(ToFloatRegister(a));
    200 }
    201 
    202 static inline AnyRegister ToAnyRegister(const LAllocation* a) {
    203  return ToAnyRegister(*a);
    204 }
    205 
    206 static inline AnyRegister ToAnyRegister(const LDefinition* def) {
    207  return ToAnyRegister(def->output());
    208 }
    209 
    210 static inline ValueOperand ToOutValue(LInstruction* ins) {
    211 #if defined(JS_NUNBOX32)
    212  return ValueOperand(ToRegister(ins->getDef(TYPE_INDEX)),
    213                      ToRegister(ins->getDef(PAYLOAD_INDEX)));
    214 #elif defined(JS_PUNBOX64)
    215  return ValueOperand(ToRegister(ins->getDef(0)));
    216 #else
    217 #  error "Unknown"
    218 #endif
    219 }
    220 
    221 static inline ValueOperand ToValue(const LBoxAllocation& a) {
    222 #if defined(JS_NUNBOX32)
    223  return ValueOperand(ToRegister(a.type()), ToRegister(a.payload()));
    224 #elif defined(JS_PUNBOX64)
    225  return ValueOperand(ToRegister(a.value()));
    226 #else
    227 #  error "Unknown"
    228 #endif
    229 }
    230 
    231 // For argument construction for calls. Argslots are Value-sized.
    232 Address CodeGeneratorShared::AddressOfPassedArg(uint32_t slot) const {
    233  MOZ_ASSERT(masm.framePushed() == frameSize());
    234 
    235  MOZ_ASSERT(slot > 0);
    236  MOZ_ASSERT(slot <= graph.argumentSlotCount());
    237 
    238  uint32_t offsetFromBase = offsetOfPassedArgSlots_ + slot * sizeof(Value);
    239  MOZ_ASSERT(offsetFromBase <= frameSize());
    240 
    241  // Space for passed arguments is reserved below a function's local stack
    242  // storage. Note that passedArgSlotsOffset_ is aligned to at least
    243  // sizeof(Value) to ensure proper alignment.
    244  MOZ_ASSERT((offsetFromBase % sizeof(Value)) == 0);
    245 
    246  if (JitOptions.baseRegForLocals == BaseRegForAddress::SP) {
    247    return Address(masm.getStackPointer(), frameSize() - offsetFromBase);
    248  }
    249  MOZ_ASSERT(JitOptions.baseRegForLocals == BaseRegForAddress::FP);
    250  return Address(FramePointer, -int32_t(offsetFromBase));
    251 }
    252 
    253 uint32_t CodeGeneratorShared::UnusedStackBytesForCall(
    254    uint32_t numArgSlots) const {
    255  MOZ_ASSERT(masm.framePushed() == frameSize());
    256  MOZ_ASSERT(numArgSlots <= graph.argumentSlotCount());
    257  uint32_t unusedArgSlots = graph.argumentSlotCount() - numArgSlots;
    258  return unusedArgSlots * sizeof(Value);
    259 }
    260 
    261 template <BaseRegForAddress Base>
    262 Address CodeGeneratorShared::ToAddress(const LAllocation& a) const {
    263  MOZ_ASSERT(a.isMemory() || a.isStackArea());
    264  MOZ_ASSERT(masm.framePushed() == frameSize());
    265 
    266  if (a.isArgument()) {
    267    // Use the frame pointer, unless the caller explicitly requested a
    268    // stack-pointer-relative address.
    269    uint32_t offsetFromFP = offsetOfArgsFromFP_ + a.toArgument()->index();
    270    if constexpr (Base == BaseRegForAddress::SP) {
    271      return Address(masm.getStackPointer(), frameSize() + offsetFromFP);
    272    } else {
    273      static_assert(Base == BaseRegForAddress::Default ||
    274                    Base == BaseRegForAddress::FP);
    275      return Address(FramePointer, offsetFromFP);
    276    }
    277  }
    278 
    279  uint32_t slot =
    280      a.isStackSlot() ? a.toStackSlot()->slot() : a.toStackArea()->base();
    281  MOZ_ASSERT(slot > 0 && slot <= graph.localSlotsSize());
    282  MOZ_ASSERT(slot <= frameSize());
    283 
    284  BaseRegForAddress base = Base;
    285  if constexpr (Base == BaseRegForAddress::Default) {
    286    base = JitOptions.baseRegForLocals;
    287  }
    288 
    289  if (base == BaseRegForAddress::FP) {
    290    return Address(FramePointer, -int32_t(slot));
    291  }
    292  MOZ_ASSERT(base == BaseRegForAddress::SP);
    293  return Address(masm.getStackPointer(), frameSize() - slot);
    294 }
    295 
    296 template <BaseRegForAddress Base>
    297 Address CodeGeneratorShared::ToAddress(const LAllocation* a) const {
    298  return ToAddress<Base>(*a);
    299 }
    300 
    301 template <BaseRegForAddress Base>
    302 Address CodeGeneratorShared::ToAddress(const LInt64Allocation& a) const {
    303 #if JS_BITS_PER_WORD == 32
    304  Address low = ToAddress<Base>(a.low());
    305  MOZ_ASSERT(HighWord(low) == ToAddress<Base>(a.high()));
    306  return low;
    307 #else
    308  return ToAddress<Base>(a.value());
    309 #endif
    310 }
    311 
    312 // static
    313 Address CodeGeneratorShared::ToAddress(Register elements,
    314                                       const LAllocation* index,
    315                                       Scalar::Type type) {
    316  int32_t idx = ToInt32(index);
    317  int32_t offset;
    318  MOZ_ALWAYS_TRUE(ArrayOffsetFitsInInt32(idx, type, &offset));
    319  return Address(elements, offset);
    320 }
    321 
    322 void CodeGeneratorShared::saveLive(LInstruction* ins) {
    323  MOZ_ASSERT(!ins->isCall());
    324  LSafepoint* safepoint = ins->safepoint();
    325  masm.PushRegsInMask(safepoint->liveRegs());
    326 }
    327 
    328 void CodeGeneratorShared::restoreLive(LInstruction* ins) {
    329  MOZ_ASSERT(!ins->isCall());
    330  LSafepoint* safepoint = ins->safepoint();
    331  masm.PopRegsInMask(safepoint->liveRegs());
    332 }
    333 
    334 void CodeGeneratorShared::restoreLiveIgnore(LInstruction* ins,
    335                                            LiveRegisterSet ignore) {
    336  MOZ_ASSERT(!ins->isCall());
    337  LSafepoint* safepoint = ins->safepoint();
    338  masm.PopRegsInMaskIgnore(safepoint->liveRegs(), ignore);
    339 }
    340 
    341 LiveRegisterSet CodeGeneratorShared::liveVolatileRegs(LInstruction* ins) {
    342  MOZ_ASSERT(!ins->isCall());
    343  LSafepoint* safepoint = ins->safepoint();
    344  LiveRegisterSet regs;
    345  regs.set() = RegisterSet::Intersect(safepoint->liveRegs().set(),
    346                                      RegisterSet::Volatile());
    347  return regs;
    348 }
    349 
    350 void CodeGeneratorShared::saveLiveVolatile(LInstruction* ins) {
    351  LiveRegisterSet regs = liveVolatileRegs(ins);
    352  masm.PushRegsInMask(regs);
    353 }
    354 
    355 void CodeGeneratorShared::restoreLiveVolatile(LInstruction* ins) {
    356  LiveRegisterSet regs = liveVolatileRegs(ins);
    357  masm.PopRegsInMask(regs);
    358 }
    359 
    360 inline bool CodeGeneratorShared::isGlobalObject(JSObject* object) {
    361  // Calling object->is<GlobalObject>() is racy because this relies on
    362  // checking the group and this can be changed while we are compiling off the
    363  // main thread. Note that we only check for the script realm's global here.
    364  return object == gen->realm->maybeGlobal();
    365 }
    366 
    367 }  // namespace jit
    368 }  // namespace js
    369 
    370 #endif /* jit_shared_CodeGenerator_shared_inl_h */