LCOV - code coverage report
Current view: top level - js/src/jit - Recover.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 46 956 4.8 %
Date: 2017-07-14 16:53:18 Functions: 8 169 4.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             : #include "jit/Recover.h"
       8             : 
       9             : #include "mozilla/SizePrintfMacros.h"
      10             : 
      11             : #include "jsapi.h"
      12             : #include "jscntxt.h"
      13             : #include "jsiter.h"
      14             : #include "jsmath.h"
      15             : #include "jsobj.h"
      16             : #include "jsstr.h"
      17             : 
      18             : #include "builtin/RegExp.h"
      19             : #include "builtin/SIMD.h"
      20             : #include "builtin/TypedObject.h"
      21             : 
      22             : #include "gc/Heap.h"
      23             : 
      24             : #include "jit/JitFrameIterator.h"
      25             : #include "jit/JitSpewer.h"
      26             : #include "jit/MIR.h"
      27             : #include "jit/MIRGraph.h"
      28             : #include "jit/VMFunctions.h"
      29             : #include "vm/Interpreter.h"
      30             : #include "vm/String.h"
      31             : 
      32             : #include "vm/Interpreter-inl.h"
      33             : #include "vm/NativeObject-inl.h"
      34             : 
      35             : using namespace js;
      36             : using namespace js::jit;
      37             : 
      38             : bool
      39           0 : MNode::writeRecoverData(CompactBufferWriter& writer) const
      40             : {
      41           0 :     MOZ_CRASH("This instruction is not serializable");
      42             : }
      43             : 
      44             : void
      45         840 : RInstruction::readRecoverData(CompactBufferReader& reader, RInstructionStorage* raw)
      46             : {
      47         840 :     uint32_t op = reader.readUnsigned();
      48         840 :     switch (Opcode(op)) {
      49             : #   define MATCH_OPCODES_(op)                                           \
      50             :       case Recover_##op:                                                \
      51             :         static_assert(sizeof(R##op) <= sizeof(RInstructionStorage),     \
      52             :                       "storage space must be big enough to store R" #op); \
      53             :         static_assert(alignof(R##op) <= alignof(RInstructionStorage),   \
      54             :                       "storage space must be aligned adequate to store R" #op); \
      55             :         new (raw->addr()) R##op(reader);                                \
      56             :         break;
      57             : 
      58         840 :         RECOVER_OPCODE_LIST(MATCH_OPCODES_)
      59             : #   undef MATCH_OPCODES_
      60             : 
      61             :       case Recover_Invalid:
      62             :       default:
      63           0 :         MOZ_CRASH("Bad decoding of the previous instruction?");
      64             :     }
      65         840 : }
      66             : 
      67             : bool
      68         210 : MResumePoint::writeRecoverData(CompactBufferWriter& writer) const
      69             : {
      70         210 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ResumePoint));
      71             : 
      72         210 :     MBasicBlock* bb = block();
      73         210 :     JSFunction* fun = bb->info().funMaybeLazy();
      74         210 :     JSScript* script = bb->info().script();
      75         210 :     uint32_t exprStack = stackDepth() - bb->info().ninvoke();
      76             : 
      77             : #ifdef DEBUG
      78             :     // Ensure that all snapshot which are encoded can safely be used for
      79             :     // bailouts.
      80         210 :     if (GetJitContext()->cx) {
      81             :         uint32_t stackDepth;
      82             :         bool reachablePC;
      83           0 :         jsbytecode* bailPC = pc();
      84             : 
      85           0 :         if (mode() == MResumePoint::ResumeAfter)
      86           0 :             bailPC = GetNextPc(pc());
      87             : 
      88           0 :         if (!ReconstructStackDepth(GetJitContext()->cx, script,
      89             :                                    bailPC, &stackDepth, &reachablePC))
      90             :         {
      91           0 :             return false;
      92             :         }
      93             : 
      94           0 :         if (reachablePC) {
      95           0 :             if (JSOp(*bailPC) == JSOP_FUNCALL) {
      96             :                 // For fun.call(this, ...); the reconstructStackDepth will
      97             :                 // include the this. When inlining that is not included.  So the
      98             :                 // exprStackSlots will be one less.
      99           0 :                 MOZ_ASSERT(stackDepth - exprStack <= 1);
     100           0 :             } else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
     101           0 :                        !IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
     102             :             {
     103             :                 // For fun.apply({}, arguments) the reconstructStackDepth will
     104             :                 // have stackdepth 4, but it could be that we inlined the
     105             :                 // funapply. In that case exprStackSlots, will have the real
     106             :                 // arguments in the slots and not be 4.
     107             : 
     108             :                 // With accessors, we have different stack depths depending on
     109             :                 // whether or not we inlined the accessor, as the inlined stack
     110             :                 // contains a callee function that should never have been there
     111             :                 // and we might just be capturing an uneventful property site,
     112             :                 // in which case there won't have been any violence.
     113           0 :                 MOZ_ASSERT(exprStack == stackDepth);
     114             :             }
     115             :         }
     116             :     }
     117             : #endif
     118             : 
     119             :     // Test if we honor the maximum of arguments at all times.  This is a sanity
     120             :     // check and not an algorithm limit. So check might be a bit too loose.  +4
     121             :     // to account for scope chain, return value, this value and maybe
     122             :     // arguments_object.
     123         210 :     MOZ_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
     124             : 
     125             : #ifdef JS_JITSPEW
     126         210 :     uint32_t implicit = StartArgSlot(script);
     127             : #endif
     128         210 :     uint32_t formalArgs = CountArgSlots(script, fun);
     129         210 :     uint32_t nallocs = formalArgs + script->nfixed() + exprStack;
     130             : 
     131         210 :     JitSpew(JitSpew_IonSnapshots, "Starting frame; implicit %u, formals %u, fixed %" PRIuSIZE ", exprs %u",
     132         210 :             implicit, formalArgs - implicit, script->nfixed(), exprStack);
     133             : 
     134         210 :     uint32_t pcoff = script->pcToOffset(pc());
     135         210 :     JitSpew(JitSpew_IonSnapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs);
     136         210 :     writer.writeUnsigned(pcoff);
     137         210 :     writer.writeUnsigned(nallocs);
     138         210 :     return true;
     139             : }
     140             : 
     141         840 : RResumePoint::RResumePoint(CompactBufferReader& reader)
     142             : {
     143         840 :     pcOffset_ = reader.readUnsigned();
     144         840 :     numOperands_ = reader.readUnsigned();
     145         840 :     JitSpew(JitSpew_IonSnapshots, "Read RResumePoint (pc offset %u, nslots %u)",
     146         840 :             pcOffset_, numOperands_);
     147         840 : }
     148             : 
     149             : bool
     150           0 : RResumePoint::recover(JSContext* cx, SnapshotIterator& iter) const
     151             : {
     152           0 :     MOZ_CRASH("This instruction is not recoverable.");
     153             : }
     154             : 
     155             : bool
     156           0 : MBitNot::writeRecoverData(CompactBufferWriter& writer) const
     157             : {
     158           0 :     MOZ_ASSERT(canRecoverOnBailout());
     159           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitNot));
     160           0 :     return true;
     161             : }
     162             : 
     163           0 : RBitNot::RBitNot(CompactBufferReader& reader)
     164           0 : { }
     165             : 
     166             : bool
     167           0 : RBitNot::recover(JSContext* cx, SnapshotIterator& iter) const
     168             : {
     169           0 :     RootedValue operand(cx, iter.read());
     170             : 
     171             :     int32_t result;
     172           0 :     if (!js::BitNot(cx, operand, &result))
     173           0 :         return false;
     174             : 
     175           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
     176           0 :     iter.storeInstructionResult(rootedResult);
     177           0 :     return true;
     178             : }
     179             : 
     180             : bool
     181           0 : MBitAnd::writeRecoverData(CompactBufferWriter& writer) const
     182             : {
     183           0 :     MOZ_ASSERT(canRecoverOnBailout());
     184           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitAnd));
     185           0 :     return true;
     186             : }
     187             : 
     188           0 : RBitAnd::RBitAnd(CompactBufferReader& reader)
     189           0 : { }
     190             : 
     191             : bool
     192           0 : RBitAnd::recover(JSContext* cx, SnapshotIterator& iter) const
     193             : {
     194           0 :     RootedValue lhs(cx, iter.read());
     195           0 :     RootedValue rhs(cx, iter.read());
     196             :     int32_t result;
     197           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     198             : 
     199           0 :     if (!js::BitAnd(cx, lhs, rhs, &result))
     200           0 :         return false;
     201             : 
     202           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
     203           0 :     iter.storeInstructionResult(rootedResult);
     204           0 :     return true;
     205             : }
     206             : 
     207             : bool
     208           0 : MBitOr::writeRecoverData(CompactBufferWriter& writer) const
     209             : {
     210           0 :     MOZ_ASSERT(canRecoverOnBailout());
     211           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitOr));
     212           0 :     return true;
     213             : }
     214             : 
     215           0 : RBitOr::RBitOr(CompactBufferReader& reader)
     216           0 : {}
     217             : 
     218             : bool
     219           0 : RBitOr::recover(JSContext* cx, SnapshotIterator& iter) const
     220             : {
     221           0 :     RootedValue lhs(cx, iter.read());
     222           0 :     RootedValue rhs(cx, iter.read());
     223             :     int32_t result;
     224           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     225             : 
     226           0 :     if (!js::BitOr(cx, lhs, rhs, &result))
     227           0 :         return false;
     228             : 
     229           0 :     RootedValue asValue(cx, js::Int32Value(result));
     230           0 :     iter.storeInstructionResult(asValue);
     231           0 :     return true;
     232             : }
     233             : 
     234             : bool
     235           0 : MBitXor::writeRecoverData(CompactBufferWriter& writer) const
     236             : {
     237           0 :     MOZ_ASSERT(canRecoverOnBailout());
     238           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_BitXor));
     239           0 :     return true;
     240             : }
     241             : 
     242           0 : RBitXor::RBitXor(CompactBufferReader& reader)
     243           0 : { }
     244             : 
     245             : bool
     246           0 : RBitXor::recover(JSContext* cx, SnapshotIterator& iter) const
     247             : {
     248           0 :     RootedValue lhs(cx, iter.read());
     249           0 :     RootedValue rhs(cx, iter.read());
     250             : 
     251             :     int32_t result;
     252           0 :     if (!js::BitXor(cx, lhs, rhs, &result))
     253           0 :         return false;
     254             : 
     255           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
     256           0 :     iter.storeInstructionResult(rootedResult);
     257           0 :     return true;
     258             : }
     259             : 
     260             : bool
     261           0 : MLsh::writeRecoverData(CompactBufferWriter& writer) const
     262             : {
     263           0 :     MOZ_ASSERT(canRecoverOnBailout());
     264           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Lsh));
     265           0 :     return true;
     266             : }
     267             : 
     268           0 : RLsh::RLsh(CompactBufferReader& reader)
     269           0 : {}
     270             : 
     271             : bool
     272           0 : RLsh::recover(JSContext* cx, SnapshotIterator& iter) const
     273             : {
     274           0 :     RootedValue lhs(cx, iter.read());
     275           0 :     RootedValue rhs(cx, iter.read());
     276             :     int32_t result;
     277           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     278             : 
     279           0 :     if (!js::BitLsh(cx, lhs, rhs, &result))
     280           0 :         return false;
     281             : 
     282           0 :     RootedValue asValue(cx, js::Int32Value(result));
     283           0 :     iter.storeInstructionResult(asValue);
     284           0 :     return true;
     285             : }
     286             : 
     287             : bool
     288           0 : MRsh::writeRecoverData(CompactBufferWriter& writer) const
     289             : {
     290           0 :     MOZ_ASSERT(canRecoverOnBailout());
     291           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Rsh));
     292           0 :     return true;
     293             : }
     294             : 
     295           0 : RRsh::RRsh(CompactBufferReader& reader)
     296           0 : { }
     297             : 
     298             : bool
     299           0 : RRsh::recover(JSContext* cx, SnapshotIterator& iter) const
     300             : {
     301           0 :     RootedValue lhs(cx, iter.read());
     302           0 :     RootedValue rhs(cx, iter.read());
     303           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     304             : 
     305             :     int32_t result;
     306           0 :     if (!js::BitRsh(cx, lhs, rhs, &result))
     307           0 :         return false;
     308             : 
     309           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
     310           0 :     iter.storeInstructionResult(rootedResult);
     311           0 :     return true;
     312             : }
     313             : 
     314             : bool
     315           0 : MUrsh::writeRecoverData(CompactBufferWriter& writer) const
     316             : {
     317           0 :     MOZ_ASSERT(canRecoverOnBailout());
     318           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Ursh));
     319           0 :     return true;
     320             : }
     321             : 
     322           0 : RUrsh::RUrsh(CompactBufferReader& reader)
     323           0 : { }
     324             : 
     325             : bool
     326           0 : RUrsh::recover(JSContext* cx, SnapshotIterator& iter) const
     327             : {
     328           0 :     RootedValue lhs(cx, iter.read());
     329           0 :     RootedValue rhs(cx, iter.read());
     330           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     331             : 
     332           0 :     RootedValue result(cx);
     333           0 :     if (!js::UrshOperation(cx, lhs, rhs, &result))
     334           0 :         return false;
     335             : 
     336           0 :     iter.storeInstructionResult(result);
     337           0 :     return true;
     338             : }
     339             : 
     340             : bool
     341           0 : MSignExtend::writeRecoverData(CompactBufferWriter& writer) const
     342             : {
     343           0 :     MOZ_ASSERT(canRecoverOnBailout());
     344           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_SignExtend));
     345           0 :     MOZ_ASSERT(Mode(uint8_t(mode_)) == mode_);
     346           0 :     writer.writeByte(uint8_t(mode_));
     347           0 :     return true;
     348             : }
     349             : 
     350           0 : RSignExtend::RSignExtend(CompactBufferReader& reader)
     351             : {
     352           0 :     mode_ = reader.readByte();
     353           0 : }
     354             : 
     355             : bool
     356           0 : RSignExtend::recover(JSContext* cx, SnapshotIterator& iter) const
     357             : {
     358           0 :     RootedValue operand(cx, iter.read());
     359             : 
     360             :     int32_t result;
     361           0 :     switch (MSignExtend::Mode(mode_)) {
     362             :       case MSignExtend::Byte:
     363           0 :         if (!js::SignExtendOperation<int8_t>(cx, operand, &result))
     364           0 :             return false;
     365           0 :         break;
     366             :       case MSignExtend::Half:
     367           0 :         if (!js::SignExtendOperation<int16_t>(cx, operand, &result))
     368           0 :             return false;
     369           0 :         break;
     370             :     }
     371             : 
     372           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
     373           0 :     iter.storeInstructionResult(rootedResult);
     374           0 :     return true;
     375             : }
     376             : 
     377             : bool
     378           0 : MAdd::writeRecoverData(CompactBufferWriter& writer) const
     379             : {
     380           0 :     MOZ_ASSERT(canRecoverOnBailout());
     381           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Add));
     382           0 :     writer.writeByte(specialization_ == MIRType::Float32);
     383           0 :     return true;
     384             : }
     385             : 
     386           0 : RAdd::RAdd(CompactBufferReader& reader)
     387             : {
     388           0 :     isFloatOperation_ = reader.readByte();
     389           0 : }
     390             : 
     391             : bool
     392           0 : RAdd::recover(JSContext* cx, SnapshotIterator& iter) const
     393             : {
     394           0 :     RootedValue lhs(cx, iter.read());
     395           0 :     RootedValue rhs(cx, iter.read());
     396           0 :     RootedValue result(cx);
     397             : 
     398           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     399           0 :     if (!js::AddValues(cx, &lhs, &rhs, &result))
     400           0 :         return false;
     401             : 
     402             :     // MIRType::Float32 is a specialization embedding the fact that the result is
     403             :     // rounded to a Float32.
     404           0 :     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
     405           0 :         return false;
     406             : 
     407           0 :     iter.storeInstructionResult(result);
     408           0 :     return true;
     409             : }
     410             : 
     411             : bool
     412           0 : MSub::writeRecoverData(CompactBufferWriter& writer) const
     413             : {
     414           0 :     MOZ_ASSERT(canRecoverOnBailout());
     415           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Sub));
     416           0 :     writer.writeByte(specialization_ == MIRType::Float32);
     417           0 :     return true;
     418             : }
     419             : 
     420           0 : RSub::RSub(CompactBufferReader& reader)
     421             : {
     422           0 :     isFloatOperation_ = reader.readByte();
     423           0 : }
     424             : 
     425             : bool
     426           0 : RSub::recover(JSContext* cx, SnapshotIterator& iter) const
     427             : {
     428           0 :     RootedValue lhs(cx, iter.read());
     429           0 :     RootedValue rhs(cx, iter.read());
     430           0 :     RootedValue result(cx);
     431             : 
     432           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     433           0 :     if (!js::SubValues(cx, &lhs, &rhs, &result))
     434           0 :         return false;
     435             : 
     436             :     // MIRType::Float32 is a specialization embedding the fact that the result is
     437             :     // rounded to a Float32.
     438           0 :     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
     439           0 :         return false;
     440             : 
     441           0 :     iter.storeInstructionResult(result);
     442           0 :     return true;
     443             : }
     444             : 
     445             : bool
     446           0 : MMul::writeRecoverData(CompactBufferWriter& writer) const
     447             : {
     448           0 :     MOZ_ASSERT(canRecoverOnBailout());
     449           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Mul));
     450           0 :     writer.writeByte(specialization_ == MIRType::Float32);
     451           0 :     MOZ_ASSERT(Mode(uint8_t(mode_)) == mode_);
     452           0 :     writer.writeByte(uint8_t(mode_));
     453           0 :     return true;
     454             : }
     455             : 
     456           0 : RMul::RMul(CompactBufferReader& reader)
     457             : {
     458           0 :     isFloatOperation_ = reader.readByte();
     459           0 :     mode_ = reader.readByte();
     460           0 : }
     461             : 
     462             : bool
     463           0 : RMul::recover(JSContext* cx, SnapshotIterator& iter) const
     464             : {
     465           0 :     RootedValue lhs(cx, iter.read());
     466           0 :     RootedValue rhs(cx, iter.read());
     467           0 :     RootedValue result(cx);
     468             : 
     469           0 :     if (MMul::Mode(mode_) == MMul::Normal) {
     470           0 :         if (!js::MulValues(cx, &lhs, &rhs, &result))
     471           0 :             return false;
     472             : 
     473             :         // MIRType::Float32 is a specialization embedding the fact that the
     474             :         // result is rounded to a Float32.
     475           0 :         if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
     476           0 :             return false;
     477             :     } else {
     478           0 :         MOZ_ASSERT(MMul::Mode(mode_) == MMul::Integer);
     479           0 :         if (!js::math_imul_handle(cx, lhs, rhs, &result))
     480           0 :             return false;
     481             :     }
     482             : 
     483           0 :     iter.storeInstructionResult(result);
     484           0 :     return true;
     485             : }
     486             : 
     487             : bool
     488           0 : MDiv::writeRecoverData(CompactBufferWriter& writer) const
     489             : {
     490           0 :     MOZ_ASSERT(canRecoverOnBailout());
     491           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Div));
     492           0 :     writer.writeByte(specialization_ == MIRType::Float32);
     493           0 :     return true;
     494             : }
     495             : 
     496           0 : RDiv::RDiv(CompactBufferReader& reader)
     497             : {
     498           0 :     isFloatOperation_ = reader.readByte();
     499           0 : }
     500             : 
     501             : bool
     502           0 : RDiv::recover(JSContext* cx, SnapshotIterator& iter) const
     503             : {
     504           0 :     RootedValue lhs(cx, iter.read());
     505           0 :     RootedValue rhs(cx, iter.read());
     506           0 :     RootedValue result(cx);
     507             : 
     508           0 :     if (!js::DivValues(cx, &lhs, &rhs, &result))
     509           0 :         return false;
     510             : 
     511             :     // MIRType::Float32 is a specialization embedding the fact that the result is
     512             :     // rounded to a Float32.
     513           0 :     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
     514           0 :         return false;
     515             : 
     516           0 :     iter.storeInstructionResult(result);
     517           0 :     return true;
     518             : }
     519             : 
     520             : bool
     521           0 : MMod::writeRecoverData(CompactBufferWriter& writer) const
     522             : {
     523           0 :     MOZ_ASSERT(canRecoverOnBailout());
     524           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Mod));
     525           0 :     return true;
     526             : }
     527             : 
     528           0 : RMod::RMod(CompactBufferReader& reader)
     529           0 : { }
     530             : 
     531             : bool
     532           0 : RMod::recover(JSContext* cx, SnapshotIterator& iter) const
     533             : {
     534           0 :     RootedValue lhs(cx, iter.read());
     535           0 :     RootedValue rhs(cx, iter.read());
     536           0 :     RootedValue result(cx);
     537             : 
     538           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     539           0 :     if (!js::ModValues(cx, &lhs, &rhs, &result))
     540           0 :         return false;
     541             : 
     542           0 :     iter.storeInstructionResult(result);
     543           0 :     return true;
     544             : }
     545             : 
     546             : bool
     547           0 : MNot::writeRecoverData(CompactBufferWriter& writer) const
     548             : {
     549           0 :     MOZ_ASSERT(canRecoverOnBailout());
     550           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Not));
     551           0 :     return true;
     552             : }
     553             : 
     554           0 : RNot::RNot(CompactBufferReader& reader)
     555           0 : { }
     556             : 
     557             : bool
     558           0 : RNot::recover(JSContext* cx, SnapshotIterator& iter) const
     559             : {
     560           0 :     RootedValue v(cx, iter.read());
     561           0 :     RootedValue result(cx);
     562             : 
     563           0 :     result.setBoolean(!ToBoolean(v));
     564             : 
     565           0 :     iter.storeInstructionResult(result);
     566           0 :     return true;
     567             : }
     568             : 
     569             : bool
     570           0 : MConcat::writeRecoverData(CompactBufferWriter& writer) const
     571             : {
     572           0 :     MOZ_ASSERT(canRecoverOnBailout());
     573           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Concat));
     574           0 :     return true;
     575             : }
     576             : 
     577           0 : RConcat::RConcat(CompactBufferReader& reader)
     578           0 : {}
     579             : 
     580             : bool
     581           0 : RConcat::recover(JSContext* cx, SnapshotIterator& iter) const
     582             : {
     583           0 :     RootedValue lhs(cx, iter.read());
     584           0 :     RootedValue rhs(cx, iter.read());
     585           0 :     RootedValue result(cx);
     586             : 
     587           0 :     MOZ_ASSERT(!lhs.isObject() && !rhs.isObject());
     588           0 :     if (!js::AddValues(cx, &lhs, &rhs, &result))
     589           0 :         return false;
     590             : 
     591           0 :     iter.storeInstructionResult(result);
     592           0 :     return true;
     593             : }
     594             : 
     595           0 : RStringLength::RStringLength(CompactBufferReader& reader)
     596           0 : {}
     597             : 
     598             : bool
     599           0 : RStringLength::recover(JSContext* cx, SnapshotIterator& iter) const
     600             : {
     601           0 :     RootedValue operand(cx, iter.read());
     602           0 :     RootedValue result(cx);
     603             : 
     604           0 :     MOZ_ASSERT(!operand.isObject());
     605           0 :     if (!js::GetLengthProperty(operand, &result))
     606           0 :         return false;
     607             : 
     608           0 :     iter.storeInstructionResult(result);
     609           0 :     return true;
     610             : }
     611             : 
     612             : bool
     613           0 : MStringLength::writeRecoverData(CompactBufferWriter& writer) const
     614             : {
     615           0 :     MOZ_ASSERT(canRecoverOnBailout());
     616           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_StringLength));
     617           0 :     return true;
     618             : }
     619             : 
     620             : bool
     621           0 : MArgumentsLength::writeRecoverData(CompactBufferWriter& writer) const
     622             : {
     623           0 :     MOZ_ASSERT(canRecoverOnBailout());
     624           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ArgumentsLength));
     625           0 :     return true;
     626             : }
     627             : 
     628           0 : RArgumentsLength::RArgumentsLength(CompactBufferReader& reader)
     629           0 : { }
     630             : 
     631             : bool
     632           0 : RArgumentsLength::recover(JSContext* cx, SnapshotIterator& iter) const
     633             : {
     634           0 :     RootedValue result(cx);
     635             : 
     636           0 :     result.setInt32(iter.readOuterNumActualArgs());
     637             : 
     638           0 :     iter.storeInstructionResult(result);
     639           0 :     return true;
     640             : }
     641             : 
     642             : bool
     643           0 : MFloor::writeRecoverData(CompactBufferWriter& writer) const
     644             : {
     645           0 :     MOZ_ASSERT(canRecoverOnBailout());
     646           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Floor));
     647           0 :     return true;
     648             : }
     649             : 
     650           0 : RFloor::RFloor(CompactBufferReader& reader)
     651           0 : { }
     652             : 
     653           0 : bool RFloor::recover(JSContext* cx, SnapshotIterator& iter) const
     654             : {
     655           0 :     RootedValue v(cx, iter.read());
     656           0 :     RootedValue result(cx);
     657             : 
     658           0 :     if (!js::math_floor_handle(cx, v, &result))
     659           0 :         return false;
     660             : 
     661           0 :     iter.storeInstructionResult(result);
     662           0 :     return true;
     663             : }
     664             : 
     665             : bool
     666           0 : MCeil::writeRecoverData(CompactBufferWriter& writer) const
     667             : {
     668           0 :     MOZ_ASSERT(canRecoverOnBailout());
     669           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Ceil));
     670           0 :     return true;
     671             : }
     672             : 
     673           0 : RCeil::RCeil(CompactBufferReader& reader)
     674           0 : { }
     675             : 
     676             : 
     677             : bool
     678           0 : RCeil::recover(JSContext* cx, SnapshotIterator& iter) const
     679             : {
     680           0 :     RootedValue v(cx, iter.read());
     681           0 :     RootedValue result(cx);
     682             : 
     683           0 :     if (!js::math_ceil_handle(cx, v, &result))
     684           0 :         return false;
     685             : 
     686           0 :     iter.storeInstructionResult(result);
     687           0 :     return true;
     688             : }
     689             : 
     690             : bool
     691           0 : MRound::writeRecoverData(CompactBufferWriter& writer) const
     692             : {
     693           0 :     MOZ_ASSERT(canRecoverOnBailout());
     694           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
     695           0 :     return true;
     696             : }
     697             : 
     698           0 : RRound::RRound(CompactBufferReader& reader)
     699           0 : {}
     700             : 
     701             : bool
     702           0 : RRound::recover(JSContext* cx, SnapshotIterator& iter) const
     703             : {
     704           0 :     RootedValue arg(cx, iter.read());
     705           0 :     RootedValue result(cx);
     706             : 
     707           0 :     MOZ_ASSERT(!arg.isObject());
     708           0 :     if(!js::math_round_handle(cx, arg, &result))
     709           0 :         return false;
     710             : 
     711           0 :     iter.storeInstructionResult(result);
     712           0 :     return true;
     713             : }
     714             : 
     715             : bool
     716           0 : MCharCodeAt::writeRecoverData(CompactBufferWriter& writer) const
     717             : {
     718           0 :     MOZ_ASSERT(canRecoverOnBailout());
     719           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_CharCodeAt));
     720           0 :     return true;
     721             : }
     722             : 
     723           0 : RCharCodeAt::RCharCodeAt(CompactBufferReader& reader)
     724           0 : {}
     725             : 
     726             : bool
     727           0 : RCharCodeAt::recover(JSContext* cx, SnapshotIterator& iter) const
     728             : {
     729           0 :     RootedString lhs(cx, iter.read().toString());
     730           0 :     RootedValue rhs(cx, iter.read());
     731           0 :     RootedValue result(cx);
     732             : 
     733           0 :     if (!js::str_charCodeAt_impl(cx, lhs, rhs, &result))
     734           0 :         return false;
     735             : 
     736           0 :     iter.storeInstructionResult(result);
     737           0 :     return true;
     738             : }
     739             : 
     740             : bool
     741           0 : MFromCharCode::writeRecoverData(CompactBufferWriter& writer) const
     742             : {
     743           0 :     MOZ_ASSERT(canRecoverOnBailout());
     744           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_FromCharCode));
     745           0 :     return true;
     746             : }
     747             : 
     748           0 : RFromCharCode::RFromCharCode(CompactBufferReader& reader)
     749           0 : {}
     750             : 
     751             : bool
     752           0 : RFromCharCode::recover(JSContext* cx, SnapshotIterator& iter) const
     753             : {
     754           0 :     RootedValue operand(cx, iter.read());
     755           0 :     RootedValue result(cx);
     756             : 
     757           0 :     MOZ_ASSERT(!operand.isObject());
     758           0 :     if (!js::str_fromCharCode_one_arg(cx, operand, &result))
     759           0 :         return false;
     760             : 
     761           0 :     iter.storeInstructionResult(result);
     762           0 :     return true;
     763             : }
     764             : 
     765             : bool
     766           0 : MPow::writeRecoverData(CompactBufferWriter& writer) const
     767             : {
     768           0 :     MOZ_ASSERT(canRecoverOnBailout());
     769           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Pow));
     770           0 :     return true;
     771             : }
     772             : 
     773           0 : RPow::RPow(CompactBufferReader& reader)
     774           0 : { }
     775             : 
     776             : bool
     777           0 : RPow::recover(JSContext* cx, SnapshotIterator& iter) const
     778             : {
     779           0 :     RootedValue base(cx, iter.read());
     780           0 :     RootedValue power(cx, iter.read());
     781           0 :     RootedValue result(cx);
     782             : 
     783           0 :     MOZ_ASSERT(base.isNumber() && power.isNumber());
     784           0 :     if (!js::math_pow_handle(cx, base, power, &result))
     785           0 :         return false;
     786             : 
     787           0 :     iter.storeInstructionResult(result);
     788           0 :     return true;
     789             : }
     790             : 
     791             : bool
     792           0 : MPowHalf::writeRecoverData(CompactBufferWriter& writer) const
     793             : {
     794           0 :     MOZ_ASSERT(canRecoverOnBailout());
     795           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_PowHalf));
     796           0 :     return true;
     797             : }
     798             : 
     799           0 : RPowHalf::RPowHalf(CompactBufferReader& reader)
     800           0 : { }
     801             : 
     802             : bool
     803           0 : RPowHalf::recover(JSContext* cx, SnapshotIterator& iter) const
     804             : {
     805           0 :     RootedValue base(cx, iter.read());
     806           0 :     RootedValue power(cx);
     807           0 :     RootedValue result(cx);
     808           0 :     power.setNumber(0.5);
     809             : 
     810           0 :     MOZ_ASSERT(base.isNumber());
     811           0 :     if (!js::math_pow_handle(cx, base, power, &result))
     812           0 :         return false;
     813             : 
     814           0 :     iter.storeInstructionResult(result);
     815           0 :     return true;
     816             : }
     817             : 
     818             : bool
     819           0 : MMinMax::writeRecoverData(CompactBufferWriter& writer) const
     820             : {
     821           0 :     MOZ_ASSERT(canRecoverOnBailout());
     822           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_MinMax));
     823           0 :     writer.writeByte(isMax_);
     824           0 :     return true;
     825             : }
     826             : 
     827           0 : RMinMax::RMinMax(CompactBufferReader& reader)
     828             : {
     829           0 :     isMax_ = reader.readByte();
     830           0 : }
     831             : 
     832             : bool
     833           0 : RMinMax::recover(JSContext* cx, SnapshotIterator& iter) const
     834             : {
     835           0 :     RootedValue a(cx, iter.read());
     836           0 :     RootedValue b(cx, iter.read());
     837           0 :     RootedValue result(cx);
     838             : 
     839           0 :     if (!js::minmax_impl(cx, isMax_, a, b, &result))
     840           0 :         return false;
     841             : 
     842           0 :     iter.storeInstructionResult(result);
     843           0 :     return true;
     844             : }
     845             : 
     846             : bool
     847           0 : MAbs::writeRecoverData(CompactBufferWriter& writer) const
     848             : {
     849           0 :     MOZ_ASSERT(canRecoverOnBailout());
     850           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Abs));
     851           0 :     return true;
     852             : }
     853             : 
     854           0 : RAbs::RAbs(CompactBufferReader& reader)
     855           0 : { }
     856             : 
     857             : bool
     858           0 : RAbs::recover(JSContext* cx, SnapshotIterator& iter) const
     859             : {
     860           0 :     RootedValue v(cx, iter.read());
     861           0 :     RootedValue result(cx);
     862             : 
     863           0 :     if (!js::math_abs_handle(cx, v, &result))
     864           0 :         return false;
     865             : 
     866           0 :     iter.storeInstructionResult(result);
     867           0 :     return true;
     868             : }
     869             : 
     870             : bool
     871           0 : MSqrt::writeRecoverData(CompactBufferWriter& writer) const
     872             : {
     873           0 :     MOZ_ASSERT(canRecoverOnBailout());
     874           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Sqrt));
     875           0 :     writer.writeByte(type() == MIRType::Float32);
     876           0 :     return true;
     877             : }
     878             : 
     879           0 : RSqrt::RSqrt(CompactBufferReader& reader)
     880             : {
     881           0 :     isFloatOperation_ = reader.readByte();
     882           0 : }
     883             : 
     884             : bool
     885           0 : RSqrt::recover(JSContext* cx, SnapshotIterator& iter) const
     886             : {
     887           0 :     RootedValue num(cx, iter.read());
     888           0 :     RootedValue result(cx);
     889             : 
     890           0 :     MOZ_ASSERT(num.isNumber());
     891           0 :     if (!math_sqrt_handle(cx, num, &result))
     892           0 :         return false;
     893             : 
     894             :     // MIRType::Float32 is a specialization embedding the fact that the result is
     895             :     // rounded to a Float32.
     896           0 :     if (isFloatOperation_ && !RoundFloat32(cx, result, &result))
     897           0 :         return false;
     898             : 
     899           0 :     iter.storeInstructionResult(result);
     900           0 :     return true;
     901             : }
     902             : 
     903             : bool
     904           0 : MAtan2::writeRecoverData(CompactBufferWriter& writer) const
     905             : {
     906           0 :     MOZ_ASSERT(canRecoverOnBailout());
     907           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Atan2));
     908           0 :     return true;
     909             : }
     910             : 
     911           0 : RAtan2::RAtan2(CompactBufferReader& reader)
     912           0 : { }
     913             : 
     914             : bool
     915           0 : RAtan2::recover(JSContext* cx, SnapshotIterator& iter) const
     916             : {
     917           0 :     RootedValue y(cx, iter.read());
     918           0 :     RootedValue x(cx, iter.read());
     919           0 :     RootedValue result(cx);
     920             : 
     921           0 :     if(!math_atan2_handle(cx, y, x, &result))
     922           0 :         return false;
     923             : 
     924           0 :     iter.storeInstructionResult(result);
     925           0 :     return true;
     926             : }
     927             : 
     928             : bool
     929           0 : MHypot::writeRecoverData(CompactBufferWriter& writer) const
     930             : {
     931           0 :     MOZ_ASSERT(canRecoverOnBailout());
     932           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Hypot));
     933           0 :     writer.writeUnsigned(uint32_t(numOperands()));
     934           0 :     return true;
     935             : }
     936             : 
     937           0 : RHypot::RHypot(CompactBufferReader& reader)
     938           0 :     : numOperands_(reader.readUnsigned())
     939           0 : { }
     940             : 
     941             : bool
     942           0 : RHypot::recover(JSContext* cx, SnapshotIterator& iter) const
     943             : {
     944           0 :     JS::AutoValueVector vec(cx);
     945             : 
     946           0 :     if (!vec.reserve(numOperands_))
     947           0 :         return false;
     948             : 
     949           0 :     for (uint32_t i = 0 ; i < numOperands_ ; ++i)
     950           0 :        vec.infallibleAppend(iter.read());
     951             : 
     952           0 :     RootedValue result(cx);
     953             : 
     954           0 :     if(!js::math_hypot_handle(cx, vec, &result))
     955           0 :         return false;
     956             : 
     957           0 :     iter.storeInstructionResult(result);
     958           0 :     return true;
     959             : }
     960             : 
     961             : bool
     962           0 : MMathFunction::writeRecoverData(CompactBufferWriter& writer) const
     963             : {
     964           0 :     MOZ_ASSERT(canRecoverOnBailout());
     965           0 :     switch (function_) {
     966             :       case Round:
     967           0 :         writer.writeUnsigned(uint32_t(RInstruction::Recover_Round));
     968           0 :         return true;
     969             :       case Sin:
     970             :       case Log:
     971           0 :         writer.writeUnsigned(uint32_t(RInstruction::Recover_MathFunction));
     972           0 :         writer.writeByte(function_);
     973           0 :         return true;
     974             :       default:
     975           0 :         MOZ_CRASH("Unknown math function.");
     976             :     }
     977             : }
     978             : 
     979           0 : RMathFunction::RMathFunction(CompactBufferReader& reader)
     980             : {
     981           0 :     function_ = reader.readByte();
     982           0 : }
     983             : 
     984             : bool
     985           0 : RMathFunction::recover(JSContext* cx, SnapshotIterator& iter) const
     986             : {
     987           0 :     switch (function_) {
     988             :       case MMathFunction::Sin: {
     989           0 :         RootedValue arg(cx, iter.read());
     990           0 :         RootedValue result(cx);
     991             : 
     992           0 :         if (!js::math_sin_handle(cx, arg, &result))
     993           0 :             return false;
     994             : 
     995           0 :         iter.storeInstructionResult(result);
     996           0 :         return true;
     997             :       }
     998             :       case MMathFunction::Log: {
     999           0 :         RootedValue arg(cx, iter.read());
    1000           0 :         RootedValue result(cx);
    1001             : 
    1002           0 :         if (!js::math_log_handle(cx, arg, &result))
    1003           0 :             return false;
    1004             : 
    1005           0 :         iter.storeInstructionResult(result);
    1006           0 :         return true;
    1007             :       }
    1008             :       default:
    1009           0 :         MOZ_CRASH("Unknown math function.");
    1010             :     }
    1011             : }
    1012             : 
    1013             : bool
    1014           0 : MRandom::writeRecoverData(CompactBufferWriter& writer) const
    1015             : {
    1016           0 :     MOZ_ASSERT(this->canRecoverOnBailout());
    1017           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Random));
    1018           0 :     return true;
    1019             : }
    1020             : 
    1021           0 : RRandom::RRandom(CompactBufferReader& reader)
    1022           0 : {}
    1023             : 
    1024             : bool
    1025           0 : RRandom::recover(JSContext* cx, SnapshotIterator& iter) const
    1026             : {
    1027           0 :     iter.storeInstructionResult(DoubleValue(math_random_impl(cx)));
    1028           0 :     return true;
    1029             : }
    1030             : 
    1031             : bool
    1032           0 : MStringSplit::writeRecoverData(CompactBufferWriter& writer) const
    1033             : {
    1034           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1035           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_StringSplit));
    1036           0 :     return true;
    1037             : }
    1038             : 
    1039           0 : RStringSplit::RStringSplit(CompactBufferReader& reader)
    1040           0 : {}
    1041             : 
    1042             : bool
    1043           0 : RStringSplit::recover(JSContext* cx, SnapshotIterator& iter) const
    1044             : {
    1045           0 :     RootedString str(cx, iter.read().toString());
    1046           0 :     RootedString sep(cx, iter.read().toString());
    1047           0 :     RootedObjectGroup group(cx, ObjectGroupCompartment::getStringSplitStringGroup(cx));
    1048           0 :     if (!group) {
    1049           0 :         return false;
    1050             :     }
    1051           0 :     RootedValue result(cx);
    1052             : 
    1053           0 :     JSObject* res = str_split_string(cx, group, str, sep, INT32_MAX);
    1054           0 :     if (!res)
    1055           0 :         return false;
    1056             : 
    1057           0 :     result.setObject(*res);
    1058           0 :     iter.storeInstructionResult(result);
    1059           0 :     return true;
    1060             : }
    1061             : 
    1062             : bool
    1063           0 : MNaNToZero::writeRecoverData(CompactBufferWriter& writer) const
    1064             : {
    1065           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1066           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NaNToZero));
    1067           0 :     return true;
    1068             : }
    1069             : 
    1070           0 : RNaNToZero::RNaNToZero(CompactBufferReader& reader)
    1071           0 : { }
    1072             : 
    1073             : 
    1074             : bool
    1075           0 : RNaNToZero::recover(JSContext* cx, SnapshotIterator& iter) const
    1076             : {
    1077           0 :     RootedValue v(cx, iter.read());
    1078           0 :     RootedValue result(cx);
    1079           0 :     MOZ_ASSERT(v.isDouble() || v.isInt32());
    1080             : 
    1081             :     // x ? x : 0.0
    1082           0 :     if (ToBoolean(v))
    1083           0 :         result = v;
    1084             :     else
    1085           0 :         result.setDouble(0.0);
    1086             : 
    1087           0 :     iter.storeInstructionResult(result);
    1088           0 :     return true;
    1089             : }
    1090             : 
    1091             : bool
    1092           0 : MRegExpMatcher::writeRecoverData(CompactBufferWriter& writer) const
    1093             : {
    1094           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1095           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_RegExpMatcher));
    1096           0 :     return true;
    1097             : }
    1098             : 
    1099           0 : RRegExpMatcher::RRegExpMatcher(CompactBufferReader& reader)
    1100           0 : {}
    1101             : 
    1102             : bool
    1103           0 : RRegExpMatcher::recover(JSContext* cx, SnapshotIterator& iter) const
    1104             : {
    1105           0 :     RootedObject regexp(cx, &iter.read().toObject());
    1106           0 :     RootedString input(cx, iter.read().toString());
    1107           0 :     int32_t lastIndex = iter.read().toInt32();
    1108             : 
    1109           0 :     RootedValue result(cx);
    1110           0 :     if (!RegExpMatcherRaw(cx, regexp, input, lastIndex, nullptr, &result))
    1111           0 :         return false;
    1112             : 
    1113           0 :     iter.storeInstructionResult(result);
    1114           0 :     return true;
    1115             : }
    1116             : 
    1117             : bool
    1118           0 : MRegExpSearcher::writeRecoverData(CompactBufferWriter& writer) const
    1119             : {
    1120           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1121           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_RegExpSearcher));
    1122           0 :     return true;
    1123             : }
    1124             : 
    1125           0 : RRegExpSearcher::RRegExpSearcher(CompactBufferReader& reader)
    1126           0 : {}
    1127             : 
    1128             : bool
    1129           0 : RRegExpSearcher::recover(JSContext* cx, SnapshotIterator& iter) const
    1130             : {
    1131           0 :     RootedObject regexp(cx, &iter.read().toObject());
    1132           0 :     RootedString input(cx, iter.read().toString());
    1133           0 :     int32_t lastIndex = iter.read().toInt32();
    1134             : 
    1135             :     int32_t result;
    1136           0 :     if (!RegExpSearcherRaw(cx, regexp, input, lastIndex, nullptr, &result))
    1137           0 :         return false;
    1138             : 
    1139           0 :     RootedValue resultVal(cx);
    1140           0 :     resultVal.setInt32(result);
    1141           0 :     iter.storeInstructionResult(resultVal);
    1142           0 :     return true;
    1143             : }
    1144             : 
    1145             : bool
    1146           0 : MRegExpTester::writeRecoverData(CompactBufferWriter& writer) const
    1147             : {
    1148           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1149           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_RegExpTester));
    1150           0 :     return true;
    1151             : }
    1152             : 
    1153           0 : RRegExpTester::RRegExpTester(CompactBufferReader& reader)
    1154           0 : { }
    1155             : 
    1156             : bool
    1157           0 : RRegExpTester::recover(JSContext* cx, SnapshotIterator& iter) const
    1158             : {
    1159           0 :     RootedString string(cx, iter.read().toString());
    1160           0 :     RootedObject regexp(cx, &iter.read().toObject());
    1161           0 :     int32_t lastIndex = iter.read().toInt32();
    1162             :     int32_t endIndex;
    1163             : 
    1164           0 :     if (!js::RegExpTesterRaw(cx, regexp, string, lastIndex, &endIndex))
    1165           0 :         return false;
    1166             : 
    1167           0 :     RootedValue result(cx);
    1168           0 :     result.setInt32(endIndex);
    1169           0 :     iter.storeInstructionResult(result);
    1170           0 :     return true;
    1171             : }
    1172             : 
    1173             : bool
    1174           0 : MTypeOf::writeRecoverData(CompactBufferWriter& writer) const
    1175             : {
    1176           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1177           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_TypeOf));
    1178           0 :     return true;
    1179             : }
    1180             : 
    1181           0 : RTypeOf::RTypeOf(CompactBufferReader& reader)
    1182           0 : { }
    1183             : 
    1184             : bool
    1185           0 : RTypeOf::recover(JSContext* cx, SnapshotIterator& iter) const
    1186             : {
    1187           0 :     RootedValue v(cx, iter.read());
    1188             : 
    1189           0 :     RootedValue result(cx, StringValue(TypeOfOperation(v, cx->runtime())));
    1190           0 :     iter.storeInstructionResult(result);
    1191           0 :     return true;
    1192             : }
    1193             : 
    1194             : bool
    1195           0 : MToDouble::writeRecoverData(CompactBufferWriter& writer) const
    1196             : {
    1197           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1198           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ToDouble));
    1199           0 :     return true;
    1200             : }
    1201             : 
    1202           0 : RToDouble::RToDouble(CompactBufferReader& reader)
    1203           0 : { }
    1204             : 
    1205             : bool
    1206           0 : RToDouble::recover(JSContext* cx, SnapshotIterator& iter) const
    1207             : {
    1208           0 :     RootedValue v(cx, iter.read());
    1209           0 :     RootedValue result(cx);
    1210             : 
    1211           0 :     MOZ_ASSERT(!v.isObject());
    1212           0 :     MOZ_ASSERT(!v.isSymbol());
    1213             : 
    1214             :     double dbl;
    1215           0 :     if (!ToNumber(cx, v, &dbl))
    1216           0 :         return false;
    1217             : 
    1218           0 :     result.setDouble(dbl);
    1219           0 :     iter.storeInstructionResult(result);
    1220           0 :     return true;
    1221             : }
    1222             : 
    1223             : bool
    1224           0 : MToFloat32::writeRecoverData(CompactBufferWriter& writer) const
    1225             : {
    1226           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1227           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ToFloat32));
    1228           0 :     return true;
    1229             : }
    1230             : 
    1231           0 : RToFloat32::RToFloat32(CompactBufferReader& reader)
    1232           0 : { }
    1233             : 
    1234             : bool
    1235           0 : RToFloat32::recover(JSContext* cx, SnapshotIterator& iter) const
    1236             : {
    1237           0 :     RootedValue v(cx, iter.read());
    1238           0 :     RootedValue result(cx);
    1239             : 
    1240           0 :     MOZ_ASSERT(!v.isObject());
    1241           0 :     if (!RoundFloat32(cx, v, &result))
    1242           0 :         return false;
    1243             : 
    1244           0 :     iter.storeInstructionResult(result);
    1245           0 :     return true;
    1246             : }
    1247             : 
    1248             : bool
    1249           0 : MTruncateToInt32::writeRecoverData(CompactBufferWriter& writer) const
    1250             : {
    1251           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1252           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_TruncateToInt32));
    1253           0 :     return true;
    1254             : }
    1255             : 
    1256           0 : RTruncateToInt32::RTruncateToInt32(CompactBufferReader& reader)
    1257           0 : { }
    1258             : 
    1259             : bool
    1260           0 : RTruncateToInt32::recover(JSContext* cx, SnapshotIterator& iter) const
    1261             : {
    1262           0 :     RootedValue value(cx, iter.read());
    1263           0 :     RootedValue result(cx);
    1264             : 
    1265             :     int32_t trunc;
    1266           0 :     if (!JS::ToInt32(cx, value, &trunc))
    1267           0 :         return false;
    1268             : 
    1269           0 :     result.setInt32(trunc);
    1270           0 :     iter.storeInstructionResult(result);
    1271           0 :     return true;
    1272             : }
    1273             : 
    1274             : bool
    1275          53 : MNewObject::writeRecoverData(CompactBufferWriter& writer) const
    1276             : {
    1277          53 :     MOZ_ASSERT(canRecoverOnBailout());
    1278          53 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewObject));
    1279          53 :     MOZ_ASSERT(Mode(uint8_t(mode_)) == mode_);
    1280          53 :     writer.writeByte(uint8_t(mode_));
    1281          53 :     return true;
    1282             : }
    1283             : 
    1284           0 : RNewObject::RNewObject(CompactBufferReader& reader)
    1285             : {
    1286           0 :     mode_ = MNewObject::Mode(reader.readByte());
    1287           0 : }
    1288             : 
    1289             : bool
    1290           0 : RNewObject::recover(JSContext* cx, SnapshotIterator& iter) const
    1291             : {
    1292           0 :     RootedObject templateObject(cx, &iter.read().toObject());
    1293           0 :     RootedValue result(cx);
    1294           0 :     JSObject* resultObject = nullptr;
    1295             : 
    1296             :     // See CodeGenerator::visitNewObjectVMCall
    1297           0 :     switch (mode_) {
    1298             :       case MNewObject::ObjectLiteral:
    1299           0 :         resultObject = NewObjectOperationWithTemplate(cx, templateObject);
    1300           0 :         break;
    1301             :       case MNewObject::ObjectCreate:
    1302           0 :         resultObject = ObjectCreateWithTemplate(cx, templateObject.as<PlainObject>());
    1303           0 :         break;
    1304             :     }
    1305             : 
    1306           0 :     if (!resultObject)
    1307           0 :         return false;
    1308             : 
    1309           0 :     result.setObject(*resultObject);
    1310           0 :     iter.storeInstructionResult(result);
    1311           0 :     return true;
    1312             : }
    1313             : 
    1314             : bool
    1315           0 : MNewTypedArray::writeRecoverData(CompactBufferWriter& writer) const
    1316             : {
    1317           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1318           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewTypedArray));
    1319           0 :     return true;
    1320             : }
    1321             : 
    1322           0 : RNewTypedArray::RNewTypedArray(CompactBufferReader& reader)
    1323             : {
    1324           0 : }
    1325             : 
    1326             : bool
    1327           0 : RNewTypedArray::recover(JSContext* cx, SnapshotIterator& iter) const
    1328             : {
    1329           0 :     RootedObject templateObject(cx, &iter.read().toObject());
    1330           0 :     RootedValue result(cx);
    1331             : 
    1332           0 :     uint32_t length = templateObject.as<TypedArrayObject>()->length();
    1333           0 :     JSObject* resultObject = TypedArrayCreateWithTemplate(cx, templateObject, length);
    1334           0 :     if (!resultObject)
    1335           0 :         return false;
    1336             : 
    1337           0 :     result.setObject(*resultObject);
    1338           0 :     iter.storeInstructionResult(result);
    1339           0 :     return true;
    1340             : }
    1341             : 
    1342             : bool
    1343           0 : MNewArray::writeRecoverData(CompactBufferWriter& writer) const
    1344             : {
    1345           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1346           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewArray));
    1347           0 :     writer.writeUnsigned(length());
    1348           0 :     return true;
    1349             : }
    1350             : 
    1351           0 : RNewArray::RNewArray(CompactBufferReader& reader)
    1352             : {
    1353           0 :     count_ = reader.readUnsigned();
    1354           0 : }
    1355             : 
    1356             : bool
    1357           0 : RNewArray::recover(JSContext* cx, SnapshotIterator& iter) const
    1358             : {
    1359           0 :     RootedObject templateObject(cx, &iter.read().toObject());
    1360           0 :     RootedValue result(cx);
    1361           0 :     RootedObjectGroup group(cx, templateObject->group());
    1362             : 
    1363           0 :     JSObject* resultObject = NewFullyAllocatedArrayTryUseGroup(cx, group, count_);
    1364           0 :     if (!resultObject)
    1365           0 :         return false;
    1366             : 
    1367           0 :     result.setObject(*resultObject);
    1368           0 :     iter.storeInstructionResult(result);
    1369           0 :     return true;
    1370             : }
    1371             : 
    1372             : bool
    1373          45 : MNewIterator::writeRecoverData(CompactBufferWriter& writer) const
    1374             : {
    1375          45 :     MOZ_ASSERT(canRecoverOnBailout());
    1376          45 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewIterator));
    1377          45 :     writer.writeByte(type_);
    1378          45 :     return true;
    1379             : }
    1380             : 
    1381           0 : RNewIterator::RNewIterator(CompactBufferReader& reader)
    1382             : {
    1383           0 :     type_ = reader.readByte();
    1384           0 : }
    1385             : 
    1386             : bool
    1387           0 : RNewIterator::recover(JSContext* cx, SnapshotIterator& iter) const
    1388             : {
    1389           0 :     RootedObject templateObject(cx, &iter.read().toObject());
    1390           0 :     RootedValue result(cx);
    1391             : 
    1392           0 :     JSObject* resultObject = nullptr;
    1393           0 :     switch (MNewIterator::Type(type_)) {
    1394             :       case MNewIterator::ArrayIterator:
    1395           0 :         resultObject = NewArrayIteratorObject(cx);
    1396           0 :         break;
    1397             :       case MNewIterator::StringIterator:
    1398           0 :         resultObject = NewStringIteratorObject(cx);
    1399           0 :         break;
    1400             :     }
    1401             : 
    1402           0 :     if (!resultObject)
    1403           0 :         return false;
    1404             : 
    1405           0 :     result.setObject(*resultObject);
    1406           0 :     iter.storeInstructionResult(result);
    1407           0 :     return true;
    1408             : }
    1409             : 
    1410             : bool
    1411           0 : MNewDerivedTypedObject::writeRecoverData(CompactBufferWriter& writer) const
    1412             : {
    1413           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1414           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_NewDerivedTypedObject));
    1415           0 :     return true;
    1416             : }
    1417             : 
    1418           0 : RNewDerivedTypedObject::RNewDerivedTypedObject(CompactBufferReader& reader)
    1419           0 : { }
    1420             : 
    1421             : bool
    1422           0 : RNewDerivedTypedObject::recover(JSContext* cx, SnapshotIterator& iter) const
    1423             : {
    1424           0 :     Rooted<TypeDescr*> descr(cx, &iter.read().toObject().as<TypeDescr>());
    1425           0 :     Rooted<TypedObject*> owner(cx, &iter.read().toObject().as<TypedObject>());
    1426           0 :     int32_t offset = iter.read().toInt32();
    1427             : 
    1428           0 :     JSObject* obj = OutlineTypedObject::createDerived(cx, descr, owner, offset);
    1429           0 :     if (!obj)
    1430           0 :         return false;
    1431             : 
    1432           0 :     RootedValue result(cx, ObjectValue(*obj));
    1433           0 :     iter.storeInstructionResult(result);
    1434           0 :     return true;
    1435             : }
    1436             : 
    1437             : bool
    1438           0 : MCreateThisWithTemplate::writeRecoverData(CompactBufferWriter& writer) const
    1439             : {
    1440           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1441           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_CreateThisWithTemplate));
    1442           0 :     return true;
    1443             : }
    1444             : 
    1445           0 : RCreateThisWithTemplate::RCreateThisWithTemplate(CompactBufferReader& reader)
    1446             : {
    1447           0 : }
    1448             : 
    1449             : bool
    1450           0 : RCreateThisWithTemplate::recover(JSContext* cx, SnapshotIterator& iter) const
    1451             : {
    1452           0 :     RootedObject templateObject(cx, &iter.read().toObject());
    1453             : 
    1454             :     // See CodeGenerator::visitCreateThisWithTemplate
    1455           0 :     JSObject* resultObject = NewObjectOperationWithTemplate(cx, templateObject);
    1456           0 :     if (!resultObject)
    1457           0 :         return false;
    1458             : 
    1459           0 :     RootedValue result(cx);
    1460           0 :     result.setObject(*resultObject);
    1461           0 :     iter.storeInstructionResult(result);
    1462           0 :     return true;
    1463             : }
    1464             : 
    1465             : bool
    1466           0 : MLambda::writeRecoverData(CompactBufferWriter& writer) const
    1467             : {
    1468           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1469           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_Lambda));
    1470           0 :     return true;
    1471             : }
    1472             : 
    1473           0 : RLambda::RLambda(CompactBufferReader& reader)
    1474             : {
    1475           0 : }
    1476             : 
    1477             : bool
    1478           0 : RLambda::recover(JSContext* cx, SnapshotIterator& iter) const
    1479             : {
    1480           0 :     RootedObject scopeChain(cx, &iter.read().toObject());
    1481           0 :     RootedFunction fun(cx, &iter.read().toObject().as<JSFunction>());
    1482             : 
    1483           0 :     JSObject* resultObject = js::Lambda(cx, fun, scopeChain);
    1484           0 :     if (!resultObject)
    1485           0 :         return false;
    1486             : 
    1487           0 :     RootedValue result(cx);
    1488           0 :     result.setObject(*resultObject);
    1489           0 :     iter.storeInstructionResult(result);
    1490           0 :     return true;
    1491             : }
    1492             : 
    1493             : bool
    1494           0 : MLambdaArrow::writeRecoverData(CompactBufferWriter& writer) const
    1495             : {
    1496           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1497           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_LambdaArrow));
    1498           0 :     return true;
    1499             : }
    1500             : 
    1501           0 : RLambdaArrow::RLambdaArrow(CompactBufferReader& reader)
    1502             : {
    1503           0 : }
    1504             : 
    1505             : bool
    1506           0 : RLambdaArrow::recover(JSContext* cx, SnapshotIterator& iter) const
    1507             : {
    1508           0 :     RootedObject scopeChain(cx, &iter.read().toObject());
    1509           0 :     RootedValue newTarget(cx, iter.read());
    1510           0 :     RootedFunction fun(cx, &iter.read().toObject().as<JSFunction>());
    1511             : 
    1512           0 :     JSObject* resultObject = js::LambdaArrow(cx, fun, scopeChain, newTarget);
    1513           0 :     if (!resultObject)
    1514           0 :         return false;
    1515             : 
    1516           0 :     RootedValue result(cx);
    1517           0 :     result.setObject(*resultObject);
    1518           0 :     iter.storeInstructionResult(result);
    1519           0 :     return true;
    1520             : }
    1521             : 
    1522             : bool
    1523           0 : MSimdBox::writeRecoverData(CompactBufferWriter& writer) const
    1524             : {
    1525           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1526           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_SimdBox));
    1527             :     static_assert(unsigned(SimdType::Count) < 0x100, "assuming SimdType fits in 8 bits");
    1528           0 :     writer.writeByte(uint8_t(simdType()));
    1529           0 :     return true;
    1530             : }
    1531             : 
    1532           0 : RSimdBox::RSimdBox(CompactBufferReader& reader)
    1533             : {
    1534           0 :     type_ = reader.readByte();
    1535           0 : }
    1536             : 
    1537             : bool
    1538           0 : RSimdBox::recover(JSContext* cx, SnapshotIterator& iter) const
    1539             : {
    1540           0 :     JSObject* resultObject = nullptr;
    1541           0 :     RValueAllocation a = iter.readAllocation();
    1542           0 :     MOZ_ASSERT(iter.allocationReadable(a));
    1543           0 :     MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG, a.fpuReg().isSimd128());
    1544           0 :     const FloatRegisters::RegisterContent* raw = iter.floatAllocationPointer(a);
    1545           0 :     switch (SimdType(type_)) {
    1546             :       case SimdType::Bool8x16:
    1547           0 :         resultObject = js::CreateSimd<Bool8x16>(cx, (const Bool8x16::Elem*) raw);
    1548           0 :         break;
    1549             :       case SimdType::Int8x16:
    1550           0 :         resultObject = js::CreateSimd<Int8x16>(cx, (const Int8x16::Elem*) raw);
    1551           0 :         break;
    1552             :       case SimdType::Uint8x16:
    1553           0 :         resultObject = js::CreateSimd<Uint8x16>(cx, (const Uint8x16::Elem*) raw);
    1554           0 :         break;
    1555             :       case SimdType::Bool16x8:
    1556           0 :         resultObject = js::CreateSimd<Bool16x8>(cx, (const Bool16x8::Elem*) raw);
    1557           0 :         break;
    1558             :       case SimdType::Int16x8:
    1559           0 :         resultObject = js::CreateSimd<Int16x8>(cx, (const Int16x8::Elem*) raw);
    1560           0 :         break;
    1561             :       case SimdType::Uint16x8:
    1562           0 :         resultObject = js::CreateSimd<Uint16x8>(cx, (const Uint16x8::Elem*) raw);
    1563           0 :         break;
    1564             :       case SimdType::Bool32x4:
    1565           0 :         resultObject = js::CreateSimd<Bool32x4>(cx, (const Bool32x4::Elem*) raw);
    1566           0 :         break;
    1567             :       case SimdType::Int32x4:
    1568           0 :         resultObject = js::CreateSimd<Int32x4>(cx, (const Int32x4::Elem*) raw);
    1569           0 :         break;
    1570             :       case SimdType::Uint32x4:
    1571           0 :         resultObject = js::CreateSimd<Uint32x4>(cx, (const Uint32x4::Elem*) raw);
    1572           0 :         break;
    1573             :       case SimdType::Float32x4:
    1574           0 :         resultObject = js::CreateSimd<Float32x4>(cx, (const Float32x4::Elem*) raw);
    1575           0 :         break;
    1576             :       case SimdType::Float64x2:
    1577           0 :         MOZ_CRASH("NYI, RSimdBox of Float64x2");
    1578             :         break;
    1579             :       case SimdType::Bool64x2:
    1580           0 :         MOZ_CRASH("NYI, RSimdBox of Bool64x2");
    1581             :         break;
    1582             :       case SimdType::Count:
    1583           0 :         MOZ_CRASH("RSimdBox of Count is unreachable");
    1584             :     }
    1585             : 
    1586           0 :     if (!resultObject)
    1587           0 :         return false;
    1588             : 
    1589           0 :     RootedValue result(cx);
    1590           0 :     result.setObject(*resultObject);
    1591           0 :     iter.storeInstructionResult(result);
    1592           0 :     return true;
    1593             : }
    1594             : 
    1595             : bool
    1596          98 : MObjectState::writeRecoverData(CompactBufferWriter& writer) const
    1597             : {
    1598          98 :     MOZ_ASSERT(canRecoverOnBailout());
    1599          98 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ObjectState));
    1600          98 :     writer.writeUnsigned(numSlots());
    1601          98 :     return true;
    1602             : }
    1603             : 
    1604           0 : RObjectState::RObjectState(CompactBufferReader& reader)
    1605             : {
    1606           0 :     numSlots_ = reader.readUnsigned();
    1607           0 : }
    1608             : 
    1609             : bool
    1610           0 : RObjectState::recover(JSContext* cx, SnapshotIterator& iter) const
    1611             : {
    1612           0 :     RootedObject object(cx, &iter.read().toObject());
    1613           0 :     RootedValue val(cx);
    1614             : 
    1615           0 :     if (object->is<UnboxedPlainObject>()) {
    1616           0 :         const UnboxedLayout& layout = object->as<UnboxedPlainObject>().layout();
    1617             : 
    1618           0 :         RootedId id(cx);
    1619           0 :         RootedValue receiver(cx, ObjectValue(*object));
    1620           0 :         const UnboxedLayout::PropertyVector& properties = layout.properties();
    1621           0 :         for (size_t i = 0; i < properties.length(); i++) {
    1622           0 :             val = iter.read();
    1623             : 
    1624             :             // This is the default placeholder value of MObjectState, when no
    1625             :             // properties are defined yet.
    1626           0 :             if (val.isUndefined())
    1627           0 :                 continue;
    1628             : 
    1629           0 :             id = NameToId(properties[i].name);
    1630           0 :             ObjectOpResult result;
    1631             : 
    1632             :             // SetProperty can only fail due to OOM.
    1633           0 :             if (!SetProperty(cx, object, id, val, receiver, result))
    1634           0 :                 return false;
    1635           0 :             if (!result)
    1636           0 :                 return result.reportError(cx, object, id);
    1637             :         }
    1638             :     } else {
    1639           0 :         RootedNativeObject nativeObject(cx, &object->as<NativeObject>());
    1640           0 :         MOZ_ASSERT(nativeObject->slotSpan() == numSlots());
    1641             : 
    1642           0 :         for (size_t i = 0; i < numSlots(); i++) {
    1643           0 :             val = iter.read();
    1644           0 :             nativeObject->setSlot(i, val);
    1645             :         }
    1646             :     }
    1647             : 
    1648           0 :     val.setObject(*object);
    1649           0 :     iter.storeInstructionResult(val);
    1650           0 :     return true;
    1651             : }
    1652             : 
    1653             : bool
    1654           0 : MArrayState::writeRecoverData(CompactBufferWriter& writer) const
    1655             : {
    1656           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1657           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_ArrayState));
    1658           0 :     writer.writeUnsigned(numElements());
    1659           0 :     return true;
    1660             : }
    1661             : 
    1662           0 : RArrayState::RArrayState(CompactBufferReader& reader)
    1663             : {
    1664           0 :     numElements_ = reader.readUnsigned();
    1665           0 : }
    1666             : 
    1667             : bool
    1668           0 : RArrayState::recover(JSContext* cx, SnapshotIterator& iter) const
    1669             : {
    1670           0 :     RootedValue result(cx);
    1671           0 :     ArrayObject* object = &iter.read().toObject().as<ArrayObject>();
    1672           0 :     uint32_t initLength = iter.read().toInt32();
    1673             : 
    1674           0 :     object->setDenseInitializedLength(initLength);
    1675           0 :     for (size_t index = 0; index < numElements(); index++) {
    1676           0 :         Value val = iter.read();
    1677             : 
    1678           0 :         if (index >= initLength) {
    1679           0 :             MOZ_ASSERT(val.isUndefined());
    1680           0 :             continue;
    1681             :         }
    1682             : 
    1683           0 :         object->initDenseElement(index, val);
    1684             :     }
    1685             : 
    1686           0 :     result.setObject(*object);
    1687           0 :     iter.storeInstructionResult(result);
    1688           0 :     return true;
    1689             : }
    1690             : 
    1691             : bool
    1692           0 : MAssertRecoveredOnBailout::writeRecoverData(CompactBufferWriter& writer) const
    1693             : {
    1694           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1695           0 :     MOZ_RELEASE_ASSERT(input()->isRecoveredOnBailout() == mustBeRecovered_,
    1696             :         "assertRecoveredOnBailout failed during compilation");
    1697           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_AssertRecoveredOnBailout));
    1698           0 :     return true;
    1699             : }
    1700             : 
    1701           0 : RAssertRecoveredOnBailout::RAssertRecoveredOnBailout(CompactBufferReader& reader)
    1702           0 : { }
    1703             : 
    1704           0 : bool RAssertRecoveredOnBailout::recover(JSContext* cx, SnapshotIterator& iter) const
    1705             : {
    1706           0 :     RootedValue result(cx);
    1707           0 :     iter.read(); // skip the unused operand.
    1708           0 :     result.setUndefined();
    1709           0 :     iter.storeInstructionResult(result);
    1710           0 :     return true;
    1711             : }
    1712             : 
    1713             : bool
    1714           0 : MStringReplace::writeRecoverData(CompactBufferWriter& writer) const
    1715             : {
    1716           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1717           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_StringReplace));
    1718           0 :     writer.writeByte(isFlatReplacement_);
    1719           0 :     return true;
    1720             : }
    1721             : 
    1722           0 : RStringReplace::RStringReplace(CompactBufferReader& reader)
    1723             : {
    1724           0 :     isFlatReplacement_ = reader.readByte();
    1725           0 : }
    1726             : 
    1727           0 : bool RStringReplace::recover(JSContext* cx, SnapshotIterator& iter) const
    1728             : {
    1729           0 :     RootedString string(cx, iter.read().toString());
    1730           0 :     RootedString pattern(cx, iter.read().toString());
    1731           0 :     RootedString replace(cx, iter.read().toString());
    1732             : 
    1733           0 :     JSString* result = isFlatReplacement_ ? js::str_flat_replace_string(cx, string, pattern, replace) :
    1734           0 :                                             js::str_replace_string_raw(cx, string, pattern, replace);
    1735             : 
    1736           0 :     if (!result)
    1737           0 :         return false;
    1738             : 
    1739           0 :     iter.storeInstructionResult(StringValue(result));
    1740           0 :     return true;
    1741             : }
    1742             : 
    1743             : bool
    1744           0 : MAtomicIsLockFree::writeRecoverData(CompactBufferWriter& writer) const
    1745             : {
    1746           0 :     MOZ_ASSERT(canRecoverOnBailout());
    1747           0 :     writer.writeUnsigned(uint32_t(RInstruction::Recover_AtomicIsLockFree));
    1748           0 :     return true;
    1749             : }
    1750             : 
    1751           0 : RAtomicIsLockFree::RAtomicIsLockFree(CompactBufferReader& reader)
    1752           0 : { }
    1753             : 
    1754             : bool
    1755           0 : RAtomicIsLockFree::recover(JSContext* cx, SnapshotIterator& iter) const
    1756             : {
    1757           0 :     RootedValue operand(cx, iter.read());
    1758           0 :     MOZ_ASSERT(operand.isInt32());
    1759             : 
    1760             :     int32_t result;
    1761           0 :     if (!js::AtomicIsLockFree(cx, operand, &result))
    1762           0 :         return false;
    1763             : 
    1764           0 :     RootedValue rootedResult(cx, js::Int32Value(result));
    1765           0 :     iter.storeInstructionResult(rootedResult);
    1766           0 :     return true;
    1767           9 : }

Generated by: LCOV version 1.13