js/src/jit/Recover.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/Recover.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,110 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "jit/Recover.h"
    1.11 +
    1.12 +#include "jit/IonSpewer.h"
    1.13 +#include "jit/MIR.h"
    1.14 +#include "jit/MIRGraph.h"
    1.15 +
    1.16 +using namespace js;
    1.17 +using namespace js::jit;
    1.18 +
    1.19 +void
    1.20 +RInstruction::readRecoverData(CompactBufferReader &reader, RInstructionStorage *raw)
    1.21 +{
    1.22 +    uint32_t op = reader.readUnsigned();
    1.23 +    switch (Opcode(op)) {
    1.24 +      case Recover_ResumePoint:
    1.25 +        new (raw->addr()) RResumePoint(reader);
    1.26 +        break;
    1.27 +      default:
    1.28 +        MOZ_ASSUME_UNREACHABLE("Bad decoding of the previous instruction?");
    1.29 +        break;
    1.30 +    }
    1.31 +}
    1.32 +
    1.33 +bool
    1.34 +MResumePoint::writeRecoverData(CompactBufferWriter &writer) const
    1.35 +{
    1.36 +    writer.writeUnsigned(uint32_t(RInstruction::Recover_ResumePoint));
    1.37 +
    1.38 +    MBasicBlock *bb = block();
    1.39 +    JSFunction *fun = bb->info().funMaybeLazy();
    1.40 +    JSScript *script = bb->info().script();
    1.41 +    uint32_t exprStack = stackDepth() - bb->info().ninvoke();
    1.42 +
    1.43 +#ifdef DEBUG
    1.44 +    // Ensure that all snapshot which are encoded can safely be used for
    1.45 +    // bailouts.
    1.46 +    if (GetIonContext()->cx) {
    1.47 +        uint32_t stackDepth;
    1.48 +        bool reachablePC;
    1.49 +        jsbytecode *bailPC = pc();
    1.50 +
    1.51 +        if (mode() == MResumePoint::ResumeAfter)
    1.52 +            bailPC = GetNextPc(pc());
    1.53 +
    1.54 +        if (!ReconstructStackDepth(GetIonContext()->cx, script,
    1.55 +                                   bailPC, &stackDepth, &reachablePC))
    1.56 +        {
    1.57 +            return false;
    1.58 +        }
    1.59 +
    1.60 +        if (reachablePC) {
    1.61 +            if (JSOp(*bailPC) == JSOP_FUNCALL) {
    1.62 +                // For fun.call(this, ...); the reconstructStackDepth will
    1.63 +                // include the this. When inlining that is not included.  So the
    1.64 +                // exprStackSlots will be one less.
    1.65 +                MOZ_ASSERT(stackDepth - exprStack <= 1);
    1.66 +            } else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
    1.67 +                       !IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
    1.68 +            {
    1.69 +                // For fun.apply({}, arguments) the reconstructStackDepth will
    1.70 +                // have stackdepth 4, but it could be that we inlined the
    1.71 +                // funapply. In that case exprStackSlots, will have the real
    1.72 +                // arguments in the slots and not be 4.
    1.73 +
    1.74 +                // With accessors, we have different stack depths depending on
    1.75 +                // whether or not we inlined the accessor, as the inlined stack
    1.76 +                // contains a callee function that should never have been there
    1.77 +                // and we might just be capturing an uneventful property site,
    1.78 +                // in which case there won't have been any violence.
    1.79 +                MOZ_ASSERT(exprStack == stackDepth);
    1.80 +            }
    1.81 +        }
    1.82 +    }
    1.83 +#endif
    1.84 +
    1.85 +    // Test if we honor the maximum of arguments at all times.  This is a sanity
    1.86 +    // check and not an algorithm limit. So check might be a bit too loose.  +4
    1.87 +    // to account for scope chain, return value, this value and maybe
    1.88 +    // arguments_object.
    1.89 +    MOZ_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
    1.90 +
    1.91 +    uint32_t implicit = StartArgSlot(script);
    1.92 +    uint32_t formalArgs = CountArgSlots(script, fun);
    1.93 +    uint32_t nallocs = formalArgs + script->nfixed() + exprStack;
    1.94 +
    1.95 +    IonSpew(IonSpew_Snapshots, "Starting frame; implicit %u, formals %u, fixed %u, exprs %u",
    1.96 +            implicit, formalArgs - implicit, script->nfixed(), exprStack);
    1.97 +
    1.98 +    uint32_t pcoff = script->pcToOffset(pc());
    1.99 +    IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs);
   1.100 +    writer.writeUnsigned(pcoff);
   1.101 +    writer.writeUnsigned(nallocs);
   1.102 +    return true;
   1.103 +}
   1.104 +
   1.105 +RResumePoint::RResumePoint(CompactBufferReader &reader)
   1.106 +{
   1.107 +    static_assert(sizeof(*this) <= sizeof(RInstructionStorage),
   1.108 +                  "Storage space is too small to decode this recover instruction.");
   1.109 +    pcOffset_ = reader.readUnsigned();
   1.110 +    numOperands_ = reader.readUnsigned();
   1.111 +    IonSpew(IonSpew_Snapshots, "Read RResumePoint (pc offset %u, nslots %u)",
   1.112 +            pcOffset_, numOperands_);
   1.113 +}

mercurial