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 +}