PageRenderTime 140ms CodeModel.GetById 23ms RepoModel.GetById 7ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/jsemit.h

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C++ Header | 777 lines | 402 code | 98 blank | 277 comment | 17 complexity | 38bc47109b221ec5f26bd211a82181ea MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=8 sw=4 et tw=79:
  3. *
  4. * ***** BEGIN LICENSE BLOCK *****
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is Mozilla Communicator client code, released
  18. * March 31, 1998.
  19. *
  20. * The Initial Developer of the Original Code is
  21. * Netscape Communications Corporation.
  22. * Portions created by the Initial Developer are Copyright (C) 1998
  23. * the Initial Developer. All Rights Reserved.
  24. *
  25. * Contributor(s):
  26. *
  27. * Alternatively, the contents of this file may be used under the terms of
  28. * either of the GNU General Public License Version 2 or later (the "GPL"),
  29. * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  30. * in which case the provisions of the GPL or the LGPL are applicable instead
  31. * of those above. If you wish to allow use of your version of this file only
  32. * under the terms of either the GPL or the LGPL, and not to allow others to
  33. * use your version of this file under the terms of the MPL, indicate your
  34. * decision by deleting the provisions above and replace them with the notice
  35. * and other provisions required by the GPL or the LGPL. If you do not delete
  36. * the provisions above, a recipient may use your version of this file under
  37. * the terms of any one of the MPL, the GPL or the LGPL.
  38. *
  39. * ***** END LICENSE BLOCK ***** */
  40. #ifndef jsemit_h___
  41. #define jsemit_h___
  42. /*
  43. * JS bytecode generation.
  44. */
  45. #include "jsstddef.h"
  46. #include "jstypes.h"
  47. #include "jsatom.h"
  48. #include "jsopcode.h"
  49. #include "jsscript.h"
  50. #include "jsprvtd.h"
  51. #include "jspubtd.h"
  52. JS_BEGIN_EXTERN_C
  53. /*
  54. * NB: If you add enumerators for scope statements, add them between STMT_WITH
  55. * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add
  56. * non-looping statement enumerators, add them before STMT_DO_LOOP or you will
  57. * break the STMT_TYPE_IS_LOOP macro.
  58. *
  59. * Also remember to keep the statementName array in jsemit.c in sync.
  60. */
  61. typedef enum JSStmtType {
  62. STMT_LABEL, /* labeled statement: L: s */
  63. STMT_IF, /* if (then) statement */
  64. STMT_ELSE, /* else clause of if statement */
  65. STMT_SEQ, /* synthetic sequence of statements */
  66. STMT_BLOCK, /* compound statement: { s1[;... sN] } */
  67. STMT_SWITCH, /* switch statement */
  68. STMT_WITH, /* with statement */
  69. STMT_CATCH, /* catch block */
  70. STMT_TRY, /* try block */
  71. STMT_FINALLY, /* finally block */
  72. STMT_SUBROUTINE, /* gosub-target subroutine body */
  73. STMT_DO_LOOP, /* do/while loop statement */
  74. STMT_FOR_LOOP, /* for loop statement */
  75. STMT_FOR_IN_LOOP, /* for/in loop statement */
  76. STMT_WHILE_LOOP, /* while loop statement */
  77. STMT_LIMIT
  78. } JSStmtType;
  79. #define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))
  80. /*
  81. * A comment on the encoding of the JSStmtType enum and type-testing macros:
  82. *
  83. * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may
  84. * become, a lexical scope. It therefore includes block and switch (the two
  85. * low-numbered "maybe" scope types) and excludes with (with has dynamic scope
  86. * pending the "reformed with" in ES4/JS2). It includes all try-catch-finally
  87. * types, which are high-numbered maybe-scope types.
  88. *
  89. * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly
  90. * links to other scoping statement info records. It excludes the two early
  91. * "maybe" types, block and switch, as well as the try and both finally types,
  92. * since try and the other trailing maybe-scope types don't need block scope
  93. * unless they contain let declarations.
  94. *
  95. * We treat WITH as a static scope because it prevents lexical binding from
  96. * continuing further up the static scope chain. With the lost "reformed with"
  97. * proposal for ES4, we would be able to model it statically, too.
  98. */
  99. #define STMT_TYPE_MAYBE_SCOPE(type) \
  100. (type != STMT_WITH && \
  101. STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))
  102. #define STMT_TYPE_LINKS_SCOPE(type) \
  103. STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)
  104. #define STMT_TYPE_IS_TRYING(type) \
  105. STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)
  106. #define STMT_TYPE_IS_LOOP(type) ((type) >= STMT_DO_LOOP)
  107. #define STMT_MAYBE_SCOPE(stmt) STMT_TYPE_MAYBE_SCOPE((stmt)->type)
  108. #define STMT_LINKS_SCOPE(stmt) (STMT_TYPE_LINKS_SCOPE((stmt)->type) || \
  109. ((stmt)->flags & SIF_SCOPE))
  110. #define STMT_IS_TRYING(stmt) STMT_TYPE_IS_TRYING((stmt)->type)
  111. #define STMT_IS_LOOP(stmt) STMT_TYPE_IS_LOOP((stmt)->type)
  112. typedef struct JSStmtInfo JSStmtInfo;
  113. struct JSStmtInfo {
  114. uint16 type; /* statement type */
  115. uint16 flags; /* flags, see below */
  116. ptrdiff_t update; /* loop update offset (top if none) */
  117. ptrdiff_t breaks; /* offset of last break in loop */
  118. ptrdiff_t continues; /* offset of last continue in loop */
  119. union {
  120. JSAtom *label; /* name of LABEL */
  121. JSObject *blockObj; /* block scope object */
  122. } u;
  123. JSStmtInfo *down; /* info for enclosing statement */
  124. JSStmtInfo *downScope; /* next enclosing lexical scope */
  125. };
  126. #define SIF_SCOPE 0x0001 /* statement has its own lexical scope */
  127. #define SIF_BODY_BLOCK 0x0002 /* STMT_BLOCK type is a function body */
  128. #define SIF_FOR_BLOCK 0x0004 /* for (let ...) induced block scope */
  129. /*
  130. * To reuse space in JSStmtInfo, rename breaks and continues for use during
  131. * try/catch/finally code generation and backpatching. To match most common
  132. * use cases, the macro argument is a struct, not a struct pointer. Only a
  133. * loop, switch, or label statement info record can have breaks and continues,
  134. * and only a for loop has an update backpatch chain, so it's safe to overlay
  135. * these for the "trying" JSStmtTypes.
  136. */
  137. #define CATCHNOTE(stmt) ((stmt).update)
  138. #define GOSUBS(stmt) ((stmt).breaks)
  139. #define GUARDJUMP(stmt) ((stmt).continues)
  140. #define AT_TOP_LEVEL(tc) \
  141. (!(tc)->topStmt || ((tc)->topStmt->flags & SIF_BODY_BLOCK))
  142. #define SET_STATEMENT_TOP(stmt, top) \
  143. ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
  144. struct JSTreeContext { /* tree context for semantic checks */
  145. uint16 flags; /* statement state flags, see below */
  146. uint16 ngvars; /* max. no. of global variables/regexps */
  147. JSStmtInfo *topStmt; /* top of statement info stack */
  148. JSStmtInfo *topScopeStmt; /* top lexical scope statement */
  149. JSObject *blockChain; /* compile time block scope chain (NB: one
  150. deeper than the topScopeStmt/downScope
  151. chain when in head of let block/expr) */
  152. JSParseNode *blockNode; /* parse node for a lexical scope.
  153. XXX combine with blockChain? */
  154. JSAtomList decls; /* function, const, and var declarations */
  155. JSParseContext *parseContext;
  156. union {
  157. JSFunction *fun; /* function to store argument and variable
  158. names when flags & TCF_IN_FUNCTION */
  159. JSObject *scopeChain; /* scope chain object for the script */
  160. } u;
  161. #ifdef JS_SCOPE_DEPTH_METER
  162. uint16 scopeDepth; /* current lexical scope chain depth */
  163. uint16 maxScopeDepth; /* maximum lexical scope chain depth */
  164. #endif
  165. };
  166. #define TCF_IN_FUNCTION 0x01 /* parsing inside function body */
  167. #define TCF_RETURN_EXPR 0x02 /* function has 'return expr;' */
  168. #define TCF_RETURN_VOID 0x04 /* function has 'return;' */
  169. #define TCF_IN_FOR_INIT 0x08 /* parsing init expr of for; exclude 'in' */
  170. #define TCF_FUN_CLOSURE_VS_VAR 0x10 /* function and var with same name */
  171. #define TCF_FUN_USES_NONLOCALS 0x20 /* function refers to non-local names */
  172. #define TCF_FUN_HEAVYWEIGHT 0x40 /* function needs Call object per call */
  173. #define TCF_FUN_IS_GENERATOR 0x80 /* parsed yield statement in function */
  174. #define TCF_HAS_DEFXMLNS 0x100 /* default xml namespace = ...; parsed */
  175. #define TCF_HAS_FUNCTION_STMT 0x200 /* block contains a function statement */
  176. #define TCF_GENEXP_LAMBDA 0x400 /* flag lambda from generator expression */
  177. #define TCF_COMPILE_N_GO 0x800 /* compiler-and-go mode of script, can
  178. optimize name references based on scope
  179. chain */
  180. #define TCF_NO_SCRIPT_RVAL 0x1000 /* API caller does not want result value
  181. from global script */
  182. /*
  183. * Flags to propagate out of the blocks.
  184. */
  185. #define TCF_RETURN_FLAGS (TCF_RETURN_EXPR | TCF_RETURN_VOID)
  186. /*
  187. * Flags to propagate from FunctionBody.
  188. */
  189. #define TCF_FUN_FLAGS (TCF_FUN_IS_GENERATOR | \
  190. TCF_FUN_HEAVYWEIGHT | \
  191. TCF_FUN_USES_NONLOCALS | \
  192. TCF_FUN_CLOSURE_VS_VAR)
  193. /*
  194. * Flags field, not stored in JSTreeContext.flags, for passing staticDepth
  195. * into js_CompileScript.
  196. */
  197. #define TCF_STATIC_DEPTH_MASK 0xffff0000
  198. #define TCF_GET_STATIC_DEPTH(f) ((uint32)(f) >> 16)
  199. #define TCF_PUT_STATIC_DEPTH(d) ((uint16)(d) << 16)
  200. #ifdef JS_SCOPE_DEPTH_METER
  201. # define JS_SCOPE_DEPTH_METERING(code) ((void) (code))
  202. #else
  203. # define JS_SCOPE_DEPTH_METERING(code) ((void) 0)
  204. #endif
  205. #define TREE_CONTEXT_INIT(tc, pc) \
  206. ((tc)->flags = (tc)->ngvars = 0, \
  207. (tc)->topStmt = (tc)->topScopeStmt = NULL, \
  208. (tc)->blockChain = NULL, \
  209. ATOM_LIST_INIT(&(tc)->decls), \
  210. (tc)->blockNode = NULL, \
  211. (tc)->parseContext = (pc), \
  212. (tc)->u.scopeChain = NULL, \
  213. JS_SCOPE_DEPTH_METERING((tc)->scopeDepth = (tc)->maxScopeDepth = 0))
  214. /*
  215. * For functions TREE_CONTEXT_FINISH is called the second time to finish the
  216. * extra tc created during code generation. We skip stats update in such
  217. * cases.
  218. */
  219. #define TREE_CONTEXT_FINISH(cx, tc) \
  220. JS_SCOPE_DEPTH_METERING( \
  221. (tc)->maxScopeDepth == (uintN) -1 || \
  222. JS_BASIC_STATS_ACCUM(&(cx)->runtime->lexicalScopeDepthStats, \
  223. (tc)->maxScopeDepth))
  224. /*
  225. * Span-dependent instructions are jumps whose span (from the jump bytecode to
  226. * the jump target) may require 2 or 4 bytes of immediate operand.
  227. */
  228. typedef struct JSSpanDep JSSpanDep;
  229. typedef struct JSJumpTarget JSJumpTarget;
  230. struct JSSpanDep {
  231. ptrdiff_t top; /* offset of first bytecode in an opcode */
  232. ptrdiff_t offset; /* offset - 1 within opcode of jump operand */
  233. ptrdiff_t before; /* original offset - 1 of jump operand */
  234. JSJumpTarget *target; /* tagged target pointer or backpatch delta */
  235. };
  236. /*
  237. * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets
  238. * sorted by offset from left to right, so that targets after a span-dependent
  239. * instruction whose jump offset operand must be extended can be found quickly
  240. * and adjusted upward (toward higher offsets).
  241. */
  242. struct JSJumpTarget {
  243. ptrdiff_t offset; /* offset of span-dependent jump target */
  244. int balance; /* AVL tree balance number */
  245. JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */
  246. };
  247. #define JT_LEFT 0
  248. #define JT_RIGHT 1
  249. #define JT_OTHER_DIR(dir) (1 - (dir))
  250. #define JT_IMBALANCE(dir) (((dir) << 1) - 1)
  251. #define JT_DIR(imbalance) (((imbalance) + 1) >> 1)
  252. /*
  253. * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear,
  254. * so we can maintain backpatch chains when using span dependency records to
  255. * hold jump offsets that overflow 16 bits.
  256. */
  257. #define JT_TAG_BIT ((jsword) 1)
  258. #define JT_UNTAG_SHIFT 1
  259. #define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))
  260. #define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))
  261. #define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT)
  262. #define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)
  263. #define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)
  264. #define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)
  265. #define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))
  266. #define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))
  267. #define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt))
  268. #define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \
  269. JT_CLR_TAG((sd)->target))
  270. #define SD_SET_BPDELTA(sd,bp) ((sd)->target = BPDELTA_TO_JT(bp))
  271. #define SD_GET_BPDELTA(sd) (JS_ASSERT(!JT_HAS_TAG((sd)->target)), \
  272. JT_TO_BPDELTA((sd)->target))
  273. /* Avoid asserting twice by expanding SD_GET_TARGET in the "then" clause. */
  274. #define SD_SPAN(sd,pivot) (SD_GET_TARGET(sd) \
  275. ? JT_CLR_TAG((sd)->target)->offset - (pivot) \
  276. : 0)
  277. typedef struct JSTryNode JSTryNode;
  278. struct JSTryNode {
  279. JSTryNote note;
  280. JSTryNode *prev;
  281. };
  282. typedef struct JSEmittedObjectList {
  283. uint32 length; /* number of emitted so far objects */
  284. JSParsedObjectBox *lastPob; /* last emitted object */
  285. } JSEmittedObjectList;
  286. extern void
  287. FinishParsedObjects(JSEmittedObjectList *emittedList, JSObjectArray *objectMap);
  288. struct JSCodeGenerator {
  289. JSTreeContext treeContext; /* base state: statement info stack, etc. */
  290. JSArenaPool *codePool; /* pointer to thread code arena pool */
  291. JSArenaPool *notePool; /* pointer to thread srcnote arena pool */
  292. void *codeMark; /* low watermark in cg->codePool */
  293. void *noteMark; /* low watermark in cg->notePool */
  294. struct {
  295. jsbytecode *base; /* base of JS bytecode vector */
  296. jsbytecode *limit; /* one byte beyond end of bytecode */
  297. jsbytecode *next; /* pointer to next free bytecode */
  298. jssrcnote *notes; /* source notes, see below */
  299. uintN noteCount; /* number of source notes so far */
  300. uintN noteMask; /* growth increment for notes */
  301. ptrdiff_t lastNoteOffset; /* code offset for last source note */
  302. uintN currentLine; /* line number for tree-based srcnote gen */
  303. } prolog, main, *current;
  304. JSAtomList atomList; /* literals indexed for mapping */
  305. uintN firstLine; /* first line, for js_NewScriptFromCG */
  306. intN stackDepth; /* current stack depth in script frame */
  307. uintN maxStackDepth; /* maximum stack depth so far */
  308. uintN ntrynotes; /* number of allocated so far try notes */
  309. JSTryNode *lastTryNode; /* the last allocated try node */
  310. JSSpanDep *spanDeps; /* span dependent instruction records */
  311. JSJumpTarget *jumpTargets; /* AVL tree of jump target offsets */
  312. JSJumpTarget *jtFreeList; /* JT_LEFT-linked list of free structs */
  313. uintN numSpanDeps; /* number of span dependencies */
  314. uintN numJumpTargets; /* number of jump targets */
  315. ptrdiff_t spanDepTodo; /* offset from main.base of potentially
  316. unoptimized spandeps */
  317. uintN arrayCompDepth; /* stack depth of array in comprehension */
  318. uintN emitLevel; /* js_EmitTree recursion level */
  319. JSAtomList constList; /* compile time constants */
  320. JSEmittedObjectList objectList; /* list of emitted so far objects */
  321. JSEmittedObjectList regexpList; /* list of emitted so far regexp
  322. that will be cloned during execution */
  323. uintN staticDepth; /* static frame chain depth */
  324. JSAtomList upvarList; /* map of atoms to upvar indexes */
  325. JSUpvarArray upvarMap; /* indexed upvar pairs (JS_realloc'ed) */
  326. JSCodeGenerator *parent; /* enclosing function or global context */
  327. };
  328. #define CG_TS(cg) TS((cg)->treeContext.parseContext)
  329. #define CG_BASE(cg) ((cg)->current->base)
  330. #define CG_LIMIT(cg) ((cg)->current->limit)
  331. #define CG_NEXT(cg) ((cg)->current->next)
  332. #define CG_CODE(cg,offset) (CG_BASE(cg) + (offset))
  333. #define CG_OFFSET(cg) PTRDIFF(CG_NEXT(cg), CG_BASE(cg), jsbytecode)
  334. #define CG_NOTES(cg) ((cg)->current->notes)
  335. #define CG_NOTE_COUNT(cg) ((cg)->current->noteCount)
  336. #define CG_NOTE_MASK(cg) ((cg)->current->noteMask)
  337. #define CG_LAST_NOTE_OFFSET(cg) ((cg)->current->lastNoteOffset)
  338. #define CG_CURRENT_LINE(cg) ((cg)->current->currentLine)
  339. #define CG_PROLOG_BASE(cg) ((cg)->prolog.base)
  340. #define CG_PROLOG_LIMIT(cg) ((cg)->prolog.limit)
  341. #define CG_PROLOG_NEXT(cg) ((cg)->prolog.next)
  342. #define CG_PROLOG_CODE(cg,poff) (CG_PROLOG_BASE(cg) + (poff))
  343. #define CG_PROLOG_OFFSET(cg) PTRDIFF(CG_PROLOG_NEXT(cg), CG_PROLOG_BASE(cg),\
  344. jsbytecode)
  345. #define CG_SWITCH_TO_MAIN(cg) ((cg)->current = &(cg)->main)
  346. #define CG_SWITCH_TO_PROLOG(cg) ((cg)->current = &(cg)->prolog)
  347. /*
  348. * Initialize cg to allocate bytecode space from codePool, source note space
  349. * from notePool, and all other arena-allocated temporaries from cx->tempPool.
  350. */
  351. extern JS_FRIEND_API(void)
  352. js_InitCodeGenerator(JSContext *cx, JSCodeGenerator *cg, JSParseContext *pc,
  353. JSArenaPool *codePool, JSArenaPool *notePool,
  354. uintN lineno);
  355. /*
  356. * Release cg->codePool, cg->notePool, and cx->tempPool to marks set by
  357. * js_InitCodeGenerator. Note that cgs are magic: they own the arena pool
  358. * "tops-of-stack" space above their codeMark, noteMark, and tempMark points.
  359. * This means you cannot alloc from tempPool and save the pointer beyond the
  360. * next JS_FinishCodeGenerator.
  361. */
  362. extern JS_FRIEND_API(void)
  363. js_FinishCodeGenerator(JSContext *cx, JSCodeGenerator *cg);
  364. /*
  365. * Emit one bytecode.
  366. */
  367. extern ptrdiff_t
  368. js_Emit1(JSContext *cx, JSCodeGenerator *cg, JSOp op);
  369. /*
  370. * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
  371. */
  372. extern ptrdiff_t
  373. js_Emit2(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1);
  374. /*
  375. * Emit three bytecodes, an opcode with two bytes of immediate operands.
  376. */
  377. extern ptrdiff_t
  378. js_Emit3(JSContext *cx, JSCodeGenerator *cg, JSOp op, jsbytecode op1,
  379. jsbytecode op2);
  380. /*
  381. * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
  382. */
  383. extern ptrdiff_t
  384. js_EmitN(JSContext *cx, JSCodeGenerator *cg, JSOp op, size_t extra);
  385. /*
  386. * Unsafe macro to call js_SetJumpOffset and return false if it does.
  387. */
  388. #define CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,BAD_EXIT) \
  389. JS_BEGIN_MACRO \
  390. if (!js_SetJumpOffset(cx, cg, pc, off)) { \
  391. BAD_EXIT; \
  392. } \
  393. JS_END_MACRO
  394. #define CHECK_AND_SET_JUMP_OFFSET(cx,cg,pc,off) \
  395. CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx,cg,pc,off,return JS_FALSE)
  396. #define CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx,cg,off,BAD_EXIT) \
  397. CHECK_AND_SET_JUMP_OFFSET_CUSTOM(cx, cg, CG_CODE(cg,off), \
  398. CG_OFFSET(cg) - (off), BAD_EXIT)
  399. #define CHECK_AND_SET_JUMP_OFFSET_AT(cx,cg,off) \
  400. CHECK_AND_SET_JUMP_OFFSET_AT_CUSTOM(cx, cg, off, return JS_FALSE)
  401. extern JSBool
  402. js_SetJumpOffset(JSContext *cx, JSCodeGenerator *cg, jsbytecode *pc,
  403. ptrdiff_t off);
  404. /* Test whether we're in a statement of given type. */
  405. extern JSBool
  406. js_InStatement(JSTreeContext *tc, JSStmtType type);
  407. /* Test whether we're in a with statement. */
  408. #define js_InWithStatement(tc) js_InStatement(tc, STMT_WITH)
  409. /*
  410. * Push the C-stack-allocated struct at stmt onto the stmtInfo stack.
  411. */
  412. extern void
  413. js_PushStatement(JSTreeContext *tc, JSStmtInfo *stmt, JSStmtType type,
  414. ptrdiff_t top);
  415. /*
  416. * Push a block scope statement and link blockObj into tc->blockChain. To pop
  417. * this statement info record, use js_PopStatement as usual, or if appropriate
  418. * (if generating code), js_PopStatementCG.
  419. */
  420. extern void
  421. js_PushBlockScope(JSTreeContext *tc, JSStmtInfo *stmt, JSObject *blockObj,
  422. ptrdiff_t top);
  423. /*
  424. * Pop tc->topStmt. If the top JSStmtInfo struct is not stack-allocated, it
  425. * is up to the caller to free it.
  426. */
  427. extern void
  428. js_PopStatement(JSTreeContext *tc);
  429. /*
  430. * Like js_PopStatement(&cg->treeContext), also patch breaks and continues
  431. * unless the top statement info record represents a try-catch-finally suite.
  432. * May fail if a jump offset overflows.
  433. */
  434. extern JSBool
  435. js_PopStatementCG(JSContext *cx, JSCodeGenerator *cg);
  436. /*
  437. * Define and lookup a primitive jsval associated with the const named by atom.
  438. * js_DefineCompileTimeConstant analyzes the constant-folded initializer at pn
  439. * and saves the const's value in cg->constList, if it can be used at compile
  440. * time. It returns true unless an error occurred.
  441. *
  442. * If the initializer's value could not be saved, js_DefineCompileTimeConstant
  443. * calls will return the undefined value. js_DefineCompileTimeConstant tries
  444. * to find a const value memorized for atom, returning true with *vp set to a
  445. * value other than undefined if the constant was found, true with *vp set to
  446. * JSVAL_VOID if not found, and false on error.
  447. */
  448. extern JSBool
  449. js_DefineCompileTimeConstant(JSContext *cx, JSCodeGenerator *cg, JSAtom *atom,
  450. JSParseNode *pn);
  451. /*
  452. * Find a lexically scoped variable (one declared by let, catch, or an array
  453. * comprehension) named by atom, looking in tc's compile-time scopes.
  454. *
  455. * If a WITH statement is reached along the scope stack, return its statement
  456. * info record, so callers can tell that atom is ambiguous. If slotp is not
  457. * null, then if atom is found, set *slotp to its stack slot, otherwise to -1.
  458. * This means that if slotp is not null, all the block objects on the lexical
  459. * scope chain must have had their depth slots computed by the code generator,
  460. * so the caller must be under js_EmitTree.
  461. *
  462. * In any event, directly return the statement info record in which atom was
  463. * found. Otherwise return null.
  464. */
  465. extern JSStmtInfo *
  466. js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp);
  467. /*
  468. * Emit code into cg for the tree rooted at pn.
  469. */
  470. extern JSBool
  471. js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn);
  472. /*
  473. * Emit function code using cg for the tree rooted at body.
  474. */
  475. extern JSBool
  476. js_EmitFunctionScript(JSContext *cx, JSCodeGenerator *cg, JSParseNode *body);
  477. /*
  478. * Source notes generated along with bytecode for decompiling and debugging.
  479. * A source note is a uint8 with 5 bits of type and 3 of offset from the pc of
  480. * the previous note. If 3 bits of offset aren't enough, extended delta notes
  481. * (SRC_XDELTA) consisting of 2 set high order bits followed by 6 offset bits
  482. * are emitted before the next note. Some notes have operand offsets encoded
  483. * immediately after them, in note bytes or byte-triples.
  484. *
  485. * Source Note Extended Delta
  486. * +7-6-5-4-3+2-1-0+ +7-6-5+4-3-2-1-0+
  487. * |note-type|delta| |1 1| ext-delta |
  488. * +---------+-----+ +---+-----------+
  489. *
  490. * At most one "gettable" note (i.e., a note of type other than SRC_NEWLINE,
  491. * SRC_SETLINE, and SRC_XDELTA) applies to a given bytecode.
  492. *
  493. * NB: the js_SrcNoteSpec array in jsemit.c is indexed by this enum, so its
  494. * initializers need to match the order here.
  495. *
  496. * Note on adding new source notes: every pair of bytecodes (A, B) where A and
  497. * B have disjoint sets of source notes that could apply to each bytecode may
  498. * reuse the same note type value for two notes (snA, snB) that have the same
  499. * arity, offsetBias, and isSpanDep initializers in js_SrcNoteSpec. This is
  500. * why SRC_IF and SRC_INITPROP have the same value below. For bad historical
  501. * reasons, some bytecodes below that could be overlayed have not been, but
  502. * before using SRC_EXTENDED, consider compressing the existing note types.
  503. *
  504. * Don't forget to update JSXDR_BYTECODE_VERSION in jsxdrapi.h for all such
  505. * incompatible source note or other bytecode changes.
  506. */
  507. typedef enum JSSrcNoteType {
  508. SRC_NULL = 0, /* terminates a note vector */
  509. SRC_IF = 1, /* JSOP_IFEQ bytecode is from an if-then */
  510. SRC_BREAK = 1, /* JSOP_GOTO is a break */
  511. SRC_INITPROP = 1, /* disjoint meaning applied to JSOP_INITELEM or
  512. to an index label in a regular (structuring)
  513. or a destructuring object initialiser */
  514. SRC_GENEXP = 1, /* JSOP_ANONFUNOBJ from generator expression */
  515. SRC_IF_ELSE = 2, /* JSOP_IFEQ bytecode is from an if-then-else */
  516. SRC_FOR_IN = 2, /* JSOP_GOTO to for-in loop condition from
  517. before loop (same arity as SRC_IF_ELSE) */
  518. SRC_FOR = 3, /* JSOP_NOP or JSOP_POP in for(;;) loop head */
  519. SRC_WHILE = 4, /* JSOP_GOTO to for or while loop condition
  520. from before loop, else JSOP_NOP at top of
  521. do-while loop */
  522. SRC_CONTINUE = 5, /* JSOP_GOTO is a continue, not a break;
  523. also used on JSOP_ENDINIT if extra comma
  524. at end of array literal: [1,2,,] */
  525. SRC_DECL = 6, /* type of a declaration (var, const, let*) */
  526. SRC_DESTRUCT = 6, /* JSOP_DUP starting a destructuring assignment
  527. operation, with SRC_DECL_* offset operand */
  528. SRC_PCDELTA = 7, /* distance forward from comma-operator to
  529. next POP, or from CONDSWITCH to first CASE
  530. opcode, etc. -- always a forward delta */
  531. SRC_GROUPASSIGN = 7, /* SRC_DESTRUCT variant for [a, b] = [c, d] */
  532. SRC_ASSIGNOP = 8, /* += or another assign-op follows */
  533. SRC_COND = 9, /* JSOP_IFEQ is from conditional ?: operator */
  534. SRC_BRACE = 10, /* mandatory brace, for scope or to avoid
  535. dangling else */
  536. SRC_HIDDEN = 11, /* opcode shouldn't be decompiled */
  537. SRC_PCBASE = 12, /* distance back from annotated getprop or
  538. setprop op to left-most obj.prop.subprop
  539. bytecode -- always a backward delta */
  540. SRC_LABEL = 13, /* JSOP_NOP for label: with atomid immediate */
  541. SRC_LABELBRACE = 14, /* JSOP_NOP for label: {...} begin brace */
  542. SRC_ENDBRACE = 15, /* JSOP_NOP for label: {...} end brace */
  543. SRC_BREAK2LABEL = 16, /* JSOP_GOTO for 'break label' with atomid */
  544. SRC_CONT2LABEL = 17, /* JSOP_GOTO for 'continue label' with atomid */
  545. SRC_SWITCH = 18, /* JSOP_*SWITCH with offset to end of switch,
  546. 2nd off to first JSOP_CASE if condswitch */
  547. SRC_FUNCDEF = 19, /* JSOP_NOP for function f() with atomid */
  548. SRC_CATCH = 20, /* catch block has guard */
  549. SRC_EXTENDED = 21, /* extended source note, 32-159, in next byte */
  550. SRC_NEWLINE = 22, /* bytecode follows a source newline */
  551. SRC_SETLINE = 23, /* a file-absolute source line number note */
  552. SRC_XDELTA = 24 /* 24-31 are for extended delta notes */
  553. } JSSrcNoteType;
  554. /*
  555. * Constants for the SRC_DECL source note. Note that span-dependent bytecode
  556. * selection means that any SRC_DECL offset greater than SRC_DECL_LET may need
  557. * to be adjusted, but these "offsets" are too small to span a span-dependent
  558. * instruction, so can be used to denote distinct declaration syntaxes to the
  559. * decompiler.
  560. *
  561. * NB: the var_prefix array in jsopcode.c depends on these dense indexes from
  562. * SRC_DECL_VAR through SRC_DECL_LET.
  563. */
  564. #define SRC_DECL_VAR 0
  565. #define SRC_DECL_CONST 1
  566. #define SRC_DECL_LET 2
  567. #define SRC_DECL_NONE 3
  568. #define SN_TYPE_BITS 5
  569. #define SN_DELTA_BITS 3
  570. #define SN_XDELTA_BITS 6
  571. #define SN_TYPE_MASK (JS_BITMASK(SN_TYPE_BITS) << SN_DELTA_BITS)
  572. #define SN_DELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_DELTA_BITS))
  573. #define SN_XDELTA_MASK ((ptrdiff_t)JS_BITMASK(SN_XDELTA_BITS))
  574. #define SN_MAKE_NOTE(sn,t,d) (*(sn) = (jssrcnote) \
  575. (((t) << SN_DELTA_BITS) \
  576. | ((d) & SN_DELTA_MASK)))
  577. #define SN_MAKE_XDELTA(sn,d) (*(sn) = (jssrcnote) \
  578. ((SRC_XDELTA << SN_DELTA_BITS) \
  579. | ((d) & SN_XDELTA_MASK)))
  580. #define SN_IS_XDELTA(sn) ((*(sn) >> SN_DELTA_BITS) >= SRC_XDELTA)
  581. #define SN_TYPE(sn) ((JSSrcNoteType)(SN_IS_XDELTA(sn) \
  582. ? SRC_XDELTA \
  583. : *(sn) >> SN_DELTA_BITS))
  584. #define SN_SET_TYPE(sn,type) SN_MAKE_NOTE(sn, type, SN_DELTA(sn))
  585. #define SN_IS_GETTABLE(sn) (SN_TYPE(sn) < SRC_NEWLINE)
  586. #define SN_DELTA(sn) ((ptrdiff_t)(SN_IS_XDELTA(sn) \
  587. ? *(sn) & SN_XDELTA_MASK \
  588. : *(sn) & SN_DELTA_MASK))
  589. #define SN_SET_DELTA(sn,delta) (SN_IS_XDELTA(sn) \
  590. ? SN_MAKE_XDELTA(sn, delta) \
  591. : SN_MAKE_NOTE(sn, SN_TYPE(sn), delta))
  592. #define SN_DELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_DELTA_BITS))
  593. #define SN_XDELTA_LIMIT ((ptrdiff_t)JS_BIT(SN_XDELTA_BITS))
  594. /*
  595. * Offset fields follow certain notes and are frequency-encoded: an offset in
  596. * [0,0x7f] consumes one byte, an offset in [0x80,0x7fffff] takes three, and
  597. * the high bit of the first byte is set.
  598. */
  599. #define SN_3BYTE_OFFSET_FLAG 0x80
  600. #define SN_3BYTE_OFFSET_MASK 0x7f
  601. typedef struct JSSrcNoteSpec {
  602. const char *name; /* name for disassembly/debugging output */
  603. int8 arity; /* number of offset operands */
  604. uint8 offsetBias; /* bias of offset(s) from annotated pc */
  605. int8 isSpanDep; /* 1 or -1 if offsets could span extended ops,
  606. 0 otherwise; sign tells span direction */
  607. } JSSrcNoteSpec;
  608. extern JS_FRIEND_DATA(JSSrcNoteSpec) js_SrcNoteSpec[];
  609. extern JS_FRIEND_API(uintN) js_SrcNoteLength(jssrcnote *sn);
  610. #define SN_LENGTH(sn) ((js_SrcNoteSpec[SN_TYPE(sn)].arity == 0) ? 1 \
  611. : js_SrcNoteLength(sn))
  612. #define SN_NEXT(sn) ((sn) + SN_LENGTH(sn))
  613. /* A source note array is terminated by an all-zero element. */
  614. #define SN_MAKE_TERMINATOR(sn) (*(sn) = SRC_NULL)
  615. #define SN_IS_TERMINATOR(sn) (*(sn) == SRC_NULL)
  616. /*
  617. * Append a new source note of the given type (and therefore size) to cg's
  618. * notes dynamic array, updating cg->noteCount. Return the new note's index
  619. * within the array pointed at by cg->current->notes. Return -1 if out of
  620. * memory.
  621. */
  622. extern intN
  623. js_NewSrcNote(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type);
  624. extern intN
  625. js_NewSrcNote2(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
  626. ptrdiff_t offset);
  627. extern intN
  628. js_NewSrcNote3(JSContext *cx, JSCodeGenerator *cg, JSSrcNoteType type,
  629. ptrdiff_t offset1, ptrdiff_t offset2);
  630. /*
  631. * NB: this function can add at most one extra extended delta note.
  632. */
  633. extern jssrcnote *
  634. js_AddToSrcNoteDelta(JSContext *cx, JSCodeGenerator *cg, jssrcnote *sn,
  635. ptrdiff_t delta);
  636. /*
  637. * Get and set the offset operand identified by which (0 for the first, etc.).
  638. */
  639. extern JS_FRIEND_API(ptrdiff_t)
  640. js_GetSrcNoteOffset(jssrcnote *sn, uintN which);
  641. extern JSBool
  642. js_SetSrcNoteOffset(JSContext *cx, JSCodeGenerator *cg, uintN index,
  643. uintN which, ptrdiff_t offset);
  644. /*
  645. * Finish taking source notes in cx's notePool, copying final notes to the new
  646. * stable store allocated by the caller and passed in via notes. Return false
  647. * on malloc failure, which means this function reported an error.
  648. *
  649. * To compute the number of jssrcnotes to allocate and pass in via notes, use
  650. * the CG_COUNT_FINAL_SRCNOTES macro. This macro knows a lot about details of
  651. * js_FinishTakingSrcNotes, SO DON'T CHANGE jsemit.c's js_FinishTakingSrcNotes
  652. * FUNCTION WITHOUT CHECKING WHETHER THIS MACRO NEEDS CORRESPONDING CHANGES!
  653. */
  654. #define CG_COUNT_FINAL_SRCNOTES(cg, cnt) \
  655. JS_BEGIN_MACRO \
  656. ptrdiff_t diff_ = CG_PROLOG_OFFSET(cg) - (cg)->prolog.lastNoteOffset; \
  657. cnt = (cg)->prolog.noteCount + (cg)->main.noteCount + 1; \
  658. if ((cg)->prolog.noteCount && \
  659. (cg)->prolog.currentLine != (cg)->firstLine) { \
  660. if (diff_ > SN_DELTA_MASK) \
  661. cnt += JS_HOWMANY(diff_ - SN_DELTA_MASK, SN_XDELTA_MASK); \
  662. cnt += 2 + (((cg)->firstLine > SN_3BYTE_OFFSET_MASK) << 1); \
  663. } else if (diff_ > 0) { \
  664. if (cg->main.noteCount) { \
  665. jssrcnote *sn_ = (cg)->main.notes; \
  666. diff_ -= SN_IS_XDELTA(sn_) \
  667. ? SN_XDELTA_MASK - (*sn_ & SN_XDELTA_MASK) \
  668. : SN_DELTA_MASK - (*sn_ & SN_DELTA_MASK); \
  669. } \
  670. if (diff_ > 0) \
  671. cnt += JS_HOWMANY(diff_, SN_XDELTA_MASK); \
  672. } \
  673. JS_END_MACRO
  674. extern JSBool
  675. js_FinishTakingSrcNotes(JSContext *cx, JSCodeGenerator *cg, jssrcnote *notes);
  676. extern void
  677. js_FinishTakingTryNotes(JSCodeGenerator *cg, JSTryNoteArray *array);
  678. JS_END_EXTERN_C
  679. #endif /* jsemit_h___ */