author | Birunthan Mohanathas <birunthan@mohanathas.com> |
Tue, 24 Sep 2013 22:59:43 -0400 | |
changeset 148619 | 5d34afe94163e58ad32ded6f3bc47e3c389b1e60 |
parent 148618 | 0a28d2e865e47f512f34a038051fce2c7987731e |
child 148620 | 0b4ab192b28984ac0056c091713bc02fd67b4d58 |
push id | 25349 |
push user | ryanvm@gmail.com |
push date | Wed, 25 Sep 2013 18:52:12 +0000 |
treeherder | mozilla-central@39f30376058c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ehsan |
bugs | 784739 |
milestone | 27.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/js/src/devtools/Instruments.cpp +++ b/js/src/devtools/Instruments.cpp @@ -65,17 +65,17 @@ private: SYMBOL(DTPerformanceSessionCreate) \ SYMBOL(DTPerformanceSessionAddInstrument) \ SYMBOL(DTPerformanceSessionIsRecording) \ SYMBOL(DTPerformanceSessionStart) \ SYMBOL(DTPerformanceSessionStop) \ SYMBOL(DTPerformanceSessionSave) #define SYMBOL(_sym) \ - _sym##Function _sym = NULL; + _sym##Function _sym = nullptr; DTPERFORMANCE_SYMBOLS #undef SYMBOL void* LoadDTPerformanceLibraries(bool dontLoad) { @@ -101,17 +101,17 @@ LoadDTPerformanceLibrary() return false; } } #define SYMBOL(_sym) \ _sym = reinterpret_cast<_sym##Function>(dlsym(DTPerformanceLibrary, #_sym)); \ if (!_sym) { \ dlclose(DTPerformanceLibrary); \ - DTPerformanceLibrary = NULL; \ + DTPerformanceLibrary = nullptr; \ return false; \ } DTPERFORMANCE_SYMBOLS #undef SYMBOL dlclose(DTPerformanceLibrary); @@ -120,26 +120,27 @@ LoadDTPerformanceLibrary() } static DTPerformanceSessionRef gSession; bool Error(CFErrorRef error) { if (gSession) { - CFErrorRef unused = NULL; - DTPerformanceSessionStop(gSession, NULL, &unused); + CFErrorRef unused = nullptr; + DTPerformanceSessionStop(gSession, nullptr, &unused); CFRelease(gSession); - gSession = NULL; + gSession = nullptr; } #ifdef DEBUG AutoReleased<CFDataRef> data = - CFStringCreateExternalRepresentation(NULL, CFErrorCopyDescription(error), + CFStringCreateExternalRepresentation(nullptr, + CFErrorCopyDescription(error), kCFStringEncodingUTF8, '?'); - if (data != NULL) { + if (data != nullptr) { printf("%.*s\n\n", (int)CFDataGetLength(data), CFDataGetBytePtr(data)); } #endif return false; } bool Start() @@ -148,22 +149,23 @@ Start() return false; } if (!LoadDTPerformanceLibrary()) { return false; } AutoReleased<CFStringRef> process = - CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"), getpid()); + CFStringCreateWithFormat(kCFAllocatorDefault, nullptr, CFSTR("%d"), + getpid()); if (!process) { return false; } - CFErrorRef error = NULL; - gSession = DTPerformanceSessionCreate(NULL, process, NULL, &error); + CFErrorRef error = nullptr; + gSession = DTPerformanceSessionCreate(nullptr, process, nullptr, &error); if (!gSession) { return Error(error); } AutoReleased<CFNumberRef> interval = CFNumberCreate(0, kCFNumberIntType, &kSamplingInterval); if (!interval) { return false; @@ -175,59 +177,59 @@ Start() (const void**)values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!options) { return false; } if (!DTPerformanceSessionAddInstrument(gSession, CFSTR(DTPerformanceSession_TimeProfiler), - options, NULL, &error)) { + options, nullptr, &error)) { return Error(error); } return Resume(); } void Pause() { if (gSession && DTPerformanceSessionIsRecording(gSession)) { - CFErrorRef error = NULL; - if (!DTPerformanceSessionStop(gSession, NULL, &error)) { + CFErrorRef error = nullptr; + if (!DTPerformanceSessionStop(gSession, nullptr, &error)) { Error(error); } } } bool Resume() { if (!gSession) { return false; } - CFErrorRef error = NULL; - return DTPerformanceSessionStart(gSession, NULL, &error) || + CFErrorRef error = nullptr; + return DTPerformanceSessionStart(gSession, nullptr, &error) || Error(error); } void Stop(const char* profileName) { Pause(); - CFErrorRef error = NULL; + CFErrorRef error = nullptr; AutoReleased<CFStringRef> name = - CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%s%s"), "/tmp/", - profileName ? profileName : "mozilla"); + CFStringCreateWithFormat(kCFAllocatorDefault, nullptr, CFSTR("%s%s"), + "/tmp/", profileName ? profileName : "mozilla"); if (!DTPerformanceSessionSave(gSession, name, &error)) { Error(error); return; } CFRelease(gSession); - gSession = NULL; + gSession = nullptr; } } // namespace Instruments #endif /* __APPLE__ */
--- a/js/src/ds/InlineMap.h +++ b/js/src/ds/InlineMap.h @@ -219,17 +219,17 @@ class InlineMap if (usingMap()) return Ptr(map.lookup(key)); for (InlineElem *it = inl, *end = inl + inlNext; it != end; ++it) { if (it->key == key) return Ptr(it); } - return Ptr(NULL); + return Ptr(nullptr); } JS_ALWAYS_INLINE AddPtr lookupForAdd(const K &key) { if (usingMap()) return AddPtr(map.lookupForAdd(key)); for (InlineElem *it = inl, *end = inl + inlNext; it != end; ++it) { @@ -278,18 +278,18 @@ class InlineMap } return add(p, key, value); } void remove(Ptr p) { JS_ASSERT(p); if (p.isInlinePtr) { JS_ASSERT(inlCount > 0); - JS_ASSERT(p.inlPtr->key != NULL); - p.inlPtr->key = NULL; + JS_ASSERT(p.inlPtr->key != nullptr); + p.inlPtr->key = nullptr; --inlCount; return; } JS_ASSERT(map.initialized() && usingMap()); map.remove(p.mapPtr); } void remove(const K &key) { @@ -302,44 +302,44 @@ class InlineMap friend class InlineMap; WordMapRange mapRange; InlineElem *cur; InlineElem *end; bool isInline; explicit Range(WordMapRange r) - : cur(NULL), end(NULL), /* Avoid GCC 4.3.3 over-warning. */ + : cur(nullptr), end(nullptr), /* Avoid GCC 4.3.3 over-warning. */ isInline(false) { mapRange = r; JS_ASSERT(!isInlineRange()); } Range(const InlineElem *begin, const InlineElem *end_) : cur(const_cast<InlineElem *>(begin)), end(const_cast<InlineElem *>(end_)), isInline(true) { advancePastNulls(cur); JS_ASSERT(isInlineRange()); } bool checkInlineRangeInvariants() const { JS_ASSERT(uintptr_t(cur) <= uintptr_t(end)); - JS_ASSERT_IF(cur != end, cur->key != NULL); + JS_ASSERT_IF(cur != end, cur->key != nullptr); return true; } bool isInlineRange() const { JS_ASSERT_IF(isInline, checkInlineRangeInvariants()); return isInline; } void advancePastNulls(InlineElem *begin) { InlineElem *newCur = begin; - while (newCur < end && NULL == newCur->key) + while (newCur < end && nullptr == newCur->key) ++newCur; JS_ASSERT(uintptr_t(newCur) <= uintptr_t(end)); cur = newCur; } void bumpCurPtr() { JS_ASSERT(isInlineRange()); advancePastNulls(cur + 1);
--- a/js/src/ds/LifoAlloc.cpp +++ b/js/src/ds/LifoAlloc.cpp @@ -17,17 +17,17 @@ namespace js { namespace detail { BumpChunk * BumpChunk::new_(size_t chunkSize) { JS_ASSERT(RoundUpPow2(chunkSize) == chunkSize); void *mem = js_malloc(chunkSize); if (!mem) - return NULL; + return nullptr; BumpChunk *result = new (mem) BumpChunk(chunkSize - sizeof(BumpChunk)); // We assume that the alignment of sAlign is less than that of // the underlying memory allocator -- creating a new BumpChunk should // always satisfy the sAlign alignment constraint. JS_ASSERT(AlignPtr(result->bump) == result->bump); return result; } @@ -60,17 +60,17 @@ void LifoAlloc::freeAll() { while (first) { BumpChunk *victim = first; first = first->next(); decrementCurSize(victim->computedSizeOfIncludingThis()); BumpChunk::delete_(victim); } - first = latest = last = NULL; + first = latest = last = nullptr; // Nb: maintaining curSize_ correctly isn't easy. Fortunately, this is an // excellent sanity check. JS_ASSERT(curSize_ == 0); } LifoAlloc::BumpChunk * LifoAlloc::getOrCreateChunk(size_t n) @@ -88,28 +88,28 @@ LifoAlloc::getOrCreateChunk(size_t n) size_t defaultChunkFreeSpace = defaultChunkSize_ - sizeof(BumpChunk); size_t chunkSize; if (n > defaultChunkFreeSpace) { size_t allocSizeWithHeader = n + sizeof(BumpChunk); // Guard for overflow. if (allocSizeWithHeader < n || (allocSizeWithHeader & (size_t(1) << (BitSize<size_t>::value - 1)))) { - return NULL; + return nullptr; } chunkSize = RoundUpPow2(allocSizeWithHeader); } else { chunkSize = defaultChunkSize_; } // If we get here, we couldn't find an existing BumpChunk to fill the request. BumpChunk *newChunk = BumpChunk::new_(chunkSize); if (!newChunk) - return NULL; + return nullptr; if (!first) { latest = first = last = newChunk; } else { JS_ASSERT(latest && !latest->next()); latest->setNext(newChunk); latest = last = newChunk; } @@ -129,17 +129,17 @@ LifoAlloc::transferFrom(LifoAlloc *other if (!other->first) return; incrementCurSize(other->curSize_); if (other->isEmpty()) appendUnused(other->first, other->last); else appendUsed(other->first, other->latest, other->last); - other->first = other->last = other->latest = NULL; + other->first = other->last = other->latest = nullptr; other->curSize_ = 0; } void LifoAlloc::transferUnusedFrom(LifoAlloc *other) { JS_ASSERT(!markCount); JS_ASSERT(latest == first); @@ -159,12 +159,12 @@ LifoAlloc::transferUnusedFrom(LifoAlloc for (BumpChunk *chunk = other->latest->next(); chunk; chunk = chunk->next()) { size_t size = chunk->computedSizeOfIncludingThis(); incrementCurSize(size); other->decrementCurSize(size); } } appendUnused(other->latest->next(), other->last); - other->latest->setNext(NULL); + other->latest->setNext(nullptr); other->last = other->latest; } }
--- a/js/src/ds/LifoAlloc.h +++ b/js/src/ds/LifoAlloc.h @@ -50,17 +50,17 @@ class BumpChunk size_t bumpSpaceSize; // size of the data area char *headerBase() { return reinterpret_cast<char *>(this); } char *bumpBase() const { return limit - bumpSpaceSize; } explicit BumpChunk(size_t bumpSpaceSize) : bump(reinterpret_cast<char *>(MOZ_THIS_IN_INITIALIZER_LIST()) + sizeof(BumpChunk)), limit(bump + bumpSpaceSize), - next_(NULL), bumpSpaceSize(bumpSpaceSize) + next_(nullptr), bumpSpaceSize(bumpSpaceSize) { JS_ASSERT(bump == AlignPtr(bump)); } void setBump(void *ptr) { JS_ASSERT(bumpBase() <= ptr); JS_ASSERT(ptr <= limit); #if defined(DEBUG) || defined(MOZ_HAVE_MEM_CHECKS) @@ -125,21 +125,21 @@ class BumpChunk // Try to perform an allocation of size |n|, return null if not possible. JS_ALWAYS_INLINE void *tryAlloc(size_t n) { char *aligned = AlignPtr(bump); char *newBump = aligned + n; if (newBump > limit) - return NULL; + return nullptr; // Check for overflow. if (JS_UNLIKELY(newBump < bump)) - return NULL; + return nullptr; JS_ASSERT(canAlloc(n)); // Ensure consistency between "can" and "try". setBump(newBump); return aligned; } void *allocInfallible(size_t n) { void *result = tryAlloc(n); @@ -176,17 +176,17 @@ class LifoAlloc // and add it to the chain appropriately. // // Side effect: if retval is non-null, |first| and |latest| are initialized // appropriately. BumpChunk *getOrCreateChunk(size_t n); void reset(size_t defaultChunkSize) { JS_ASSERT(mozilla::RoundUpPow2(defaultChunkSize) == defaultChunkSize); - first = latest = last = NULL; + first = latest = last = nullptr; defaultChunkSize_ = defaultChunkSize; markCount = 0; curSize_ = 0; } // Append unused chunks to the end of this LifoAlloc. void appendUnused(BumpChunk *start, BumpChunk *end) { JS_ASSERT(start && end); @@ -262,17 +262,17 @@ class LifoAlloc void *alloc(size_t n) { JS_OOM_POSSIBLY_FAIL(); void *result; if (latest && (result = latest->tryAlloc(n))) return result; if (!getOrCreateChunk(n)) - return NULL; + return nullptr; return latest->allocInfallible(n); } JS_ALWAYS_INLINE void *allocInfallible(size_t n) { void *result; if (latest && (result = latest->tryAlloc(n))) @@ -302,17 +302,17 @@ class LifoAlloc latest = latestBefore; return true; } template <typename T> T *newArray(size_t count) { void *mem = alloc(sizeof(T) * count); if (!mem) - return NULL; + return nullptr; JS_STATIC_ASSERT(mozilla::IsPod<T>::value); return (T *) mem; } // Create an array with uninitialized elements of type |T|. // The caller is responsible for initialization. template <typename T> T *newArrayUninitialized(size_t count) { @@ -320,17 +320,17 @@ class LifoAlloc } class Mark { BumpChunk *chunk; void *markInChunk; friend class LifoAlloc; Mark(BumpChunk *chunk, void *markInChunk) : chunk(chunk), markInChunk(markInChunk) {} public: - Mark() : chunk(NULL), markInChunk(NULL) {} + Mark() : chunk(nullptr), markInChunk(nullptr) {} }; Mark mark() { markCount++; return latest ? Mark(latest, latest->mark()) : Mark(); } void release(Mark mark) { @@ -425,17 +425,17 @@ class LifoAlloc } JS_ASSERT(uintptr_t(position_) + size <= uintptr_t(chunk_->end())); } public: Enum(LifoAlloc &alloc) : alloc_(&alloc), chunk_(alloc.first), - position_(static_cast<char *>(alloc.first ? alloc.first->start() : NULL)) + position_(static_cast<char *>(alloc.first ? alloc.first->start() : nullptr)) {} // Return true if there are no more bytes to enumerate. bool empty() { return !chunk_ || (chunk_ == alloc_->latest && position_ >= chunk_->mark()); } // Move the read position forward by the size of one T.
--- a/js/src/ds/SplayTree.h +++ b/js/src/ds/SplayTree.h @@ -23,47 +23,47 @@ namespace js { template <class T, class C> class SplayTree { struct Node { T item; Node *left, *right, *parent; Node(const T &item) - : item(item), left(NULL), right(NULL), parent(NULL) + : item(item), left(nullptr), right(nullptr), parent(nullptr) {} }; LifoAlloc *alloc; Node *root, *freeList; SplayTree(const SplayTree &) MOZ_DELETE; SplayTree &operator=(const SplayTree &) MOZ_DELETE; public: - SplayTree(LifoAlloc *alloc = NULL) - : alloc(alloc), root(NULL), freeList(NULL) + SplayTree(LifoAlloc *alloc = nullptr) + : alloc(alloc), root(nullptr), freeList(nullptr) {} void setAllocator(LifoAlloc *alloc) { this->alloc = alloc; } bool empty() const { return !root; } bool contains(const T &v, T *res) { if (!root) return false; Node *last = lookup(v); splay(last); - checkCoherency(root, NULL); + checkCoherency(root, nullptr); if (C::compare(v, last->item) == 0) { *res = last->item; return true; } return false; } bool insert(const T &v) @@ -83,17 +83,17 @@ class SplayTree JS_ASSERT(cmp); Node *&parentPointer = (cmp < 0) ? last->left : last->right; JS_ASSERT(!parentPointer); parentPointer = element; element->parent = last; splay(element); - checkCoherency(root, NULL); + checkCoherency(root, nullptr); return true; } void remove(const T &v) { Node *last = lookup(v); JS_ASSERT(last && C::compare(v, last->item) == 0); @@ -111,33 +111,33 @@ class SplayTree swapChild = swap->left; } else if (root->right) { swap = root->right; while (swap->left) swap = swap->left; swapChild = swap->right; } else { freeNode(root); - root = NULL; + root = nullptr; return; } // The selected node has at most one child, in swapChild. Detach it // from the subtree by replacing it with that child. if (swap == swap->parent->left) swap->parent->left = swapChild; else swap->parent->right = swapChild; if (swapChild) swapChild->parent = swap->parent; root->item = swap->item; freeNode(swap); - checkCoherency(root, NULL); + checkCoherency(root, nullptr); } template <class Op> void forEach(Op op) { forEachInner(op, root); } @@ -250,31 +250,31 @@ class SplayTree forEachInner(op, node->right); } Node *checkCoherency(Node *node, Node *minimum) { #ifdef DEBUG if (!node) { JS_ASSERT(!root); - return NULL; + return nullptr; } JS_ASSERT_IF(!node->parent, node == root); JS_ASSERT_IF(minimum, C::compare(minimum->item, node->item) < 0); if (node->left) { JS_ASSERT(node->left->parent == node); Node *leftMaximum = checkCoherency(node->left, minimum); JS_ASSERT(C::compare(leftMaximum->item, node->item) < 0); } if (node->right) { JS_ASSERT(node->right->parent == node); return checkCoherency(node->right, node); } return node; #else - return NULL; + return nullptr; #endif } }; } /* namespace js */ #endif /* ds_SplayTree_h */
--- a/js/src/gdb/gdb-tests.cpp +++ b/js/src/gdb/gdb-tests.cpp @@ -49,35 +49,35 @@ void reportError(JSContext *cx, const ch void breakpoint() { // If we leave this function empty, the linker will unify it with other // empty functions throughout SpiderMonkey. If we then set a GDB // breakpoint on it, that breakpoint will hit at all sorts of random // times. So make it perform a distinctive side effect. fprintf(stderr, "Called " __FILE__ ":breakpoint\n"); } -GDBFragment *GDBFragment::allFragments = NULL; +GDBFragment *GDBFragment::allFragments = nullptr; int main (int argc, const char **argv) { JSRuntime *runtime = checkPtr(JS_NewRuntime(1024 * 1024, JS_USE_HELPER_THREADS)); JS_SetGCParameter(runtime, JSGC_MAX_BYTES, 0xffffffff); JS_SetNativeStackQuota(runtime, 5000000); JSContext *cx = checkPtr(JS_NewContext(runtime, 8192)); JS_SetErrorReporter(cx, reportError); JSAutoRequest ar(cx); /* Create the global object. */ JS::CompartmentOptions options; options.setVersion(JSVERSION_LATEST); - RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, NULL, - JS::FireOnNewGlobalHook, options))); + RootedObject global(cx, checkPtr(JS_NewGlobalObject(cx, &global_class, + nullptr, JS::FireOnNewGlobalHook, options))); js::SetDefaultObjectForContext(cx, global); JSAutoCompartment ac(cx, global); /* Populate the global object with the standard globals, like Object and Array. */ checkBool(JS_InitStandardClasses(cx, global));
--- a/js/src/gdb/tests/test-JSObject.cpp +++ b/js/src/gdb/tests/test-JSObject.cpp @@ -25,16 +25,16 @@ FRAGMENT(JSObject, simple) { (void) funcPtr; (void) &plainRef; (void) &funcRef; (void) plainRaw; (void) funcRaw; } FRAGMENT(JSObject, null) { - JS::Rooted<JSObject *> null(cx, NULL); + JS::Rooted<JSObject *> null(cx, nullptr); JSObject *nullRaw = null; breakpoint(); (void) null; (void) nullRaw; }
--- a/js/src/gdb/tests/test-JSString.cpp +++ b/js/src/gdb/tests/test-JSString.cpp @@ -2,17 +2,17 @@ #include "jsatom.h" #include "jscntxt.h" // When JSGC_ANALYSIS is #defined, Rooted<JSFlatString*> needs the definition // of JSFlatString in order to figure out its ThingRootKind #include "vm/String.h" FRAGMENT(JSString, simple) { - JS::Rooted<JSString *> empty(cx, JS_NewStringCopyN(cx, NULL, 0)); + JS::Rooted<JSString *> empty(cx, JS_NewStringCopyN(cx, nullptr, 0)); JS::Rooted<JSString *> x(cx, JS_NewStringCopyN(cx, "x", 1)); JS::Rooted<JSString *> z(cx, JS_NewStringCopyZ(cx, "z")); // I expect this will be a non-inlined string. JS::Rooted<JSString *> stars(cx, JS_NewStringCopyZ(cx, "*************************" "*************************" "*************************" @@ -34,17 +34,17 @@ FRAGMENT(JSString, simple) { (void) z; (void) stars; (void) xz; (void) doubleStars; (void) xRaw; } FRAGMENT(JSString, null) { - JS::Rooted<JSString *> null(cx, NULL); + JS::Rooted<JSString *> null(cx, nullptr); JSString *nullRaw = null; breakpoint(); (void) null; (void) nullRaw; }
--- a/js/src/gdb/tests/test-Root.cpp +++ b/js/src/gdb/tests/test-Root.cpp @@ -1,13 +1,13 @@ #include "gdb-tests.h" #include "jsapi.h" FRAGMENT(Root, null) { - JS::Rooted<JSObject *> null(cx, NULL); + JS::Rooted<JSObject *> null(cx, nullptr); breakpoint(); (void) null; } void callee(JS::Handle<JSObject *> obj, JS::MutableHandle<JSObject *> mutableObj) {
--- a/js/src/perf/jsperf.cpp +++ b/js/src/perf/jsperf.cpp @@ -201,38 +201,38 @@ pm_finalize(JSFreeOp* fop, JSObject* obj // Helpers (declared above) static PerfMeasurement* GetPM(JSContext* cx, JS::HandleValue value, const char* fname) { if (!value.isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_NOT_NONNULL_OBJECT); - return NULL; + return nullptr; } RootedObject obj(cx, &value.toObject()); PerfMeasurement* p = (PerfMeasurement*) - JS_GetInstancePrivate(cx, obj, &pm_class, NULL); + JS_GetInstancePrivate(cx, obj, &pm_class, nullptr); if (p) return p; // JS_GetInstancePrivate only sets an exception if its last argument // is nonzero, so we have to do it by hand. JS_ReportErrorNumber(cx, js_GetErrorMessage, 0, JSMSG_INCOMPATIBLE_PROTO, pm_class.name, fname, JS_GetClass(obj)->name); - return NULL; + return nullptr; } namespace JS { JSObject* RegisterPerfMeasurement(JSContext *cx, JSObject *global) { RootedObject prototype(cx); - prototype = JS_InitClass(cx, global, NULL /* parent */, + prototype = JS_InitClass(cx, global, nullptr /* parent */, &pm_class, pm_construct, 1, pm_props, pm_fns, 0, 0); if (!prototype) return 0; RootedObject ctor(cx); ctor = JS_GetConstructor(cx, prototype); if (!ctor)
--- a/js/src/perf/jsperf.h +++ b/js/src/perf/jsperf.h @@ -117,17 +117,17 @@ class JS_FRIEND_API(PerfMeasurement) * Javascript object passed as an argument (this will normally be a * global object). The JS-visible API is identical to the C++ API. */ extern JS_FRIEND_API(JSObject*) RegisterPerfMeasurement(JSContext *cx, JSObject *global); /* * Given a Value which contains an instance of the aforementioned - * wrapper class, extract the C++ object. Returns NULL if the + * wrapper class, extract the C++ object. Returns nullptr if the * Value is not an instance of the wrapper. */ extern JS_FRIEND_API(PerfMeasurement*) ExtractPerfMeasurement(Value wrapper); } // namespace JS #endif /* perf_jsperf_h */