LCOV - app.info - js/src/jsopcode.h

LCOV - code coverage report
| Current view: | directory - js/src - jsopcode.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 66 | 38 | 57.6 %
| Date: | 2012-04-07 | Functions: | 20 | 12 | 60.0 %

           1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  *
           3                 :  * ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           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/
          10                 :  *
          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
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is Mozilla Communicator client code, released
          17                 :  * March 31, 1998.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Netscape Communications Corporation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 1998
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #ifndef jsopcode_h___
          41                 : #define jsopcode_h___
          42                 :
          43                 : /*
          44                 :  * JS bytecode definitions.
          45                 :  */
          46                 : #include <stddef.h>
          47                 : #include "jsprvtd.h"
          48                 : #include "jspubtd.h"
          49                 : #include "jsutil.h"
          50                 :
          51                 : JS_BEGIN_EXTERN_C
          52                 :
          53                 : /*
          54                 :  * JS operation bytecodes.
          55                 :  */
          56                 : typedef enum JSOp {
          57                 : #define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
          58                 :     op = val,
          59                 : #include "jsopcode.tbl"
          60                 : #undef OPDEF
          61                 :     JSOP_LIMIT,
          62                 :
          63                 :     /*
          64                 :      * These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETPROP,
          65                 :      * JSOP_SETELEM, and comprehension-tails, respectively.  They are never
          66                 :      * stored in bytecode, so they don't preempt valid opcodes.
          67                 :      */
          68                 :     JSOP_GETPROP2 = JSOP_LIMIT,
          69                 :     JSOP_GETELEM2 = JSOP_LIMIT + 1,
          70                 :     JSOP_FORLOCAL = JSOP_LIMIT + 2,
          71                 :     JSOP_FAKE_LIMIT = JSOP_FORLOCAL
          72                 : } JSOp;
          73                 :
          74                 : /*
          75                 :  * JS bytecode formats.
          76                 :  */
          77                 : #define JOF_BYTE          0       /* single bytecode, no immediates */
          78                 : #define JOF_JUMP          1       /* signed 16-bit jump offset immediate */
          79                 : #define JOF_ATOM          2       /* unsigned 16-bit constant index */
          80                 : #define JOF_UINT16        3       /* unsigned 16-bit immediate operand */
          81                 : #define JOF_TABLESWITCH   4       /* table switch */
          82                 : #define JOF_LOOKUPSWITCH  5       /* lookup switch */
          83                 : #define JOF_QARG          6       /* quickened get/set function argument ops */
          84                 : #define JOF_LOCAL         7       /* var or block-local variable */
          85                 : #define JOF_DOUBLE        8       /* uint32_t index for double value */
          86                 : #define JOF_UINT24        12      /* extended unsigned 24-bit literal (index) */
          87                 : #define JOF_UINT8         13      /* uint8_t immediate, e.g. top 8 bits of 24-bit
          88                 :                                      atom index */
          89                 : #define JOF_INT32         14      /* int32_t immediate operand */
          90                 : #define JOF_OBJECT        15      /* unsigned 16-bit object index */
          91                 : #define JOF_SLOTOBJECT    16      /* uint16_t slot index + object index */
          92                 : #define JOF_REGEXP        17      /* unsigned 32-bit regexp index */
          93                 : #define JOF_INT8          18      /* int8_t immediate operand */
          94                 : #define JOF_ATOMOBJECT    19      /* uint16_t constant index + object index */
          95                 : #define JOF_UINT16PAIR    20      /* pair of uint16_t immediates */
          96                 : #define JOF_TYPEMASK      0x001f  /* mask for above immediate types */
          97                 :
          98                 : #define JOF_NAME          (1U<<5) /* name operation */
          99                 : #define JOF_PROP          (2U<<5) /* obj.prop operation */
         100                 : #define JOF_ELEM          (3U<<5) /* obj[index] operation */
         101                 : #define JOF_XMLNAME       (4U<<5) /* XML name: *, a::b, @a, @a::b, etc. */
         102                 : #define JOF_VARPROP       (5U<<5) /* x.prop for this, arg, var, or local x */
         103                 : #define JOF_MODEMASK      (7U<<5) /* mask for above addressing modes */
         104                 : #define JOF_SET           (1U<<8) /* set (i.e., assignment) operation */
         105                 : #define JOF_DEL           (1U<<9) /* delete operation */
         106                 : #define JOF_DEC          (1U<<10) /* decrement (--, not ++) opcode */
         107                 : #define JOF_INC          (2U<<10) /* increment (++, not --) opcode */
         108                 : #define JOF_INCDEC       (3U<<10) /* increment or decrement opcode */
         109                 : #define JOF_POST         (1U<<12) /* postorder increment or decrement */
         110                 : #define JOF_ASSIGNING     JOF_SET /* hint for Class.resolve, used for ops
         111                 :                                      that do simplex assignment */
         112                 : #define JOF_DETECTING    (1U<<14) /* object detection for JSNewResolveOp */
         113                 : #define JOF_BACKPATCH    (1U<<15) /* backpatch placeholder during codegen */
         114                 : #define JOF_LEFTASSOC    (1U<<16) /* left-associative operator */
         115                 : #define JOF_DECLARING    (1U<<17) /* var, const, or function declaration op */
         116                 : /* (1U<<18) is unused */
         117                 : #define JOF_PARENHEAD    (1U<<20) /* opcode consumes value of expression in
         118                 :                                      parenthesized statement head */
         119                 : #define JOF_INVOKE       (1U<<21) /* JSOP_CALL, JSOP_NEW, JSOP_EVAL */
         120                 : #define JOF_TMPSLOT      (1U<<22) /* interpreter uses extra temporary slot
         121                 :                                      to root intermediate objects besides
         122                 :                                      the slots opcode uses */
         123                 : #define JOF_TMPSLOT2     (2U<<22) /* interpreter uses extra 2 temporary slot
         124                 :                                      besides the slots opcode uses */
         125                 : #define JOF_TMPSLOT3     (3U<<22) /* interpreter uses extra 3 temporary slot
         126                 :                                      besides the slots opcode uses */
         127                 : #define JOF_TMPSLOT_SHIFT 22
         128                 : #define JOF_TMPSLOT_MASK  (JS_BITMASK(2) << JOF_TMPSLOT_SHIFT)
         129                 :
         130                 : /* (1U<<24) is unused */
         131                 : #define JOF_GNAME        (1U<<25) /* predicted global name */
         132                 : #define JOF_TYPESET      (1U<<26) /* has an entry in a script's type sets */
         133                 : #define JOF_DECOMPOSE    (1U<<27) /* followed by an equivalent decomposed
         134                 :                                    * version of the opcode */
         135                 : #define JOF_ARITH        (1U<<28) /* unary or binary arithmetic opcode */
         136                 :
         137                 : /* Shorthands for type from format and type from opcode. */
         138                 : #define JOF_TYPE(fmt)   ((fmt) & JOF_TYPEMASK)
         139                 : #define JOF_OPTYPE(op)  JOF_TYPE(js_CodeSpec[op].format)
         140                 :
         141                 : /* Shorthands for mode from format and mode from opcode. */
         142                 : #define JOF_MODE(fmt)   ((fmt) & JOF_MODEMASK)
         143                 : #define JOF_OPMODE(op)  JOF_MODE(js_CodeSpec[op].format)
         144                 :
         145                 : #define JOF_TYPE_IS_EXTENDED_JUMP(t) \
         146                 :     ((unsigned)((t) - JOF_JUMP) <= (unsigned)(JOF_LOOKUPSWITCH - JOF_JUMP))
         147                 :
         148                 : /*
         149                 :  * Immediate operand getters, setters, and bounds.
         150                 :  */
         151                 :
         152                 : static JS_ALWAYS_INLINE uint8_t
         153       172151976 : GET_UINT8(jsbytecode *pc)
         154                 : {
         155       172151976 :     return (uint8_t) pc[1];
         156                 : }
         157                 :
         158                 : static JS_ALWAYS_INLINE void
         159                 : SET_UINT8(jsbytecode *pc, uint8_t u)
         160                 : {
         161                 :     pc[1] = (jsbytecode) u;
         162                 : }
         163                 :
         164                 : /* Common uint16_t immediate format helpers. */
         165                 : #define UINT16_LEN              2
         166                 : #define UINT16_HI(i)            ((jsbytecode)((i) >> 8))
         167                 : #define UINT16_LO(i)            ((jsbytecode)(i))
         168                 : #define GET_UINT16(pc)          ((unsigned)(((pc)[1] << 8) | (pc)[2]))
         169                 : #define SET_UINT16(pc,i)        ((pc)[1] = UINT16_HI(i), (pc)[2] = UINT16_LO(i))
         170                 : #define UINT16_LIMIT            ((unsigned)1 << 16)
         171                 :
         172                 : /* Helpers for accessing the offsets of jump opcodes. */
         173                 : #define JUMP_OFFSET_LEN         4
         174                 : #define JUMP_OFFSET_MIN         INT32_MIN
         175                 : #define JUMP_OFFSET_MAX         INT32_MAX
         176                 :
         177                 : static JS_ALWAYS_INLINE int32_t
         178       181998583 : GET_JUMP_OFFSET(jsbytecode *pc)
         179                 : {
         180       181998583 :     return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
         181                 : }
         182                 :
         183                 : static JS_ALWAYS_INLINE void
         184          685677 : SET_JUMP_OFFSET(jsbytecode *pc, int32_t off)
         185                 : {
         186          685677 :     pc[1] = (jsbytecode)(off >> 24);
         187          685677 :     pc[2] = (jsbytecode)(off >> 16);
         188          685677 :     pc[3] = (jsbytecode)(off >> 8);
         189          685677 :     pc[4] = (jsbytecode)off;
         190          685677 : }
         191                 :
         192                 : #define UINT32_INDEX_LEN        4
         193                 :
         194                 : static JS_ALWAYS_INLINE uint32_t
         195        26122759 : GET_UINT32_INDEX(const jsbytecode *pc)
         196                 : {
         197        26122759 :     return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
         198                 : }
         199                 :
         200                 : static JS_ALWAYS_INLINE void
         201         2966390 : SET_UINT32_INDEX(jsbytecode *pc, uint32_t index)
         202                 : {
         203         2966390 :     pc[1] = (jsbytecode)(index >> 24);
         204         2966390 :     pc[2] = (jsbytecode)(index >> 16);
         205         2966390 :     pc[3] = (jsbytecode)(index >> 8);
         206         2966390 :     pc[4] = (jsbytecode)index;
         207         2966390 : }
         208                 :
         209                 : #define UINT24_HI(i)            ((jsbytecode)((i) >> 16))
         210                 : #define UINT24_MID(i)           ((jsbytecode)((i) >> 8))
         211                 : #define UINT24_LO(i)            ((jsbytecode)(i))
         212                 : #define GET_UINT24(pc)          ((jsatomid)(((pc)[1] << 16) |                 \
         213                 :                                             ((pc)[2] << 8) |                  \
         214                 :                                             (pc)[3]))
         215                 : #define SET_UINT24(pc,i)        ((pc)[1] = UINT24_HI(i),                      \
         216                 :                                  (pc)[2] = UINT24_MID(i),                     \
         217                 :                                  (pc)[3] = UINT24_LO(i))
         218                 :
         219                 : #define GET_INT8(pc)            (int8_t((pc)[1]))
         220                 :
         221                 : #define GET_INT32(pc)           (((uint32_t((pc)[1]) << 24) |                 \
         222                 :                                   (uint32_t((pc)[2]) << 16) |                 \
         223                 :                                   (uint32_t((pc)[3]) << 8)  |                 \
         224                 :                                   uint32_t((pc)[4])))
         225                 : #define SET_INT32(pc,i)         ((pc)[1] = (jsbytecode)(uint32_t(i) >> 24),   \
         226                 :                                  (pc)[2] = (jsbytecode)(uint32_t(i) >> 16),   \
         227                 :                                  (pc)[3] = (jsbytecode)(uint32_t(i) >> 8),    \
         228                 :                                  (pc)[4] = (jsbytecode)uint32_t(i))
         229                 :
         230                 : /* Index limit is determined by SN_3BYTE_OFFSET_FLAG, see frontend/BytecodeEmitter.h. */
         231                 : #define INDEX_LIMIT_LOG2        23
         232                 : #define INDEX_LIMIT             (uint32_t(1) << INDEX_LIMIT_LOG2)
         233                 :
         234                 : /* Actual argument count operand format helpers. */
         235                 : #define ARGC_HI(argc)           UINT16_HI(argc)
         236                 : #define ARGC_LO(argc)           UINT16_LO(argc)
         237                 : #define GET_ARGC(pc)            GET_UINT16(pc)
         238                 : #define ARGC_LIMIT              UINT16_LIMIT
         239                 :
         240                 : /* Synonyms for quick JOF_QARG and JOF_LOCAL bytecodes. */
         241                 : #define GET_ARGNO(pc)           GET_UINT16(pc)
         242                 : #define SET_ARGNO(pc,argno)     SET_UINT16(pc,argno)
         243                 : #define ARGNO_LEN               2
         244                 : #define ARGNO_LIMIT             UINT16_LIMIT
         245                 :
         246                 : #define GET_SLOTNO(pc)          GET_UINT16(pc)
         247                 : #define SET_SLOTNO(pc,varno)    SET_UINT16(pc,varno)
         248                 : #define SLOTNO_LEN              2
         249                 : #define SLOTNO_LIMIT            UINT16_LIMIT
         250                 :
         251                 : struct JSCodeSpec {
         252                 :     int8_t              length;         /* length including opcode byte */
         253                 :     int8_t              nuses;          /* arity, -1 if variadic */
         254                 :     int8_t              ndefs;          /* number of stack results */
         255                 :     uint8_t             prec;           /* operator precedence */
         256                 :     uint32_t            format;         /* immediate operand format */
         257                 :
         258         2969784 :     uint32_t type() const { return JOF_TYPE(format); }
         259                 : };
         260                 :
         261                 : extern const JSCodeSpec js_CodeSpec[];
         262                 : extern unsigned            js_NumCodeSpecs;
         263                 : extern const char       *js_CodeName[];
         264                 : extern const char       js_EscapeMap[];
         265                 :
         266                 : /* Silence unreferenced formal parameter warnings */
         267                 : #ifdef _MSC_VER
         268                 : #pragma warning(push)
         269                 : #pragma warning(disable:4100)
         270                 : #endif
         271                 :
         272                 : /*
         273                 :  * Return a GC'ed string containing the chars in str, with any non-printing
         274                 :  * chars or quotes (' or " as specified by the quote argument) escaped, and
         275                 :  * with the quote character at the beginning and end of the result string.
         276                 :  */
         277                 : extern JSString *
         278                 : js_QuoteString(JSContext *cx, JSString *str, jschar quote);
         279                 :
         280                 : /*
         281                 :  * JSPrinter operations, for printf style message formatting.  The return
         282                 :  * value from js_GetPrinterOutput() is the printer's cumulative output, in
         283                 :  * a GC'ed string.
         284                 :  *
         285                 :  * strict is true if the context in which the output will appear has
         286                 :  * already been marked as strict, thus indicating that nested
         287                 :  * functions need not be re-marked with a strict directive.  It should
         288                 :  * be false in the outermost printer.
         289                 :  */
         290                 :
         291                 : extern JSPrinter *
         292                 : js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun,
         293                 :               unsigned indent, JSBool pretty, JSBool grouped, JSBool strict);
         294                 :
         295                 : extern void
         296                 : js_DestroyPrinter(JSPrinter *jp);
         297                 :
         298                 : extern JSString *
         299                 : js_GetPrinterOutput(JSPrinter *jp);
         300                 :
         301                 : extern int
         302                 : js_printf(JSPrinter *jp, const char *format, ...);
         303                 :
         304                 : extern JSBool
         305                 : js_puts(JSPrinter *jp, const char *s);
         306                 :
         307                 : #define GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom)                       \
         308                 :     JS_BEGIN_MACRO                                                            \
         309                 :         JS_ASSERT(js_CodeSpec[*(pc)].format & JOF_ATOM);                      \
         310                 :         (atom) = (script)->getAtom(GET_UINT32_INDEX((pc) + (pcoff)));         \
         311                 :     JS_END_MACRO
         312                 :
         313                 : #define GET_NAME_FROM_BYTECODE(script, pc, pcoff, name)                       \
         314                 :     JS_BEGIN_MACRO                                                            \
         315                 :         JSAtom *atom_;                                                        \
         316                 :         GET_ATOM_FROM_BYTECODE(script, pc, pcoff, atom_);                     \
         317                 :         JS_ASSERT(js_CodeSpec[*(pc)].format & (JOF_NAME | JOF_PROP));         \
         318                 :         (name) = atom_->asPropertyName();                                     \
         319                 :     JS_END_MACRO
         320                 :
         321                 : namespace js {
         322                 :
         323                 : extern unsigned
         324                 : StackUses(JSScript *script, jsbytecode *pc);
         325                 :
         326                 : extern unsigned
         327                 : StackDefs(JSScript *script, jsbytecode *pc);
         328                 :
         329                 : }  /* namespace js */
         330                 :
         331                 : /*
         332                 :  * Decompilers, for script, function, and expression pretty-printing.
         333                 :  */
         334                 : extern JSBool
         335                 : js_DecompileScript(JSPrinter *jp, JSScript *script);
         336                 :
         337                 : extern JSBool
         338                 : js_DecompileFunctionBody(JSPrinter *jp);
         339                 :
         340                 : extern JSBool
         341                 : js_DecompileFunction(JSPrinter *jp);
         342                 :
         343                 : /*
         344                 :  * Some C++ compilers treat the language linkage (extern "C" vs.
         345                 :  * extern "C++") as part of function (and thus pointer-to-function)
         346                 :  * types. The use of this typedef (defined in "C") ensures that
         347                 :  * js_DecompileToString's definition (in "C++") gets matched up with
         348                 :  * this declaration.
         349                 :  */
         350                 : typedef JSBool (* JSDecompilerPtr)(JSPrinter *);
         351                 :
         352                 : extern JSString *
         353                 : js_DecompileToString(JSContext *cx, const char *name, JSFunction *fun,
         354                 :                      unsigned indent, JSBool pretty, JSBool grouped, JSBool strict,
         355                 :                      JSDecompilerPtr decompiler);
         356                 :
         357                 : /*
         358                 :  * Find the source expression that resulted in v, and return a newly allocated
         359                 :  * C-string containing it.  Fall back on v's string conversion (fallback) if we
         360                 :  * can't find the bytecode that generated and pushed v on the operand stack.
         361                 :  *
         362                 :  * Search the current stack frame if spindex is JSDVG_SEARCH_STACK.  Don't
         363                 :  * look for v on the stack if spindex is JSDVG_IGNORE_STACK.  Otherwise,
         364                 :  * spindex is the negative index of v, measured from cx->fp->sp, or from a
         365                 :  * lower frame's sp if cx->fp is native.
         366                 :  *
         367                 :  * The caller must call JS_free on the result after a succsesful call.
         368                 :  */
         369                 : extern char *
         370                 : js_DecompileValueGenerator(JSContext *cx, int spindex, jsval v,
         371                 :                            JSString *fallback);
         372                 :
         373                 : /*
         374                 :  * Given bytecode address pc in script's main program code, return the operand
         375                 :  * stack depth just before (JSOp) *pc executes.
         376                 :  */
         377                 : extern unsigned
         378                 : js_ReconstructStackDepth(JSContext *cx, JSScript *script, jsbytecode *pc);
         379                 :
         380                 : #ifdef _MSC_VER
         381                 : #pragma warning(pop)
         382                 : #endif
         383                 :
         384                 : JS_END_EXTERN_C
         385                 :
         386                 : #define JSDVG_IGNORE_STACK      0
         387                 : #define JSDVG_SEARCH_STACK      1
         388                 :
         389                 : /*
         390                 :  * Get the length of variable-length bytecode like JSOP_TABLESWITCH.
         391                 :  */
         392                 : extern size_t
         393                 : js_GetVariableBytecodeLength(jsbytecode *pc);
         394                 :
         395                 : namespace js {
         396                 :
         397                 : static inline char *
         398            3518 : DecompileValueGenerator(JSContext *cx, int spindex, const Value &v,
         399                 :                         JSString *fallback)
         400                 : {
         401            3518 :     return js_DecompileValueGenerator(cx, spindex, v, fallback);
         402                 : }
         403                 :
         404                 : /*
         405                 :  * Sprintf, but with unlimited and automatically allocated buffering.
         406                 :  */
         407                 : class Sprinter
         408                 : {
         409                 :   public:
         410                 :     struct InvariantChecker
         411                 :     {
         412                 :         const Sprinter *parent;
         413                 :
         414         2490208 :         explicit InvariantChecker(const Sprinter *p) : parent(p) {
         415         2490208 :             parent->checkInvariants();
         416         2490208 :         }
         417                 :
         418         2490208 :         ~InvariantChecker() {
         419         2490208 :             parent->checkInvariants();
         420         2490208 :         }
         421                 :     };
         422                 :
         423                 :     JSContext               *context;       /* context executing the decompiler */
         424                 :
         425                 :   private:
         426                 :     static const size_t     DefaultSize;
         427                 : #ifdef DEBUG
         428                 :     bool                    initialized;    /* true if this is initialized, use for debug builds */
         429                 : #endif
         430                 :     char                    *base;          /* malloc'd buffer address */
         431                 :     size_t                  size;           /* size of buffer allocated at base */
         432                 :     ptrdiff_t               offset;         /* offset of next free char in buffer */
         433                 :
         434                 :     bool realloc_(size_t newSize);
         435                 :
         436                 :   public:
         437                 :     explicit Sprinter(JSContext *cx);
         438                 :     ~Sprinter();
         439                 :
         440                 :     /* Initialize this sprinter, returns false on error */
         441                 :     bool init();
         442                 :
         443                 :     void checkInvariants() const;
         444                 :
         445                 :     const char *string() const;
         446                 :     const char *stringEnd() const;
         447                 :     /* Returns the string at offset |off| */
         448                 :     char *stringAt(ptrdiff_t off) const;
         449                 :     /* Returns the char at offset |off| */
         450                 :     char &operator[](size_t off);
         451                 :     /* Test if this Sprinter is empty */
         452                 :     bool empty() const;
         453                 :
         454                 :     /*
         455                 :      * Attempt to reserve len + 1 space (for a trailing NULL byte). If the
         456                 :      * attempt succeeds, return a pointer to the start of that space and adjust the
         457                 :      * internal content. The caller *must* completely fill this space on success.
         458                 :      */
         459                 :     char *reserve(size_t len);
         460                 :     /* Like reserve, but memory is initialized to 0 */
         461                 :     char *reserveAndClear(size_t len);
         462                 :
         463                 :     /*
         464                 :      * Puts |len| characters from |s| at the current position and return an offset to
         465                 :      * the beginning of this new data
         466                 :      */
         467                 :     ptrdiff_t put(const char *s, size_t len);
         468                 :     ptrdiff_t put(const char *s);
         469                 :     ptrdiff_t putString(JSString *str);
         470                 :
         471                 :     /* Prints a formatted string into the buffer */
         472                 :     int printf(const char *fmt, ...);
         473                 :
         474                 :     /* Change the offset */
         475                 :     void setOffset(const char *end);
         476                 :     void setOffset(ptrdiff_t off);
         477                 :
         478                 :     /* Get the offset */
         479                 :     ptrdiff_t getOffset() const;
         480                 :     ptrdiff_t getOffsetOf(const char *string) const;
         481                 : };
         482                 :
         483                 : extern ptrdiff_t
         484                 : Sprint(Sprinter *sp, const char *format, ...);
         485                 :
         486                 : extern bool
         487                 : CallResultEscapes(jsbytecode *pc);
         488                 :
         489                 : static inline unsigned
         490              63 : GetDecomposeLength(jsbytecode *pc, size_t len)
         491                 : {
         492                 :     /*
         493                 :      * The last byte of a DECOMPOSE op stores the decomposed length.  This is a
         494                 :      * constant: perhaps we should just hardcode values instead?
         495                 :      */
         496              63 :     JS_ASSERT(size_t(js_CodeSpec[*pc].length) == len);
         497              63 :     return (unsigned) pc[len - 1];
         498                 : }
         499                 :
         500                 : static inline unsigned
         501       898282006 : GetBytecodeLength(jsbytecode *pc)
         502                 : {
         503       898282006 :     JSOp op = (JSOp)*pc;
         504       898282006 :     JS_ASSERT(op < JSOP_LIMIT);
         505                 :
         506       898282006 :     if (js_CodeSpec[op].length != -1)
         507       898278294 :         return js_CodeSpec[op].length;
         508            3712 :     return js_GetVariableBytecodeLength(pc);
         509                 : }
         510                 :
         511                 : extern bool
         512                 : IsValidBytecodeOffset(JSContext *cx, JSScript *script, size_t offset);
         513                 :
         514                 : inline bool
         515         2969784 : FlowsIntoNext(JSOp op)
         516                 : {
         517                 :     /* JSOP_YIELD is considered to flow into the next instruction, like JSOP_CALL. */
         518                 :     return op != JSOP_STOP && op != JSOP_RETURN && op != JSOP_RETRVAL && op != JSOP_THROW &&
         519         2969784 :            op != JSOP_GOTO && op != JSOP_RETSUB;
         520                 : }
         521                 :
         522                 : /*
         523                 :  * Counts accumulated for a single opcode in a script. The counts tracked vary
         524                 :  * between opcodes, and this structure ensures that counts are accessed in a
         525                 :  * coherent fashion.
         526                 :  */
         527                 : class PCCounts
         528                 : {
         529                 :     friend struct ::JSScript;
         530                 :     double *counts;
         531                 : #ifdef DEBUG
         532                 :     size_t capacity;
         533                 : #endif
         534                 :
         535                 :  public:
         536                 :
         537                 :     enum BaseCounts {
         538                 :         BASE_INTERP = 0,
         539                 :         BASE_METHODJIT,
         540                 :
         541                 :         BASE_METHODJIT_STUBS,
         542                 :         BASE_METHODJIT_CODE,
         543                 :         BASE_METHODJIT_PICS,
         544                 :
         545                 :         BASE_LIMIT
         546                 :     };
         547                 :
         548                 :     enum AccessCounts {
         549                 :         ACCESS_MONOMORPHIC = BASE_LIMIT,
         550                 :         ACCESS_DIMORPHIC,
         551                 :         ACCESS_POLYMORPHIC,
         552                 :
         553                 :         ACCESS_BARRIER,
         554                 :         ACCESS_NOBARRIER,
         555                 :
         556                 :         ACCESS_UNDEFINED,
         557                 :         ACCESS_NULL,
         558                 :         ACCESS_BOOLEAN,
         559                 :         ACCESS_INT32,
         560                 :         ACCESS_DOUBLE,
         561                 :         ACCESS_STRING,
         562                 :         ACCESS_OBJECT,
         563                 :
         564                 :         ACCESS_LIMIT
         565                 :     };
         566                 :
         567               0 :     static bool accessOp(JSOp op) {
         568                 :         /*
         569                 :          * Access ops include all name, element and property reads, as well as
         570                 :          * SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment).
         571                 :          */
         572               0 :         if (op == JSOP_SETELEM || op == JSOP_SETPROP)
         573               0 :             return true;
         574               0 :         int format = js_CodeSpec[op].format;
         575               0 :         return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP))
         576               0 :             && !(format & (JOF_SET | JOF_INCDEC));
         577                 :     }
         578                 :
         579                 :     enum ElementCounts {
         580                 :         ELEM_ID_INT = ACCESS_LIMIT,
         581                 :         ELEM_ID_DOUBLE,
         582                 :         ELEM_ID_OTHER,
         583                 :         ELEM_ID_UNKNOWN,
         584                 :
         585                 :         ELEM_OBJECT_TYPED,
         586                 :         ELEM_OBJECT_PACKED,
         587                 :         ELEM_OBJECT_DENSE,
         588                 :         ELEM_OBJECT_OTHER,
         589                 :
         590                 :         ELEM_LIMIT
         591                 :     };
         592                 :
         593               0 :     static bool elementOp(JSOp op) {
         594               0 :         return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_ELEM);
         595                 :     }
         596                 :
         597                 :     enum PropertyCounts {
         598                 :         PROP_STATIC = ACCESS_LIMIT,
         599                 :         PROP_DEFINITE,
         600                 :         PROP_OTHER,
         601                 :
         602                 :         PROP_LIMIT
         603                 :     };
         604                 :
         605               0 :     static bool propertyOp(JSOp op) {
         606               0 :         return accessOp(op) && (JOF_MODE(js_CodeSpec[op].format) == JOF_PROP);
         607                 :     }
         608                 :
         609                 :     enum ArithCounts {
         610                 :         ARITH_INT = BASE_LIMIT,
         611                 :         ARITH_DOUBLE,
         612                 :         ARITH_OTHER,
         613                 :         ARITH_UNKNOWN,
         614                 :
         615                 :         ARITH_LIMIT
         616                 :     };
         617                 :
         618               0 :     static bool arithOp(JSOp op) {
         619               0 :         return !!(js_CodeSpec[op].format & (JOF_INCDEC | JOF_ARITH));
         620                 :     }
         621                 :
         622               0 :     static size_t numCounts(JSOp op)
         623                 :     {
         624               0 :         if (accessOp(op)) {
         625               0 :             if (elementOp(op))
         626               0 :                 return ELEM_LIMIT;
         627               0 :             if (propertyOp(op))
         628               0 :                 return PROP_LIMIT;
         629               0 :             return ACCESS_LIMIT;
         630                 :         }
         631               0 :         if (arithOp(op))
         632               0 :             return ARITH_LIMIT;
         633               0 :         return BASE_LIMIT;
         634                 :     }
         635                 :
         636                 :     static const char *countName(JSOp op, size_t which);
         637                 :
         638               0 :     double *rawCounts() { return counts; }
         639                 :
         640               0 :     double& get(size_t which) {
         641               0 :         JS_ASSERT(which < capacity);
         642               0 :         return counts[which];
         643                 :     }
         644                 :
         645                 :     /* Boolean conversion, for 'if (counters) ...' */
         646               0 :     operator void*() const {
         647               0 :         return counts;
         648                 :     }
         649                 : };
         650                 :
         651                 : } /* namespace js */
         652                 :
         653                 : #if defined(DEBUG)
         654                 : /*
         655                 :  * Disassemblers, for debugging only.
         656                 :  */
         657                 : extern JS_FRIEND_API(JSBool)
         658                 : js_Disassemble(JSContext *cx, JSScript *script, JSBool lines, js::Sprinter *sp);
         659                 :
         660                 : extern JS_FRIEND_API(unsigned)
         661                 : js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc, unsigned loc,
         662                 :                 JSBool lines, js::Sprinter *sp);
         663                 :
         664                 : extern JS_FRIEND_API(void)
         665                 : js_DumpPCCounts(JSContext *cx, JSScript *script, js::Sprinter *sp);
         666                 : #endif
         667                 :
         668                 : #endif /* jsopcode_h___ */

Generated by: LCOV version 1.7