LCOV - code coverage report
Current view: directory - js/src - jsfun.h (source / functions) Found Hit Coverage
Test: app.info Lines: 52 52 100.0 %
Date: 2012-06-02 Functions: 25 25 100.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 jsfun_h___
      41                 : #define jsfun_h___
      42                 : /*
      43                 :  * JS function definitions.
      44                 :  */
      45                 : #include "jsprvtd.h"
      46                 : #include "jspubtd.h"
      47                 : #include "jsobj.h"
      48                 : #include "jsatom.h"
      49                 : #include "jsscript.h"
      50                 : #include "jsstr.h"
      51                 : 
      52                 : #include "gc/Barrier.h"
      53                 : 
      54                 : /*
      55                 :  * The high two bits of JSFunction.flags encode whether the function is native
      56                 :  * or interpreted, and if interpreted, what kind of optimized closure form (if
      57                 :  * any) it might be.
      58                 :  *
      59                 :  *   00   not interpreted
      60                 :  *   01   interpreted, neither flat nor null closure
      61                 :  *   10   interpreted, flat closure
      62                 :  *   11   interpreted, null closure
      63                 :  *
      64                 :  * isFlatClosure() implies isInterpreted() and u.i.script->upvarsOffset != 0.
      65                 :  * isNullClosure() implies isInterpreted() and u.i.script->upvarsOffset == 0.
      66                 :  *
      67                 :  * isInterpreted() but not isFlatClosure() and u.i.script->upvarsOffset != 0
      68                 :  * is an Algol-like function expression or nested function, i.e., a function
      69                 :  * that never escapes upward or downward (heapward), and is only ever called.
      70                 :  *
      71                 :  * Finally, isInterpreted() and u.i.script->upvarsOffset == 0 could be either
      72                 :  * a non-closure (a global function definition, or any function that uses no
      73                 :  * outer names), or a closure of an escaping function that uses outer names
      74                 :  * whose values can't be snapshot (because the outer names could be reassigned
      75                 :  * after the closure is formed, or because assignments could not be analyzed
      76                 :  * due to with or eval).
      77                 :  *
      78                 :  * Such a hard-case function must use JSOP_NAME, etc., and reify outer function
      79                 :  * activations' call objects, etc. if it's not a global function.
      80                 :  *
      81                 :  * NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
      82                 :  * bit only, never stored in fun->flags.
      83                 :  *
      84                 :  * If we need more bits in the future, all flags for interpreted functions can
      85                 :  * move to u.i.script->flags. For now we use function flag bits to minimize
      86                 :  * pointer-chasing.
      87                 :  */
      88                 : // 0x0001 was JSFUN_JOINABLE, but was deleted for bug 739808.
      89                 : #define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
      90                 :                                        global object */
      91                 : 
      92                 : #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
      93                 : #define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
      94                 : #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.n */
      95                 : #define JSFUN_FLAT_CLOSURE  0x8000  /* flat (aka "display") closure */
      96                 : #define JSFUN_NULL_CLOSURE  0xc000  /* null closure entrains no scope chain */
      97                 : #define JSFUN_KINDMASK      0xc000  /* encode interp vs. native and closure
      98                 :                                        optimization level -- see above */
      99                 : 
     100                 : namespace js { class FunctionExtended; }
     101                 : 
     102                 : struct JSFunction : public JSObject
     103                 : {
     104                 :     uint16_t        nargs;        /* maximum number of specified arguments,
     105                 :                                      reflected as f.length/f.arity */
     106                 :     uint16_t        flags;        /* flags, see JSFUN_* below and in jsapi.h */
     107                 :     union U {
     108                 :         struct Native {
     109                 :             js::Native  native;   /* native method pointer or null */
     110                 :             js::Class   *clasp;   /* class of objects constructed
     111                 :                                      by this function */
     112                 :         } n;
     113                 :         struct Scripted {
     114                 :             JSScript    *script_; /* interpreted bytecode descriptor or null;
     115                 :                                      use the accessor! */
     116                 :             JSObject    *env_;    /* environment for new activations;
     117                 :                                      use the accessor! */
     118                 :         } i;
     119                 :         void            *nativeOrScript;
     120                 :     } u;
     121                 :     JSAtom          *atom;        /* name for diagnostics and decompiling */
     122                 : 
     123                 :     bool optimizedClosure()  const { return kind() > JSFUN_INTERPRETED; }
     124      1755728364 :     bool isInterpreted()     const { return kind() >= JSFUN_INTERPRETED; }
     125        51426890 :     bool isNative()          const { return !isInterpreted(); }
     126          220923 :     bool isNativeConstructor() const { return flags & JSFUN_CONSTRUCTOR; }
     127        44956295 :     bool isHeavyweight()     const { return JSFUN_HEAVYWEIGHT_TEST(flags); }
     128         2200455 :     bool isNullClosure()     const { return kind() == JSFUN_NULL_CLOSURE; }
     129        65804583 :     bool isFlatClosure()     const { return kind() == JSFUN_FLAT_CLOSURE; }
     130        13319219 :     bool isFunctionPrototype() const { return flags & JSFUN_PROTOTYPE; }
     131        24247117 :     bool isInterpretedConstructor() const { return isInterpreted() && !isFunctionPrototype(); }
     132                 : 
     133      1825758607 :     uint16_t kind()          const { return flags & JSFUN_KINDMASK; }
     134          809715 :     void setKind(uint16_t k) {
     135          809715 :         JS_ASSERT(!(k & ~JSFUN_KINDMASK));
     136          809715 :         flags = (flags & ~JSFUN_KINDMASK) | k;
     137          809715 :     }
     138                 : 
     139                 :     /* Returns the strictness of this function, which must be interpreted. */
     140                 :     inline bool inStrictMode() const;
     141                 : 
     142          991083 :     void setArgCount(uint16_t nargs) {
     143          991083 :         JS_ASSERT(this->nargs == 0);
     144          991083 :         this->nargs = nargs;
     145          991083 :     }
     146                 : 
     147                 :     /* uint16_t representation bounds number of call object dynamic slots. */
     148                 :     enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
     149                 : 
     150                 : #define JS_LOCAL_NAME_TO_ATOM(nameWord)  ((JSAtom *) ((nameWord) & ~uintptr_t(1)))
     151                 : #define JS_LOCAL_NAME_IS_CONST(nameWord) ((((nameWord) & uintptr_t(1))) != 0)
     152                 : 
     153                 :     bool mightEscape() const {
     154                 :         return isInterpreted() && (isFlatClosure() || !script()->bindings.hasUpvars());
     155                 :     }
     156                 : 
     157             606 :     bool joinable() const {
     158             606 :         return false;
     159                 :     }
     160                 : 
     161                 :     /*
     162                 :      * For an interpreted function, accessors for the initial scope object of
     163                 :      * activations (stack frames) of the function.
     164                 :      */
     165                 :     inline JSObject *environment() const;
     166                 :     inline void setEnvironment(JSObject *obj);
     167                 :     inline void initEnvironment(JSObject *obj);
     168                 : 
     169           47585 :     static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
     170                 : 
     171      1501606268 :     js::HeapPtrScript &script() const {
     172      1501606268 :         JS_ASSERT(isInterpreted());
     173      1501606268 :         return *(js::HeapPtrScript *)&u.i.script_;
     174                 :     }
     175                 : 
     176                 :     inline void setScript(JSScript *script_);
     177                 :     inline void initScript(JSScript *script_);
     178                 : 
     179         1868089 :     JSScript *maybeScript() const {
     180         1868089 :         return isInterpreted() ? script().get() : NULL;
     181                 :     }
     182                 : 
     183          388490 :     JSNative native() const {
     184          388490 :         JS_ASSERT(isNative());
     185          388490 :         return u.n.native;
     186                 :     }
     187                 : 
     188          351473 :     JSNative maybeNative() const {
     189          351473 :         return isInterpreted() ? NULL : native();
     190                 :     }
     191                 : 
     192            5719 :     static unsigned offsetOfNativeOrScript() {
     193                 :         JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, i.script_));
     194                 :         JS_STATIC_ASSERT(offsetof(U, n.native) == offsetof(U, nativeOrScript));
     195            5719 :         return offsetof(JSFunction, u.nativeOrScript);
     196                 :     }
     197                 : 
     198                 :     js::Class *getConstructorClass() const {
     199                 :         JS_ASSERT(isNative());
     200                 :         return u.n.clasp;
     201                 :     }
     202                 : 
     203          391372 :     void setConstructorClass(js::Class *clasp) {
     204          391372 :         JS_ASSERT(isNative());
     205          391372 :         u.n.clasp = clasp;
     206          391372 :     }
     207                 : 
     208                 : #if JS_BITS_PER_WORD == 32
     209                 :     static const js::gc::AllocKind FinalizeKind = js::gc::FINALIZE_OBJECT2;
     210                 :     static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::FINALIZE_OBJECT4;
     211                 : #else
     212                 :     static const js::gc::AllocKind FinalizeKind = js::gc::FINALIZE_OBJECT4;
     213                 :     static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::FINALIZE_OBJECT8;
     214                 : #endif
     215                 : 
     216                 :     inline void trace(JSTracer *trc);
     217                 : 
     218                 :     /* Bound function accessors. */
     219                 : 
     220                 :     inline bool initBoundFunction(JSContext *cx, const js::Value &thisArg,
     221                 :                                   const js::Value *args, unsigned argslen);
     222                 : 
     223                 :     inline JSObject *getBoundFunctionTarget() const;
     224                 :     inline const js::Value &getBoundFunctionThis() const;
     225                 :     inline const js::Value &getBoundFunctionArgument(unsigned which) const;
     226                 :     inline size_t getBoundFunctionArgumentCount() const;
     227                 : 
     228                 :   private:
     229                 :     inline js::FunctionExtended *toExtended();
     230                 :     inline const js::FunctionExtended *toExtended() const;
     231                 : 
     232       132433030 :     inline bool isExtended() const {
     233                 :         JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind);
     234       132433030 :         JS_ASSERT(!!(flags & JSFUN_EXTENDED) == (getAllocKind() == ExtendedFinalizeKind));
     235       132433030 :         return !!(flags & JSFUN_EXTENDED);
     236                 :     }
     237                 : 
     238                 :   public:
     239                 :     /* Accessors for data stored in extended functions. */
     240                 : 
     241                 :     inline void initializeExtended();
     242                 : 
     243                 :     inline void setExtendedSlot(size_t which, const js::Value &val);
     244                 :     inline const js::Value &getExtendedSlot(size_t which) const;
     245                 : 
     246                 :     /*
     247                 :      * Flat closures with one or more upvars snapshot the upvars' values
     248                 :      * into a vector of js::Values referenced from here. This is a private
     249                 :      * pointer but is set only at creation and does not need to be barriered.
     250                 :      */
     251                 :     static const uint32_t FLAT_CLOSURE_UPVARS_SLOT = 0;
     252                 : 
     253                 :     static inline size_t getFlatClosureUpvarsOffset();
     254                 : 
     255                 :     inline js::Value getFlatClosureUpvar(uint32_t i) const;
     256                 :     inline void setFlatClosureUpvar(uint32_t i, const js::Value &v);
     257                 :     inline void initFlatClosureUpvar(uint32_t i, const js::Value &v);
     258                 : 
     259                 :   private:
     260                 :     inline bool hasFlatClosureUpvars() const;
     261                 :     inline js::HeapValue *getFlatClosureUpvars() const;
     262                 :   public:
     263                 : 
     264                 :     /* See comments in fun_finalize. */
     265                 :     inline void finalizeUpvars();
     266                 : 
     267                 :     /* Slot holding associated method property, needed for foo.caller handling. */
     268                 :     static const uint32_t METHOD_PROPERTY_SLOT = 0;
     269                 : 
     270                 :     /* For cloned methods, slot holding the object this was cloned as a property from. */
     271                 :     static const uint32_t METHOD_OBJECT_SLOT = 1;
     272                 : 
     273                 :     /* Whether this is a function cloned from a method. */
     274                 :     inline bool isClonedMethod() const;
     275                 : 
     276                 :     /* For a cloned method, pointer to the object the method was cloned for. */
     277                 :     inline JSObject *methodObj() const;
     278                 :     inline void setMethodObj(JSObject& obj);
     279                 : 
     280                 :     /*
     281                 :      * Method name imputed from property uniquely assigned to or initialized,
     282                 :      * where the function does not need to be cloned to carry a scope chain or
     283                 :      * flattened upvars. This is set on both the original and cloned function.
     284                 :      */
     285                 :     inline JSAtom *methodAtom() const;
     286                 :     inline void setMethodAtom(JSAtom *atom);
     287                 : 
     288                 :     /*
     289                 :      * Measures things hanging off this JSFunction that are counted by the
     290                 :      * |miscSize| argument in JSObject::sizeOfExcludingThis().
     291                 :      */
     292                 :     size_t sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const;
     293                 : 
     294                 :   private:
     295                 :     /* 
     296                 :      * These member functions are inherited from JSObject, but should never be applied to
     297                 :      * a value statically known to be a JSFunction.
     298                 :      */
     299                 :     inline JSFunction *toFunction() MOZ_DELETE;
     300                 :     inline const JSFunction *toFunction() const MOZ_DELETE;
     301                 : };
     302                 : 
     303                 : inline JSFunction *
     304       258430158 : JSObject::toFunction()
     305                 : {
     306       258430158 :     JS_ASSERT(JS_ObjectIsFunction(NULL, this));
     307       258430158 :     return static_cast<JSFunction *>(this);
     308                 : }
     309                 : 
     310                 : inline const JSFunction *
     311           16046 : JSObject::toFunction() const
     312                 : {
     313           16046 :     JS_ASSERT(JS_ObjectIsFunction(NULL, const_cast<JSObject *>(this)));
     314           16046 :     return static_cast<const JSFunction *>(this);
     315                 : }
     316                 : 
     317                 : extern JSString *
     318                 : fun_toStringHelper(JSContext *cx, JSObject *obj, unsigned indent);
     319                 : 
     320                 : extern JSFunction *
     321                 : js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, unsigned nargs,
     322                 :                unsigned flags, js::HandleObject parent, JSAtom *atom,
     323                 :                js::gc::AllocKind kind = JSFunction::FinalizeKind);
     324                 : 
     325                 : extern JSFunction * JS_FASTCALL
     326                 : js_CloneFunctionObject(JSContext *cx, JSFunction *fun, JSObject *parent, JSObject *proto,
     327                 :                        js::gc::AllocKind kind = JSFunction::FinalizeKind);
     328                 : 
     329                 : extern JSFunction * JS_FASTCALL
     330                 : js_AllocFlatClosure(JSContext *cx, JSFunction *fun, JSObject *scopeChain);
     331                 : 
     332                 : extern JSFunction *
     333                 : js_NewFlatClosure(JSContext *cx, JSFunction *fun);
     334                 : 
     335                 : extern JSFunction *
     336                 : js_DefineFunction(JSContext *cx, js::HandleObject obj, jsid id, JSNative native,
     337                 :                   unsigned nargs, unsigned flags,
     338                 :                   js::gc::AllocKind kind = JSFunction::FinalizeKind);
     339                 : 
     340                 : /*
     341                 :  * Flags for js_ValueToFunction and js_ReportIsNotFunction.
     342                 :  */
     343                 : #define JSV2F_CONSTRUCT         INITIAL_CONSTRUCT
     344                 : #define JSV2F_SEARCH_STACK      0x10000
     345                 : 
     346                 : extern JSFunction *
     347                 : js_ValueToFunction(JSContext *cx, const js::Value *vp, unsigned flags);
     348                 : 
     349                 : extern JSObject *
     350                 : js_ValueToCallableObject(JSContext *cx, js::Value *vp, unsigned flags);
     351                 : 
     352                 : extern void
     353                 : js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, unsigned flags);
     354                 : 
     355                 : extern void
     356                 : js_PutCallObject(js::StackFrame *fp);
     357                 : 
     358                 : namespace js {
     359                 : 
     360                 : /*
     361                 :  * Function extended with reserved slots for use by various kinds of functions.
     362                 :  * Most functions do not have these extensions, but enough are that efficient
     363                 :  * storage is required (no malloc'ed reserved slots).
     364                 :  */
     365                 : class FunctionExtended : public JSFunction
     366                 : {
     367                 :     friend struct JSFunction;
     368                 : 
     369                 :     /* Reserved slots available for storage by particular native functions. */
     370                 :     HeapValue extendedSlots[2];
     371                 : };
     372                 : 
     373                 : } // namespace js
     374                 : 
     375                 : inline js::FunctionExtended *
     376        33482676 : JSFunction::toExtended()
     377                 : {
     378        33482676 :     JS_ASSERT(isExtended());
     379        33482676 :     return static_cast<js::FunctionExtended *>(this);
     380                 : }
     381                 : 
     382                 : inline const js::FunctionExtended *
     383        46245276 : JSFunction::toExtended() const
     384                 : {
     385        46245276 :     JS_ASSERT(isExtended());
     386        46245276 :     return static_cast<const js::FunctionExtended *>(this);
     387                 : }
     388                 : 
     389                 : /*
     390                 :  * Get the arguments object for the given frame.  If the frame is strict mode
     391                 :  * code, its current arguments will be copied into the arguments object.
     392                 :  *
     393                 :  * NB: Callers *must* get the arguments object before any parameters are
     394                 :  *     mutated when the frame is strict mode code!  The emitter ensures this
     395                 :  *     occurs for strict mode functions containing syntax which might mutate a
     396                 :  *     named parameter by synthesizing an arguments access at the start of the
     397                 :  *     function.
     398                 :  */
     399                 : extern js::ArgumentsObject *
     400                 : js_GetArgsObject(JSContext *cx, js::StackFrame *fp);
     401                 : 
     402                 : extern void
     403                 : js_PutArgsObject(js::StackFrame *fp);
     404                 : 
     405                 : inline bool
     406          704274 : js_IsNamedLambda(JSFunction *fun) { return (fun->flags & JSFUN_LAMBDA) && fun->atom; }
     407                 : 
     408                 : namespace js {
     409                 : 
     410                 : extern JSBool
     411                 : XDRFunctionObject(JSXDRState *xdr, JSObject **objp);
     412                 : 
     413                 : } /* namespace js */
     414                 : 
     415                 : extern JSBool
     416                 : js_fun_apply(JSContext *cx, unsigned argc, js::Value *vp);
     417                 : 
     418                 : extern JSBool
     419                 : js_fun_call(JSContext *cx, unsigned argc, js::Value *vp);
     420                 : 
     421                 : #endif /* jsfun_h___ */

Generated by: LCOV version 1.7