1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/vm/SavedStacks.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,144 @@ 1.4 + 1.5 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.6 + * vim: set ts=8 sts=4 et sw=4 tw=99: 1.7 + * This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#ifndef vm_SavedStacks_h 1.12 +#define vm_SavedStacks_h 1.13 + 1.14 +#include "jscntxt.h" 1.15 +#include "js/HashTable.h" 1.16 +#include "vm/Stack.h" 1.17 + 1.18 +namespace js { 1.19 + 1.20 +class SavedFrame : public JSObject { 1.21 + friend class SavedStacks; 1.22 + 1.23 + public: 1.24 + static const Class class_; 1.25 + static void finalize(FreeOp *fop, JSObject *obj); 1.26 + 1.27 + // Prototype methods and properties to be exposed to JS. 1.28 + static const JSPropertySpec properties[]; 1.29 + static const JSFunctionSpec methods[]; 1.30 + static bool construct(JSContext *cx, unsigned argc, Value *vp); 1.31 + static bool sourceProperty(JSContext *cx, unsigned argc, Value *vp); 1.32 + static bool lineProperty(JSContext *cx, unsigned argc, Value *vp); 1.33 + static bool columnProperty(JSContext *cx, unsigned argc, Value *vp); 1.34 + static bool functionDisplayNameProperty(JSContext *cx, unsigned argc, Value *vp); 1.35 + static bool parentProperty(JSContext *cx, unsigned argc, Value *vp); 1.36 + static bool toStringMethod(JSContext *cx, unsigned argc, Value *vp); 1.37 + 1.38 + // Convenient getters for SavedFrame's reserved slots for use from C++. 1.39 + JSAtom *getSource(); 1.40 + size_t getLine(); 1.41 + size_t getColumn(); 1.42 + JSAtom *getFunctionDisplayName(); 1.43 + SavedFrame *getParent(); 1.44 + JSPrincipals *getPrincipals(); 1.45 + 1.46 + bool isSelfHosted(); 1.47 + 1.48 + struct Lookup; 1.49 + struct HashPolicy; 1.50 + 1.51 + typedef HashSet<SavedFrame *, 1.52 + HashPolicy, 1.53 + SystemAllocPolicy> Set; 1.54 + 1.55 + private: 1.56 + void initFromLookup(Lookup &lookup); 1.57 + 1.58 + enum { 1.59 + // The reserved slots in the SavedFrame class. 1.60 + JSSLOT_SOURCE, 1.61 + JSSLOT_LINE, 1.62 + JSSLOT_COLUMN, 1.63 + JSSLOT_FUNCTIONDISPLAYNAME, 1.64 + JSSLOT_PARENT, 1.65 + JSSLOT_PRINCIPALS, 1.66 + JSSLOT_PRIVATE_PARENT, 1.67 + 1.68 + // The total number of reserved slots in the SavedFrame class. 1.69 + JSSLOT_COUNT 1.70 + }; 1.71 + 1.72 + // Because we hash the parent pointer, we need to rekey a saved frame 1.73 + // whenever its parent was relocated by the GC. However, the GC doesn't 1.74 + // notify us when this occurs. As a work around, we keep a duplicate copy of 1.75 + // the parent pointer as a private value in a reserved slot. Whenever the 1.76 + // private value parent pointer doesn't match the regular parent pointer, we 1.77 + // know that GC moved the parent and we need to update our private value and 1.78 + // rekey the saved frame in its hash set. These two methods are helpers for 1.79 + // this process. 1.80 + bool parentMoved(); 1.81 + void updatePrivateParent(); 1.82 + 1.83 + static SavedFrame *checkThis(JSContext *cx, CallArgs &args, const char *fnName); 1.84 +}; 1.85 + 1.86 +struct SavedFrame::Lookup { 1.87 + Lookup(JSAtom *source, size_t line, size_t column, JSAtom *functionDisplayName, 1.88 + Handle<SavedFrame*> parent, JSPrincipals *principals) 1.89 + : source(source), 1.90 + line(line), 1.91 + column(column), 1.92 + functionDisplayName(functionDisplayName), 1.93 + parent(parent), 1.94 + principals(principals) 1.95 + { 1.96 + JS_ASSERT(source); 1.97 + } 1.98 + 1.99 + JSAtom *source; 1.100 + size_t line; 1.101 + size_t column; 1.102 + JSAtom *functionDisplayName; 1.103 + Handle<SavedFrame*> parent; 1.104 + JSPrincipals *principals; 1.105 +}; 1.106 + 1.107 +struct SavedFrame::HashPolicy 1.108 +{ 1.109 + typedef SavedFrame::Lookup Lookup; 1.110 + typedef PointerHasher<SavedFrame *, 3> SavedFramePtrHasher; 1.111 + typedef PointerHasher<JSPrincipals *, 3> JSPrincipalsPtrHasher; 1.112 + 1.113 + static HashNumber hash(const Lookup &lookup); 1.114 + static bool match(SavedFrame *existing, const Lookup &lookup); 1.115 + 1.116 + typedef SavedFrame* Key; 1.117 + static void rekey(Key &key, const Key &newKey); 1.118 +}; 1.119 + 1.120 +class SavedStacks { 1.121 + public: 1.122 + SavedStacks() : frames(), savedFrameProto(nullptr) { } 1.123 + 1.124 + bool init(); 1.125 + bool initialized() const { return frames.initialized(); } 1.126 + bool saveCurrentStack(JSContext *cx, MutableHandle<SavedFrame*> frame); 1.127 + void sweep(JSRuntime *rt); 1.128 + uint32_t count(); 1.129 + void clear(); 1.130 + 1.131 + size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.132 + 1.133 + private: 1.134 + SavedFrame::Set frames; 1.135 + JSObject *savedFrameProto; 1.136 + 1.137 + bool insertFrames(JSContext *cx, ScriptFrameIter &iter, MutableHandle<SavedFrame*> frame); 1.138 + SavedFrame *getOrCreateSavedFrame(JSContext *cx, SavedFrame::Lookup &lookup); 1.139 + // |SavedFrame.prototype| is created lazily and held weakly. It should only 1.140 + // be accessed through this method. 1.141 + JSObject *getOrCreateSavedFramePrototype(JSContext *cx); 1.142 + SavedFrame *createFrameFromLookup(JSContext *cx, SavedFrame::Lookup &lookup); 1.143 +}; 1.144 + 1.145 +} /* namespace js */ 1.146 + 1.147 +#endif /* vm_SavedStacks_h */