📄 jsemit.h
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */#ifndef jsemit_h___#define jsemit_h___/* * JS bytecode generation. */#include "jsstddef.h"#include "jstypes.h"#include "jsatom.h"#include "jsopcode.h"#include "jsprvtd.h"#include "jspubtd.h"JS_BEGIN_EXTERN_C/* * NB: If you add enumerators for scope statements, add them between STMT_WITH * and STMT_CATCH, or you will break the STMT_TYPE_IS_SCOPE macro. If you add * non-looping statement enumerators, add them before STMT_DO_LOOP or you will * break the STMT_TYPE_IS_LOOP macro. * * Also remember to keep the statementName array in jsemit.c in sync. */typedef enum JSStmtType { STMT_LABEL, /* labeled statement: L: s */ STMT_IF, /* if (then) statement */ STMT_ELSE, /* else clause of if statement */ STMT_BODY, /* synthetic body of function with destructuring formal parameters */ STMT_BLOCK, /* compound statement: { s1[;... sN] } */ STMT_SWITCH, /* switch statement */ STMT_WITH, /* with statement */ STMT_CATCH, /* catch block */ STMT_TRY, /* try block */ STMT_FINALLY, /* finally block */ STMT_SUBROUTINE, /* gosub-target subroutine body */ STMT_DO_LOOP, /* do/while loop statement */ STMT_FOR_LOOP, /* for loop statement */ STMT_FOR_IN_LOOP, /* for/in loop statement */ STMT_WHILE_LOOP /* while loop statement */} JSStmtType;#define STMT_TYPE_IN_RANGE(t,b,e) ((uint)((t) - (b)) <= (uintN)((e) - (b)))/* * A comment on the encoding of the JSStmtType enum and type-testing macros: * * STMT_TYPE_MAYBE_SCOPE tells whether a statement type is always, or may * become, a lexical scope. It therefore includes block and switch (the two * low-numbered "maybe" scope types) and excludes with (with has dynamic scope * pending the "reformed with" in ES4/JS2). It includes all try-catch-finally * types, which are high-numbered maybe-scope types. * * STMT_TYPE_LINKS_SCOPE tells whether a JSStmtInfo of the given type eagerly * links to other scoping statement info records. It excludes the two early * "maybe" types, block and switch, as well as the try and both finally types, * since try and the other trailing maybe-scope types don't need block scope * unless they contain let declarations. * * We treat with as a static scope because it prevents lexical binding from * continuing further up the static scope chain. With the "reformed with" * proposal for JS2, we'll be able to model it statically, too. */#define STMT_TYPE_MAYBE_SCOPE(type) \ (type != STMT_WITH && \ STMT_TYPE_IN_RANGE(type, STMT_BLOCK, STMT_SUBROUTINE))#define STMT_TYPE_LINKS_SCOPE(type) \ STMT_TYPE_IN_RANGE(type, STMT_WITH, STMT_CATCH)#define STMT_TYPE_IS_TRYING(type) \ STMT_TYPE_IN_RANGE(type, STMT_TRY, STMT_SUBROUTINE)#define STMT_TYPE_IS_LOOP(type) ((type) >= STMT_DO_LOOP)#define STMT_MAYBE_SCOPE(stmt) STMT_TYPE_MAYBE_SCOPE((stmt)->type)#define STMT_LINKS_SCOPE(stmt) (STMT_TYPE_LINKS_SCOPE((stmt)->type) || \ ((stmt)->flags & SIF_SCOPE))#define STMT_IS_TRYING(stmt) STMT_TYPE_IS_TRYING((stmt)->type)#define STMT_IS_LOOP(stmt) STMT_TYPE_IS_LOOP((stmt)->type)typedef struct JSStmtInfo JSStmtInfo;struct JSStmtInfo { uint16 type; /* statement type */ uint16 flags; /* flags, see below */ ptrdiff_t update; /* loop update offset (top if none) */ ptrdiff_t breaks; /* offset of last break in loop */ ptrdiff_t continues; /* offset of last continue in loop */ JSAtom *atom; /* name of LABEL, or block scope object */ JSStmtInfo *down; /* info for enclosing statement */ JSStmtInfo *downScope; /* next enclosing lexical scope */};#define SIF_SCOPE 0x0001 /* statement has its own lexical scope */#define SIF_BODY_BLOCK 0x0002 /* STMT_BLOCK type is a function body *//* * To reuse space in JSStmtInfo, rename breaks and continues for use during * try/catch/finally code generation and backpatching. To match most common * use cases, the macro argument is a struct, not a struct pointer. Only a * loop, switch, or label statement info record can have breaks and continues, * and only a for loop has an update backpatch chain, so it's safe to overlay * these for the "trying" JSStmtTypes. */#define CATCHNOTE(stmt) ((stmt).update)#define GOSUBS(stmt) ((stmt).breaks)#define GUARDJUMP(stmt) ((stmt).continues)#define AT_TOP_LEVEL(tc) \ (!(tc)->topStmt || ((tc)->topStmt->flags & SIF_BODY_BLOCK))#define SET_STATEMENT_TOP(stmt, top) \ ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))struct JSTreeContext { /* tree context for semantic checks */ uint16 flags; /* statement state flags, see below */ uint16 numGlobalVars; /* max. no. of global variables/regexps */ uint32 tryCount; /* total count of try statements parsed */ uint32 globalUses; /* optimizable global var uses in total */ uint32 loopyGlobalUses;/* optimizable global var uses in loops */ JSStmtInfo *topStmt; /* top of statement info stack */ JSStmtInfo *topScopeStmt; /* top lexical scope statement */ JSObject *blockChain; /* compile time block scope chain (NB: one deeper than the topScopeStmt/downScope chain when in head of let block/expr) */ JSParseNode *blockNode; /* parse node for a lexical scope. XXX combine with blockChain? */ JSAtomList decls; /* function, const, and var declarations */ JSParseNode *nodeList; /* list of recyclable parse-node structs */};#define TCF_COMPILING 0x01 /* generating bytecode; this tc is a cg */#define TCF_IN_FUNCTION 0x02 /* parsing inside function body */#define TCF_RETURN_EXPR 0x04 /* function has 'return expr;' */#define TCF_RETURN_VOID 0x08 /* function has 'return;' */#define TCF_RETURN_FLAGS 0x0C /* propagate these out of blocks */#define TCF_IN_FOR_INIT 0x10 /* parsing init expr of for; exclude 'in' */#define TCF_FUN_CLOSURE_VS_VAR 0x20 /* function and var with same name */#define TCF_FUN_USES_NONLOCALS 0x40 /* function refers to non-local names */#define TCF_FUN_HEAVYWEIGHT 0x80 /* function needs Call object per call */#define TCF_FUN_IS_GENERATOR 0x100 /* parsed yield statement in function */#define TCF_FUN_FLAGS 0x1E0 /* flags to propagate from FunctionBody */#define TCF_HAS_DEFXMLNS 0x200 /* default xml namespace = ...; parsed */#define TCF_HAS_FUNCTION_STMT 0x400 /* block contains a function statement */#define TREE_CONTEXT_INIT(tc) \ ((tc)->flags = (tc)->numGlobalVars = 0, \ (tc)->tryCount = (tc)->globalUses = (tc)->loopyGlobalUses = 0, \ (tc)->topStmt = (tc)->topScopeStmt = NULL, \ (tc)->blockChain = NULL, \ ATOM_LIST_INIT(&(tc)->decls), \ (tc)->nodeList = NULL, (tc)->blockNode = NULL)#define TREE_CONTEXT_FINISH(tc) \ ((void)0)/* * Span-dependent instructions are jumps whose span (from the jump bytecode to * the jump target) may require 2 or 4 bytes of immediate operand. */typedef struct JSSpanDep JSSpanDep;typedef struct JSJumpTarget JSJumpTarget;struct JSSpanDep { ptrdiff_t top; /* offset of first bytecode in an opcode */ ptrdiff_t offset; /* offset - 1 within opcode of jump operand */ ptrdiff_t before; /* original offset - 1 of jump operand */ JSJumpTarget *target; /* tagged target pointer or backpatch delta */};/* * Jump targets are stored in an AVL tree, for O(log(n)) lookup with targets * sorted by offset from left to right, so that targets after a span-dependent * instruction whose jump offset operand must be extended can be found quickly * and adjusted upward (toward higher offsets). */struct JSJumpTarget { ptrdiff_t offset; /* offset of span-dependent jump target */ int balance; /* AVL tree balance number */ JSJumpTarget *kids[2]; /* left and right AVL tree child pointers */};#define JT_LEFT 0#define JT_RIGHT 1#define JT_OTHER_DIR(dir) (1 - (dir))#define JT_IMBALANCE(dir) (((dir) << 1) - 1)#define JT_DIR(imbalance) (((imbalance) + 1) >> 1)/* * Backpatch deltas are encoded in JSSpanDep.target if JT_TAG_BIT is clear, * so we can maintain backpatch chains when using span dependency records to * hold jump offsets that overflow 16 bits. */#define JT_TAG_BIT ((jsword) 1)#define JT_UNTAG_SHIFT 1#define JT_SET_TAG(jt) ((JSJumpTarget *)((jsword)(jt) | JT_TAG_BIT))#define JT_CLR_TAG(jt) ((JSJumpTarget *)((jsword)(jt) & ~JT_TAG_BIT))#define JT_HAS_TAG(jt) ((jsword)(jt) & JT_TAG_BIT)#define BITS_PER_PTRDIFF (sizeof(ptrdiff_t) * JS_BITS_PER_BYTE)#define BITS_PER_BPDELTA (BITS_PER_PTRDIFF - 1 - JT_UNTAG_SHIFT)#define BPDELTA_MAX (((ptrdiff_t)1 << BITS_PER_BPDELTA) - 1)#define BPDELTA_TO_JT(bp) ((JSJumpTarget *)((bp) << JT_UNTAG_SHIFT))#define JT_TO_BPDELTA(jt) ((ptrdiff_t)((jsword)(jt) >> JT_UNTAG_SHIFT))#define SD_SET_TARGET(sd,jt) ((sd)->target = JT_SET_TAG(jt))#define SD_GET_TARGET(sd) (JS_ASSERT(JT_HAS_TAG((sd)->target)), \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -