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-06-02 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       195983721 : GET_UINT8(jsbytecode *pc)
     154                 : {
     155       195983721 :     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       190066876 : GET_JUMP_OFFSET(jsbytecode *pc)
     179                 : {
     180       190066876 :     return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
     181                 : }
     182                 : 
     183                 : static JS_ALWAYS_INLINE void
     184         4911268 : SET_JUMP_OFFSET(jsbytecode *pc, int32_t off)
     185                 : {
     186         4911268 :     pc[1] = (jsbytecode)(off >> 24);
     187         4911268 :     pc[2] = (jsbytecode)(off >> 16);
     188         4911268 :     pc[3] = (jsbytecode)(off >> 8);
     189         4911268 :     pc[4] = (jsbytecode)off;
     190         4911268 : }
     191                 : 
     192                 : #define UINT32_INDEX_LEN        4
     193                 : 
     194                 : static JS_ALWAYS_INLINE uint32_t
     195        78203260 : GET_UINT32_INDEX(const jsbytecode *pc)
     196                 : {
     197        78203260 :     return (pc[1] << 24) | (pc[2] << 16) | (pc[3] << 8) | pc[4];
     198                 : }
     199                 : 
     200                 : static JS_ALWAYS_INLINE void
     201        29083502 : SET_UINT32_INDEX(jsbytecode *pc, uint32_t index)
     202                 : {
     203        29083502 :     pc[1] = (jsbytecode)(index >> 24);
     204        29083502 :     pc[2] = (jsbytecode)(index >> 16);
     205        29083502 :     pc[3] = (jsbytecode)(index >> 8);
     206        29083502 :     pc[4] = (jsbytecode)index;
     207        29083502 : }
     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         2969977 :     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            4794 : DecompileValueGenerator(JSContext *cx, int spindex, const Value &v,
     399                 :                         JSString *fallback)
     400                 : {
     401            4794 :     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         2429979 :         explicit InvariantChecker(const Sprinter *p) : parent(p) {
     415         2429979 :             parent->checkInvariants();
     416         2429979 :         }
     417                 : 
     418         2429979 :         ~InvariantChecker() {
     419         2429979 :             parent->checkInvariants();
     420         2429979 :         }
     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             132 : 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             132 :     JS_ASSERT(size_t(js_CodeSpec[*pc].length) == len);
     497             132 :     return (unsigned) pc[len - 1];
     498                 : }
     499                 : 
     500                 : static inline unsigned
     501      1033028625 : GetBytecodeLength(jsbytecode *pc)
     502                 : {
     503      1033028625 :     JSOp op = (JSOp)*pc;
     504      1033028625 :     JS_ASSERT(op < JSOP_LIMIT);
     505                 : 
     506      1033028625 :     if (js_CodeSpec[op].length != -1)
     507      1033017460 :         return js_CodeSpec[op].length;
     508           11165 :     return js_GetVariableBytecodeLength(pc);
     509                 : }
     510                 : 
     511                 : extern bool
     512                 : IsValidBytecodeOffset(JSContext *cx, JSScript *script, size_t offset);
     513                 : 
     514                 : inline bool
     515         2969977 : 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         2969977 :            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
     525                 :  * a coherent fashion.
     526                 :  */
     527                 : class OpcodeCounts
     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_COUNT
     546                 :     };
     547                 : 
     548                 :     enum AccessCounts {
     549                 :         ACCESS_MONOMORPHIC = BASE_COUNT,
     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_COUNT
     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 || op == JSOP_SETMETHOD)
     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_COUNT,
     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_COUNT
     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_COUNT,
     599                 :         PROP_DEFINITE,
     600                 :         PROP_OTHER,
     601                 : 
     602                 :         PROP_COUNT
     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_COUNT,
     611                 :         ARITH_DOUBLE,
     612                 :         ARITH_OTHER,
     613                 :         ARITH_UNKNOWN,
     614                 : 
     615                 :         ARITH_COUNT
     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_COUNT;
     627               0 :             if (propertyOp(op))
     628               0 :                 return PROP_COUNT;
     629               0 :             return ACCESS_COUNT;
     630                 :         }
     631               0 :         if (arithOp(op))
     632               0 :             return ARITH_COUNT;
     633               0 :         return BASE_COUNT;
     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