js/src/frontend/BytecodeEmitter.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef frontend_BytecodeEmitter_h
     8 #define frontend_BytecodeEmitter_h
    10 /*
    11  * JS bytecode generation.
    12  */
    14 #include "jscntxt.h"
    15 #include "jsopcode.h"
    16 #include "jsscript.h"
    18 #include "frontend/ParseMaps.h"
    19 #include "frontend/SourceNotes.h"
    21 namespace js {
    22 namespace frontend {
    24 class FullParseHandler;
    25 class ObjectBox;
    26 class ParseNode;
    27 template <typename ParseHandler> class Parser;
    28 class SharedContext;
    29 class TokenStream;
    31 class CGConstList {
    32     Vector<Value> list;
    33   public:
    34     CGConstList(ExclusiveContext *cx) : list(cx) {}
    35     bool append(Value v) { JS_ASSERT_IF(v.isString(), v.toString()->isAtom()); return list.append(v); }
    36     size_t length() const { return list.length(); }
    37     void finish(ConstArray *array);
    38 };
    40 struct CGObjectList {
    41     uint32_t            length;     /* number of emitted so far objects */
    42     ObjectBox           *lastbox;   /* last emitted object */
    44     CGObjectList() : length(0), lastbox(nullptr) {}
    46     unsigned add(ObjectBox *objbox);
    47     unsigned indexOf(JSObject *obj);
    48     void finish(ObjectArray *array);
    49     ObjectBox* find(uint32_t index);
    50 };
    52 struct CGTryNoteList {
    53     Vector<JSTryNote> list;
    54     CGTryNoteList(ExclusiveContext *cx) : list(cx) {}
    56     bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
    57     size_t length() const { return list.length(); }
    58     void finish(TryNoteArray *array);
    59 };
    61 struct CGBlockScopeList {
    62     Vector<BlockScopeNote> list;
    63     CGBlockScopeList(ExclusiveContext *cx) : list(cx) {}
    65     bool append(uint32_t scopeObject, uint32_t offset, uint32_t parent);
    66     uint32_t findEnclosingScope(uint32_t index);
    67     void recordEnd(uint32_t index, uint32_t offset);
    68     size_t length() const { return list.length(); }
    69     void finish(BlockScopeArray *array);
    70 };
    72 struct StmtInfoBCE;
    74 // Use zero inline elements because these go on the stack and affect how many
    75 // nested functions are possible.
    76 typedef Vector<jsbytecode, 0> BytecodeVector;
    77 typedef Vector<jssrcnote, 0> SrcNotesVector;
    79 struct BytecodeEmitter
    80 {
    81     typedef StmtInfoBCE StmtInfo;
    83     SharedContext   *const sc;      /* context shared between parsing and bytecode generation */
    85     BytecodeEmitter *const parent;  /* enclosing function or global context */
    87     Rooted<JSScript*> script;       /* the JSScript we're ultimately producing */
    89     struct EmitSection {
    90         BytecodeVector code;        /* bytecode */
    91         SrcNotesVector notes;       /* source notes, see below */
    92         ptrdiff_t   lastNoteOffset; /* code offset for last source note */
    93         uint32_t    currentLine;    /* line number for tree-based srcnote gen */
    94         uint32_t    lastColumn;     /* zero-based column index on currentLine of
    95                                        last SRC_COLSPAN-annotated opcode */
    97         EmitSection(ExclusiveContext *cx, uint32_t lineNum)
    98           : code(cx), notes(cx), lastNoteOffset(0), currentLine(lineNum), lastColumn(0)
    99         {}
   100     };
   101     EmitSection prolog, main, *current;
   103     /* the parser */
   104     Parser<FullParseHandler> *const parser;
   106     HandleScript    evalCaller;     /* scripted caller info for eval and dbgapi */
   108     StmtInfoBCE     *topStmt;       /* top of statement info stack */
   109     StmtInfoBCE     *topScopeStmt;  /* top lexical scope statement */
   110     Rooted<NestedScopeObject *> staticScope;
   111                                     /* compile time scope chain */
   113     OwnedAtomIndexMapPtr atomIndices; /* literals indexed for mapping */
   114     unsigned        firstLine;      /* first line, for JSScript::initFromEmitter */
   116     int32_t         stackDepth;     /* current stack depth in script frame */
   117     uint32_t        maxStackDepth;  /* maximum stack depth so far */
   119     uint32_t        arrayCompDepth; /* stack depth of array in comprehension */
   121     unsigned        emitLevel;      /* js::frontend::EmitTree recursion level */
   123     CGConstList     constList;      /* constants to be included with the script */
   125     CGObjectList    objectList;     /* list of emitted objects */
   126     CGObjectList    regexpList;     /* list of emitted regexp that will be
   127                                        cloned during execution */
   128     CGTryNoteList   tryNoteList;    /* list of emitted try notes */
   129     CGBlockScopeList blockScopeList;/* list of emitted block scope notes */
   131     uint16_t        typesetCount;   /* Number of JOF_TYPESET opcodes generated */
   133     bool            hasSingletons:1;    /* script contains singleton initializer JSOP_OBJECT */
   135     bool            emittingForInit:1;  /* true while emitting init expr of for; exclude 'in' */
   137     bool            emittingRunOnceLambda:1; /* true while emitting a lambda which is only
   138                                                 expected to run once. */
   139     bool            lazyRunOnceLambda:1; /* true while lazily emitting a script for
   140                                           * a lambda which is only expected to run once. */
   142     bool isRunOnceLambda();
   144     bool            insideEval:1;       /* True if compiling an eval-expression or a function
   145                                            nested inside an eval. */
   147     const bool      hasGlobalScope:1;   /* frontend::CompileScript's scope chain is the
   148                                            global object */
   150     enum EmitterMode {
   151         Normal,
   153         /*
   154          * Emit JSOP_GETINTRINSIC instead of JSOP_NAME and assert that
   155          * JSOP_NAME and JSOP_*GNAME don't ever get emitted. See the comment
   156          * for the field |selfHostingMode| in Parser.h for details.
   157          */
   158         SelfHosting,
   160         /*
   161          * Check the static scope chain of the root function for resolving free
   162          * variable accesses in the script.
   163          */
   164         LazyFunction
   165     };
   167     const EmitterMode emitterMode;
   169     /*
   170      * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
   171      * space above their tempMark points. This means that you cannot alloc from
   172      * tempLifoAlloc and save the pointer beyond the next BytecodeEmitter
   173      * destruction.
   174      */
   175     BytecodeEmitter(BytecodeEmitter *parent, Parser<FullParseHandler> *parser, SharedContext *sc,
   176                     HandleScript script, bool insideEval, HandleScript evalCaller,
   177                     bool hasGlobalScope, uint32_t lineNum, EmitterMode emitterMode = Normal);
   178     bool init();
   180     bool isAliasedName(ParseNode *pn);
   182     MOZ_ALWAYS_INLINE
   183     bool makeAtomIndex(JSAtom *atom, jsatomid *indexp) {
   184         AtomIndexAddPtr p = atomIndices->lookupForAdd(atom);
   185         if (p) {
   186             *indexp = p.value();
   187             return true;
   188         }
   190         jsatomid index = atomIndices->count();
   191         if (!atomIndices->add(p, atom, index))
   192             return false;
   194         *indexp = index;
   195         return true;
   196     }
   198     bool isInLoop();
   199     bool checkSingletonContext();
   201     bool needsImplicitThis();
   203     void tellDebuggerAboutCompiledScript(ExclusiveContext *cx);
   205     inline TokenStream *tokenStream();
   207     BytecodeVector &code() const { return current->code; }
   208     jsbytecode *code(ptrdiff_t offset) const { return current->code.begin() + offset; }
   209     ptrdiff_t offset() const { return current->code.end() - current->code.begin(); }
   210     ptrdiff_t prologOffset() const { return prolog.code.end() - prolog.code.begin(); }
   211     void switchToMain() { current = &main; }
   212     void switchToProlog() { current = &prolog; }
   214     SrcNotesVector &notes() const { return current->notes; }
   215     ptrdiff_t lastNoteOffset() const { return current->lastNoteOffset; }
   216     unsigned currentLine() const { return current->currentLine; }
   217     unsigned lastColumn() const { return current->lastColumn; }
   219     bool reportError(ParseNode *pn, unsigned errorNumber, ...);
   220     bool reportStrictWarning(ParseNode *pn, unsigned errorNumber, ...);
   221     bool reportStrictModeError(ParseNode *pn, unsigned errorNumber, ...);
   222 };
   224 /*
   225  * Emit one bytecode.
   226  */
   227 ptrdiff_t
   228 Emit1(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op);
   230 /*
   231  * Emit two bytecodes, an opcode (op) with a byte of immediate operand (op1).
   232  */
   233 ptrdiff_t
   234 Emit2(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1);
   236 /*
   237  * Emit three bytecodes, an opcode with two bytes of immediate operands.
   238  */
   239 ptrdiff_t
   240 Emit3(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, jsbytecode op1, jsbytecode op2);
   242 /*
   243  * Emit (1 + extra) bytecodes, for N bytes of op and its immediate operand.
   244  */
   245 ptrdiff_t
   246 EmitN(ExclusiveContext *cx, BytecodeEmitter *bce, JSOp op, size_t extra);
   248 /*
   249  * Emit code into bce for the tree rooted at pn.
   250  */
   251 bool
   252 EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn);
   254 /*
   255  * Emit function code using bce for the tree rooted at body.
   256  */
   257 bool
   258 EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *body);
   260 /*
   261  * Append a new source note of the given type (and therefore size) to bce's
   262  * notes dynamic array, updating bce->noteCount. Return the new note's index
   263  * within the array pointed at by bce->current->notes. Return -1 if out of
   264  * memory.
   265  */
   266 int
   267 NewSrcNote(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type);
   269 int
   270 NewSrcNote2(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset);
   272 int
   273 NewSrcNote3(ExclusiveContext *cx, BytecodeEmitter *bce, SrcNoteType type, ptrdiff_t offset1,
   274                ptrdiff_t offset2);
   276 /* NB: this function can add at most one extra extended delta note. */
   277 bool
   278 AddToSrcNoteDelta(ExclusiveContext *cx, BytecodeEmitter *bce, jssrcnote *sn, ptrdiff_t delta);
   280 bool
   281 FinishTakingSrcNotes(ExclusiveContext *cx, BytecodeEmitter *bce, uint32_t *out);
   283 void
   284 CopySrcNotes(BytecodeEmitter *bce, jssrcnote *destination, uint32_t nsrcnotes);
   286 } /* namespace frontend */
   287 } /* namespace js */
   289 #endif /* frontend_BytecodeEmitter_h */

mercurial