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 #ifndef jsopcodeinlines_h
8 #define jsopcodeinlines_h
9 
10 #include "jsopcode.h"
11 
12 #include "jsscript.h"
13 
14 namespace js {
15 
16 static inline unsigned
GetDefCount(JSScript * script,unsigned offset)17 GetDefCount(JSScript* script, unsigned offset)
18 {
19     jsbytecode* pc = script->offsetToPC(offset);
20 
21     /*
22      * Add an extra pushed value for OR/AND opcodes, so that they are included
23      * in the pushed array of stack values for type inference.
24      */
25     switch (JSOp(*pc)) {
26       case JSOP_OR:
27       case JSOP_AND:
28         return 1;
29       case JSOP_PICK:
30         /*
31          * Pick pops and pushes how deep it looks in the stack + 1
32          * items. i.e. if the stack were |a b[2] c[1] d[0]|, pick 2
33          * would pop b, c, and d to rearrange the stack to |a c[0]
34          * d[1] b[2]|.
35          */
36         return pc[1] + 1;
37       default:
38         return StackDefs(script, pc);
39     }
40 }
41 
42 static inline unsigned
GetUseCount(JSScript * script,unsigned offset)43 GetUseCount(JSScript* script, unsigned offset)
44 {
45     jsbytecode* pc = script->offsetToPC(offset);
46 
47     if (JSOp(*pc) == JSOP_PICK)
48         return pc[1] + 1;
49     if (CodeSpec[*pc].nuses == -1)
50         return StackUses(script, pc);
51     return CodeSpec[*pc].nuses;
52 }
53 
54 static inline JSOp
ReverseCompareOp(JSOp op)55 ReverseCompareOp(JSOp op)
56 {
57     switch (op) {
58       case JSOP_GT:
59         return JSOP_LT;
60       case JSOP_GE:
61         return JSOP_LE;
62       case JSOP_LT:
63         return JSOP_GT;
64       case JSOP_LE:
65         return JSOP_GE;
66       case JSOP_EQ:
67       case JSOP_NE:
68       case JSOP_STRICTEQ:
69       case JSOP_STRICTNE:
70         return op;
71       default:
72         MOZ_CRASH("unrecognized op");
73     }
74 }
75 
76 static inline JSOp
NegateCompareOp(JSOp op)77 NegateCompareOp(JSOp op)
78 {
79     switch (op) {
80       case JSOP_GT:
81         return JSOP_LE;
82       case JSOP_GE:
83         return JSOP_LT;
84       case JSOP_LT:
85         return JSOP_GE;
86       case JSOP_LE:
87         return JSOP_GT;
88       case JSOP_EQ:
89         return JSOP_NE;
90       case JSOP_NE:
91         return JSOP_EQ;
92       case JSOP_STRICTNE:
93         return JSOP_STRICTEQ;
94       case JSOP_STRICTEQ:
95         return JSOP_STRICTNE;
96       default:
97         MOZ_CRASH("unrecognized op");
98     }
99 }
100 
101 class BytecodeRange {
102   public:
BytecodeRange(JSContext * cx,JSScript * script)103     BytecodeRange(JSContext* cx, JSScript* script)
104       : script(cx, script), pc(script->code()), end(pc + script->length())
105     {}
empty()106     bool empty() const { return pc == end; }
frontPC()107     jsbytecode* frontPC() const { return pc; }
frontOpcode()108     JSOp frontOpcode() const { return JSOp(*pc); }
frontOffset()109     size_t frontOffset() const { return script->pcToOffset(pc); }
popFront()110     void popFront() { pc += GetBytecodeLength(pc); }
111 
112   private:
113     RootedScript script;
114     jsbytecode* pc;
115     jsbytecode* end;
116 };
117 
118 } // namespace js
119 
120 #endif /* jsopcodeinlines_h */
121