LCOV - app.info - js/src/vm/Debugger.h

LCOV - code coverage report
| Current view: | directory - js/src/vm - Debugger.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 50 | 50 | 100.0 %
| Date: | 2012-04-07 | Functions: | 18 | 18 | 100.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=8 sw=4 et tw=99 ft=cpp:
           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 Debugger object.
          18                 :  *
          19                 :  * The Initial Developer of the Original Code is
          20                 :  * Mozilla Foundation.
          21                 :  * Portions created by the Initial Developer are Copyright (C) 1998-1999
          22                 :  * the Initial Developer. All Rights Reserved.
          23                 :  *
          24                 :  * Contributors:
          25                 :  *   Jim Blandy <jimb@mozilla.com>
          26                 :  *   Jason Orendorff <jorendorff@mozilla.com>
          27                 :  *
          28                 :  * Alternatively, the contents of this file may be used under the terms of
          29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          32                 :  * of those above. If you wish to allow use of your version of this file only
          33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          34                 :  * use your version of this file under the terms of the MPL, indicate your
          35                 :  * decision by deleting the provisions above and replace them with the notice
          36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          37                 :  * the provisions above, a recipient may use your version of this file under
          38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          39                 :  *
          40                 :  * ***** END LICENSE BLOCK ***** */
          41                 :
          42                 : #ifndef Debugger_h__
          43                 : #define Debugger_h__
          44                 :
          45                 : #include "mozilla/Attributes.h"
          46                 :
          47                 : #include "jsapi.h"
          48                 : #include "jsclist.h"
          49                 : #include "jscntxt.h"
          50                 : #include "jscompartment.h"
          51                 : #include "jsgc.h"
          52                 : #include "jsweakmap.h"
          53                 : #include "jswrapper.h"
          54                 :
          55                 : #include "gc/Barrier.h"
          56                 : #include "js/HashTable.h"
          57                 : #include "vm/GlobalObject.h"
          58                 :
          59                 : namespace js {
          60                 :
          61                 : class Debugger {
          62                 :     friend class Breakpoint;
          63                 :     friend JSBool (::JS_DefineDebuggerObject)(JSContext *cx, JSObject *obj);
          64                 :
          65                 :   public:
          66                 :     enum Hook {
          67                 :         OnDebuggerStatement,
          68                 :         OnExceptionUnwind,
          69                 :         OnNewScript,
          70                 :         OnEnterFrame,
          71                 :         HookCount
          72                 :     };
          73                 :
          74                 :     enum {
          75                 :         JSSLOT_DEBUG_PROTO_START,
          76                 :         JSSLOT_DEBUG_FRAME_PROTO = JSSLOT_DEBUG_PROTO_START,
          77                 :         JSSLOT_DEBUG_ENV_PROTO,
          78                 :         JSSLOT_DEBUG_OBJECT_PROTO,
          79                 :         JSSLOT_DEBUG_SCRIPT_PROTO,
          80                 :         JSSLOT_DEBUG_PROTO_STOP,
          81                 :         JSSLOT_DEBUG_HOOK_START = JSSLOT_DEBUG_PROTO_STOP,
          82                 :         JSSLOT_DEBUG_HOOK_STOP = JSSLOT_DEBUG_HOOK_START + HookCount,
          83                 :         JSSLOT_DEBUG_COUNT = JSSLOT_DEBUG_HOOK_STOP
          84                 :     };
          85                 :
          86                 :   private:
          87                 :     JSCList link;                       /* See JSRuntime::debuggerList. */
          88                 :     HeapPtrObject object;               /* The Debugger object. Strong reference. */
          89                 :     GlobalObjectSet debuggees;          /* Debuggee globals. Cross-compartment weak references. */
          90                 :     js::HeapPtrObject uncaughtExceptionHook; /* Strong reference. */
          91                 :     bool enabled;
          92                 :     JSCList breakpoints;                /* cyclic list of all js::Breakpoints in this debugger */
          93                 :
          94                 :     /*
          95                 :      * Map from stack frames that are currently on the stack to Debugger.Frame
          96                 :      * instances.
          97                 :      *
          98                 :      * The keys are always live stack frames. We drop them from this map as
          99                 :      * soon as they leave the stack (see slowPathOnLeaveFrame) and in
         100                 :      * removeDebuggee.
         101                 :      *
         102                 :      * We don't trace the keys of this map (the frames are on the stack and
         103                 :      * thus necessarily live), but we do trace the values. It's like a WeakMap
         104                 :      * that way, but since stack frames are not gc-things, the implementation
         105                 :      * has to be different.
         106                 :      */
         107                 :     typedef HashMap<StackFrame *, HeapPtrObject, DefaultHasher<StackFrame *>, RuntimeAllocPolicy>
         108                 :         FrameMap;
         109                 :     FrameMap frames;
         110                 :
         111                 :     /* An ephemeral map from JSScript* to Debugger.Script instances. */
         112                 :     typedef WeakMap<HeapPtrScript, HeapPtrObject> ScriptWeakMap;
         113                 :     ScriptWeakMap scripts;
         114                 :
         115                 :     /* The map from debuggee objects to their Debugger.Object instances. */
         116                 :     typedef WeakMap<HeapPtrObject, HeapPtrObject> ObjectWeakMap;
         117                 :     ObjectWeakMap objects;
         118                 :
         119                 :     /* The map from debuggee Envs to Debugger.Environment instances. */
         120                 :     ObjectWeakMap environments;
         121                 :
         122                 :     class FrameRange;
         123                 :     class ScriptQuery;
         124                 :
         125                 :     bool addDebuggeeGlobal(JSContext *cx, GlobalObject *obj);
         126                 :     void removeDebuggeeGlobal(FreeOp *fop, GlobalObject *global,
         127                 :                               GlobalObjectSet::Enum *compartmentEnum,
         128                 :                               GlobalObjectSet::Enum *debugEnum);
         129                 :
         130                 :     /*
         131                 :      * Cope with an error or exception in a debugger hook.
         132                 :      *
         133                 :      * If callHook is true, then call the uncaughtExceptionHook, if any. If, in
         134                 :      * addition, vp is non-null, then parse the value returned by
         135                 :      * uncaughtExceptionHook as a resumption value.
         136                 :      *
         137                 :      * If there is no uncaughtExceptionHook, or if it fails, report and clear
         138                 :      * the pending exception on ac.context and return JSTRAP_ERROR.
         139                 :      *
         140                 :      * This always calls ac.leave(); ac is a parameter because this method must
         141                 :      * do some things in the debugger compartment and some things in the
         142                 :      * debuggee compartment.
         143                 :      */
         144                 :     JSTrapStatus handleUncaughtException(AutoCompartment &ac, Value *vp, bool callHook);
         145                 :
         146                 :     /*
         147                 :      * Handle the result of a hook that is expected to return a resumption
         148                 :      * value <https://wiki.mozilla.org/Debugger#Resumption_Values>. This is called
         149                 :      * when we return from a debugging hook to debuggee code. The interpreter wants
         150                 :      * a (JSTrapStatus, Value) pair telling it how to proceed.
         151                 :      *
         152                 :      * Precondition: ac is entered. We are in the debugger compartment.
         153                 :      *
         154                 :      * Postcondition: This called ac.leave(). See handleUncaughtException.
         155                 :      *
         156                 :      * If ok is false, the hook failed. If an exception is pending in
         157                 :      * ac.context(), return handleUncaughtException(ac, vp, callhook).
         158                 :      * Otherwise just return JSTRAP_ERROR.
         159                 :      *
         160                 :      * If ok is true, there must be no exception pending in ac.context(). rv may be:
         161                 :      *     undefined - Return JSTRAP_CONTINUE to continue execution normally.
         162                 :      *     {return: value} or {throw: value} - Call unwrapDebuggeeValue to
         163                 :      *         unwrap value. Store the result in *vp and return JSTRAP_RETURN
         164                 :      *         or JSTRAP_THROW. The interpreter will force the current frame to
         165                 :      *         return or throw an exception.
         166                 :      *     null - Return JSTRAP_ERROR to terminate the debuggee with an
         167                 :      *         uncatchable error.
         168                 :      *     anything else - Make a new TypeError the pending exception and
         169                 :      *         return handleUncaughtException(ac, vp, callHook).
         170                 :      */
         171                 :     JSTrapStatus parseResumptionValue(AutoCompartment &ac, bool ok, const Value &rv, Value *vp,
         172                 :                                       bool callHook = true);
         173                 :
         174                 :     JSObject *unwrapDebuggeeArgument(JSContext *cx, const Value &v);
         175                 :
         176                 :     static void traceObject(JSTracer *trc, JSObject *obj);
         177                 :     void trace(JSTracer *trc);
         178                 :     static void finalize(FreeOp *fop, JSObject *obj);
         179                 :     void markKeysInCompartment(JSTracer *tracer);
         180                 :
         181                 :     static Class jsclass;
         182                 :
         183                 :     static Debugger *fromThisValue(JSContext *cx, const CallArgs &ca, const char *fnname);
         184                 :     static JSBool getEnabled(JSContext *cx, unsigned argc, Value *vp);
         185                 :     static JSBool setEnabled(JSContext *cx, unsigned argc, Value *vp);
         186                 :     static JSBool getHookImpl(JSContext *cx, unsigned argc, Value *vp, Hook which);
         187                 :     static JSBool setHookImpl(JSContext *cx, unsigned argc, Value *vp, Hook which);
         188                 :     static JSBool getOnDebuggerStatement(JSContext *cx, unsigned argc, Value *vp);
         189                 :     static JSBool setOnDebuggerStatement(JSContext *cx, unsigned argc, Value *vp);
         190                 :     static JSBool getOnExceptionUnwind(JSContext *cx, unsigned argc, Value *vp);
         191                 :     static JSBool setOnExceptionUnwind(JSContext *cx, unsigned argc, Value *vp);
         192                 :     static JSBool getOnNewScript(JSContext *cx, unsigned argc, Value *vp);
         193                 :     static JSBool setOnNewScript(JSContext *cx, unsigned argc, Value *vp);
         194                 :     static JSBool getOnEnterFrame(JSContext *cx, unsigned argc, Value *vp);
         195                 :     static JSBool setOnEnterFrame(JSContext *cx, unsigned argc, Value *vp);
         196                 :     static JSBool getUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp);
         197                 :     static JSBool setUncaughtExceptionHook(JSContext *cx, unsigned argc, Value *vp);
         198                 :     static JSBool addDebuggee(JSContext *cx, unsigned argc, Value *vp);
         199                 :     static JSBool removeDebuggee(JSContext *cx, unsigned argc, Value *vp);
         200                 :     static JSBool hasDebuggee(JSContext *cx, unsigned argc, Value *vp);
         201                 :     static JSBool getDebuggees(JSContext *cx, unsigned argc, Value *vp);
         202                 :     static JSBool getNewestFrame(JSContext *cx, unsigned argc, Value *vp);
         203                 :     static JSBool clearAllBreakpoints(JSContext *cx, unsigned argc, Value *vp);
         204                 :     static JSBool findScripts(JSContext *cx, unsigned argc, Value *vp);
         205                 :     static JSBool wrap(JSContext *cx, unsigned argc, Value *vp);
         206                 :     static JSBool construct(JSContext *cx, unsigned argc, Value *vp);
         207                 :     static JSPropertySpec properties[];
         208                 :     static JSFunctionSpec methods[];
         209                 :
         210                 :     JSObject *getHook(Hook hook) const;
         211                 :     bool hasAnyLiveHooks() const;
         212                 :
         213                 :     static JSTrapStatus slowPathOnEnterFrame(JSContext *cx, Value *vp);
         214                 :     static bool slowPathOnLeaveFrame(JSContext *cx, bool ok);
         215                 :     static void slowPathOnNewScript(JSContext *cx, JSScript *script,
         216                 :                                     GlobalObject *compileAndGoGlobal);
         217                 :     static JSTrapStatus dispatchHook(JSContext *cx, Value *vp, Hook which);
         218                 :
         219                 :     JSTrapStatus fireDebuggerStatement(JSContext *cx, Value *vp);
         220                 :     JSTrapStatus fireExceptionUnwind(JSContext *cx, Value *vp);
         221                 :     JSTrapStatus fireEnterFrame(JSContext *cx, Value *vp);
         222                 :
         223                 :     /*
         224                 :      * Allocate and initialize a Debugger.Script instance whose referent is
         225                 :      * |script|.
         226                 :      */
         227                 :     JSObject *newDebuggerScript(JSContext *cx, JSScript *script);
         228                 :
         229                 :     /*
         230                 :      * Receive a "new script" event from the engine. A new script was compiled
         231                 :      * or deserialized.
         232                 :      */
         233                 :     void fireNewScript(JSContext *cx, JSScript *script);
         234                 :
         235                 :     static inline Debugger *fromLinks(JSCList *links);
         236                 :     inline Breakpoint *firstBreakpoint() const;
         237                 :
         238                 :   public:
         239                 :     Debugger(JSContext *cx, JSObject *dbg);
         240                 :     ~Debugger();
         241                 :
         242                 :     bool init(JSContext *cx);
         243                 :     inline const js::HeapPtrObject &toJSObject() const;
         244                 :     inline js::HeapPtrObject &toJSObjectRef();
         245                 :     static inline Debugger *fromJSObject(JSObject *obj);
         246                 :     static Debugger *fromChildJSObject(JSObject *obj);
         247                 :
         248                 :     /*********************************** Methods for interaction with the GC. */
         249                 :
         250                 :     /*
         251                 :      * A Debugger object is live if:
         252                 :      *   * the Debugger JSObject is live (Debugger::trace handles this case); OR
         253                 :      *   * it is in the middle of dispatching an event (the event dispatching
         254                 :      *     code roots it in this case); OR
         255                 :      *   * it is enabled, and it is debugging at least one live compartment,
         256                 :      *     and at least one of the following is true:
         257                 :      *       - it has a debugger hook installed
         258                 :      *       - it has a breakpoint set on a live script
         259                 :      *       - it has a watchpoint set on a live object.
         260                 :      *
         261                 :      * Debugger::markAllIteratively handles the last case. If it finds any
         262                 :      * Debugger objects that are definitely live but not yet marked, it marks
         263                 :      * them and returns true. If not, it returns false.
         264                 :      */
         265                 :     static void markCrossCompartmentDebuggerObjectReferents(JSTracer *tracer);
         266                 :     static bool markAllIteratively(GCMarker *trc);
         267                 :     static void sweepAll(FreeOp *fop);
         268                 :     static void detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global,
         269                 :                                              GlobalObjectSet::Enum *compartmentEnum);
         270                 :
         271                 :     static inline JSTrapStatus onEnterFrame(JSContext *cx, Value *vp);
         272                 :     static inline bool onLeaveFrame(JSContext *cx, bool ok);
         273                 :     static inline JSTrapStatus onDebuggerStatement(JSContext *cx, Value *vp);
         274                 :     static inline JSTrapStatus onExceptionUnwind(JSContext *cx, Value *vp);
         275                 :     static inline void onNewScript(JSContext *cx, JSScript *script,
         276                 :                                    GlobalObject *compileAndGoGlobal);
         277                 :     static JSTrapStatus onTrap(JSContext *cx, Value *vp);
         278                 :     static JSTrapStatus onSingleStep(JSContext *cx, Value *vp);
         279                 :
         280                 :     /************************************* Functions for use by Debugger.cpp. */
         281                 :
         282                 :     inline bool observesEnterFrame() const;
         283                 :     inline bool observesNewScript() const;
         284                 :     inline bool observesGlobal(GlobalObject *global) const;
         285                 :     inline bool observesFrame(StackFrame *fp) const;
         286                 :
         287                 :     /*
         288                 :      * If env is NULL, call vp->setNull() and return true. Otherwise, find or
         289                 :      * create a Debugger.Environment object for the given Env. On success,
         290                 :      * store the Environment object in *vp and return true.
         291                 :      */
         292                 :     bool wrapEnvironment(JSContext *cx, Env *env, Value *vp);
         293                 :
         294                 :     /*
         295                 :      * Like cx->compartment->wrap(cx, vp), but for the debugger compartment.
         296                 :      *
         297                 :      * Preconditions: *vp is a value from a debuggee compartment; cx is in the
         298                 :      * debugger's compartment.
         299                 :      *
         300                 :      * If *vp is an object, this produces a (new or existing) Debugger.Object
         301                 :      * wrapper for it. Otherwise this is the same as JSCompartment::wrap.
         302                 :      */
         303                 :     bool wrapDebuggeeValue(JSContext *cx, Value *vp);
         304                 :
         305                 :     /*
         306                 :      * Unwrap a Debug.Object, without rewrapping it for any particular debuggee
         307                 :      * compartment.
         308                 :      *
         309                 :      * Preconditions: cx is in the debugger compartment. *vp is a value in that
         310                 :      * compartment. (*vp should be a "debuggee value", meaning it is the
         311                 :      * debugger's reflection of a value in the debuggee.)
         312                 :      *
         313                 :      * If *vp is a Debugger.Object, store the referent in *vp. Otherwise, if *vp
         314                 :      * is an object, throw a TypeError, because it is not a debuggee
         315                 :      * value. Otherwise *vp is a primitive, so leave it alone.
         316                 :      *
         317                 :      * When passing values from the debuggee to the debugger:
         318                 :      *     enter debugger compartment;
         319                 :      *     call wrapDebuggeeValue;  // compartment- and debugger-wrapping
         320                 :      *
         321                 :      * When passing values from the debugger to the debuggee:
         322                 :      *     call unwrapDebuggeeValue;  // debugger-unwrapping
         323                 :      *     enter debuggee compartment;
         324                 :      *     call cx->compartment->wrap;  // compartment-rewrapping
         325                 :      *
         326                 :      * (Extreme nerd sidebar: Unwrapping happens in two steps because there are
         327                 :      * two different kinds of symmetry at work: regardless of which direction
         328                 :      * we're going, we want any exceptions to be created and thrown in the
         329                 :      * debugger compartment--mirror symmetry. But compartment wrapping always
         330                 :      * happens in the target compartment--rotational symmetry.)
         331                 :      */
         332                 :     bool unwrapDebuggeeValue(JSContext *cx, Value *vp);
         333                 :
         334                 :     /* Store the Debugger.Frame object for the frame fp in *vp. */
         335                 :     bool getScriptFrame(JSContext *cx, StackFrame *fp, Value *vp);
         336                 :
         337                 :     /*
         338                 :      * Set |*status| and |*value| to a (JSTrapStatus, Value) pair reflecting a
         339                 :      * standard SpiderMonkey call state: a boolean success value |ok|, a return
         340                 :      * value |rv|, and a context |cx| that may or may not have an exception set.
         341                 :      * If an exception was pending on |cx|, it is cleared (and |ok| is asserted
         342                 :      * to be false).
         343                 :      */
         344                 :     static void resultToCompletion(JSContext *cx, bool ok, const Value &rv,
         345                 :                                    JSTrapStatus *status, Value *value);
         346                 :
         347                 :     /*
         348                 :      * Set |*result| to a JavaScript completion value corresponding to |status|
         349                 :      * and |value|. |value| should be the return value or exception value, not
         350                 :      * wrapped as a debuggee value. |cx| must be in the debugger compartment.
         351                 :      */
         352                 :     bool newCompletionValue(JSContext *cx, JSTrapStatus status, Value value, Value *result);
         353                 :
         354                 :     /*
         355                 :      * Precondition: we are in the debuggee compartment (ac is entered) and ok
         356                 :      * is true if the operation in the debuggee compartment succeeded, false on
         357                 :      * error or exception.
         358                 :      *
         359                 :      * Postcondition: we are in the debugger compartment, having called
         360                 :      * ac.leave() even if an error occurred.
         361                 :      *
         362                 :      * On success, a completion value is in vp and ac.context does not have a
         363                 :      * pending exception. (This ordinarily returns true even if the ok argument
         364                 :      * is false.)
         365                 :      */
         366                 :     bool receiveCompletionValue(AutoCompartment &ac, bool ok, Value val, Value *vp);
         367                 :
         368                 :     /*
         369                 :      * Return the Debugger.Script object for |script|, or create a new one if
         370                 :      * needed. The context |cx| must be in the debugger compartment; |script|
         371                 :      * must be a script in a debuggee compartment.
         372                 :      */
         373                 :     JSObject *wrapScript(JSContext *cx, JSScript *script);
         374                 :
         375                 :   private:
         376                 :     Debugger(const Debugger &) MOZ_DELETE;
         377                 :     Debugger & operator=(const Debugger &) MOZ_DELETE;
         378                 : };
         379                 :
         380            1172 : class BreakpointSite {
         381                 :     friend class Breakpoint;
         382                 :     friend struct ::JSCompartment;
         383                 :     friend struct ::JSScript;
         384                 :     friend class Debugger;
         385                 :
         386                 :   public:
         387                 :     JSScript * const script;
         388                 :     jsbytecode * const pc;
         389                 :
         390                 :   private:
         391                 :     /*
         392                 :      * The holder object for script, if known, else NULL.  This is NULL for
         393                 :      * cached eval scripts and for JSD1 traps. It is always non-null for JSD2
         394                 :      * breakpoints in held scripts.
         395                 :      */
         396                 :     GlobalObject *scriptGlobal;
         397                 :
         398                 :     JSCList breakpoints;  /* cyclic list of all js::Breakpoints at this instruction */
         399                 :     size_t enabledCount;  /* number of breakpoints in the list that are enabled */
         400                 :     JSTrapHandler trapHandler;  /* jsdbgapi trap state */
         401                 :     HeapValue trapClosure;
         402                 :
         403                 :     void recompile(FreeOp *fop);
         404                 :
         405                 :   public:
         406                 :     BreakpointSite(JSScript *script, jsbytecode *pc);
         407                 :     Breakpoint *firstBreakpoint() const;
         408                 :     bool hasBreakpoint(Breakpoint *bp);
         409                 :     bool hasTrap() const { return !!trapHandler; }
         410                 :     GlobalObject *getScriptGlobal() const { return scriptGlobal; }
         411                 :
         412                 :     void inc(FreeOp *fop);
         413                 :     void dec(FreeOp *fop);
         414                 :     void setTrap(FreeOp *fop, JSTrapHandler handler, const Value &closure);
         415                 :     void clearTrap(FreeOp *fop, JSTrapHandler *handlerp = NULL, Value *closurep = NULL);
         416                 :     void destroyIfEmpty(FreeOp *fop);
         417                 : };
         418                 :
         419                 : /*
         420                 :  * Each Breakpoint is a member of two linked lists: its debugger's list and its
         421                 :  * site's list.
         422                 :  *
         423                 :  * GC rules:
         424                 :  *   - script is live, breakpoint exists, and debugger is enabled
         425                 :  *      ==> debugger is live
         426                 :  *   - script is live, breakpoint exists, and debugger is live
         427                 :  *      ==> retain the breakpoint and the handler object is live
         428                 :  *
         429                 :  * Debugger::markAllIteratively implements these two rules. It uses
         430                 :  * Debugger::hasAnyLiveHooks to check for rule 1.
         431                 :  *
         432                 :  * Nothing else causes a breakpoint to be retained, so if its script or
         433                 :  * debugger is collected, the breakpoint is destroyed during GC sweep phase,
         434                 :  * even if the debugger compartment isn't being GC'd. This is implemented in
         435                 :  * JSCompartment::sweepBreakpoints.
         436                 :  */
         437            1269 : class Breakpoint {
         438                 :     friend struct ::JSCompartment;
         439                 :     friend class Debugger;
         440                 :
         441                 :   public:
         442                 :     Debugger * const debugger;
         443                 :     BreakpointSite * const site;
         444                 :   private:
         445                 :     js::HeapPtrObject handler;
         446                 :     JSCList debuggerLinks;
         447                 :     JSCList siteLinks;
         448                 :
         449                 :   public:
         450                 :     static Breakpoint *fromDebuggerLinks(JSCList *links);
         451                 :     static Breakpoint *fromSiteLinks(JSCList *links);
         452                 :     Breakpoint(Debugger *debugger, BreakpointSite *site, JSObject *handler);
         453                 :     void destroy(FreeOp *fop);
         454                 :     Breakpoint *nextInDebugger();
         455                 :     Breakpoint *nextInSite();
         456             873 :     const HeapPtrObject &getHandler() const { return handler; }
         457             163 :     HeapPtrObject &getHandlerRef() { return handler; }
         458                 : };
         459                 :
         460                 : Debugger *
         461           14434 : Debugger::fromLinks(JSCList *links)
         462                 : {
         463           14434 :     unsigned char *p = reinterpret_cast<unsigned char *>(links);
         464           14434 :     return reinterpret_cast<Debugger *>(p - offsetof(Debugger, link));
         465                 : }
         466                 :
         467                 : Breakpoint *
         468            6940 : Debugger::firstBreakpoint() const
         469                 : {
         470            6940 :     if (JS_CLIST_IS_EMPTY(&breakpoints))
         471            6519 :         return NULL;
         472             421 :     return Breakpoint::fromDebuggerLinks(JS_NEXT_LINK(&breakpoints));
         473                 : }
         474                 :
         475                 : const js::HeapPtrObject &
         476           34638 : Debugger::toJSObject() const
         477                 : {
         478           34638 :     JS_ASSERT(object);
         479           34638 :     return object;
         480                 : }
         481                 :
         482                 : js::HeapPtrObject &
         483            6857 : Debugger::toJSObjectRef()
         484                 : {
         485            6857 :     JS_ASSERT(object);
         486            6857 :     return object;
         487                 : }
         488                 :
         489                 : Debugger *
         490          178220 : Debugger::fromJSObject(JSObject *obj)
         491                 : {
         492          178220 :     JS_ASSERT(js::GetObjectClass(obj) == &jsclass);
         493          178220 :     return (Debugger *) obj->getPrivate();
         494                 : }
         495                 :
         496                 : bool
         497           33903 : Debugger::observesEnterFrame() const
         498                 : {
         499           33903 :     return enabled && getHook(OnEnterFrame);
         500                 : }
         501                 :
         502                 : bool
         503           11110 : Debugger::observesNewScript() const
         504                 : {
         505           11110 :     return enabled && getHook(OnNewScript);
         506                 : }
         507                 :
         508                 : bool
         509           36443 : Debugger::observesGlobal(GlobalObject *global) const
         510                 : {
         511           36443 :     return debuggees.has(global);
         512                 : }
         513                 :
         514                 : bool
         515           35903 : Debugger::observesFrame(StackFrame *fp) const
         516                 : {
         517           35903 :     return !fp->isDummyFrame() && observesGlobal(&fp->scopeChain().global());
         518                 : }
         519                 :
         520                 : JSTrapStatus
         521        12393915 : Debugger::onEnterFrame(JSContext *cx, Value *vp)
         522                 : {
         523        12393915 :     if (cx->compartment->getDebuggees().empty())
         524        12365741 :         return JSTRAP_CONTINUE;
         525           28174 :     return slowPathOnEnterFrame(cx, vp);
         526                 : }
         527                 :
         528                 : bool
         529        12394644 : Debugger::onLeaveFrame(JSContext *cx, bool ok)
         530                 : {
         531                 :     /* Traps must be cleared from eval frames, see slowPathOnLeaveFrame. */
         532        12394644 :     bool evalTraps = cx->fp()->isEvalFrame() &&
         533        12394644 :                      cx->fp()->script()->hasAnyBreakpointsOrStepMode();
         534        12394644 :     if (!cx->compartment->getDebuggees().empty() || evalTraps)
         535           28368 :         ok = slowPathOnLeaveFrame(cx, ok);
         536        12394644 :     return ok;
         537                 : }
         538                 :
         539                 : JSTrapStatus
         540            8173 : Debugger::onDebuggerStatement(JSContext *cx, Value *vp)
         541                 : {
         542            8173 :     return cx->compartment->getDebuggees().empty()
         543                 :            ? JSTRAP_CONTINUE
         544            8173 :            : dispatchHook(cx, vp, OnDebuggerStatement);
         545                 : }
         546                 :
         547                 : JSTrapStatus
         548            1116 : Debugger::onExceptionUnwind(JSContext *cx, Value *vp)
         549                 : {
         550            1116 :     return cx->compartment->getDebuggees().empty()
         551                 :            ? JSTRAP_CONTINUE
         552            1116 :            : dispatchHook(cx, vp, OnExceptionUnwind);
         553                 : }
         554                 :
         555                 : void
         556          107244 : Debugger::onNewScript(JSContext *cx, JSScript *script, GlobalObject *compileAndGoGlobal)
         557                 : {
         558          107244 :     JS_ASSERT_IF(script->compileAndGo, compileAndGoGlobal);
         559          107244 :     JS_ASSERT_IF(!script->compileAndGo, !compileAndGoGlobal);
         560          107244 :     if (!script->compartment()->getDebuggees().empty())
         561            9834 :         slowPathOnNewScript(cx, script, compileAndGoGlobal);
         562          107244 : }
         563                 :
         564                 : extern JSBool
         565                 : EvaluateInEnv(JSContext *cx, Env *env, StackFrame *fp, const jschar *chars,
         566                 :               unsigned length, const char *filename, unsigned lineno, Value *rval);
         567                 :
         568                 : }
         569                 :
         570                 : #endif /* Debugger_h__ */

Generated by: LCOV version 1.7