diff --git a/js/public/ProfilingFrameIterator.h b/js/public/ProfilingFrameIterator.h index 37cd8658b686..cf6c565d81da 100644 --- a/js/public/ProfilingFrameIterator.h +++ b/js/public/ProfilingFrameIterator.h @@ -109,7 +109,7 @@ class JS_PUBLIC_API(ProfilingFrameIterator) void *returnAddress; void *activation; const char *label; - bool hasTrackedOptimizations; + bool mightHaveTrackedOptimizations; }; uint32_t extractStack(Frame *frames, uint32_t offset, uint32_t end) const; diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index b247c51b1d8b..8f7fb194d969 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -1862,7 +1862,7 @@ JS::ProfilingFrameIterator::extractStack(Frame *frames, uint32_t offset, uint32_ frames[offset].returnAddress = nullptr; frames[offset].activation = activation_; frames[offset].label = asmJSIter().label(); - frames[offset].hasTrackedOptimizations = false; + frames[offset].mightHaveTrackedOptimizations = false; return 1; } @@ -1898,21 +1898,16 @@ JS::ProfilingFrameIterator::extractStack(Frame *frames, uint32_t offset, uint32_ frames[offset + i].returnAddress = returnAddr; frames[offset + i].activation = activation_; frames[offset + i].label = labels[i]; - frames[offset + i].hasTrackedOptimizations = false; + frames[offset + i].mightHaveTrackedOptimizations = false; } - // Extract the index into the side table of optimization information and - // store it on the youngest frame. All inlined frames will have the same - // optimization information by virtue of sharing the JitcodeGlobalEntry, - // but such information is only interpretable on the youngest frame. + // A particular return address might have tracked optimizations only if + // there are any optimizations at all. // - // FIXMEshu: disabled until we can ensure the optimization info is live - // when we write out the JSON stream of the profile. - if (false && entry.hasTrackedOptimizations()) { - uint32_t dummy; - mozilla::Maybe index = entry.trackedOptimizationIndexAtAddr(returnAddr, &dummy); - frames[offset].hasTrackedOptimizations = index.isSome(); - } + // All inlined Ion frames will have the same optimization information by + // virtue of sharing the JitcodeGlobalEntry, but such information is only + // interpretable on the youngest frame. + frames[offset].mightHaveTrackedOptimizations = entry.hasTrackedOptimizations(); return depth; } diff --git a/tools/profiler/ProfileEntry.cpp b/tools/profiler/ProfileEntry.cpp index da93db056013..c714472cc5bc 100644 --- a/tools/profiler/ProfileEntry.cpp +++ b/tools/profiler/ProfileEntry.cpp @@ -343,7 +343,7 @@ void UniqueJITOptimizations::stream(JSStreamWriter& b, JSRuntime* rt) } void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JSRuntime* rt, - UniqueJITOptimizations &aUniqueOpts) + UniqueJITOptimizations& aUniqueOpts) { b.BeginArray(); @@ -468,7 +468,8 @@ void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JS } readAheadPos = (framePos + incBy) % mEntrySize; if (readAheadPos != mWritePos && - mEntries[readAheadPos].mTagName == 'J') { + (mEntries[readAheadPos].mTagName == 'J' || + mEntries[readAheadPos].mTagName == 'O')) { void* pc = mEntries[readAheadPos].mTagPtr; // TODOshu: cannot stream tracked optimization info if @@ -486,11 +487,16 @@ void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JS // Sampled JIT optimizations are deduplicated by // aUniqueOpts to save space. Stream an index that // references into the optimizations array. - Maybe optsIndex = aUniqueOpts.getIndex(pc, rt); - if (optsIndex.isSome()) { - b.NameValue("optsIndex", optsIndex.value()); + bool mightHaveTrackedOpts = mEntries[readAheadPos].mTagName == 'O'; + if (mightHaveTrackedOpts) { + Maybe optsIndex = aUniqueOpts.getIndex(pc, rt); + if (optsIndex.isSome()) { + b.NameValue("optsIndex", optsIndex.value()); + } } } + + incBy++; } b.EndObject(); } diff --git a/tools/profiler/TableTicker.cpp b/tools/profiler/TableTicker.cpp index 2d419a639930..9cec5dce6219 100644 --- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -596,11 +596,16 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native // Check to see if JS jit stack frame is top-most if (jsStackAddr > nativeStackAddr) { MOZ_ASSERT(jsIndex >= 0); - addDynamicTag(aProfile, 'c', jsFrames[jsIndex].label); + const JS::ProfilingFrameIterator::Frame& jsFrame = jsFrames[jsIndex]; + addDynamicTag(aProfile, 'c', jsFrame.label); - // Stringifying optimization information is delayed until streaming - // time. To re-lookup the entry in the JitcodeGlobalTable, we need to - // store the JIT code address ('J') in the circular buffer. + // Stringifying optimization information and the JIT tier is delayed + // until streaming time. To re-lookup the entry in the + // JitcodeGlobalTable, we need to store the JIT code address in the + // circular buffer. + // + // Frames which may have optimization information are tagged by an 'O' + // entry. Otherwise they are tagged by a 'J' entry. // // Note that we cannot do this when we are sychronously sampling the // current thread; that is, when called from profiler_get_backtrace. The @@ -611,12 +616,11 @@ void mergeStacksIntoProfile(ThreadProfile& aProfile, TickSample* aSample, Native // its JIT code. This means that if we inserted such 'J' entries into // the buffer, nsRefreshDriver would now be holding on to a backtrace // with stale JIT code return addresses. - MOZ_ASSERT_IF(jsFrames[jsIndex].hasTrackedOptimizations, - jsFrames[jsIndex].kind == JS::ProfilingFrameIterator::Frame_Ion); if (!aSample->isSamplingCurrentThread && - (jsFrames[jsIndex].kind == JS::ProfilingFrameIterator::Frame_Ion || - jsFrames[jsIndex].kind == JS::ProfilingFrameIterator::Frame_Baseline)) { - aProfile.addTag(ProfileEntry('J', jsFrames[jsIndex].returnAddress)); + (jsFrame.kind == JS::ProfilingFrameIterator::Frame_Ion || + jsFrame.kind == JS::ProfilingFrameIterator::Frame_Baseline)) { + char entryTag = jsFrame.mightHaveTrackedOptimizations ? 'O' : 'J'; + aProfile.addTag(ProfileEntry(entryTag, jsFrames[jsIndex].returnAddress)); } jsIndex--;