1 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil -*- */
2 /* vim: set ts=40 sw=4 et tw=99: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is the Mozilla SpiderMonkey bytecode analysis
18 * The Initial Developer of the Original Code is
20 * Portions created by the Initial Developer are Copyright (C) 2010
21 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* Definitions for javascript analysis. */
41 #ifndef jsanalyze_h___
42 #define jsanalyze_h___
55 /* Information about a bytecode instruction. */
60 /* Whether there are any incoming jumps to this instruction. */
63 /* Whether this instruction has been analyzed to get its output defines and stack. */
66 /* Whether this is a catch/finally entry point. */
67 bool exceptionEntry
: 1;
69 /* Whether this is in a try block. */
72 /* Whether this is a method JIT safe point. */
75 /* Stack depth before this opcode. */
79 * The set of locals defined at this point. This does not include locals which
80 * were unconditionally defined at an earlier point in the script.
91 bool mergeDefines(JSContext
*cx
,
92 Script
*script
, bool initial
, uint32 newDepth
,
93 uint32
*newArray
, uint32 newCount
);
95 /* Whether a local variable is in the define set at this bytecode. */
96 bool isDefined(uint32 slot
)
99 for (size_t ind
= 0; ind
< defineCount
; ind
++) {
100 if (defineArray
[ind
] == slot
)
107 /* Information about a script. */
110 friend struct Bytecode
;
115 /* Maximum number of locals to consider for a script. */
116 static const unsigned LOCAL_LIMIT
= 50;
118 /* Offsets at which each local becomes unconditionally defined, or a value below. */
121 static const uint32 LOCAL_USE_BEFORE_DEF
= uint32(-1);
122 static const uint32 LOCAL_CONDITIONALLY_DEFINED
= uint32(-2);
130 /* Pool for allocating analysis structures which will not outlive this script. */
133 void analyze(JSContext
*cx
, JSScript
*script
);
137 * For analysis scripts allocated on the stack. Scripts don't have constructors,
138 * and must be zeroed out before being used.
140 ~Script() { destroy(); }
142 /* Whether we ran out of memory during analysis. */
143 bool OOM() { return outOfMemory
; }
145 /* Whether the script was analyzed successfully. */
146 bool failed() { return hadFailure
; }
148 /* Whether there are POPV/SETRVAL bytecodes which can write to the frame's rval. */
149 bool usesReturnValue() const { return usesRval
; }
151 /* Whether there are NAME bytecodes which can access the frame's scope chain. */
152 bool usesScopeChain() const { return usesScope
; }
154 /* Accessors for bytecode information. */
156 Bytecode
& getCode(uint32 offset
) {
157 JS_ASSERT(offset
< script
->length
);
158 JS_ASSERT(code
[offset
]);
159 return *code
[offset
];
161 Bytecode
& getCode(jsbytecode
*pc
) { return getCode(pc
- script
->code
); }
163 Bytecode
* maybeCode(uint32 offset
) {
164 JS_ASSERT(offset
< script
->length
);
167 Bytecode
* maybeCode(jsbytecode
*pc
) { return maybeCode(pc
- script
->code
); }
169 bool jumpTarget(uint32 offset
) {
170 JS_ASSERT(offset
< script
->length
);
171 return code
[offset
] && code
[offset
]->jumpTarget
;
173 bool jumpTarget(jsbytecode
*pc
) { return jumpTarget(pc
- script
->code
); }
175 /* Accessors for local variable information. */
177 unsigned localCount() {
178 return (script
->nfixed
>= LOCAL_LIMIT
) ? LOCAL_LIMIT
: script
->nfixed
;
181 bool localHasUseBeforeDef(uint32 local
) {
182 JS_ASSERT(local
< script
->nfixed
&& !failed());
183 return local
>= localCount() || locals
[local
] == LOCAL_USE_BEFORE_DEF
;
186 /* These return true for variables that may have a use before def. */
187 bool localDefined(uint32 local
, uint32 offset
) {
188 return localHasUseBeforeDef(local
) || (locals
[local
] <= offset
) ||
189 getCode(offset
).isDefined(local
);
191 bool localDefined(uint32 local
, jsbytecode
*pc
) {
192 return localDefined(local
, pc
- script
->code
);
196 void setOOM(JSContext
*cx
) {
198 js_ReportOutOfMemory(cx
);
203 inline bool addJump(JSContext
*cx
, unsigned offset
,
204 unsigned *currentOffset
, unsigned *forwardJump
,
205 unsigned stackDepth
, uint32
*defineArray
, unsigned defineCount
);
207 inline void setLocal(uint32 local
, uint32 offset
);
210 } /* namespace analyze */
213 #endif // jsanalyze_h___