зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to inbound. a=merge CLOSED TREE
This commit is contained in:
Коммит
d2e89cd600
|
@ -13,7 +13,6 @@
|
|||
|
||||
#include "nsEscape.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIUUIDGenerator.h"
|
||||
|
||||
#include "mozilla/GkRustUtils.h"
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import type {
|
|||
|
||||
const breakpointSvg = document.createElement("div");
|
||||
breakpointSvg.innerHTML =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 15" width="60" height="15"><path d="M53.07.5H1.5c-.54 0-1 .46-1 1v12c0 .54.46 1 1 1h51.57c.58 0 1.15-.26 1.53-.7l4.7-6.3-4.7-6.3c-.38-.44-.95-.7-1.53-.7z"/></svg>';
|
||||
'<svg viewBox="0 0 60 15" width="60" height="15"><path d="M53.07.5H1.5c-.54 0-1 .46-1 1v12c0 .54.46 1 1 1h51.57c.58 0 1.15-.26 1.53-.7l4.7-6.3-4.7-6.3c-.38-.44-.95-.7-1.53-.7z"/></svg>';
|
||||
|
||||
type Props = {
|
||||
cx: ThreadContext,
|
||||
|
|
|
@ -30,7 +30,7 @@ type Props = {
|
|||
|
||||
const breakpointButton = document.createElement("button");
|
||||
breakpointButton.innerHTML =
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 13" width="11" height="13"><path d="M5.07.5H1.5c-.54 0-1 .46-1 1v10c0 .54.46 1 1 1h3.57c.58 0 1.15-.26 1.53-.7l3.7-5.3-3.7-5.3C6.22.76 5.65.5 5.07.5z"/></svg>';
|
||||
'<svg viewBox="0 0 11 13" width="11" height="13"><path d="M5.07.5H1.5c-.54 0-1 .46-1 1v10c0 .54.46 1 1 1h3.57c.58 0 1.15-.26 1.53-.7l3.7-5.3-3.7-5.3C6.22.76 5.65.5 5.07.5z"/></svg>';
|
||||
|
||||
function makeBookmark({ breakpoint }, { onClick, onContextMenu }) {
|
||||
const bp = breakpointButton.cloneNode(true);
|
||||
|
|
|
@ -61,14 +61,14 @@ class WhyPaused extends PureComponent<Props, State> {
|
|||
renderMessage(why: ExceptionReason) {
|
||||
if (why.type == "exception" && why.exception) {
|
||||
return (
|
||||
<div className={"message warning"}>
|
||||
<div className="message warning">
|
||||
{this.renderExceptionSummary(why.exception)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof why.message == "string") {
|
||||
return <div className={"message"}>{why.message}</div>;
|
||||
return <div className="message">{why.message}</div>;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -78,33 +78,29 @@ class WhyPaused extends PureComponent<Props, State> {
|
|||
const { endPanelCollapsed, why } = this.props;
|
||||
const reason = getPauseReason(why);
|
||||
|
||||
if (reason) {
|
||||
if (!endPanelCollapsed) {
|
||||
return (
|
||||
<div className={"pane why-paused"}>
|
||||
<div>
|
||||
<div className="pause reason">
|
||||
{L10N.getStr(reason)}
|
||||
{this.renderMessage(why)}
|
||||
</div>
|
||||
<div className="info icon">
|
||||
<AccessibleImage className="info" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (!reason || endPanelCollapsed) {
|
||||
return <div className={this.state.hideWhyPaused} />;
|
||||
}
|
||||
return <div className={this.state.hideWhyPaused} />;
|
||||
|
||||
return (
|
||||
<div className="pane why-paused">
|
||||
<div>
|
||||
<div className="pause reason">
|
||||
{L10N.getStr(reason)}
|
||||
{this.renderMessage(why)}
|
||||
</div>
|
||||
<div className="info icon">
|
||||
<AccessibleImage className="info" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const thread = getCurrentThread(state);
|
||||
return {
|
||||
endPanelCollapsed: getPaneCollapse(state, "end"),
|
||||
why: getWhy(state, thread),
|
||||
};
|
||||
};
|
||||
const mapStateToProps = state => ({
|
||||
endPanelCollapsed: getPaneCollapse(state, "end"),
|
||||
why: getWhy(state, getCurrentThread(state)),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(WhyPaused);
|
||||
|
|
|
@ -82,6 +82,15 @@ void CanonicalBrowsingContext::GetCurrentRemoteType(nsAString& aRemoteType,
|
|||
aRemoteType.Assign(cp->GetRemoteType());
|
||||
}
|
||||
|
||||
void CanonicalBrowsingContext::SetOwnerProcessId(uint64_t aProcessId) {
|
||||
MOZ_LOG(GetLog(), LogLevel::Debug,
|
||||
("SetOwnerProcessId for 0x%08" PRIx64 " (0x%08" PRIx64
|
||||
" -> 0x%08" PRIx64 ")",
|
||||
Id(), mProcessId, aProcessId));
|
||||
|
||||
mProcessId = aProcessId;
|
||||
}
|
||||
|
||||
void CanonicalBrowsingContext::GetWindowGlobals(
|
||||
nsTArray<RefPtr<WindowGlobalParent>>& aWindows) {
|
||||
aWindows.SetCapacity(mWindowGlobals.Count());
|
||||
|
@ -129,6 +138,18 @@ void CanonicalBrowsingContext::SetEmbedderWindowGlobal(
|
|||
|
||||
bool CanonicalBrowsingContext::ValidateTransaction(
|
||||
const Transaction& aTransaction, ContentParent* aProcess) {
|
||||
if (MOZ_LOG_TEST(GetLog(), LogLevel::Debug)) {
|
||||
#define MOZ_BC_FIELD(name, ...) \
|
||||
if (aTransaction.m##name.isSome()) { \
|
||||
MOZ_LOG(GetLog(), LogLevel::Debug, \
|
||||
("Validate Transaction 0x%08" PRIx64 " set " #name \
|
||||
" (from: 0x%08" PRIx64 " owner: 0x%08" PRIx64 ")", \
|
||||
Id(), aProcess ? static_cast<uint64_t>(aProcess->ChildID()) : 0, \
|
||||
mProcessId)); \
|
||||
}
|
||||
#include "mozilla/dom/BrowsingContextFieldList.h"
|
||||
}
|
||||
|
||||
// Check that the correct process is performing sets for transactions with
|
||||
// non-racy fields.
|
||||
if (aTransaction.HasNonRacyField()) {
|
||||
|
|
|
@ -38,7 +38,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
|
||||
void GetCurrentRemoteType(nsAString& aRemoteType, ErrorResult& aRv) const;
|
||||
|
||||
void SetOwnerProcessId(uint64_t aProcessId) { mProcessId = aProcessId; }
|
||||
void SetOwnerProcessId(uint64_t aProcessId);
|
||||
|
||||
void GetWindowGlobals(nsTArray<RefPtr<WindowGlobalParent>>& aWindows);
|
||||
|
||||
|
|
|
@ -175,6 +175,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
mDetachedSubdocFrame(nullptr),
|
||||
mPendingSwitchID(0),
|
||||
mChildID(0),
|
||||
mRemoteType(VoidString()),
|
||||
mDepthTooGreat(false),
|
||||
mIsTopLevelContent(false),
|
||||
mDestroyCalled(false),
|
||||
|
@ -191,6 +192,11 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
mIsRemoteFrame = ShouldUseRemoteProcess();
|
||||
MOZ_ASSERT(!mIsRemoteFrame || !mBrowsingContext->HasOpener(),
|
||||
"Cannot pass aOpener for a remote frame!");
|
||||
|
||||
if (mIsRemoteFrame &&
|
||||
!aOwner->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType, mRemoteType)) {
|
||||
mRemoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
||||
|
@ -200,6 +206,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
mDetachedSubdocFrame(nullptr),
|
||||
mPendingSwitchID(0),
|
||||
mChildID(0),
|
||||
mRemoteType(VoidString()),
|
||||
mDepthTooGreat(false),
|
||||
mIsTopLevelContent(false),
|
||||
mDestroyCalled(false),
|
||||
|
@ -216,6 +223,7 @@ nsFrameLoader::nsFrameLoader(Element* aOwner, BrowsingContext* aBrowsingContext,
|
|||
if (aOptions.mRemoteType.WasPassed() &&
|
||||
(!aOptions.mRemoteType.Value().IsVoid())) {
|
||||
mIsRemoteFrame = true;
|
||||
mRemoteType = aOptions.mRemoteType.Value();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2661,14 +2669,13 @@ bool nsFrameLoader::TryRemoteBrowserInternal() {
|
|||
if (XRE_IsContentProcess()) {
|
||||
mBrowsingContext->SetEmbedderElement(mOwnerContent);
|
||||
|
||||
mRemoteBrowser = ContentChild::CreateBrowser(
|
||||
this, context, NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
|
||||
mBrowsingContext);
|
||||
mRemoteBrowser = ContentChild::CreateBrowser(this, context, mRemoteType,
|
||||
mBrowsingContext);
|
||||
return !!mRemoteBrowser;
|
||||
}
|
||||
|
||||
mRemoteBrowser = ContentParent::CreateBrowser(
|
||||
context, ownerElement, mBrowsingContext, openerContentParent,
|
||||
context, ownerElement, mRemoteType, mBrowsingContext, openerContentParent,
|
||||
sameTabGroupAs, nextRemoteTabId);
|
||||
if (!mRemoteBrowser) {
|
||||
return false;
|
||||
|
|
|
@ -512,6 +512,8 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
|
||||
RefPtr<mozilla::dom::TabListener> mSessionStoreListener;
|
||||
|
||||
nsString mRemoteType;
|
||||
|
||||
bool mDepthTooGreat : 1;
|
||||
bool mIsTopLevelContent : 1;
|
||||
bool mDestroyCalled : 1;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#ifndef WEBGLCONTEXT_H_
|
||||
#define WEBGLCONTEXT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
|
@ -1507,7 +1508,8 @@ class WebGLContext : public nsICanvasRenderingContextInternal,
|
|||
|
||||
mutable GLenum mWebGLError;
|
||||
|
||||
webgl::ShaderValidator* CreateShaderValidator(GLenum shaderType) const;
|
||||
std::unique_ptr<webgl::ShaderValidator> CreateShaderValidator(
|
||||
GLenum shaderType) const;
|
||||
|
||||
// some GL constants
|
||||
uint32_t mGLMaxTextureUnits = 0;
|
||||
|
|
|
@ -474,51 +474,46 @@ static RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
|
|||
|
||||
{
|
||||
const auto& fragShader = prog->FragShader();
|
||||
MOZ_RELEASE_ASSERT(fragShader);
|
||||
MOZ_RELEASE_ASSERT(fragShader->Validator());
|
||||
const auto& handle = fragShader->Validator()->mHandle;
|
||||
const auto version = sh::GetShaderVersion(handle);
|
||||
const auto& compileResults = fragShader->CompileResults();
|
||||
const auto version = compileResults->mShaderVersion;
|
||||
|
||||
const auto fnAddInfo = [&](const webgl::FragOutputInfo& x) {
|
||||
info->fragOutputs.insert({x.loc, x});
|
||||
};
|
||||
|
||||
if (version == 300) {
|
||||
const auto& fragOutputs = sh::GetOutputVariables(handle);
|
||||
if (fragOutputs) {
|
||||
for (const auto& cur : *fragOutputs) {
|
||||
auto loc = cur.location;
|
||||
if (loc == -1) loc = 0;
|
||||
for (const auto& cur : compileResults->mOutputVariables) {
|
||||
auto loc = cur.location;
|
||||
if (loc == -1) loc = 0;
|
||||
|
||||
const auto info = webgl::FragOutputInfo{
|
||||
uint8_t(loc), nsCString(cur.name.c_str()),
|
||||
nsCString(cur.mappedName.c_str()), FragOutputBaseType(cur.type)};
|
||||
if (!cur.isArray()) {
|
||||
fnAddInfo(info);
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(cur.arraySizes.size() == 1);
|
||||
for (uint32_t i = 0; i < cur.arraySizes[0]; ++i) {
|
||||
const auto indexStr = nsPrintfCString("[%u]", i);
|
||||
const auto info = webgl::FragOutputInfo{
|
||||
uint8_t(loc), nsCString(cur.name.c_str()),
|
||||
nsCString(cur.mappedName.c_str()), FragOutputBaseType(cur.type)};
|
||||
if (!cur.isArray()) {
|
||||
fnAddInfo(info);
|
||||
continue;
|
||||
}
|
||||
MOZ_ASSERT(cur.arraySizes.size() == 1);
|
||||
for (uint32_t i = 0; i < cur.arraySizes[0]; ++i) {
|
||||
const auto indexStr = nsPrintfCString("[%u]", i);
|
||||
|
||||
auto userName = info.userName;
|
||||
userName.Append(indexStr);
|
||||
auto mappedName = info.mappedName;
|
||||
mappedName.Append(indexStr);
|
||||
auto userName = info.userName;
|
||||
userName.Append(indexStr);
|
||||
auto mappedName = info.mappedName;
|
||||
mappedName.Append(indexStr);
|
||||
|
||||
const auto indexedInfo = webgl::FragOutputInfo{
|
||||
uint8_t(info.loc + i), userName, mappedName, info.baseType};
|
||||
fnAddInfo(indexedInfo);
|
||||
}
|
||||
const auto indexedInfo = webgl::FragOutputInfo{
|
||||
uint8_t(info.loc + i), userName, mappedName, info.baseType};
|
||||
fnAddInfo(indexedInfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// ANGLE's translator doesn't tell us about non-user frag outputs. :(
|
||||
|
||||
const auto& translatedSource = fragShader->TranslatedSource();
|
||||
const auto& translatedSource = compileResults->mObjectCode;
|
||||
uint32_t drawBuffers = 1;
|
||||
if (translatedSource.Find("(gl_FragData[1]") != -1 ||
|
||||
translatedSource.Find("(webgl_FragData[1]") != -1) {
|
||||
if (translatedSource.find("(gl_FragData[1]") != std::string::npos ||
|
||||
translatedSource.find("(webgl_FragData[1]") != std::string::npos) {
|
||||
// The matching with the leading '(' prevents cleverly-named user vars
|
||||
// breaking this. Since ANGLE initializes all outputs, if this is an MRT
|
||||
// shader, FragData[1] will be present. FragData[0] is valid for non-MRT
|
||||
|
@ -536,10 +531,8 @@ static RefPtr<const webgl::LinkedProgramInfo> QueryProgramInfo(
|
|||
}
|
||||
|
||||
const auto& vertShader = prog->VertShader();
|
||||
MOZ_RELEASE_ASSERT(vertShader);
|
||||
MOZ_RELEASE_ASSERT(vertShader->Validator());
|
||||
const auto& handle = vertShader->Validator()->mHandle;
|
||||
const auto numViews = sh::GetVertexShaderNumViews(handle);
|
||||
const auto& vertCompileResults = vertShader->CompileResults();
|
||||
const auto numViews = vertCompileResults->mVertexShaderNumViews;
|
||||
if (numViews != -1) {
|
||||
info->zLayerCount = AssertedCast<uint8_t>(numViews);
|
||||
}
|
||||
|
@ -1153,13 +1146,15 @@ bool WebGLProgram::ValidateForLink() {
|
|||
mLinkLog.AssignLiteral("Must have a compiled vertex shader attached.");
|
||||
return false;
|
||||
}
|
||||
const auto& vertInfo = *mVertShader->CompileResults();
|
||||
|
||||
if (!mFragShader || !mFragShader->IsCompiled()) {
|
||||
mLinkLog.AssignLiteral("Must have an compiled fragment shader attached.");
|
||||
return false;
|
||||
}
|
||||
const auto& fragInfo = *mFragShader->CompileResults();
|
||||
|
||||
if (!mFragShader->CanLinkTo(mVertShader, &mLinkLog)) return false;
|
||||
if (!fragInfo.CanLinkTo(vertInfo, &mLinkLog)) return false;
|
||||
|
||||
const auto& gl = mContext->gl;
|
||||
|
||||
|
|
|
@ -38,25 +38,6 @@ static void PrintLongString(const char* const begin, const size_t len) {
|
|||
printf_stderr("%s", chunkBegin);
|
||||
}
|
||||
|
||||
// On success, writes to out_validator and out_translatedSource.
|
||||
// On failure, writes to out_translationLog.
|
||||
static bool Translate(const nsACString& source,
|
||||
webgl::ShaderValidator* validator,
|
||||
nsACString* const out_translationLog,
|
||||
nsACString* const out_translatedSource) {
|
||||
if (!validator->ValidateAndTranslate(source.BeginReading())) {
|
||||
const std::string& log = sh::GetInfoLog(validator->mHandle);
|
||||
out_translationLog->Assign(log.data(), log.length());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Success
|
||||
const std::string& output = sh::GetObjectCode(validator->mHandle);
|
||||
out_translatedSource->Assign(output.data(), output.length());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
static bool SubstringStartsWith(const std::string& testStr, size_t offset,
|
||||
const char (&refStr)[N]) {
|
||||
|
@ -93,9 +74,8 @@ static void GetCompilationStatusAndLog(gl::GLContext* gl, GLuint shader,
|
|||
WebGLShader::WebGLShader(WebGLContext* webgl, GLenum type)
|
||||
: WebGLRefCountedObject(webgl),
|
||||
mGLName(webgl->gl->fCreateShader(type)),
|
||||
mType(type),
|
||||
mTranslationSuccessful(false),
|
||||
mCompilationSuccessful(false) {
|
||||
mType(type) {
|
||||
mCompileResults = std::make_unique<webgl::ShaderValidatorResults>();
|
||||
mContext->mShaders.insertBack(this);
|
||||
}
|
||||
|
||||
|
@ -119,41 +99,44 @@ void WebGLShader::ShaderSource(const nsAString& source) {
|
|||
}
|
||||
|
||||
void WebGLShader::CompileShader() {
|
||||
mValidator = nullptr;
|
||||
mTranslationSuccessful = false;
|
||||
mCompilationSuccessful = false;
|
||||
|
||||
gl::GLContext* gl = mContext->gl;
|
||||
|
||||
mValidator.reset(mContext->CreateShaderValidator(mType));
|
||||
MOZ_ASSERT(mValidator);
|
||||
|
||||
static const bool kDumpShaders = PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS");
|
||||
if (MOZ_UNLIKELY(kDumpShaders)) {
|
||||
printf_stderr("==== begin MOZ_WEBGL_DUMP_SHADERS ====\n");
|
||||
PrintLongString(mCleanSource.BeginReading(), mCleanSource.Length());
|
||||
}
|
||||
|
||||
const bool success = Translate(mCleanSource, mValidator.get(),
|
||||
&mValidationLog, &mTranslatedSource);
|
||||
{
|
||||
const auto validator = mContext->CreateShaderValidator(mType);
|
||||
MOZ_ASSERT(validator);
|
||||
|
||||
mCompileResults =
|
||||
validator->ValidateAndTranslate(mCleanSource.BeginReading());
|
||||
}
|
||||
|
||||
mCompilationLog = mCompileResults->mInfoLog.c_str();
|
||||
const auto& success = mCompileResults->mValid;
|
||||
|
||||
if (MOZ_UNLIKELY(kDumpShaders)) {
|
||||
printf_stderr("\n==== \\/ \\/ \\/ ====\n");
|
||||
if (success) {
|
||||
PrintLongString(mTranslatedSource.BeginReading(),
|
||||
mTranslatedSource.Length());
|
||||
const auto& translated = mCompileResults->mObjectCode;
|
||||
PrintLongString(translated.data(), translated.length());
|
||||
} else {
|
||||
printf_stderr("Validation failed:\n%s", mValidationLog.BeginReading());
|
||||
printf_stderr("Validation failed:\n%s",
|
||||
mCompileResults->mInfoLog.c_str());
|
||||
}
|
||||
printf_stderr("\n==== end ====\n");
|
||||
}
|
||||
|
||||
if (!success) return;
|
||||
|
||||
mTranslationSuccessful = true;
|
||||
|
||||
const char* const parts[] = {mTranslatedSource.BeginReading()};
|
||||
gl->fShaderSource(mGLName, ArrayLength(parts), parts, nullptr);
|
||||
const std::array<const char*, 1> parts = {
|
||||
mCompileResults->mObjectCode.c_str()};
|
||||
gl->fShaderSource(mGLName, parts.size(), parts.data(), nullptr);
|
||||
|
||||
gl->fCompileShader(mGLName);
|
||||
|
||||
|
@ -161,10 +144,8 @@ void WebGLShader::CompileShader() {
|
|||
&mCompilationLog);
|
||||
}
|
||||
|
||||
void WebGLShader::GetShaderInfoLog(nsAString* out) const {
|
||||
const nsCString& log =
|
||||
!mTranslationSuccessful ? mValidationLog : mCompilationLog;
|
||||
CopyASCIItoUTF16(log, *out);
|
||||
void WebGLShader::GetShaderInfoLog(nsAString* const out) const {
|
||||
CopyASCIItoUTF16(mCompilationLog, *out);
|
||||
}
|
||||
|
||||
JS::Value WebGLShader::GetShaderParameter(GLenum pname) const {
|
||||
|
@ -191,20 +172,16 @@ void WebGLShader::GetShaderSource(nsAString* out) const {
|
|||
|
||||
void WebGLShader::GetShaderTranslatedSource(nsAString* out) const {
|
||||
out->SetIsVoid(false);
|
||||
CopyASCIItoUTF16(mTranslatedSource, *out);
|
||||
const auto& wrapper =
|
||||
nsDependentCString(mCompileResults->mObjectCode.c_str());
|
||||
CopyASCIItoUTF16(wrapper, *out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WebGLShader::CanLinkTo(const WebGLShader* prev,
|
||||
nsCString* const out_log) const {
|
||||
return mValidator->CanLinkTo(prev->mValidator.get(), out_log);
|
||||
}
|
||||
|
||||
size_t WebGLShader::CalcNumSamplerUniforms() const {
|
||||
const auto& uniforms = *sh::GetUniforms(mValidator->mHandle);
|
||||
size_t accum = 0;
|
||||
for (const auto& cur : uniforms) {
|
||||
for (const auto& cur : mCompileResults->mUniforms) {
|
||||
const auto& type = cur.type;
|
||||
if (type == LOCAL_GL_SAMPLER_2D || type == LOCAL_GL_SAMPLER_CUBE) {
|
||||
accum += cur.getArraySizeProduct();
|
||||
|
@ -214,13 +191,12 @@ size_t WebGLShader::CalcNumSamplerUniforms() const {
|
|||
}
|
||||
|
||||
size_t WebGLShader::NumAttributes() const {
|
||||
return sh::GetAttributes(mValidator->mHandle)->size();
|
||||
return mCompileResults->mAttributes.size();
|
||||
}
|
||||
|
||||
void WebGLShader::BindAttribLocation(GLuint prog, const std::string& userName,
|
||||
GLuint index) const {
|
||||
const auto& attribs = *sh::GetAttributes(mValidator->mHandle);
|
||||
for (const auto& attrib : attribs) {
|
||||
for (const auto& attrib : mCompileResults->mAttributes) {
|
||||
if (attrib.name == userName) {
|
||||
mContext->gl->fBindAttribLocation(prog, index, attrib.mappedName.c_str());
|
||||
return;
|
||||
|
@ -232,8 +208,7 @@ bool WebGLShader::FindAttribUserNameByMappedName(
|
|||
const nsACString& mappedName, nsCString* const out_userName) const {
|
||||
const std::string mappedNameStr(mappedName.BeginReading());
|
||||
|
||||
const auto& attribs = *sh::GetAttributes(mValidator->mHandle);
|
||||
for (const auto& cur : attribs) {
|
||||
for (const auto& cur : mCompileResults->mAttributes) {
|
||||
if (cur.mappedName == mappedNameStr) {
|
||||
*out_userName = cur.name.c_str();
|
||||
return true;
|
||||
|
@ -247,8 +222,7 @@ bool WebGLShader::FindVaryingByMappedName(const nsACString& mappedName,
|
|||
bool* const out_isArray) const {
|
||||
const std::string mappedNameStr(mappedName.BeginReading());
|
||||
|
||||
const auto& varyings = *sh::GetVaryings(mValidator->mHandle);
|
||||
for (const auto& cur : varyings) {
|
||||
for (const auto& cur : mCompileResults->mVaryings) {
|
||||
const sh::ShaderVariable* found;
|
||||
std::string userName;
|
||||
if (!cur.findInfoByMappedName(mappedNameStr, &found, &userName)) continue;
|
||||
|
@ -267,8 +241,8 @@ bool WebGLShader::FindUniformByMappedName(const nsACString& mappedName,
|
|||
const std::string mappedNameStr(mappedName.BeginReading(),
|
||||
mappedName.Length());
|
||||
std::string userNameStr;
|
||||
if (!mValidator->FindUniformByMappedName(mappedNameStr, &userNameStr,
|
||||
out_isArray))
|
||||
if (!mCompileResults->FindUniformByMappedName(mappedNameStr, &userNameStr,
|
||||
out_isArray))
|
||||
return false;
|
||||
|
||||
*out_userName = userNameStr.c_str();
|
||||
|
@ -277,8 +251,7 @@ bool WebGLShader::FindUniformByMappedName(const nsACString& mappedName,
|
|||
|
||||
bool WebGLShader::UnmapUniformBlockName(
|
||||
const nsACString& baseMappedName, nsCString* const out_baseUserName) const {
|
||||
const auto& interfaces = *sh::GetInterfaceBlocks(mValidator->mHandle);
|
||||
for (const auto& interface : interfaces) {
|
||||
for (const auto& interface : mCompileResults->mInterfaceBlocks) {
|
||||
const nsDependentCString interfaceMappedName(interface.mappedName.data(),
|
||||
interface.mappedName.size());
|
||||
if (baseMappedName == interfaceMappedName) {
|
||||
|
@ -299,7 +272,7 @@ void WebGLShader::MapTransformFeedbackVaryings(
|
|||
out_mappedVaryings->clear();
|
||||
out_mappedVaryings->reserve(varyings.size());
|
||||
|
||||
const auto& shaderVaryings = *sh::GetVaryings(mValidator->mHandle);
|
||||
const auto& shaderVaryings = mCompileResults->mVaryings;
|
||||
|
||||
for (const auto& wideUserName : varyings) {
|
||||
const NS_LossyConvertUTF16toASCII mozUserName(
|
||||
|
@ -326,13 +299,10 @@ JSObject* WebGLShader::WrapObject(JSContext* js,
|
|||
}
|
||||
|
||||
size_t WebGLShader::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {
|
||||
size_t validatorSize = mValidator ? mallocSizeOf(mValidator.get()) : 0;
|
||||
return mallocSizeOf(this) +
|
||||
mSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mCleanSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
validatorSize +
|
||||
mValidationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mTranslatedSource.SizeOfExcludingThisIfUnshared(mallocSizeOf) +
|
||||
mCompileResults->SizeOfIncludingThis(mallocSizeOf) +
|
||||
mCompilationLog.SizeOfExcludingThisIfUnshared(mallocSizeOf);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#define WEBGL_SHADER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -21,7 +22,7 @@
|
|||
namespace mozilla {
|
||||
|
||||
namespace webgl {
|
||||
class ShaderValidator;
|
||||
class ShaderValidatorResults;
|
||||
} // namespace webgl
|
||||
|
||||
class WebGLShader final : public nsWrapperCache,
|
||||
|
@ -46,7 +47,6 @@ class WebGLShader final : public nsWrapperCache,
|
|||
void ShaderSource(const nsAString& source);
|
||||
|
||||
// Util funcs
|
||||
bool CanLinkTo(const WebGLShader* prev, nsCString* const out_log) const;
|
||||
size_t CalcNumSamplerUniforms() const;
|
||||
size_t NumAttributes() const;
|
||||
bool FindAttribUserNameByMappedName(const nsACString& mappedName,
|
||||
|
@ -60,11 +60,8 @@ class WebGLShader final : public nsWrapperCache,
|
|||
bool UnmapUniformBlockName(const nsACString& baseMappedName,
|
||||
nsCString* const out_baseUserName) const;
|
||||
|
||||
bool IsCompiled() const {
|
||||
return mTranslationSuccessful && mCompilationSuccessful;
|
||||
}
|
||||
const auto* Validator() const { return mValidator.get(); }
|
||||
const auto& TranslatedSource() const { return mTranslatedSource; }
|
||||
bool IsCompiled() const { return mCompilationSuccessful; }
|
||||
const auto& CompileResults() const { return mCompileResults; }
|
||||
|
||||
private:
|
||||
void BindAttribLocation(GLuint prog, const std::string& userName,
|
||||
|
@ -94,12 +91,9 @@ class WebGLShader final : public nsWrapperCache,
|
|||
nsString mSource;
|
||||
nsCString mCleanSource;
|
||||
|
||||
UniquePtr<webgl::ShaderValidator> mValidator;
|
||||
nsCString mValidationLog;
|
||||
bool mTranslationSuccessful;
|
||||
nsCString mTranslatedSource;
|
||||
|
||||
bool mCompilationSuccessful;
|
||||
std::unique_ptr<const webgl::ShaderValidatorResults>
|
||||
mCompileResults; // Never null.
|
||||
bool mCompilationSuccessful = false;
|
||||
nsCString mCompilationLog;
|
||||
};
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ static ShShaderOutput ShaderOutput(gl::GLContext* gl) {
|
|||
return SH_GLSL_COMPATIBILITY_OUTPUT;
|
||||
}
|
||||
|
||||
webgl::ShaderValidator* WebGLContext::CreateShaderValidator(
|
||||
std::unique_ptr<webgl::ShaderValidator> WebGLContext::CreateShaderValidator(
|
||||
GLenum shaderType) const {
|
||||
const auto spec = (IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC);
|
||||
const auto outputLanguage = ShaderOutput(gl);
|
||||
|
@ -212,27 +212,46 @@ webgl::ShaderValidator* WebGLContext::CreateShaderValidator(
|
|||
namespace webgl {
|
||||
|
||||
/*static*/
|
||||
ShaderValidator* ShaderValidator::Create(GLenum shaderType, ShShaderSpec spec,
|
||||
ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources,
|
||||
ShCompileOptions compileOptions) {
|
||||
std::unique_ptr<ShaderValidator> ShaderValidator::Create(
|
||||
GLenum shaderType, ShShaderSpec spec, ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources, ShCompileOptions compileOptions) {
|
||||
ShHandle handle =
|
||||
sh::ConstructCompiler(shaderType, spec, outputLanguage, &resources);
|
||||
MOZ_RELEASE_ASSERT(handle);
|
||||
if (!handle) return nullptr;
|
||||
|
||||
return new ShaderValidator(handle, compileOptions,
|
||||
resources.MaxVaryingVectors);
|
||||
return std::unique_ptr<ShaderValidator>(
|
||||
new ShaderValidator(handle, compileOptions, resources.MaxVaryingVectors));
|
||||
}
|
||||
|
||||
ShaderValidator::~ShaderValidator() { sh::Destruct(mHandle); }
|
||||
|
||||
bool ShaderValidator::ValidateAndTranslate(const char* source) {
|
||||
MOZ_ASSERT(!mHasRun);
|
||||
mHasRun = true;
|
||||
std::unique_ptr<const ShaderValidatorResults>
|
||||
ShaderValidator::ValidateAndTranslate(const char* const source) const {
|
||||
auto ret = std::make_unique<ShaderValidatorResults>();
|
||||
|
||||
const char* const parts[] = {source};
|
||||
return sh::Compile(mHandle, parts, ArrayLength(parts), mCompileOptions);
|
||||
const std::array<const char*, 1> parts = {source};
|
||||
ret->mValid =
|
||||
sh::Compile(mHandle, parts.data(), parts.size(), mCompileOptions);
|
||||
|
||||
ret->mInfoLog = sh::GetInfoLog(mHandle);
|
||||
|
||||
if (ret->mValid) {
|
||||
ret->mObjectCode = sh::GetObjectCode(mHandle);
|
||||
ret->mShaderVersion = sh::GetShaderVersion(mHandle);
|
||||
ret->mVertexShaderNumViews = sh::GetVertexShaderNumViews(mHandle);
|
||||
|
||||
ret->mAttributes = *sh::GetAttributes(mHandle);
|
||||
ret->mInterfaceBlocks = *sh::GetInterfaceBlocks(mHandle);
|
||||
ret->mOutputVariables = *sh::GetOutputVariables(mHandle);
|
||||
ret->mUniforms = *sh::GetUniforms(mHandle);
|
||||
ret->mVaryings = *sh::GetVaryings(mHandle);
|
||||
|
||||
ret->mMaxVaryingVectors = mMaxVaryingVectors;
|
||||
}
|
||||
|
||||
sh::ClearResults(mHandle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
|
@ -240,91 +259,58 @@ static bool StartsWith(const std::string& haystack, const char (&needle)[N]) {
|
|||
return haystack.compare(0, N - 1, needle) == 0;
|
||||
}
|
||||
|
||||
bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
||||
nsCString* const out_log) const {
|
||||
if (!prev) {
|
||||
nsPrintfCString error("Passed in NULL prev ShaderValidator.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
bool ShaderValidatorResults::CanLinkTo(const ShaderValidatorResults& vert,
|
||||
nsCString* const out_log) const {
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(vert.mValid);
|
||||
|
||||
const auto shaderVersion = sh::GetShaderVersion(mHandle);
|
||||
if (sh::GetShaderVersion(prev->mHandle) != shaderVersion) {
|
||||
if (vert.mShaderVersion != mShaderVersion) {
|
||||
nsPrintfCString error(
|
||||
"Vertex shader version %d does not match"
|
||||
" fragment shader version %d.",
|
||||
sh::GetShaderVersion(prev->mHandle), sh::GetShaderVersion(mHandle));
|
||||
vert.mShaderVersion, mShaderVersion);
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
const std::vector<sh::Uniform>* vertPtr = sh::GetUniforms(prev->mHandle);
|
||||
const std::vector<sh::Uniform>* fragPtr = sh::GetUniforms(mHandle);
|
||||
if (!vertPtr || !fragPtr) {
|
||||
nsPrintfCString error("Could not create uniform list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
for (const auto& itrFrag : mUniforms) {
|
||||
for (const auto& itrVert : vert.mUniforms) {
|
||||
if (itrVert.name != itrFrag.name) continue;
|
||||
|
||||
for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end();
|
||||
++itrFrag) {
|
||||
for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end();
|
||||
++itrVert) {
|
||||
if (itrVert->name != itrFrag->name) continue;
|
||||
|
||||
if (!itrVert->isSameUniformAtLinkTime(*itrFrag)) {
|
||||
nsPrintfCString error(
|
||||
"Uniform `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
itrFrag->name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
if (!itrVert.isSameUniformAtLinkTime(itrFrag)) {
|
||||
nsPrintfCString error(
|
||||
"Uniform `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
itrFrag.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
const auto vertVars = sh::GetInterfaceBlocks(prev->mHandle);
|
||||
const auto fragVars = sh::GetInterfaceBlocks(mHandle);
|
||||
if (!vertVars || !fragVars) {
|
||||
nsPrintfCString error("Could not create uniform block list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& fragVar : *fragVars) {
|
||||
for (const auto& vertVar : *vertVars) {
|
||||
if (vertVar.name != fragVar.name) continue;
|
||||
|
||||
if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
|
||||
nsPrintfCString error(
|
||||
"Interface block `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
fragVar.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto& vertVaryings = sh::GetVaryings(prev->mHandle);
|
||||
const auto& fragVaryings = sh::GetVaryings(mHandle);
|
||||
if (!vertVaryings || !fragVaryings) {
|
||||
nsPrintfCString error("Could not create varying list.");
|
||||
*out_log = error;
|
||||
return false;
|
||||
for (const auto& fragVar : mInterfaceBlocks) {
|
||||
for (const auto& vertVar : vert.mInterfaceBlocks) {
|
||||
if (vertVar.name != fragVar.name) continue;
|
||||
|
||||
if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
|
||||
nsPrintfCString error(
|
||||
"Interface block `%s` is not linkable between"
|
||||
" attached shaders.",
|
||||
fragVar.name.c_str());
|
||||
*out_log = error;
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<sh::ShaderVariable> staticUseVaryingList;
|
||||
|
||||
for (const auto& fragVarying : *fragVaryings) {
|
||||
for (const auto& fragVarying : mVaryings) {
|
||||
static const char prefix[] = "gl_";
|
||||
if (StartsWith(fragVarying.name, prefix)) {
|
||||
if (fragVarying.staticUse) {
|
||||
|
@ -336,10 +322,10 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
bool definedInVertShader = false;
|
||||
bool staticVertUse = false;
|
||||
|
||||
for (const auto& vertVarying : *vertVaryings) {
|
||||
for (const auto& vertVarying : vert.mVaryings) {
|
||||
if (vertVarying.name != fragVarying.name) continue;
|
||||
|
||||
if (!vertVarying.isSameVaryingAtLinkTime(fragVarying, shaderVersion)) {
|
||||
if (!vertVarying.isSameVaryingAtLinkTime(fragVarying, mShaderVersion)) {
|
||||
nsPrintfCString error(
|
||||
"Varying `%s`is not linkable between"
|
||||
" attached shaders.",
|
||||
|
@ -377,14 +363,14 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
}
|
||||
|
||||
if (shaderVersion == 100) {
|
||||
if (mShaderVersion == 100) {
|
||||
// Enforce ESSL1 invariant linking rules.
|
||||
bool isInvariant_Position = false;
|
||||
bool isInvariant_PointSize = false;
|
||||
bool isInvariant_FragCoord = false;
|
||||
bool isInvariant_PointCoord = false;
|
||||
|
||||
for (const auto& varying : *vertVaryings) {
|
||||
for (const auto& varying : vert.mVaryings) {
|
||||
if (varying.name == "gl_Position") {
|
||||
isInvariant_Position = varying.isInvariant;
|
||||
} else if (varying.name == "gl_PointSize") {
|
||||
|
@ -392,7 +378,7 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto& varying : *fragVaryings) {
|
||||
for (const auto& varying : mVaryings) {
|
||||
if (varying.name == "gl_FragCoord") {
|
||||
isInvariant_FragCoord = varying.isInvariant;
|
||||
} else if (varying.name == "gl_PointCoord") {
|
||||
|
@ -428,13 +414,12 @@ bool ShaderValidator::CanLinkTo(const ShaderValidator* prev,
|
|||
}
|
||||
|
||||
// This must handle names like "foo.bar[0]".
|
||||
bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const {
|
||||
const std::vector<sh::Uniform>& uniforms = *sh::GetUniforms(mHandle);
|
||||
for (auto itr = uniforms.begin(); itr != uniforms.end(); ++itr) {
|
||||
bool ShaderValidatorResults::FindUniformByMappedName(
|
||||
const std::string& mappedName, std::string* const out_userName,
|
||||
bool* const out_isArray) const {
|
||||
for (const auto& cur : mUniforms) {
|
||||
const sh::ShaderVariable* found;
|
||||
if (!itr->findInfoByMappedName(mappedName, &found, out_userName)) continue;
|
||||
if (!cur.findInfoByMappedName(mappedName, &found, out_userName)) continue;
|
||||
|
||||
*out_isArray = found->isArray();
|
||||
return true;
|
||||
|
@ -442,9 +427,7 @@ bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
|||
|
||||
const size_t dotPos = mappedName.find(".");
|
||||
|
||||
const std::vector<sh::InterfaceBlock>& interfaces =
|
||||
*sh::GetInterfaceBlocks(mHandle);
|
||||
for (const auto& interface : interfaces) {
|
||||
for (const auto& interface : mInterfaceBlocks) {
|
||||
std::string mappedFieldName;
|
||||
const bool hasInstanceName = !interface.instanceName.empty();
|
||||
|
||||
|
@ -483,5 +466,30 @@ bool ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
|
|||
return false;
|
||||
}
|
||||
|
||||
size_t ShaderValidatorResults::SizeOfIncludingThis(
|
||||
const MallocSizeOf fnSizeOf) const {
|
||||
auto ret = fnSizeOf(this);
|
||||
ret += mInfoLog.size();
|
||||
ret += mObjectCode.size();
|
||||
|
||||
for (const auto& cur : mAttributes) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mInterfaceBlocks) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mOutputVariables) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mUniforms) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
for (const auto& cur : mVaryings) {
|
||||
ret += fnSizeOf(&cur);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace webgl
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -15,6 +15,31 @@
|
|||
namespace mozilla {
|
||||
namespace webgl {
|
||||
|
||||
class ShaderValidatorResults final {
|
||||
public:
|
||||
std::string mInfoLog;
|
||||
bool mValid = false;
|
||||
|
||||
std::string mObjectCode;
|
||||
int mShaderVersion = 0;
|
||||
int mVertexShaderNumViews = 0;
|
||||
|
||||
std::vector<sh::Attribute> mAttributes;
|
||||
std::vector<sh::InterfaceBlock> mInterfaceBlocks;
|
||||
std::vector<sh::OutputVariable> mOutputVariables;
|
||||
std::vector<sh::Uniform> mUniforms;
|
||||
std::vector<sh::Varying> mVaryings;
|
||||
|
||||
int mMaxVaryingVectors = 0;
|
||||
|
||||
bool CanLinkTo(const ShaderValidatorResults& vert,
|
||||
nsCString* const out_log) const;
|
||||
bool FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const;
|
||||
size_t SizeOfIncludingThis(MallocSizeOf) const;
|
||||
};
|
||||
|
||||
class ShaderValidator final {
|
||||
public:
|
||||
const ShHandle mHandle;
|
||||
|
@ -22,36 +47,24 @@ class ShaderValidator final {
|
|||
private:
|
||||
const ShCompileOptions mCompileOptions;
|
||||
const int mMaxVaryingVectors;
|
||||
bool mHasRun;
|
||||
|
||||
public:
|
||||
static ShaderValidator* Create(GLenum shaderType, ShShaderSpec spec,
|
||||
ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources,
|
||||
ShCompileOptions compileOptions);
|
||||
static std::unique_ptr<ShaderValidator> Create(
|
||||
GLenum shaderType, ShShaderSpec spec, ShShaderOutput outputLanguage,
|
||||
const ShBuiltInResources& resources, ShCompileOptions compileOptions);
|
||||
|
||||
private:
|
||||
ShaderValidator(ShHandle handle, ShCompileOptions compileOptions,
|
||||
int maxVaryingVectors)
|
||||
: mHandle(handle),
|
||||
mCompileOptions(compileOptions),
|
||||
mMaxVaryingVectors(maxVaryingVectors),
|
||||
mHasRun(false) {}
|
||||
mMaxVaryingVectors(maxVaryingVectors) {}
|
||||
|
||||
public:
|
||||
~ShaderValidator();
|
||||
|
||||
bool ValidateAndTranslate(const char* source);
|
||||
bool CanLinkTo(const ShaderValidator* prev, nsCString* const out_log) const;
|
||||
|
||||
bool FindUniformByMappedName(const std::string& mappedName,
|
||||
std::string* const out_userName,
|
||||
bool* const out_isArray) const;
|
||||
|
||||
bool ValidateTransformFeedback(
|
||||
const std::vector<nsString>& userNames, uint32_t maxComponents,
|
||||
nsCString* const out_errorText,
|
||||
std::vector<std::string>* const out_mappedNames);
|
||||
std::unique_ptr<const ShaderValidatorResults> ValidateAndTranslate(
|
||||
const char*) const;
|
||||
};
|
||||
|
||||
} // namespace webgl
|
||||
|
|
|
@ -1921,8 +1921,9 @@ static bool ValidateCopyTexImageForFeedback(const WebGLContext& webgl,
|
|||
}
|
||||
|
||||
static bool DoCopyTexOrSubImage(WebGLContext* webgl, bool isSubImage,
|
||||
WebGLTexture* const tex, const TexImageTarget target,
|
||||
GLint level, GLint xWithinSrc, GLint yWithinSrc,
|
||||
WebGLTexture* const tex,
|
||||
const TexImageTarget target, GLint level,
|
||||
GLint xWithinSrc, GLint yWithinSrc,
|
||||
uint32_t srcTotalWidth, uint32_t srcTotalHeight,
|
||||
const webgl::FormatUsageInfo* srcUsage,
|
||||
GLint xOffset, GLint yOffset, GLint zOffset,
|
||||
|
|
|
@ -1097,17 +1097,17 @@ mozilla::ipc::IPCResult ContentParent::RecvLaunchRDDProcess(
|
|||
/*static*/
|
||||
already_AddRefed<RemoteBrowser> ContentParent::CreateBrowser(
|
||||
const TabContext& aContext, Element* aFrameElement,
|
||||
BrowsingContext* aBrowsingContext, ContentParent* aOpenerContentParent,
|
||||
BrowserParent* aSameTabGroupAs, uint64_t aNextRemoteTabId) {
|
||||
const nsAString& aRemoteType, BrowsingContext* aBrowsingContext,
|
||||
ContentParent* aOpenerContentParent, BrowserParent* aSameTabGroupAs,
|
||||
uint64_t aNextRemoteTabId) {
|
||||
AUTO_PROFILER_LABEL("ContentParent::CreateBrowser", OTHER);
|
||||
|
||||
if (!sCanLaunchSubprocesses) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoString remoteType;
|
||||
if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
|
||||
remoteType)) {
|
||||
nsAutoString remoteType(aRemoteType);
|
||||
if (remoteType.IsEmpty()) {
|
||||
remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,8 +212,9 @@ class ContentParent final : public PContentParent,
|
|||
*/
|
||||
static already_AddRefed<RemoteBrowser> CreateBrowser(
|
||||
const TabContext& aContext, Element* aFrameElement,
|
||||
BrowsingContext* aBrowsingContext, ContentParent* aOpenerContentParent,
|
||||
BrowserParent* aSameTabGroupAs, uint64_t aNextRemoteTabId);
|
||||
const nsAString& aRemoteType, BrowsingContext* aBrowsingContext,
|
||||
ContentParent* aOpenerContentParent, BrowserParent* aSameTabGroupAs,
|
||||
uint64_t aNextRemoteTabId);
|
||||
|
||||
static void GetAll(nsTArray<ContentParent*>& aArray);
|
||||
|
||||
|
|
|
@ -203,9 +203,13 @@ static nsresult ChangeFrameRemoteness(WindowGlobalChild* aWgc,
|
|||
|
||||
// Actually perform the remoteness swap.
|
||||
RemotenessOptions options;
|
||||
options.mRemoteType.Construct(aRemoteType);
|
||||
options.mPendingSwitchID.Construct(aPendingSwitchId);
|
||||
|
||||
// Only set mRemoteType if it doesn't match the current process' remote type.
|
||||
if (!ContentChild::GetSingleton()->GetRemoteType().Equals(aRemoteType)) {
|
||||
options.mRemoteType.Construct(aRemoteType);
|
||||
}
|
||||
|
||||
ErrorResult error;
|
||||
flo->ChangeRemoteness(options, error);
|
||||
if (NS_WARN_IF(error.Failed())) {
|
||||
|
|
|
@ -278,8 +278,8 @@ IPCResult WindowGlobalParent::RecvDidEmbedBrowsingContext(
|
|||
already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
||||
dom::BrowsingContext* aBc, const nsAString& aRemoteType,
|
||||
uint64_t aPendingSwitchId, ErrorResult& aRv) {
|
||||
RefPtr<BrowserParent> browserParent = GetBrowserParent();
|
||||
if (NS_WARN_IF(!browserParent)) {
|
||||
RefPtr<BrowserParent> embedderBrowserParent = GetBrowserParent();
|
||||
if (NS_WARN_IF(!embedderBrowserParent)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -290,6 +290,9 @@ already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
CanonicalBrowsingContext::Cast(aBc);
|
||||
|
||||
// When the reply comes back from content, either resolve or reject.
|
||||
auto resolve =
|
||||
[=](mozilla::Tuple<nsresult, PBrowserBridgeParent*>&& aResult) {
|
||||
|
@ -301,15 +304,31 @@ already_AddRefed<Promise> WindowGlobalParent::ChangeFrameRemoteness(
|
|||
return;
|
||||
}
|
||||
|
||||
// If we got a BrowserBridgeParent, the frame is out-of-process, so pull
|
||||
// our target content process off of it. Otherwise, it's an in-process
|
||||
// frame, so we can directly use ours.
|
||||
// If we got a `BrowserBridgeParent`, the frame is out-of-process, so we
|
||||
// can get the target off of it. Otherwise, it's an in-process frame, so
|
||||
// we can use the embedder `BrowserParent`.
|
||||
RefPtr<BrowserParent> browserParent;
|
||||
if (bridge) {
|
||||
promise->MaybeResolve(
|
||||
bridge->GetBrowserParent()->Manager()->ChildID());
|
||||
browserParent = bridge->GetBrowserParent();
|
||||
} else {
|
||||
promise->MaybeResolve(browserParent->Manager()->ChildID());
|
||||
browserParent = embedderBrowserParent;
|
||||
}
|
||||
MOZ_ASSERT(browserParent);
|
||||
|
||||
if (!browserParent || !browserParent->CanSend()) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update our BrowsingContext to its new owner, if it hasn't been
|
||||
// updated yet. This can happen when switching from a out-of-process to
|
||||
// in-process frame. For remote frames, the BrowserBridgeParent::Init
|
||||
// method should've already set up the OwnerProcessId.
|
||||
uint64_t childId = browserParent->Manager()->ChildID();
|
||||
MOZ_ASSERT_IF(bridge, browsingContext->IsOwnedByProcess(childId));
|
||||
browsingContext->SetOwnerProcessId(childId);
|
||||
|
||||
promise->MaybeResolve(childId);
|
||||
};
|
||||
|
||||
auto reject = [=](ResponseRejectReason aReason) {
|
||||
|
|
|
@ -46,7 +46,6 @@ using mozilla::DefaultXDisplay;
|
|||
#include "nsIDocShell.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "GLContext.h"
|
||||
#include "EGLUtils.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "mozilla/MiscEvents.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
|
|
|
@ -84,8 +84,6 @@ add_task(async function() {
|
|||
|
||||
ok(!Cu.isDeadWrapper(content.win1), "win1 shouldn't be a dead wrapper after navigation");
|
||||
|
||||
// This load still doesn't work for some reason, so we skip it for now.
|
||||
/*
|
||||
askLoad(URL3);
|
||||
await waitLoad();
|
||||
|
||||
|
@ -94,23 +92,15 @@ add_task(async function() {
|
|||
|
||||
is(content.bc2, content.bc3, "cross to cross-origin navigation BrowsingContext match");
|
||||
ok(content.win2 == content.win3, "cross to cross-origin navigation WindowProxy match");
|
||||
*/
|
||||
|
||||
// It would also be useful and important to handle navigating back into an
|
||||
// in-process URL, but that actually doesn't work yet... so........
|
||||
/*
|
||||
askLoad(URL1);
|
||||
await waitLoad();
|
||||
let win4 = iframe.contentWindow;
|
||||
let bc4 = iframe.browsingContext;
|
||||
|
||||
is(bc3, bc4, "cross to same-origin navigation BrowsingContext match");
|
||||
try {
|
||||
is(win3, win4, "cross to same-origin navigation WindowProxy match");
|
||||
} catch(e) {
|
||||
ok(false, "cross to same-origin navigation WindowProxy exception");
|
||||
}
|
||||
*/
|
||||
content.win4 = iframe.contentWindow;
|
||||
content.bc4 = iframe.browsingContext;
|
||||
|
||||
is(content.bc3, content.bc4, "cross to same-origin navigation BrowsingContext match");
|
||||
todo(content.win3 == content.win4, "cross to same-origin navigation WindowProxty match");
|
||||
});
|
||||
} finally {
|
||||
await BrowserTestUtils.closeWindow(win);
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "EGLUtils.h"
|
||||
|
||||
#include "GLContextEGL.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl) {
|
||||
const auto& gle = GLContextEGL::Cast(gl);
|
||||
const auto& egl = gle->mEgl;
|
||||
|
||||
return egl->HasKHRImageBase() && egl->HasKHRImageTexture2D() &&
|
||||
gl->IsExtensionSupported(GLContext::OES_EGL_image);
|
||||
}
|
||||
|
||||
EGLImage CreateEGLImage(GLContext* gl, GLuint tex) {
|
||||
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
|
||||
|
||||
const auto& gle = GLContextEGL::Cast(gl);
|
||||
const auto& egl = gle->mEgl;
|
||||
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
|
||||
EGLImage image =
|
||||
egl->fCreateImage(egl->Display(), gle->mContext, LOCAL_EGL_GL_TEXTURE_2D,
|
||||
clientBuffer, nullptr);
|
||||
return image;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EGLImageWrapper
|
||||
|
||||
/*static*/
|
||||
EGLImageWrapper* EGLImageWrapper::Create(GLContext* gl, GLuint tex) {
|
||||
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
|
||||
|
||||
const auto& gle = GLContextEGL::Cast(gl);
|
||||
const auto& egl = gle->mEgl;
|
||||
const auto& display = egl->Display();
|
||||
EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
|
||||
EGLImage image = egl->fCreateImage(
|
||||
display, gle->mContext, LOCAL_EGL_GL_TEXTURE_2D, clientBuffer, nullptr);
|
||||
if (!image) {
|
||||
#ifdef DEBUG
|
||||
printf_stderr("Could not create EGL images: ERROR (0x%04x)\n",
|
||||
egl->fGetError());
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new EGLImageWrapper(egl, display, image);
|
||||
}
|
||||
|
||||
EGLImageWrapper::EGLImageWrapper(GLLibraryEGL* library, EGLDisplay display,
|
||||
EGLImage image)
|
||||
: mLibrary(library), mDisplay(display), mImage(image), mSync(0) {
|
||||
MOZ_ASSERT(mImage);
|
||||
}
|
||||
|
||||
EGLImageWrapper::~EGLImageWrapper() {
|
||||
mLibrary->fDestroyImage(mDisplay, mImage);
|
||||
}
|
||||
|
||||
bool EGLImageWrapper::FenceSync(GLContext* gl) {
|
||||
MOZ_ASSERT(!mSync);
|
||||
|
||||
if (mLibrary->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
|
||||
mSync = mLibrary->fCreateSync(mDisplay, LOCAL_EGL_SYNC_FENCE, nullptr);
|
||||
// We need to flush to make sure the sync object enters the command stream;
|
||||
// we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
|
||||
// happens on a different thread/context.
|
||||
gl->fFlush();
|
||||
}
|
||||
|
||||
if (!mSync) {
|
||||
// we failed to create one, so just do a finish
|
||||
gl->fFinish();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EGLImageWrapper::ClientWaitSync() {
|
||||
if (!mSync) {
|
||||
// if we have no sync object, then we did a Finish() earlier
|
||||
return true;
|
||||
}
|
||||
|
||||
// wait at most 1 second; this should really be never/rarely hit
|
||||
const uint64_t ns_per_ms = 1000 * 1000;
|
||||
EGLTime timeout = 1000 * ns_per_ms;
|
||||
|
||||
EGLint result = mLibrary->fClientWaitSync(mDisplay, mSync, 0, timeout);
|
||||
mLibrary->fDestroySync(mDisplay, mSync);
|
||||
mSync = nullptr;
|
||||
|
||||
return result == LOCAL_EGL_CONDITION_SATISFIED;
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
|
@ -1,52 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef EGLUTILS_H_
|
||||
#define EGLUTILS_H_
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
#include "GLTypes.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
class GLLibraryEGL;
|
||||
|
||||
bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl);
|
||||
EGLImage CreateEGLImage(GLContext* gl, GLuint tex);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EGLImageWrapper
|
||||
|
||||
class EGLImageWrapper {
|
||||
public:
|
||||
static EGLImageWrapper* Create(GLContext* gl, GLuint tex);
|
||||
|
||||
private:
|
||||
const RefPtr<GLLibraryEGL> mLibrary;
|
||||
const EGLDisplay mDisplay;
|
||||
|
||||
public:
|
||||
const EGLImage mImage;
|
||||
|
||||
private:
|
||||
EGLSync mSync;
|
||||
|
||||
EGLImageWrapper(GLLibraryEGL* library, EGLDisplay display, EGLImage image);
|
||||
|
||||
public:
|
||||
~EGLImageWrapper();
|
||||
|
||||
// Insert a sync point on the given context, which should be the current
|
||||
// active context.
|
||||
bool FenceSync(GLContext* gl);
|
||||
|
||||
bool ClientWaitSync();
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <d3d11.h>
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "GLContextEGL.h"
|
||||
#include "GLLibraryEGL.h"
|
||||
#include "GPUVideoImage.h"
|
||||
#include "ScopedGLHelpers.h"
|
||||
|
|
|
@ -542,6 +542,8 @@ class GLLibraryEGL final {
|
|||
static StaticRefPtr<GLLibraryEGL> sEGLLibrary;
|
||||
};
|
||||
|
||||
bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl);
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ EXPORTS += [
|
|||
'AndroidNativeWindow.h',
|
||||
'AndroidSurfaceTexture.h',
|
||||
'DecomposeIntoNoRepeatTriangles.h',
|
||||
'EGLUtils.h',
|
||||
'ForceDiscreteGPUHelperCGL.h',
|
||||
'GfxTexturesReporter.h',
|
||||
'GLBlitHelper.h',
|
||||
|
@ -119,7 +118,6 @@ if CONFIG['MOZ_WAYLAND']:
|
|||
UNIFIED_SOURCES += [
|
||||
'AndroidSurfaceTexture.cpp',
|
||||
'DecomposeIntoNoRepeatTriangles.cpp',
|
||||
'EGLUtils.cpp',
|
||||
'GfxTexturesReporter.cpp',
|
||||
'GLBlitHelper.cpp',
|
||||
'GLContext.cpp',
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
#include "TextureHostOGL.h"
|
||||
|
||||
#include "EGLUtils.h"
|
||||
#include "GLContext.h" // for GLContext, etc
|
||||
#include "GLContextEGL.h" // for GLContext, etc
|
||||
#include "GLLibraryEGL.h" // for GLLibraryEGL
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
|
@ -711,8 +710,17 @@ void EGLImageTextureSource::BindTexture(GLenum aTextureUnit,
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl),
|
||||
#ifdef DEBUG
|
||||
const bool supportsEglImage = [&]() {
|
||||
const auto& gle = GLContextEGL::Cast(gl);
|
||||
const auto& egl = gle->mEgl;
|
||||
|
||||
return egl->HasKHRImageBase() && egl->HasKHRImageTexture2D() &&
|
||||
gl->IsExtensionSupported(GLContext::OES_EGL_image);
|
||||
}();
|
||||
MOZ_ASSERT(supportsEglImage,
|
||||
"EGLImage not supported or disabled in runtime");
|
||||
#endif
|
||||
|
||||
GLuint tex = mCompositor->GetTemporaryTexture(mTextureTarget, aTextureUnit);
|
||||
|
||||
|
|
|
@ -105,15 +105,34 @@ class MOZ_NON_PARAM JS_PUBLIC_API ProfilingFrameIterator {
|
|||
// and less than older native and psuedo-stack frame addresses
|
||||
void* stackAddress() const;
|
||||
|
||||
enum FrameKind { Frame_Baseline, Frame_Ion, Frame_Wasm };
|
||||
enum FrameKind {
|
||||
Frame_BaselineInterpreter,
|
||||
Frame_Baseline,
|
||||
Frame_Ion,
|
||||
Frame_Wasm
|
||||
};
|
||||
|
||||
struct Frame {
|
||||
FrameKind kind;
|
||||
void* stackAddress;
|
||||
void* returnAddress;
|
||||
union {
|
||||
void* returnAddress_;
|
||||
jsbytecode* interpreterPC_;
|
||||
};
|
||||
void* activation;
|
||||
void* endStackAddress;
|
||||
const char* label;
|
||||
JSScript* interpreterScript;
|
||||
|
||||
public:
|
||||
void* returnAddress() const {
|
||||
MOZ_ASSERT(kind != Frame_BaselineInterpreter);
|
||||
return returnAddress_;
|
||||
}
|
||||
jsbytecode* interpreterPC() const {
|
||||
MOZ_ASSERT(kind == Frame_BaselineInterpreter);
|
||||
return interpreterPC_;
|
||||
}
|
||||
} JS_HAZ_GC_INVALIDATED;
|
||||
|
||||
bool isWasm() const;
|
||||
|
|
|
@ -2586,8 +2586,11 @@ static bool ReadGeckoProfilingStack(JSContext* cx, unsigned argc, Value* vp) {
|
|||
for (uint32_t i = 0; i < nframes; i++) {
|
||||
const char* frameKindStr = nullptr;
|
||||
switch (frames[i].kind) {
|
||||
case JS::ProfilingFrameIterator::Frame_BaselineInterpreter:
|
||||
frameKindStr = "baseline-interpreter";
|
||||
break;
|
||||
case JS::ProfilingFrameIterator::Frame_Baseline:
|
||||
frameKindStr = "baseline";
|
||||
frameKindStr = "baseline-jit";
|
||||
break;
|
||||
case JS::ProfilingFrameIterator::Frame_Ion:
|
||||
frameKindStr = "ion";
|
||||
|
|
|
@ -6923,6 +6923,21 @@ bool BaselineInterpreterGenerator::generate(BaselineInterpreter& interpreter) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Register BaselineInterpreter code with the profiler's JitCode table.
|
||||
{
|
||||
JitcodeGlobalEntry::BaselineInterpreterEntry entry;
|
||||
entry.init(code, code->raw(), code->rawEnd());
|
||||
|
||||
JitcodeGlobalTable* globalTable =
|
||||
cx->runtime()->jitRuntime()->getJitcodeGlobalTable();
|
||||
if (!globalTable->addEntry(entry)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
code->setHasBytecodeMap();
|
||||
}
|
||||
|
||||
// Patch loads now that we know the tableswitch base address.
|
||||
for (CodeOffset off : tableLabels_) {
|
||||
Assembler::PatchDataWithValueCheck(CodeLocationLabel(code, off),
|
||||
|
@ -6945,6 +6960,10 @@ bool BaselineInterpreterGenerator::generate(BaselineInterpreter& interpreter) {
|
|||
std::move(handler.codeCoverageOffsets()));
|
||||
}
|
||||
|
||||
if (cx->runtime()->geckoProfiler().enabled()) {
|
||||
interpreter.toggleProfilerInstrumentation(true);
|
||||
}
|
||||
|
||||
if (coverage::IsLCovEnabled()) {
|
||||
interpreter.toggleCodeCoverageInstrumentationUnchecked(true);
|
||||
}
|
||||
|
|
|
@ -1049,17 +1049,22 @@ void jit::AddSizeOfBaselineData(JSScript* script,
|
|||
}
|
||||
}
|
||||
|
||||
void jit::ToggleBaselineProfiling(JSRuntime* runtime, bool enable) {
|
||||
JitRuntime* jrt = runtime->jitRuntime();
|
||||
void jit::ToggleBaselineProfiling(JSContext* cx, bool enable) {
|
||||
JitRuntime* jrt = cx->runtime()->jitRuntime();
|
||||
if (!jrt) {
|
||||
return;
|
||||
}
|
||||
|
||||
jrt->baselineInterpreter().toggleProfilerInstrumentation(enable);
|
||||
|
||||
for (ZonesIter zone(runtime, SkipAtoms); !zone.done(); zone.next()) {
|
||||
for (ZonesIter zone(cx->runtime(), SkipAtoms); !zone.done(); zone.next()) {
|
||||
for (auto script = zone->cellIter<JSScript>(); !script.done();
|
||||
script.next()) {
|
||||
if (enable) {
|
||||
if (JitScript* jitScript = script->jitScript()) {
|
||||
jitScript->ensureProfileString(cx, script);
|
||||
}
|
||||
}
|
||||
if (!script->hasBaselineScript()) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -557,7 +557,7 @@ void FinishDiscardBaselineScript(FreeOp* fop, JSScript* script);
|
|||
void AddSizeOfBaselineData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t* data);
|
||||
|
||||
void ToggleBaselineProfiling(JSRuntime* runtime, bool enable);
|
||||
void ToggleBaselineProfiling(JSContext* cx, bool enable);
|
||||
|
||||
void ToggleBaselineTraceLoggerScripts(JSRuntime* runtime, bool enable);
|
||||
void ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable);
|
||||
|
|
|
@ -36,12 +36,12 @@ inline size_t JSJitFrameIter::prevFrameLocalSize() const {
|
|||
return current->prevFrameLocalSize();
|
||||
}
|
||||
|
||||
inline JitFrameLayout* JSJitProfilingFrameIterator::framePtr() {
|
||||
inline JitFrameLayout* JSJitProfilingFrameIterator::framePtr() const {
|
||||
MOZ_ASSERT(!done());
|
||||
return (JitFrameLayout*)fp_;
|
||||
}
|
||||
|
||||
inline JSScript* JSJitProfilingFrameIterator::frameScript() {
|
||||
inline JSScript* JSJitProfilingFrameIterator::frameScript() const {
|
||||
return ScriptFromCalleeToken(framePtr()->calleeToken());
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "jit/BaselineIC.h"
|
||||
#include "jit/JitcodeMap.h"
|
||||
#include "jit/JitFrames.h"
|
||||
#include "jit/JitScript.h"
|
||||
#include "jit/Safepoints.h"
|
||||
|
||||
using namespace js;
|
||||
|
@ -509,12 +510,16 @@ JSJitProfilingFrameIterator::JSJitProfilingFrameIterator(JSContext* cx,
|
|||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(frameScript()->hasBaselineScript());
|
||||
|
||||
// If nothing matches, for now just assume we are at the start of the last
|
||||
// frame's baseline jit code.
|
||||
// frame's baseline jit code or interpreter code.
|
||||
type_ = FrameType::BaselineJS;
|
||||
resumePCinCurrentFrame_ = frameScript()->baselineScript()->method()->raw();
|
||||
if (frameScript()->hasBaselineScript()) {
|
||||
resumePCinCurrentFrame_ = frameScript()->baselineScript()->method()->raw();
|
||||
} else {
|
||||
MOZ_ASSERT(JitOptions.baselineInterpreter);
|
||||
resumePCinCurrentFrame_ =
|
||||
cx->runtime()->jitRuntime()->baselineInterpreter().codeRaw();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ReturnType = CommonFrameLayout*>
|
||||
|
@ -565,7 +570,7 @@ bool JSJitProfilingFrameIterator::tryInitWithTable(JitcodeGlobalTable* table,
|
|||
JSScript* callee = frameScript();
|
||||
|
||||
MOZ_ASSERT(entry->isIon() || entry->isBaseline() || entry->isIonCache() ||
|
||||
entry->isDummy());
|
||||
entry->isBaselineInterpreter() || entry->isDummy());
|
||||
|
||||
// Treat dummy lookups as an empty frame sequence.
|
||||
if (entry->isDummy()) {
|
||||
|
@ -599,6 +604,12 @@ bool JSJitProfilingFrameIterator::tryInitWithTable(JitcodeGlobalTable* table,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (entry->isBaselineInterpreter()) {
|
||||
type_ = FrameType::BaselineJS;
|
||||
resumePCinCurrentFrame_ = pc;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (entry->isIonCache()) {
|
||||
void* ptr = entry->ionCacheEntry().rejoinAddr();
|
||||
const JitcodeGlobalEntry& ionEntry = table->lookupInfallible(ptr);
|
||||
|
@ -631,12 +642,15 @@ void JSJitProfilingFrameIterator::fixBaselineReturnAddress() {
|
|||
// Certain exception handling cases such as debug OSR or resuming a generator
|
||||
// with .throw() will use BaselineFrame::setOverridePc() to indicate the
|
||||
// effective |pc|. We translate the effective-pc into a Baseline code
|
||||
// address.
|
||||
if (jsbytecode* override = bl->maybeOverridePc()) {
|
||||
// address. Don't do this for frames running in the Baseline Interpreter,
|
||||
// because we don't use the return address in that case.
|
||||
jsbytecode* overridePC = bl->maybeOverridePc();
|
||||
if (overridePC && !bl->runningInInterpreter()) {
|
||||
PCMappingSlotInfo slotInfo;
|
||||
JSScript* script = bl->script();
|
||||
BaselineScript* blScript = script->baselineScript();
|
||||
resumePCinCurrentFrame_ =
|
||||
script->baselineScript()->nativeCodeForPC(script, override, &slotInfo);
|
||||
blScript->nativeCodeForPC(script, overridePC, &slotInfo);
|
||||
|
||||
// NOTE: The stack may not be synced at this PC. For the purpose of
|
||||
// profiler sampling this is fine.
|
||||
|
@ -644,6 +658,29 @@ void JSJitProfilingFrameIterator::fixBaselineReturnAddress() {
|
|||
}
|
||||
}
|
||||
|
||||
const char* JSJitProfilingFrameIterator::baselineInterpreterLabel() const {
|
||||
MOZ_ASSERT(type_ == FrameType::BaselineJS);
|
||||
return frameScript()->jitScript()->profileString();
|
||||
}
|
||||
|
||||
void JSJitProfilingFrameIterator::baselineInterpreterScriptPC(
|
||||
JSScript** script, jsbytecode** pc) const {
|
||||
MOZ_ASSERT(type_ == FrameType::BaselineJS);
|
||||
BaselineFrame* blFrame =
|
||||
(BaselineFrame*)(fp_ - BaselineFrame::FramePointerOffset -
|
||||
BaselineFrame::Size());
|
||||
*script = frameScript();
|
||||
*pc = (*script)->code();
|
||||
|
||||
if (blFrame->runningInInterpreter() &&
|
||||
blFrame->interpreterScript() == *script) {
|
||||
jsbytecode* interpPC = blFrame->interpreterPC();
|
||||
if ((*script)->containsPC(interpPC)) {
|
||||
*pc = interpPC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSJitProfilingFrameIterator::operator++() {
|
||||
JitFrameLayout* frame = framePtr();
|
||||
moveToNextFrame(frame);
|
||||
|
|
|
@ -275,8 +275,8 @@ class JSJitProfilingFrameIterator {
|
|||
FrameType type_;
|
||||
void* resumePCinCurrentFrame_;
|
||||
|
||||
inline JitFrameLayout* framePtr();
|
||||
inline JSScript* frameScript();
|
||||
inline JitFrameLayout* framePtr() const;
|
||||
inline JSScript* frameScript() const;
|
||||
MOZ_MUST_USE bool tryInitWithPC(void* pc);
|
||||
MOZ_MUST_USE bool tryInitWithTable(JitcodeGlobalTable* table, void* pc,
|
||||
bool forLastCallSite);
|
||||
|
@ -293,6 +293,9 @@ class JSJitProfilingFrameIterator {
|
|||
void operator++();
|
||||
bool done() const { return fp_ == nullptr; }
|
||||
|
||||
const char* baselineInterpreterLabel() const;
|
||||
void baselineInterpreterScriptPC(JSScript** script, jsbytecode** pc) const;
|
||||
|
||||
void* fp() const {
|
||||
MOZ_ASSERT(!done());
|
||||
return fp_;
|
||||
|
|
|
@ -40,8 +40,10 @@ static size_t NumTypeSets(JSScript* script) {
|
|||
}
|
||||
|
||||
JitScript::JitScript(JSScript* script, uint32_t typeSetOffset,
|
||||
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes)
|
||||
: typeSetOffset_(typeSetOffset),
|
||||
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes,
|
||||
const char* profileString)
|
||||
: profileString_(profileString),
|
||||
typeSetOffset_(typeSetOffset),
|
||||
bytecodeTypeMapOffset_(bytecodeTypeMapOffset),
|
||||
allocBytes_(allocBytes) {
|
||||
setTypesGeneration(script->zone()->types.generation);
|
||||
|
@ -71,6 +73,15 @@ bool JSScript::createJitScript(JSContext* cx) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Store the profile string in the JitScript if the profiler is enabled.
|
||||
const char* profileString = nullptr;
|
||||
if (cx->runtime()->geckoProfiler().enabled()) {
|
||||
profileString = cx->runtime()->geckoProfiler().profileString(cx, this);
|
||||
if (!profileString) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t numTypeSets = NumTypeSets(this);
|
||||
|
||||
static_assert(sizeof(JitScript) % sizeof(uintptr_t) == 0,
|
||||
|
@ -99,8 +110,9 @@ bool JSScript::createJitScript(JSContext* cx) {
|
|||
uint32_t typeSetOffset = sizeof(JitScript) + numICEntries() * sizeof(ICEntry);
|
||||
uint32_t bytecodeTypeMapOffset =
|
||||
typeSetOffset + numTypeSets * sizeof(StackTypeSet);
|
||||
UniquePtr<JitScript> jitScript(new (raw) JitScript(
|
||||
this, typeSetOffset, bytecodeTypeMapOffset, allocSize.value()));
|
||||
UniquePtr<JitScript> jitScript(
|
||||
new (raw) JitScript(this, typeSetOffset, bytecodeTypeMapOffset,
|
||||
allocSize.value(), profileString));
|
||||
|
||||
// Sanity check the length computations.
|
||||
MOZ_ASSERT(jitScript->numICEntries() == numICEntries());
|
||||
|
@ -173,6 +185,19 @@ void JitScript::trace(JSTracer* trc) {
|
|||
}
|
||||
}
|
||||
|
||||
void JitScript::ensureProfileString(JSContext* cx, JSScript* script) {
|
||||
MOZ_ASSERT(cx->runtime()->geckoProfiler().enabled());
|
||||
|
||||
if (profileString_) {
|
||||
return;
|
||||
}
|
||||
|
||||
profileString_ = cx->runtime()->geckoProfiler().profileString(cx, script);
|
||||
if (!profileString_) {
|
||||
MOZ_CRASH("Failed to allocate profile string");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void JitScript::printTypes(JSContext* cx, HandleScript script) {
|
||||
AutoSweepJitScript sweep(script);
|
||||
|
|
|
@ -105,6 +105,9 @@ class alignas(uintptr_t) JitScript final {
|
|||
// directly to this script.
|
||||
js::UniquePtr<Vector<DependentWasmImport>> dependentWasmImports_;
|
||||
|
||||
// Profile string used by the profiler for Baseline Interpreter frames.
|
||||
const char* profileString_ = nullptr;
|
||||
|
||||
// Offset of the StackTypeSet array.
|
||||
uint32_t typeSetOffset_ = 0;
|
||||
|
||||
|
@ -150,7 +153,8 @@ class alignas(uintptr_t) JitScript final {
|
|||
|
||||
public:
|
||||
JitScript(JSScript* script, uint32_t typeSetOffset,
|
||||
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes);
|
||||
uint32_t bytecodeTypeMapOffset, uint32_t allocBytes,
|
||||
const char* profileString);
|
||||
|
||||
#ifdef DEBUG
|
||||
~JitScript() {
|
||||
|
@ -202,6 +206,13 @@ class alignas(uintptr_t) JitScript final {
|
|||
void setActive() { flags_.active = true; }
|
||||
void resetActive() { flags_.active = false; }
|
||||
|
||||
void ensureProfileString(JSContext* cx, JSScript* script);
|
||||
|
||||
const char* profileString() const {
|
||||
MOZ_ASSERT(profileString_);
|
||||
return profileString_;
|
||||
}
|
||||
|
||||
/* Array of type sets for variables and JOF_TYPESET ops. */
|
||||
StackTypeSet* typeArray(const js::AutoSweepJitScript& sweep) {
|
||||
MOZ_ASSERT(sweep.jitScript() == this);
|
||||
|
|
|
@ -198,6 +198,26 @@ void JitcodeGlobalEntry::BaselineEntry::destroy() {
|
|||
str_ = nullptr;
|
||||
}
|
||||
|
||||
void* JitcodeGlobalEntry::BaselineInterpreterEntry::canonicalNativeAddrFor(
|
||||
void* ptr) const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bool JitcodeGlobalEntry::BaselineInterpreterEntry::callStackAtAddr(
|
||||
void* ptr, BytecodeLocationVector& results, uint32_t* depth) const {
|
||||
MOZ_CRASH("shouldn't be called for BaselineInterpreter entries");
|
||||
}
|
||||
|
||||
uint32_t JitcodeGlobalEntry::BaselineInterpreterEntry::callStackAtAddr(
|
||||
void* ptr, const char** results, uint32_t maxResults) const {
|
||||
MOZ_CRASH("shouldn't be called for BaselineInterpreter entries");
|
||||
}
|
||||
|
||||
void JitcodeGlobalEntry::BaselineInterpreterEntry::youngestFrameLocationAtAddr(
|
||||
void* ptr, JSScript** script, jsbytecode** pc) const {
|
||||
MOZ_CRASH("shouldn't be called for BaselineInterpreter entries");
|
||||
}
|
||||
|
||||
static inline JitcodeGlobalEntry& RejoinEntry(
|
||||
JSRuntime* rt, const JitcodeGlobalEntry::IonCacheEntry& cache, void* ptr) {
|
||||
MOZ_ASSERT(cache.containsPointer(ptr));
|
||||
|
@ -367,7 +387,7 @@ JitcodeGlobalEntry* JitcodeGlobalTable::lookupInternal(void* ptr) {
|
|||
|
||||
bool JitcodeGlobalTable::addEntry(const JitcodeGlobalEntry& entry) {
|
||||
MOZ_ASSERT(entry.isIon() || entry.isBaseline() || entry.isIonCache() ||
|
||||
entry.isDummy());
|
||||
entry.isBaselineInterpreter() || entry.isDummy());
|
||||
|
||||
JitcodeGlobalEntry* searchTower[JitcodeSkiplistTower::MAX_HEIGHT];
|
||||
searchInternal(entry, searchTower);
|
||||
|
@ -1523,6 +1543,9 @@ JS::ProfiledFrameHandle::ProfiledFrameHandle(JSRuntime* rt,
|
|||
|
||||
JS_PUBLIC_API JS::ProfilingFrameIterator::FrameKind
|
||||
JS::ProfiledFrameHandle::frameKind() const {
|
||||
if (entry_.isBaselineInterpreter()) {
|
||||
return JS::ProfilingFrameIterator::Frame_BaselineInterpreter;
|
||||
}
|
||||
if (entry_.isBaseline()) {
|
||||
return JS::ProfilingFrameIterator::Frame_Baseline;
|
||||
}
|
||||
|
|
|
@ -123,7 +123,16 @@ class JitcodeGlobalEntry {
|
|||
friend class JitcodeGlobalTable;
|
||||
|
||||
public:
|
||||
enum Kind { INVALID = 0, Ion, Baseline, IonCache, Dummy, Query, LIMIT };
|
||||
enum Kind {
|
||||
INVALID = 0,
|
||||
Ion,
|
||||
Baseline,
|
||||
BaselineInterpreter,
|
||||
IonCache,
|
||||
Dummy,
|
||||
Query,
|
||||
LIMIT
|
||||
};
|
||||
JS_STATIC_ASSERT(LIMIT <= 8);
|
||||
|
||||
struct BytecodeLocation {
|
||||
|
@ -414,6 +423,27 @@ class JitcodeGlobalEntry {
|
|||
bool isMarkedFromAnyThread(JSRuntime* rt);
|
||||
};
|
||||
|
||||
struct BaselineInterpreterEntry : public BaseEntry {
|
||||
void init(JitCode* code, void* nativeStartAddr, void* nativeEndAddr) {
|
||||
BaseEntry::init(BaselineInterpreter, code, nativeStartAddr,
|
||||
nativeEndAddr);
|
||||
}
|
||||
|
||||
void destroy() {}
|
||||
|
||||
void* canonicalNativeAddrFor(void* ptr) const;
|
||||
|
||||
MOZ_MUST_USE bool callStackAtAddr(void* ptr,
|
||||
BytecodeLocationVector& results,
|
||||
uint32_t* depth) const;
|
||||
|
||||
uint32_t callStackAtAddr(void* ptr, const char** results,
|
||||
uint32_t maxResults) const;
|
||||
|
||||
void youngestFrameLocationAtAddr(void* ptr, JSScript** script,
|
||||
jsbytecode** pc) const;
|
||||
};
|
||||
|
||||
struct IonCacheEntry : public BaseEntry {
|
||||
void* rejoinAddr_;
|
||||
JS::TrackedOutcome trackedOutcome_;
|
||||
|
@ -517,6 +547,9 @@ class JitcodeGlobalEntry {
|
|||
// Baseline jitcode.
|
||||
BaselineEntry baseline_;
|
||||
|
||||
// BaselineInterpreter code.
|
||||
BaselineInterpreterEntry baselineInterpreter_;
|
||||
|
||||
// IonCache stubs.
|
||||
IonCacheEntry ionCache_;
|
||||
|
||||
|
@ -540,6 +573,11 @@ class JitcodeGlobalEntry {
|
|||
baseline_ = baseline;
|
||||
}
|
||||
|
||||
explicit JitcodeGlobalEntry(const BaselineInterpreterEntry& baselineInterp)
|
||||
: JitcodeGlobalEntry() {
|
||||
baselineInterpreter_ = baselineInterp;
|
||||
}
|
||||
|
||||
explicit JitcodeGlobalEntry(const IonCacheEntry& ionCache)
|
||||
: JitcodeGlobalEntry() {
|
||||
ionCache_ = ionCache;
|
||||
|
@ -567,6 +605,9 @@ class JitcodeGlobalEntry {
|
|||
case Baseline:
|
||||
baselineEntry().destroy();
|
||||
break;
|
||||
case BaselineInterpreter:
|
||||
baselineInterpreterEntry().destroy();
|
||||
break;
|
||||
case IonCache:
|
||||
ionCacheEntry().destroy();
|
||||
break;
|
||||
|
@ -620,6 +661,7 @@ class JitcodeGlobalEntry {
|
|||
bool isValid() const { return (kind() > INVALID) && (kind() < LIMIT); }
|
||||
bool isIon() const { return kind() == Ion; }
|
||||
bool isBaseline() const { return kind() == Baseline; }
|
||||
bool isBaselineInterpreter() const { return kind() == BaselineInterpreter; }
|
||||
bool isIonCache() const { return kind() == IonCache; }
|
||||
bool isDummy() const { return kind() == Dummy; }
|
||||
bool isQuery() const { return kind() == Query; }
|
||||
|
@ -636,6 +678,10 @@ class JitcodeGlobalEntry {
|
|||
MOZ_ASSERT(isBaseline());
|
||||
return baseline_;
|
||||
}
|
||||
BaselineInterpreterEntry& baselineInterpreterEntry() {
|
||||
MOZ_ASSERT(isBaselineInterpreter());
|
||||
return baselineInterpreter_;
|
||||
}
|
||||
IonCacheEntry& ionCacheEntry() {
|
||||
MOZ_ASSERT(isIonCache());
|
||||
return ionCache_;
|
||||
|
@ -661,6 +707,10 @@ class JitcodeGlobalEntry {
|
|||
MOZ_ASSERT(isBaseline());
|
||||
return baseline_;
|
||||
}
|
||||
const BaselineInterpreterEntry& baselineInterpreterEntry() const {
|
||||
MOZ_ASSERT(isBaselineInterpreter());
|
||||
return baselineInterpreter_;
|
||||
}
|
||||
const IonCacheEntry& ionCacheEntry() const {
|
||||
MOZ_ASSERT(isIonCache());
|
||||
return ionCache_;
|
||||
|
@ -703,6 +753,8 @@ class JitcodeGlobalEntry {
|
|||
return ionEntry().callStackAtAddr(ptr, results, depth);
|
||||
case Baseline:
|
||||
return baselineEntry().callStackAtAddr(ptr, results, depth);
|
||||
case BaselineInterpreter:
|
||||
return baselineInterpreterEntry().callStackAtAddr(ptr, results, depth);
|
||||
case IonCache:
|
||||
return ionCacheEntry().callStackAtAddr(rt, ptr, results, depth);
|
||||
case Dummy:
|
||||
|
@ -720,6 +772,9 @@ class JitcodeGlobalEntry {
|
|||
return ionEntry().callStackAtAddr(ptr, results, maxResults);
|
||||
case Baseline:
|
||||
return baselineEntry().callStackAtAddr(ptr, results, maxResults);
|
||||
case BaselineInterpreter:
|
||||
return baselineInterpreterEntry().callStackAtAddr(ptr, results,
|
||||
maxResults);
|
||||
case IonCache:
|
||||
return ionCacheEntry().callStackAtAddr(rt, ptr, results, maxResults);
|
||||
case Dummy:
|
||||
|
@ -855,6 +910,7 @@ class JitcodeGlobalEntry {
|
|||
case IonCache:
|
||||
tracedAny |= ionCacheEntry().trace<ShouldTraceProvider>(trc);
|
||||
break;
|
||||
case BaselineInterpreter:
|
||||
case Dummy:
|
||||
break;
|
||||
default:
|
||||
|
@ -874,6 +930,7 @@ class JitcodeGlobalEntry {
|
|||
case IonCache:
|
||||
ionCacheEntry().sweepChildren(rt);
|
||||
break;
|
||||
case BaselineInterpreter:
|
||||
case Dummy:
|
||||
break;
|
||||
default:
|
||||
|
@ -982,6 +1039,10 @@ class JitcodeGlobalTable {
|
|||
MOZ_MUST_USE bool addEntry(const JitcodeGlobalEntry::BaselineEntry& entry) {
|
||||
return addEntry(JitcodeGlobalEntry(entry));
|
||||
}
|
||||
MOZ_MUST_USE bool addEntry(
|
||||
const JitcodeGlobalEntry::BaselineInterpreterEntry& entry) {
|
||||
return addEntry(JitcodeGlobalEntry(entry));
|
||||
}
|
||||
MOZ_MUST_USE bool addEntry(const JitcodeGlobalEntry::IonCacheEntry& entry) {
|
||||
return addEntry(JitcodeGlobalEntry(entry));
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ void GeckoProfilerRuntime::enable(bool enabled) {
|
|||
* but not jitcode for scripts with active frames on the stack. These scripts
|
||||
* need to have their profiler state toggled so they behave properly.
|
||||
*/
|
||||
jit::ToggleBaselineProfiling(rt, enabled);
|
||||
jit::ToggleBaselineProfiling(cx, enabled);
|
||||
|
||||
// Update lastProfilingFrame to point to the top-most JS jit-frame currently
|
||||
// on stack.
|
||||
|
|
|
@ -1934,10 +1934,11 @@ JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(
|
|||
Frame frame;
|
||||
frame.kind = Frame_Wasm;
|
||||
frame.stackAddress = stackAddr;
|
||||
frame.returnAddress = nullptr;
|
||||
frame.returnAddress_ = nullptr;
|
||||
frame.activation = activation_;
|
||||
frame.label = nullptr;
|
||||
frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
|
||||
frame.interpreterScript = nullptr;
|
||||
return mozilla::Some(frame);
|
||||
}
|
||||
|
||||
|
@ -1955,7 +1956,7 @@ JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(
|
|||
}
|
||||
|
||||
MOZ_ASSERT(entry->isIon() || entry->isIonCache() || entry->isBaseline() ||
|
||||
entry->isDummy());
|
||||
entry->isBaselineInterpreter() || entry->isDummy());
|
||||
|
||||
// Dummy frames produce no stack frames.
|
||||
if (entry->isDummy()) {
|
||||
|
@ -1963,11 +1964,26 @@ JS::ProfilingFrameIterator::getPhysicalFrameAndEntry(
|
|||
}
|
||||
|
||||
Frame frame;
|
||||
frame.kind = entry->isBaseline() ? Frame_Baseline : Frame_Ion;
|
||||
if (entry->isBaselineInterpreter()) {
|
||||
frame.kind = Frame_BaselineInterpreter;
|
||||
} else if (entry->isBaseline()) {
|
||||
frame.kind = Frame_Baseline;
|
||||
} else {
|
||||
frame.kind = Frame_Ion;
|
||||
}
|
||||
frame.stackAddress = stackAddr;
|
||||
frame.returnAddress = returnAddr;
|
||||
if (entry->isBaselineInterpreter()) {
|
||||
frame.label = jsJitIter().baselineInterpreterLabel();
|
||||
jsJitIter().baselineInterpreterScriptPC(&frame.interpreterScript,
|
||||
&frame.interpreterPC_);
|
||||
MOZ_ASSERT(frame.interpreterScript);
|
||||
MOZ_ASSERT(frame.interpreterPC_);
|
||||
} else {
|
||||
frame.interpreterScript = nullptr;
|
||||
frame.returnAddress_ = returnAddr;
|
||||
frame.label = nullptr;
|
||||
}
|
||||
frame.activation = activation_;
|
||||
frame.label = nullptr;
|
||||
frame.endStackAddress = activation_->asJit()->jsOrWasmExitFP();
|
||||
return mozilla::Some(frame);
|
||||
}
|
||||
|
@ -1993,6 +2009,11 @@ uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames,
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (physicalFrame->kind == Frame_BaselineInterpreter) {
|
||||
frames[offset] = physicalFrame.value();
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Extract the stack for the entry. Assume maximum inlining depth is <64
|
||||
const char* labels[64];
|
||||
uint32_t depth = entry.callStackAtAddr(cx_->runtime(),
|
||||
|
|
|
@ -3160,6 +3160,9 @@ pref("dom.largeAllocationHeader.enabled", true);
|
|||
// Disable e10s for Gecko by default. This is overridden in firefox.js.
|
||||
pref("browser.tabs.remote.autostart", false);
|
||||
|
||||
// Disable fission for Gecko by default.
|
||||
pref("fission.autostart", false);
|
||||
|
||||
// Pref to control whether we use separate content processes for top-level load
|
||||
// of file:// URIs.
|
||||
pref("browser.tabs.remote.separateFileUriProcess", true);
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[form-control.html]
|
||||
expected:
|
||||
if os == "android": FAIL
|
||||
if os == "android": FAIL # Bug 1550895
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[contain-layout-baseline-005.html]
|
||||
expected:
|
||||
if os == "android": "FAIL"
|
||||
if (os == "android"): FAIL # bug 1550895 (frequently fails on geckoview), bug 1554342
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[contain-layout-button-001.html]
|
||||
expected:
|
||||
if os == "android": "FAIL"
|
||||
if (os == "android"): FAIL # bug 1550895 (frequently fails on geckoview), bug 1556282
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
[navigation.https.sub.html]
|
||||
disabled:
|
||||
if (os == "android"): bug 1550895 (frequently fails on geckoview)
|
||||
expected: ERROR
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
[null.tentative.html]
|
||||
disabled:
|
||||
if (os == "android"): bug 1550895 (frequently fails on geckoview)
|
||||
prefs: [browser.tabs.remote.useCrossOriginPolicy:true]
|
||||
|
|
|
@ -1302,10 +1302,19 @@ static void MergeStacks(uint32_t aFeatures, bool aIsSynchronous,
|
|||
if (aIsSynchronous ||
|
||||
jsFrame.kind == JS::ProfilingFrameIterator::Frame_Wasm) {
|
||||
aCollector.CollectWasmFrame(jsFrame.label);
|
||||
} else if (jsFrame.kind ==
|
||||
JS::ProfilingFrameIterator::Frame_BaselineInterpreter) {
|
||||
// For now treat this as a C++ Interpreter frame by materializing a
|
||||
// ProfilingStackFrame.
|
||||
JSScript* script = jsFrame.interpreterScript;
|
||||
jsbytecode* pc = jsFrame.interpreterPC();
|
||||
js::ProfilingStackFrame stackFrame;
|
||||
stackFrame.initJsFrame("", jsFrame.label, script, pc);
|
||||
aCollector.CollectProfilingStackFrame(stackFrame);
|
||||
} else {
|
||||
MOZ_ASSERT(jsFrame.kind == JS::ProfilingFrameIterator::Frame_Ion ||
|
||||
jsFrame.kind == JS::ProfilingFrameIterator::Frame_Baseline);
|
||||
aCollector.CollectJitReturnAddr(jsFrame.returnAddress);
|
||||
aCollector.CollectJitReturnAddr(jsFrame.returnAddress());
|
||||
}
|
||||
|
||||
jsIndex--;
|
||||
|
|
Загрузка…
Ссылка в новой задаче