tor-browser

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

WarpBuilderShared.cpp (4418B)


      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 #include "jit/WarpBuilderShared.h"
      8 
      9 #include "jit/MIRGenerator.h"
     10 #include "jit/MIRGraph.h"
     11 
     12 using namespace js;
     13 using namespace js::jit;
     14 
     15 WarpBuilderShared::WarpBuilderShared(WarpSnapshot& snapshot,
     16                                     MIRGenerator& mirGen,
     17                                     MBasicBlock* current_)
     18    : snapshot_(snapshot),
     19      mirGen_(mirGen),
     20      alloc_(mirGen.alloc()),
     21      current(current_) {}
     22 
     23 bool WarpBuilderShared::resumeAfter(MInstruction* ins, BytecodeLocation loc) {
     24  // resumeAfter should only be used with effectful instructions. The only
     25  // exceptions are:
     26  // 1. MInt64ToBigInt, which is used to convert the result of either a call
     27  //    into Wasm code or loading from a BigIntArray, so we attach the resume
     28  //    point to that instead of to the call resp. load.
     29  // 2. MPostIntPtrConversion which is used after conversion from IntPtr.
     30  MOZ_ASSERT(ins->isEffectful() || ins->isInt64ToBigInt() ||
     31             ins->isPostIntPtrConversion());
     32  MOZ_ASSERT(!ins->isMovable());
     33 
     34  MResumePoint* resumePoint = MResumePoint::New(
     35      alloc(), ins->block(), loc.toRawBytecode(), ResumeMode::ResumeAfter);
     36  if (!resumePoint) {
     37    return false;
     38  }
     39 
     40  ins->setResumePoint(resumePoint);
     41  return true;
     42 }
     43 
     44 MConstant* WarpBuilderShared::constant(const Value& v) {
     45  MOZ_ASSERT_IF(v.isString(), v.toString()->isLinear());
     46  MOZ_ASSERT_IF(v.isGCThing(), !IsInsideNursery(v.toGCThing()));
     47 
     48  MConstant* cst = MConstant::New(alloc(), v);
     49  current->add(cst);
     50  return cst;
     51 }
     52 
     53 void WarpBuilderShared::pushConstant(const Value& v) {
     54  MConstant* cst = constant(v);
     55  current->push(cst);
     56 }
     57 
     58 MDefinition* WarpBuilderShared::unboxObjectInfallible(MDefinition* def,
     59                                                      IsMovable movable) {
     60  if (def->type() == MIRType::Object) {
     61    return def;
     62  }
     63 
     64  if (def->type() != MIRType::Value) {
     65    // Corner case: if the MIR node has a type other than Object or Value, this
     66    // code isn't actually reachable and we expect an earlier guard to fail.
     67    // Just insert a Box to satisfy MIR invariants.
     68    MOZ_ASSERT(movable == IsMovable::No);
     69    auto* box = MBox::New(alloc(), def);
     70    current->add(box);
     71    def = box;
     72  }
     73 
     74  auto* unbox = MUnbox::New(alloc(), def, MIRType::Object, MUnbox::Infallible);
     75  if (movable == IsMovable::No) {
     76    unbox->setNotMovable();
     77  }
     78  current->add(unbox);
     79  return unbox;
     80 }
     81 
     82 MCall* WarpBuilderShared::makeCall(CallInfo& callInfo, bool needsThisCheck,
     83                                   WrappedFunction* target, bool isDOMCall,
     84                                   gc::Heap initialHeap) {
     85  auto addUndefined = [this]() -> MConstant* {
     86    return constant(UndefinedValue());
     87  };
     88 
     89  return MakeCall(alloc(), addUndefined, callInfo, needsThisCheck, target,
     90                  isDOMCall, initialHeap);
     91 }
     92 
     93 MInstruction* WarpBuilderShared::makeSpreadCall(CallInfo& callInfo,
     94                                                bool needsThisCheck,
     95                                                bool isSameRealm,
     96                                                WrappedFunction* target) {
     97  MOZ_ASSERT(callInfo.argFormat() == CallInfo::ArgFormat::Array);
     98  MOZ_ASSERT_IF(needsThisCheck, !target);
     99 
    100  // Load dense elements of the argument array.
    101  MElements* elements = MElements::New(alloc(), callInfo.arrayArg());
    102  current->add(elements);
    103 
    104  if (callInfo.constructing()) {
    105    auto* newTarget = unboxObjectInfallible(callInfo.getNewTarget());
    106    auto* construct =
    107        MConstructArray::New(alloc(), target, callInfo.callee(), elements,
    108                             callInfo.thisArg(), newTarget);
    109    if (isSameRealm) {
    110      construct->setNotCrossRealm();
    111    }
    112    if (needsThisCheck) {
    113      construct->setNeedsThisCheck();
    114    }
    115    return construct;
    116  }
    117 
    118  auto* apply = MApplyArray::New(alloc(), target, callInfo.callee(), elements,
    119                                 callInfo.thisArg());
    120 
    121  if (callInfo.ignoresReturnValue()) {
    122    apply->setIgnoresReturnValue();
    123  }
    124  if (isSameRealm) {
    125    apply->setNotCrossRealm();
    126  }
    127  MOZ_ASSERT(!needsThisCheck);
    128  return apply;
    129 }