js/src/jit/Recover.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "jit/Recover.h"
michael@0 8
michael@0 9 #include "jit/IonSpewer.h"
michael@0 10 #include "jit/MIR.h"
michael@0 11 #include "jit/MIRGraph.h"
michael@0 12
michael@0 13 using namespace js;
michael@0 14 using namespace js::jit;
michael@0 15
michael@0 16 void
michael@0 17 RInstruction::readRecoverData(CompactBufferReader &reader, RInstructionStorage *raw)
michael@0 18 {
michael@0 19 uint32_t op = reader.readUnsigned();
michael@0 20 switch (Opcode(op)) {
michael@0 21 case Recover_ResumePoint:
michael@0 22 new (raw->addr()) RResumePoint(reader);
michael@0 23 break;
michael@0 24 default:
michael@0 25 MOZ_ASSUME_UNREACHABLE("Bad decoding of the previous instruction?");
michael@0 26 break;
michael@0 27 }
michael@0 28 }
michael@0 29
michael@0 30 bool
michael@0 31 MResumePoint::writeRecoverData(CompactBufferWriter &writer) const
michael@0 32 {
michael@0 33 writer.writeUnsigned(uint32_t(RInstruction::Recover_ResumePoint));
michael@0 34
michael@0 35 MBasicBlock *bb = block();
michael@0 36 JSFunction *fun = bb->info().funMaybeLazy();
michael@0 37 JSScript *script = bb->info().script();
michael@0 38 uint32_t exprStack = stackDepth() - bb->info().ninvoke();
michael@0 39
michael@0 40 #ifdef DEBUG
michael@0 41 // Ensure that all snapshot which are encoded can safely be used for
michael@0 42 // bailouts.
michael@0 43 if (GetIonContext()->cx) {
michael@0 44 uint32_t stackDepth;
michael@0 45 bool reachablePC;
michael@0 46 jsbytecode *bailPC = pc();
michael@0 47
michael@0 48 if (mode() == MResumePoint::ResumeAfter)
michael@0 49 bailPC = GetNextPc(pc());
michael@0 50
michael@0 51 if (!ReconstructStackDepth(GetIonContext()->cx, script,
michael@0 52 bailPC, &stackDepth, &reachablePC))
michael@0 53 {
michael@0 54 return false;
michael@0 55 }
michael@0 56
michael@0 57 if (reachablePC) {
michael@0 58 if (JSOp(*bailPC) == JSOP_FUNCALL) {
michael@0 59 // For fun.call(this, ...); the reconstructStackDepth will
michael@0 60 // include the this. When inlining that is not included. So the
michael@0 61 // exprStackSlots will be one less.
michael@0 62 MOZ_ASSERT(stackDepth - exprStack <= 1);
michael@0 63 } else if (JSOp(*bailPC) != JSOP_FUNAPPLY &&
michael@0 64 !IsGetPropPC(bailPC) && !IsSetPropPC(bailPC))
michael@0 65 {
michael@0 66 // For fun.apply({}, arguments) the reconstructStackDepth will
michael@0 67 // have stackdepth 4, but it could be that we inlined the
michael@0 68 // funapply. In that case exprStackSlots, will have the real
michael@0 69 // arguments in the slots and not be 4.
michael@0 70
michael@0 71 // With accessors, we have different stack depths depending on
michael@0 72 // whether or not we inlined the accessor, as the inlined stack
michael@0 73 // contains a callee function that should never have been there
michael@0 74 // and we might just be capturing an uneventful property site,
michael@0 75 // in which case there won't have been any violence.
michael@0 76 MOZ_ASSERT(exprStack == stackDepth);
michael@0 77 }
michael@0 78 }
michael@0 79 }
michael@0 80 #endif
michael@0 81
michael@0 82 // Test if we honor the maximum of arguments at all times. This is a sanity
michael@0 83 // check and not an algorithm limit. So check might be a bit too loose. +4
michael@0 84 // to account for scope chain, return value, this value and maybe
michael@0 85 // arguments_object.
michael@0 86 MOZ_ASSERT(CountArgSlots(script, fun) < SNAPSHOT_MAX_NARGS + 4);
michael@0 87
michael@0 88 uint32_t implicit = StartArgSlot(script);
michael@0 89 uint32_t formalArgs = CountArgSlots(script, fun);
michael@0 90 uint32_t nallocs = formalArgs + script->nfixed() + exprStack;
michael@0 91
michael@0 92 IonSpew(IonSpew_Snapshots, "Starting frame; implicit %u, formals %u, fixed %u, exprs %u",
michael@0 93 implicit, formalArgs - implicit, script->nfixed(), exprStack);
michael@0 94
michael@0 95 uint32_t pcoff = script->pcToOffset(pc());
michael@0 96 IonSpew(IonSpew_Snapshots, "Writing pc offset %u, nslots %u", pcoff, nallocs);
michael@0 97 writer.writeUnsigned(pcoff);
michael@0 98 writer.writeUnsigned(nallocs);
michael@0 99 return true;
michael@0 100 }
michael@0 101
michael@0 102 RResumePoint::RResumePoint(CompactBufferReader &reader)
michael@0 103 {
michael@0 104 static_assert(sizeof(*this) <= sizeof(RInstructionStorage),
michael@0 105 "Storage space is too small to decode this recover instruction.");
michael@0 106 pcOffset_ = reader.readUnsigned();
michael@0 107 numOperands_ = reader.readUnsigned();
michael@0 108 IonSpew(IonSpew_Snapshots, "Read RResumePoint (pc offset %u, nslots %u)",
michael@0 109 pcOffset_, numOperands_);
michael@0 110 }

mercurial