LCOV - app.info - js/src/vm/ArgumentsObject.cpp

LCOV - code coverage report
| Current view: | directory - js/src/vm - ArgumentsObject.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 249 | 200 | 80.3 %
| Date: | 2012-04-07 | Functions: | 18 | 17 | 94.4 %

           1                 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=8 sw=4 et tw=99:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           7                 :  * The contents of this file are subject to the Mozilla Public License Version
           8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           9                 :  * the License. You may obtain a copy of the License at
          10                 :  * http://www.mozilla.org/MPL/
          11                 :  *
          12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          14                 :  * for the specific language governing rights and limitations under the
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is SpiderMonkey arguments object code.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * the Mozilla Foundation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 2012
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributor(s):
          25                 :  *   Luke Wagner <luke@mozilla.com>
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #include "jsgc.h"
          42                 : #include "jsinfer.h"
          43                 : #include "jsinterp.h"
          44                 :
          45                 : #include "vm/GlobalObject.h"
          46                 : #include "vm/MethodGuard.h"
          47                 : #include "vm/Stack.h"
          48                 : #include "vm/Xdr.h"
          49                 :
          50                 : #include "jsobjinlines.h"
          51                 :
          52                 : #include "gc/Barrier-inl.h"
          53                 : #include "vm/ArgumentsObject-inl.h"
          54                 :
          55                 : using namespace js;
          56                 : using namespace js::gc;
          57                 :
          58                 : struct PutArg
          59                 : {
          60          362278 :     PutArg(JSCompartment *comp, ArgumentsObject &argsobj)
          61          362278 :       : compartment(comp), argsobj(argsobj), dst(argsobj.data()->slots) {}
          62                 :     JSCompartment *compartment;
          63                 :     ArgumentsObject &argsobj;
          64                 :     HeapValue *dst;
          65         1171279 :     bool operator()(unsigned i, Value *src) {
          66         1171279 :         JS_ASSERT(dst->isUndefined());
          67         1171279 :         if (!argsobj.isElementDeleted(i))
          68         1170928 :             dst->set(compartment, *src);
          69         1171279 :         ++dst;
          70         1171279 :         return true;
          71                 :     }
          72                 : };
          73                 :
          74                 : void
          75          361711 : js_PutArgsObject(StackFrame *fp)
          76                 : {
          77          361711 :     ArgumentsObject &argsobj = fp->argsObj();
          78          361711 :     if (argsobj.isNormalArguments()) {
          79          356716 :         JS_ASSERT(argsobj.maybeStackFrame() == fp);
          80          356716 :         JSCompartment *comp = fp->scopeChain().compartment();
          81          356716 :         fp->forEachCanonicalActualArg(PutArg(comp, argsobj));
          82          356716 :         argsobj.setStackFrame(NULL);
          83                 :     } else {
          84            4995 :         JS_ASSERT(!argsobj.maybeStackFrame());
          85                 :     }
          86          361711 : }
          87                 :
          88                 : ArgumentsObject *
          89          362440 : ArgumentsObject::create(JSContext *cx, uint32_t argc, JSObject &callee)
          90                 : {
          91          362440 :     JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
          92                 :
          93          362440 :     JSObject *proto = callee.global().getOrCreateObjectPrototype(cx);
          94          362440 :     if (!proto)
          95               0 :         return NULL;
          96                 :
          97          724880 :     RootedVarTypeObject type(cx);
          98                 :
          99          362440 :     type = proto->getNewType(cx);
         100          362440 :     if (!type)
         101               0 :         return NULL;
         102                 :
         103          362440 :     bool strict = callee.toFunction()->inStrictMode();
         104          362440 :     Class *clasp = strict ? &StrictArgumentsObjectClass : &NormalArgumentsObjectClass;
         105                 :
         106          724880 :     RootedVarShape emptyArgumentsShape(cx);
         107                 :     emptyArgumentsShape =
         108                 :         EmptyShape::getInitialShape(cx, clasp, proto,
         109                 :                                     proto->getParent(), FINALIZE_KIND,
         110          362440 :                                     BaseShape::INDEXED);
         111          362440 :     if (!emptyArgumentsShape)
         112               0 :         return NULL;
         113                 :
         114          362440 :     unsigned numDeletedWords = NumWordsForBitArrayOfLength(argc);
         115                 :     unsigned numBytes = offsetof(ArgumentsData, slots) +
         116                 :                         numDeletedWords * sizeof(size_t) +
         117          362440 :                         argc * sizeof(Value);
         118                 :
         119          362440 :     ArgumentsData *data = (ArgumentsData *)cx->malloc_(numBytes);
         120          362440 :     if (!data)
         121               0 :         return NULL;
         122                 :
         123          362440 :     data->callee.init(ObjectValue(callee));
         124         1533719 :     for (HeapValue *vp = data->slots; vp != data->slots + argc; vp++)
         125         1171279 :         vp->init(UndefinedValue());
         126          362440 :     data->deletedBits = (size_t *)(data->slots + argc);
         127          362440 :     ClearAllBitArrayElements(data->deletedBits, numDeletedWords);
         128                 :
         129                 :     /* We have everything needed to fill in the object, so make the object. */
         130          362440 :     JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyArgumentsShape, type, NULL);
         131          362440 :     if (!obj)
         132               0 :         return NULL;
         133                 :
         134          362440 :     ArgumentsObject &argsobj = obj->asArguments();
         135                 :
         136          362440 :     JS_ASSERT(UINT32_MAX > (uint64_t(argc) << PACKED_BITS_COUNT));
         137          362440 :     argsobj.initInitialLength(argc);
         138          362440 :     argsobj.initData(data);
         139          362440 :     argsobj.setStackFrame(NULL);
         140                 :
         141          362440 :     JS_ASSERT(argsobj.numFixedSlots() >= NormalArgumentsObject::RESERVED_SLOTS);
         142          362440 :     JS_ASSERT(argsobj.numFixedSlots() >= StrictArgumentsObject::RESERVED_SLOTS);
         143                 :
         144          362440 :     return &argsobj;
         145                 : }
         146                 :
         147                 : bool
         148          361882 : ArgumentsObject::create(JSContext *cx, StackFrame *fp)
         149                 : {
         150          361882 :     JS_ASSERT(fp->script()->needsArgsObj());
         151          361882 :     JS_ASSERT(!fp->hasCallObj());
         152                 :
         153          361882 :     ArgumentsObject *argsobj = ArgumentsObject::create(cx, fp->numActualArgs(), fp->callee());
         154          361882 :     if (!argsobj)
         155               0 :         return NULL;
         156                 :
         157                 :     /*
         158                 :      * Strict mode functions have arguments objects that copy the initial
         159                 :      * actual parameter values. Non-strict mode arguments use the frame pointer
         160                 :      * to retrieve up-to-date parameter values.
         161                 :      */
         162          361882 :     if (argsobj->isStrictArguments())
         163            5004 :         fp->forEachCanonicalActualArg(PutArg(cx->compartment, *argsobj));
         164                 :     else
         165          356878 :         argsobj->setStackFrame(fp);
         166                 :
         167          361882 :     fp->initArgsObj(*argsobj);
         168          361882 :     return argsobj;
         169                 : }
         170                 :
         171                 : ArgumentsObject *
         172             558 : ArgumentsObject::createUnexpected(JSContext *cx, StackFrame *fp)
         173                 : {
         174             558 :     ArgumentsObject *argsobj = create(cx, fp->numActualArgs(), fp->callee());
         175             558 :     if (!argsobj)
         176               0 :         return NULL;
         177                 :
         178             558 :     fp->forEachCanonicalActualArg(PutArg(cx->compartment, *argsobj));
         179             558 :     return argsobj;
         180                 : }
         181                 :
         182                 : static JSBool
         183             846 : args_delProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
         184                 : {
         185             846 :     ArgumentsObject &argsobj = obj->asArguments();
         186             846 :     if (JSID_IS_INT(id)) {
         187             414 :         unsigned arg = unsigned(JSID_TO_INT(id));
         188             414 :         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) {
         189             414 :             argsobj.setElement(arg, UndefinedValue());
         190             414 :             argsobj.markElementDeleted(arg);
         191                 :         }
         192             432 :     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
         193             432 :         argsobj.markLengthOverridden();
         194               0 :     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom)) {
         195               0 :         argsobj.asNormalArguments().clearCallee();
         196                 :     }
         197             846 :     return true;
         198                 : }
         199                 :
         200                 : static JSBool
         201            2503 : ArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
         202                 : {
         203            2503 :     if (!obj->isNormalArguments())
         204               0 :         return true;
         205                 :
         206            2503 :     NormalArgumentsObject &argsobj = obj->asNormalArguments();
         207            2503 :     if (JSID_IS_INT(id)) {
         208                 :         /*
         209                 :          * arg can exceed the number of arguments if a script changed the
         210                 :          * prototype to point to another Arguments object with a bigger argc.
         211                 :          */
         212            1108 :         unsigned arg = unsigned(JSID_TO_INT(id));
         213            1108 :         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) {
         214            1099 :             if (StackFrame *fp = argsobj.maybeStackFrame())
         215             990 :                 *vp = fp->canonicalActualArg(arg);
         216                 :             else
         217             109 :                 *vp = argsobj.element(arg);
         218                 :         }
         219            1395 :     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
         220              27 :         if (!argsobj.hasOverriddenLength())
         221              27 :             vp->setInt32(argsobj.initialLength());
         222                 :     } else {
         223            1368 :         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
         224            1368 :         const Value &v = argsobj.callee();
         225            1368 :         if (!v.isMagic(JS_OVERWRITTEN_CALLEE))
         226            1368 :             *vp = v;
         227                 :     }
         228            2503 :     return true;
         229                 : }
         230                 :
         231                 : static JSBool
         232             909 : ArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
         233                 : {
         234             909 :     if (!obj->isNormalArguments())
         235               0 :         return true;
         236                 :
         237             909 :     NormalArgumentsObject &argsobj = obj->asNormalArguments();
         238                 :
         239             909 :     if (JSID_IS_INT(id)) {
         240             504 :         unsigned arg = unsigned(JSID_TO_INT(id));
         241             504 :         if (arg < argsobj.initialLength()) {
         242             504 :             if (StackFrame *fp = argsobj.maybeStackFrame()) {
         243             468 :                 JSScript *script = fp->functionScript();
         244             468 :                 JS_ASSERT(script->needsArgsObj());
         245             468 :                 if (arg < fp->numFormalArgs())
         246             297 :                     types::TypeScript::SetArgument(cx, script, arg, *vp);
         247             468 :                 fp->canonicalActualArg(arg) = *vp;
         248             468 :                 return true;
         249                 :             }
         250                 :         }
         251                 :     } else {
         252             405 :         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
         253             405 :                   JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom));
         254                 :     }
         255                 :
         256                 :     /*
         257                 :      * For simplicity we use delete/define to replace the property with one
         258                 :      * backed by the default Object getter and setter. Note that we rely on
         259                 :      * args_delProperty to clear the corresponding reserved slot so the GC can
         260                 :      * collect its value. Note also that we must define the property instead
         261                 :      * of setting it in case the user has changed the prototype to an object
         262                 :      * that has a setter for this id.
         263                 :      */
         264             882 :     AutoValueRooter tvr(cx);
         265             441 :     return js_DeleteGeneric(cx, &argsobj, id, tvr.addr(), false) &&
         266             441 :            js_DefineProperty(cx, &argsobj, id, vp, NULL, NULL, JSPROP_ENUMERATE);
         267                 : }
         268                 :
         269                 : static JSBool
         270            5442 : args_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags,
         271                 :              JSObject **objp)
         272                 : {
         273            5442 :     *objp = NULL;
         274                 :
         275            5442 :     NormalArgumentsObject &argsobj = obj->asNormalArguments();
         276                 :
         277            5442 :     unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
         278            5442 :     if (JSID_IS_INT(id)) {
         279            4044 :         uint32_t arg = uint32_t(JSID_TO_INT(id));
         280            4044 :         if (arg >= argsobj.initialLength() || argsobj.isElementDeleted(arg))
         281            2610 :             return true;
         282                 :
         283            1434 :         attrs |= JSPROP_ENUMERATE;
         284            1398 :     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
         285             572 :         if (argsobj.hasOverriddenLength())
         286              27 :             return true;
         287                 :     } else {
         288             826 :         if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom))
         289             340 :             return true;
         290                 :
         291             486 :         if (argsobj.callee().isMagic(JS_OVERWRITTEN_CALLEE))
         292               0 :             return true;
         293                 :     }
         294                 :
         295            2465 :     Value undef = UndefinedValue();
         296            2465 :     if (!js_DefineProperty(cx, &argsobj, id, &undef, ArgGetter, ArgSetter, attrs))
         297               0 :         return JS_FALSE;
         298                 :
         299            2465 :     *objp = &argsobj;
         300            2465 :     return true;
         301                 : }
         302                 :
         303                 : bool
         304           95906 : NormalArgumentsObject::optimizedGetElem(JSContext *cx, StackFrame *fp, const Value &elem, Value *vp)
         305                 : {
         306           95906 :     JS_ASSERT(!fp->hasArgsObj());
         307                 :
         308                 :     /* Fast path: no need to convert to id when elem is already an int in range. */
         309           95906 :     if (elem.isInt32()) {
         310           95786 :         int32_t i = elem.toInt32();
         311           95786 :         if (i >= 0 && uint32_t(i) < fp->numActualArgs()) {
         312           93401 :             *vp = fp->canonicalActualArg(i);
         313           93401 :             return true;
         314                 :         }
         315                 :     }
         316                 :
         317                 :     /* Slow path: create and canonicalize an id, then emulate args_resolve. */
         318                 :
         319                 :     jsid id;
         320            2505 :     if (!ValueToId(cx, elem, &id))
         321               0 :         return false;
         322            2505 :     id = js_CheckForStringIndex(id);
         323                 :
         324            2505 :     if (JSID_IS_INT(id)) {
         325            2475 :         int32_t i = JSID_TO_INT(id);
         326            2475 :         if (i >= 0 && uint32_t(i) < fp->numActualArgs()) {
         327              90 :             *vp = fp->canonicalActualArg(i);
         328              90 :             return true;
         329                 :         }
         330                 :     }
         331                 :
         332            2415 :     if (id == ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)) {
         333               0 :         *vp = Int32Value(fp->numActualArgs());
         334               0 :         return true;
         335                 :     }
         336                 :
         337            2415 :     if (id == ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)) {
         338               0 :         *vp = ObjectValue(fp->callee());
         339               0 :         return true;
         340                 :     }
         341                 :
         342            2415 :     JSObject *proto = fp->scopeChain().global().getOrCreateObjectPrototype(cx);
         343            2415 :     if (!proto)
         344               0 :         return false;
         345                 :
         346            2415 :     return proto->getGeneric(cx, id, vp);
         347                 : }
         348                 :
         349                 : static JSBool
         350             180 : args_enumerate(JSContext *cx, JSObject *obj)
         351                 : {
         352             180 :     NormalArgumentsObject &argsobj = obj->asNormalArguments();
         353                 :
         354                 :     /*
         355                 :      * Trigger reflection in args_resolve using a series of js_LookupProperty
         356                 :      * calls.
         357                 :      */
         358             180 :     int argc = int(argsobj.initialLength());
         359             540 :     for (int i = -2; i != argc; i++) {
         360                 :         jsid id = (i == -2)
         361             180 :                   ? ATOM_TO_JSID(cx->runtime->atomState.lengthAtom)
         362                 :                   : (i == -1)
         363             180 :                   ? ATOM_TO_JSID(cx->runtime->atomState.calleeAtom)
         364             720 :                   : INT_TO_JSID(i);
         365                 :
         366                 :         JSObject *pobj;
         367                 :         JSProperty *prop;
         368             360 :         if (!js_LookupProperty(cx, &argsobj, id, &pobj, &prop))
         369               0 :             return false;
         370                 :     }
         371             180 :     return true;
         372                 : }
         373                 :
         374                 : static JSBool
         375             207 : StrictArgGetter(JSContext *cx, JSObject *obj, jsid id, Value *vp)
         376                 : {
         377             207 :     if (!obj->isStrictArguments())
         378               0 :         return true;
         379                 :
         380             207 :     StrictArgumentsObject &argsobj = obj->asStrictArguments();
         381                 :
         382             207 :     if (JSID_IS_INT(id)) {
         383                 :         /*
         384                 :          * arg can exceed the number of arguments if a script changed the
         385                 :          * prototype to point to another Arguments object with a bigger argc.
         386                 :          */
         387             207 :         unsigned arg = unsigned(JSID_TO_INT(id));
         388             207 :         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg))
         389             207 :             *vp = argsobj.element(arg);
         390                 :     } else {
         391               0 :         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
         392               0 :         if (!argsobj.hasOverriddenLength())
         393               0 :             vp->setInt32(argsobj.initialLength());
         394                 :     }
         395             207 :     return true;
         396                 : }
         397                 :
         398                 : static JSBool
         399             279 : StrictArgSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
         400                 : {
         401             279 :     if (!obj->isStrictArguments())
         402               0 :         return true;
         403                 :
         404             279 :     StrictArgumentsObject &argsobj = obj->asStrictArguments();
         405                 :
         406             279 :     if (JSID_IS_INT(id)) {
         407             279 :         unsigned arg = unsigned(JSID_TO_INT(id));
         408             279 :         if (arg < argsobj.initialLength()) {
         409             279 :             argsobj.setElement(arg, *vp);
         410             279 :             return true;
         411                 :         }
         412                 :     } else {
         413               0 :         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom));
         414                 :     }
         415                 :
         416                 :     /*
         417                 :      * For simplicity we use delete/set to replace the property with one
         418                 :      * backed by the default Object getter and setter. Note that we rely on
         419                 :      * args_delProperty to clear the corresponding reserved slot so the GC can
         420                 :      * collect its value.
         421                 :      */
         422               0 :     AutoValueRooter tvr(cx);
         423               0 :     return js_DeleteGeneric(cx, &argsobj, id, tvr.addr(), strict) &&
         424               0 :            js_SetPropertyHelper(cx, &argsobj, id, 0, vp, strict);
         425                 : }
         426                 :
         427                 : static JSBool
         428            1142 : strictargs_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp)
         429                 : {
         430            1142 :     *objp = NULL;
         431                 :
         432            1142 :     StrictArgumentsObject &argsobj = obj->asStrictArguments();
         433                 :
         434            1142 :     unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE;
         435            1142 :     PropertyOp getter = StrictArgGetter;
         436            1142 :     StrictPropertyOp setter = StrictArgSetter;
         437                 :
         438            1142 :     if (JSID_IS_INT(id)) {
         439            1094 :         uint32_t arg = uint32_t(JSID_TO_INT(id));
         440            1094 :         if (arg >= argsobj.initialLength() || argsobj.isElementDeleted(arg))
         441             603 :             return true;
         442                 :
         443             491 :         attrs |= JSPROP_ENUMERATE;
         444              48 :     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
         445              48 :         if (argsobj.hasOverriddenLength())
         446               0 :             return true;
         447                 :     } else {
         448               0 :         if (!JSID_IS_ATOM(id, cx->runtime->atomState.calleeAtom) &&
         449               0 :             !JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
         450               0 :             return true;
         451                 :         }
         452                 :
         453               0 :         attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED;
         454               0 :         getter = CastAsPropertyOp(argsobj.global().getThrowTypeError());
         455               0 :         setter = CastAsStrictPropertyOp(argsobj.global().getThrowTypeError());
         456                 :     }
         457                 :
         458             539 :     Value undef = UndefinedValue();
         459             539 :     if (!js_DefineProperty(cx, &argsobj, id, &undef, getter, setter, attrs))
         460               0 :         return false;
         461                 :
         462             539 :     *objp = &argsobj;
         463             539 :     return true;
         464                 : }
         465                 :
         466                 : static JSBool
         467               0 : strictargs_enumerate(JSContext *cx, JSObject *obj)
         468                 : {
         469               0 :     StrictArgumentsObject *argsobj = &obj->asStrictArguments();
         470                 :
         471                 :     /*
         472                 :      * Trigger reflection in strictargs_resolve using a series of
         473                 :      * js_LookupProperty calls.
         474                 :      */
         475                 :     JSObject *pobj;
         476                 :     JSProperty *prop;
         477                 :
         478                 :     // length
         479               0 :     if (!js_LookupProperty(cx, argsobj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), &pobj, &prop))
         480               0 :         return false;
         481                 :
         482                 :     // callee
         483               0 :     if (!js_LookupProperty(cx, argsobj, ATOM_TO_JSID(cx->runtime->atomState.calleeAtom), &pobj, &prop))
         484               0 :         return false;
         485                 :
         486                 :     // caller
         487               0 :     if (!js_LookupProperty(cx, argsobj, ATOM_TO_JSID(cx->runtime->atomState.callerAtom), &pobj, &prop))
         488               0 :         return false;
         489                 :
         490               0 :     for (uint32_t i = 0, argc = argsobj->initialLength(); i < argc; i++) {
         491               0 :         if (!js_LookupProperty(cx, argsobj, INT_TO_JSID(i), &pobj, &prop))
         492               0 :             return false;
         493                 :     }
         494                 :
         495               0 :     return true;
         496                 : }
         497                 :
         498                 : static void
         499          362440 : args_finalize(FreeOp *fop, JSObject *obj)
         500                 : {
         501          362440 :     fop->free_(reinterpret_cast<void *>(obj->asArguments().data()));
         502          362440 : }
         503                 :
         504                 : static void
         505            1311 : args_trace(JSTracer *trc, JSObject *obj)
         506                 : {
         507            1311 :     ArgumentsObject &argsobj = obj->asArguments();
         508            1311 :     ArgumentsData *data = argsobj.data();
         509            1311 :     MarkValue(trc, &data->callee, js_callee_str);
         510            1311 :     MarkValueRange(trc, argsobj.initialLength(), data->slots, js_arguments_str);
         511                 :
         512                 :     /*
         513                 :      * If a generator's arguments or call object escapes, and the generator
         514                 :      * frame is not executing, the generator object needs to be marked because
         515                 :      * it is not otherwise reachable. An executing generator is rooted by its
         516                 :      * invocation.  To distinguish the two cases (which imply different access
         517                 :      * paths to the generator object), we use the JSFRAME_FLOATING_GENERATOR
         518                 :      * flag, which is only set on the StackFrame kept in the generator object's
         519                 :      * JSGenerator.
         520                 :      */
         521                 : #if JS_HAS_GENERATORS
         522            1311 :     StackFrame *fp = argsobj.maybeStackFrame();
         523            1311 :     if (fp && fp->isFloatingGenerator())
         524             350 :         MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
         525                 : #endif
         526            1311 : }
         527                 :
         528                 : /*
         529                 :  * The classes below collaborate to lazily reflect and synchronize actual
         530                 :  * argument values, argument count, and callee function object stored in a
         531                 :  * StackFrame with their corresponding property values in the frame's
         532                 :  * arguments object.
         533                 :  */
         534                 : Class js::NormalArgumentsObjectClass = {
         535                 :     "Arguments",
         536                 :     JSCLASS_NEW_RESOLVE | JSCLASS_IMPLEMENTS_BARRIERS |
         537                 :     JSCLASS_HAS_RESERVED_SLOTS(NormalArgumentsObject::RESERVED_SLOTS) |
         538                 :     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
         539                 :     JSCLASS_FOR_OF_ITERATION,
         540                 :     JS_PropertyStub,         /* addProperty */
         541                 :     args_delProperty,
         542                 :     JS_PropertyStub,         /* getProperty */
         543                 :     JS_StrictPropertyStub,   /* setProperty */
         544                 :     args_enumerate,
         545                 :     reinterpret_cast<JSResolveOp>(args_resolve),
         546                 :     JS_ConvertStub,
         547                 :     args_finalize,           /* finalize   */
         548                 :     NULL,                    /* checkAccess */
         549                 :     NULL,                    /* call        */
         550                 :     NULL,                    /* construct   */
         551                 :     NULL,                    /* hasInstance */
         552                 :     args_trace,
         553                 :     {
         554                 :         NULL,       /* equality    */
         555                 :         NULL,       /* outerObject */
         556                 :         NULL,       /* innerObject */
         557                 :         JS_ElementIteratorStub,
         558                 :         NULL,       /* unused      */
         559                 :         false,      /* isWrappedNative */
         560                 :     }
         561                 : };
         562                 :
         563                 : /*
         564                 :  * Strict mode arguments is significantly less magical than non-strict mode
         565                 :  * arguments, so it is represented by a different class while sharing some
         566                 :  * functionality.
         567                 :  */
         568                 : Class js::StrictArgumentsObjectClass = {
         569                 :     "Arguments",
         570                 :     JSCLASS_NEW_RESOLVE | JSCLASS_IMPLEMENTS_BARRIERS |
         571                 :     JSCLASS_HAS_RESERVED_SLOTS(StrictArgumentsObject::RESERVED_SLOTS) |
         572                 :     JSCLASS_HAS_CACHED_PROTO(JSProto_Object) |
         573                 :     JSCLASS_FOR_OF_ITERATION,
         574                 :     JS_PropertyStub,         /* addProperty */
         575                 :     args_delProperty,
         576                 :     JS_PropertyStub,         /* getProperty */
         577                 :     JS_StrictPropertyStub,   /* setProperty */
         578                 :     strictargs_enumerate,
         579                 :     reinterpret_cast<JSResolveOp>(strictargs_resolve),
         580                 :     JS_ConvertStub,
         581                 :     args_finalize,           /* finalize   */
         582                 :     NULL,                    /* checkAccess */
         583                 :     NULL,                    /* call        */
         584                 :     NULL,                    /* construct   */
         585                 :     NULL,                    /* hasInstance */
         586                 :     args_trace,
         587                 :     {
         588                 :         NULL,       /* equality    */
         589                 :         NULL,       /* outerObject */
         590                 :         NULL,       /* innerObject */
         591                 :         JS_ElementIteratorStub,
         592                 :         NULL,       /* unused      */
         593                 :         false,      /* isWrappedNative */
         594                 :     }
         595                 : };

Generated by: LCOV version 1.7