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