PerformanceMark.cpp (5253B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "PerformanceMark.h" 8 9 #include "MainThreadUtils.h" 10 #include "Performance.h" 11 #include "mozilla/dom/MessagePortBinding.h" 12 #include "mozilla/dom/PerformanceBinding.h" 13 #include "mozilla/dom/PerformanceMarkBinding.h" 14 #include "nsContentUtils.h" 15 #include "nsGkAtoms.h" 16 17 using namespace mozilla::dom; 18 19 PerformanceMark::PerformanceMark(nsISupports* aParent, const nsAString& aName, 20 DOMHighResTimeStamp aStartTime, 21 const JS::Handle<JS::Value>& aDetail, 22 DOMHighResTimeStamp aUnclampedStartTime) 23 : PerformanceEntry(aParent, aName, nsGkAtoms::mark), 24 mStartTime(aStartTime), 25 mDetail(aDetail), 26 mUnclampedStartTime(aUnclampedStartTime) { 27 mozilla::HoldJSObjects(this); 28 } 29 30 already_AddRefed<PerformanceMark> PerformanceMark::Constructor( 31 const GlobalObject& aGlobal, const nsAString& aMarkName, 32 const PerformanceMarkOptions& aMarkOptions, ErrorResult& aRv) { 33 const nsCOMPtr<nsIGlobalObject> global = 34 do_QueryInterface(aGlobal.GetAsSupports()); 35 return PerformanceMark::Constructor(aGlobal.Context(), global, aMarkName, 36 aMarkOptions, aRv); 37 } 38 39 already_AddRefed<PerformanceMark> PerformanceMark::Constructor( 40 JSContext* aCx, nsIGlobalObject* aGlobal, const nsAString& aMarkName, 41 const PerformanceMarkOptions& aMarkOptions, ErrorResult& aRv) { 42 RefPtr<Performance> performance = Performance::Get(aCx, aGlobal); 43 if (!performance) { 44 // This is similar to the message that occurs when accessing `performance` 45 // from outside a valid global. 46 aRv.ThrowTypeError( 47 "can't access PerformanceMark constructor, performance is null"); 48 return nullptr; 49 } 50 51 if (performance->IsGlobalObjectWindow() && 52 performance->IsPerformanceTimingAttribute(aMarkName)) { 53 aRv.ThrowSyntaxError("markName cannot be a performance timing attribute"); 54 return nullptr; 55 } 56 57 DOMHighResTimeStamp startTime = aMarkOptions.mStartTime.WasPassed() 58 ? aMarkOptions.mStartTime.Value() 59 : performance->Now(); 60 // We need to get the unclamped start time to be able to add profiler markers 61 // with precise time/duration. This is not exposed to web and only used by the 62 // profiler. 63 // If a mStartTime is passed by the user, we will always have a clamped value. 64 DOMHighResTimeStamp unclampedStartTime = aMarkOptions.mStartTime.WasPassed() 65 ? startTime 66 : performance->NowUnclamped(); 67 if (startTime < 0) { 68 aRv.ThrowTypeError("Expected startTime >= 0"); 69 return nullptr; 70 } 71 72 JS::Rooted<JS::Value> detail(aCx); 73 if (aMarkOptions.mDetail.isNullOrUndefined()) { 74 detail.setNull(); 75 } else { 76 StructuredSerializeOptions serializeOptions; 77 JS::Rooted<JS::Value> valueToClone(aCx, aMarkOptions.mDetail); 78 nsContentUtils::StructuredClone(aCx, aGlobal, valueToClone, 79 serializeOptions, &detail, aRv); 80 if (aRv.Failed()) { 81 return nullptr; 82 } 83 } 84 85 return do_AddRef(new PerformanceMark(aGlobal, aMarkName, startTime, detail, 86 unclampedStartTime)); 87 } 88 89 PerformanceMark::~PerformanceMark() { mozilla::DropJSObjects(this); } 90 91 NS_IMPL_CYCLE_COLLECTION_CLASS(PerformanceMark) 92 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PerformanceMark, 93 PerformanceEntry) 94 tmp->mDetail.setUndefined(); 95 mozilla::DropJSObjects(tmp); 96 NS_IMPL_CYCLE_COLLECTION_UNLINK_END 97 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PerformanceMark, 98 PerformanceEntry) 99 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END 100 101 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(PerformanceMark, 102 PerformanceEntry) 103 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mDetail) 104 NS_IMPL_CYCLE_COLLECTION_TRACE_END 105 106 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(PerformanceMark, 107 PerformanceEntry) 108 109 JSObject* PerformanceMark::WrapObject(JSContext* aCx, 110 JS::Handle<JSObject*> aGivenProto) { 111 return PerformanceMark_Binding::Wrap(aCx, this, aGivenProto); 112 } 113 114 void PerformanceMark::GetDetail(JSContext* aCx, 115 JS::MutableHandle<JS::Value> aRetval) { 116 // Return a copy so that this method always returns the value it is set to 117 // (i.e. it'll return the same value even if the caller assigns to it). Note 118 // that if detail is an object, its contents can be mutated and this is 119 // expected. 120 aRetval.set(mDetail); 121 } 122 123 size_t PerformanceMark::SizeOfIncludingThis( 124 mozilla::MallocSizeOf aMallocSizeOf) const { 125 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); 126 }