зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to mozilla-inbound. a=merge
This commit is contained in:
Коммит
827a6c60aa
|
@ -223,6 +223,11 @@ ContentSearchUIController.prototype = {
|
|||
},
|
||||
|
||||
handleEvent(event) {
|
||||
// The event handler is triggered by external events while the search
|
||||
// element may no longer be present
|
||||
if (!document.contains(this.input)) {
|
||||
return;
|
||||
}
|
||||
this["_on" + event.type[0].toUpperCase() + event.type.substr(1)](event);
|
||||
},
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ support-files =
|
|||
support-files =
|
||||
file_favicon_change_not_in_document.html
|
||||
[browser_multiple_icons_in_short_timeframe.js]
|
||||
skip-if = verify
|
||||
[browser_rich_icons.js]
|
||||
support-files =
|
||||
file_rich_icon.html
|
||||
|
|
|
@ -2114,9 +2114,9 @@ var gMainPane = {
|
|||
if (providerDisplayName) {
|
||||
// Show cloud storage radio button with provider name in label
|
||||
let saveToCloudRadio = document.getElementById("saveToCloud");
|
||||
let cloudStrings = Services.strings.createBundle("resource://cloudstorage/preferences.properties");
|
||||
saveToCloudRadio.label = cloudStrings.formatStringFromName("saveFilesToCloudStorage",
|
||||
[providerDisplayName], 1);
|
||||
document.l10n.setAttributes(saveToCloudRadio, "save-files-to-cloud-storage", {
|
||||
"service-name": providerDisplayName,
|
||||
});
|
||||
saveToCloudRadio.hidden = false;
|
||||
|
||||
let useDownloadDirPref = Preferences.get("browser.download.useDownloadDir");
|
||||
|
|
|
@ -1027,3 +1027,8 @@ certs-view =
|
|||
certs-devices =
|
||||
.label = Security Devices…
|
||||
.accesskey = D
|
||||
|
||||
# Variables:
|
||||
# $service-name (String) - Name of a cloud storage provider like Dropbox, Google Drive, etc...
|
||||
save-files-to-cloud-storage =
|
||||
.label = Save files to { $service-name }
|
||||
|
|
|
@ -17,6 +17,12 @@
|
|||
--category-text: rgba(12,12,13);
|
||||
--category-text-selected: #0a84ff;
|
||||
|
||||
/* Dimensions from common.css #categories > .category */
|
||||
/* TODO: Values are not based on photon's 4px base distance, see bug 1501638 */
|
||||
--category-height: 48px;
|
||||
--category-padding: 10px;
|
||||
--category-transition-duration: 150ms;
|
||||
|
||||
--link-color: #0a8dff;
|
||||
--link-color-active: #003eaa;
|
||||
--link-color-hover: #0060df;
|
||||
|
|
|
@ -28,7 +28,7 @@ const { PREFERENCES } = require("../../constants");
|
|||
|
||||
const USB_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
const WIFI_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
const GLOBE_ICON_SRC = "chrome://devtools/skin/images/globe.svg";
|
||||
const GLOBE_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
|
||||
|
||||
class ConnectPage extends PureComponent {
|
||||
static get propTypes() {
|
||||
|
|
|
@ -21,7 +21,7 @@ const SidebarRuntimeItem = createFactory(require("./SidebarRuntimeItem"));
|
|||
const RefreshDevicesButton = createFactory(require("./RefreshDevicesButton"));
|
||||
const FIREFOX_ICON = "chrome://devtools/skin/images/aboutdebugging-firefox-logo.svg";
|
||||
const CONNECT_ICON = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
const GLOBE_ICON = "chrome://devtools/skin/images/globe.svg";
|
||||
const GLOBE_ICON = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
|
||||
const USB_ICON = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
|
||||
|
||||
class Sidebar extends PureComponent {
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
display: grid;
|
||||
grid-template-columns: 34px 1fr;
|
||||
font-size: 16px;
|
||||
height: 48px;
|
||||
padding-inline-end: 10px;
|
||||
padding-inline-start: 10px;
|
||||
}
|
||||
|
||||
.sidebar-fixed-item__icon {
|
||||
|
|
|
@ -11,14 +11,15 @@
|
|||
.sidebar-item {
|
||||
color: var(--sidebar-text-color);
|
||||
border-radius: 2px;
|
||||
padding-inline-end: 10px;
|
||||
padding-inline-start: 10px;
|
||||
transition: background-color 150ms;
|
||||
height: var(--category-height);
|
||||
padding-inline-end: var(--category-padding);
|
||||
padding-inline-start: var(--category-padding);
|
||||
transition: background-color var(--category-transition-duration);
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.sidebar-item:not(.sidebar-item--selectable) {
|
||||
opacity: 0.5;
|
||||
color: var(--grey-40);
|
||||
}
|
||||
|
||||
.sidebar-item--selectable:hover {
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
align-items: center;
|
||||
display: grid;
|
||||
grid-column-gap: var(--base-distance);
|
||||
grid-template-columns: 20px 1fr auto;
|
||||
grid-template-columns: calc(var(--base-distance) * 6) 1fr auto;
|
||||
}
|
||||
|
||||
.sidebar-runtime-item__icon {
|
||||
fill: currentColor;
|
||||
-moz-context-properties: fill;
|
||||
margin-inline-end: var(--base-distance);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class TabsPanel extends Component {
|
|||
const base64Favicon = btoa(String.fromCharCode.apply(String, tab.favicon));
|
||||
tab.icon = "data:image/png;base64," + base64Favicon;
|
||||
} else {
|
||||
tab.icon = "chrome://devtools/skin/images/globe.svg";
|
||||
tab.icon = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ devtools.jar:
|
|||
skin/images/aboutdebugging-firefox-logo.svg (themes/images/aboutdebugging-firefox-logo.svg)
|
||||
skin/images/aboutdebugging-firefox-nightly.svg (themes/images/aboutdebugging-firefox-nightly.svg)
|
||||
skin/images/aboutdebugging-firefox-release.svg (themes/images/aboutdebugging-firefox-release.svg)
|
||||
skin/images/aboutdebugging-globe-icon.svg (themes/images/aboutdebugging-globe-icon.svg)
|
||||
skin/images/fox-smiling.svg (themes/images/fox-smiling.svg)
|
||||
skin/images/grid.svg (themes/images/grid.svg)
|
||||
skin/images/angle-swatch.svg (themes/images/angle-swatch.svg)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!-- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 16" fill="context-fill #0b0b0b">
|
||||
<!-- We transform the icon here in order to have consistent sizes between this icon and aboutdebugging-connect-icon.svg
|
||||
which is used for USB runtimes. -->
|
||||
<g transform="scale(0.75) translate(2.5, 2.5)">
|
||||
<path d="M8 0a8 8 0 1 0 8 8 8 8 0 0 0-8-8zm5.16 4.96h-1.55a7.7 7.7 0 0 0-1.05-2.38 6.03 6.03 0 0 1 2.6 2.38zM14 8a5.96 5.96 0 0 1-.34 1.96h-1.82A12.33 12.33 0 0 0 12 8a12.33 12.33 0 0 0-.16-1.96h1.82A5.96 5.96 0 0 1 14 8zm-6 6c-1.07 0-2.04-1.2-2.57-2.96h5.14C10.04 12.8 9.07 14 8 14zM5.17 9.96a11.08 11.08 0 0 1 0-3.92h5.66A11.11 11.11 0 0 1 11 8a11.11 11.11 0 0 1-.17 1.96zM2 8a5.96 5.96 0 0 1 .34-1.96h1.82a12.36 12.36 0 0 0 0 3.92H2.33A5.96 5.96 0 0 1 2 8zm6-6c1.07 0 2.04 1.2 2.57 2.96H5.43C5.96 3.2 6.93 2 8 2zm-2.56.58a7.7 7.7 0 0 0-1.05 2.38H2.84a6.03 6.03 0 0 1 2.6-2.38zm-2.6 8.46h1.55a7.7 7.7 0 0 0 1.05 2.38 6.03 6.03 0 0 1-2.6-2.38zm7.72 2.38a7.7 7.7 0 0 0 1.05-2.38h1.56a6.03 6.03 0 0 1-2.61 2.38z"/>
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.2 KiB |
|
@ -601,16 +601,8 @@ WebGLContext::CreateAndInitGL(bool forceEnabled,
|
|||
{
|
||||
const gfx::IntSize dummySize(1, 1);
|
||||
nsCString failureId;
|
||||
RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags,
|
||||
&failureId);
|
||||
if (gl && gl->IsCoreProfile() &&
|
||||
!(flags & gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE) &&
|
||||
!gl->IsSupported(gl::GLFeature::gpu_shader5))
|
||||
{
|
||||
// See comment on "constant-index-expression" in WebGLShaderValidator.cpp.
|
||||
const auto compatFlags = flags | gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
|
||||
gl = pfnCreateOffscreen(dummySize, surfaceCaps, compatFlags, &failureId);
|
||||
}
|
||||
const RefPtr<GLContext> gl = pfnCreateOffscreen(dummySize, surfaceCaps, flags,
|
||||
&failureId);
|
||||
if (!gl) {
|
||||
out_failReasons->push_back(WebGLContext::FailureReason(failureId, info));
|
||||
}
|
||||
|
|
|
@ -305,22 +305,23 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(gl, "GFX: GL not initialized");
|
||||
|
||||
if (!gl->MakeCurrent(true)) {
|
||||
MOZ_ASSERT(false);
|
||||
*out_failReason = { "FEATURE_FAILURE_WEBGL_MAKECURRENT",
|
||||
"Failed to MakeCurrent for init." };
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unconditionally create a new format usage authority. This is
|
||||
// important when restoring contexts and extensions need to add
|
||||
// formats back into the authority.
|
||||
mFormatUsage = CreateFormatUsage(gl);
|
||||
MOZ_RELEASE_ASSERT(mFormatUsage);
|
||||
if (!mFormatUsage) {
|
||||
*out_failReason = { "FEATURE_FAILURE_WEBGL_FORMAT",
|
||||
"Failed to create mFormatUsage." };
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
const auto error = gl->fGetError();
|
||||
MOZ_ALWAYS_TRUE(!error);
|
||||
GLenum error = gl->fGetError();
|
||||
if (error != LOCAL_GL_NO_ERROR) {
|
||||
const nsPrintfCString reason("GL error 0x%x occurred during OpenGL context"
|
||||
" initialization, before WebGL initialization!",
|
||||
error);
|
||||
*out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_1", reason };
|
||||
return false;
|
||||
}
|
||||
|
||||
mDisableExtensions = gfxPrefs::WebGLDisableExtensions();
|
||||
|
@ -603,9 +604,13 @@ WebGLContext::InitAndValidateGL(FailureReason* const out_failReason)
|
|||
// Notice that the point of calling fGetError here is not only to check for
|
||||
// errors, but also to reset the error flags so that a subsequent WebGL
|
||||
// getError call will give the correct result.
|
||||
{
|
||||
const auto error = gl->fGetError();
|
||||
MOZ_ALWAYS_TRUE(!error);
|
||||
error = gl->fGetError();
|
||||
if (error != LOCAL_GL_NO_ERROR) {
|
||||
const nsPrintfCString reason("GL error 0x%x occurred during WebGL context"
|
||||
" initialization!",
|
||||
error);
|
||||
*out_failReason = { "FEATURE_FAILURE_WEBGL_GLERR_2", reason };
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsWebGL2() &&
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "WebGLShaderValidator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "gfxPrefs.h"
|
||||
#include "GLContext.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
@ -102,22 +101,12 @@ ChooseValidatorCompileOptions(const ShBuiltInResources& resources,
|
|||
////////////////////////////////////////
|
||||
|
||||
static ShShaderOutput
|
||||
ShaderOutput(gl::GLContext* const gl)
|
||||
ShaderOutput(gl::GLContext* gl)
|
||||
{
|
||||
if (gl->IsGLES()) {
|
||||
return SH_ESSL_OUTPUT;
|
||||
} else {
|
||||
uint32_t version = gl->ShadingLanguageVersion();
|
||||
|
||||
// Version 130 starts to require integral constant expressions for loop indices,
|
||||
// instead of "constant-index-expression".
|
||||
// Both version 400 and gpu_shader5 remove this restrictions.
|
||||
// gpu_shader5 went core in 400, so we can just check for the GLFeature.
|
||||
// If we're compiling for webglsl1, even for webgl2, we need gpu_shader5, or GLSL_COMPAT.
|
||||
if (!gl->IsSupported(gl::GLFeature::gpu_shader5)) {
|
||||
version = std::min<uint32_t>(version, 120);
|
||||
}
|
||||
|
||||
switch (version) {
|
||||
case 100: return SH_GLSL_COMPATIBILITY_OUTPUT;
|
||||
case 120: return SH_GLSL_COMPATIBILITY_OUTPUT;
|
||||
|
|
|
@ -11117,6 +11117,7 @@ subsuite = webgl1-ext
|
|||
subsuite = webgl1-ext
|
||||
[generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
|
||||
subsuite = webgl1-ext
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_conformance__glsl__bugs__sampler-struct-function-arg.html]
|
||||
subsuite = webgl1-ext
|
||||
skip-if = (os == 'linux') || (os == 'android')
|
||||
|
@ -11412,7 +11413,7 @@ subsuite = webgl1-ext
|
|||
subsuite = webgl1-ext
|
||||
[generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html]
|
||||
subsuite = webgl1-ext
|
||||
fail-if = (os == 'linux') || (os == 'mac')
|
||||
fail-if = (os == 'mac')
|
||||
[generated/test_conformance__glsl__misc__gl_position_unset.vert.html]
|
||||
subsuite = webgl1-ext
|
||||
[generated/test_conformance__glsl__misc__global-variable-init.html]
|
||||
|
@ -11592,7 +11593,6 @@ subsuite = webgl1-ext
|
|||
subsuite = webgl1-ext
|
||||
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
|
||||
subsuite = webgl1-ext
|
||||
fail-if = (os == 'linux')
|
||||
[generated/test_conformance__glsl__misc__shaders-with-mis-matching-uniforms.html]
|
||||
subsuite = webgl1-ext
|
||||
[generated/test_conformance__glsl__misc__shaders-with-mis-matching-varyings.html]
|
||||
|
|
|
@ -193,7 +193,9 @@ skip-if = (os == 'linux') || (os == 'mac')
|
|||
# Crashes on Linux ASAN
|
||||
skip-if = ((os == 'linux') && asan)
|
||||
|
||||
[generated/test_conformance__glsl__misc__shaders-with-invariance.html]
|
||||
[generated/test_conformance__glsl__bugs__sampler-array-using-loop-index.html]
|
||||
# Testfail on Linux after removing SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX.
|
||||
# Only happen on tryserver
|
||||
fail-if = (os == 'linux')
|
||||
|
||||
[generated/test_conformance__misc__type-conversion-test.html]
|
||||
|
@ -358,7 +360,7 @@ skip-if = (os == 'win')
|
|||
|
||||
[generated/test_conformance__glsl__misc__fragcolor-fragdata-invariant.html]
|
||||
# [unexpected fragment shader compile status] (expected: true) Declaring both gl_FragColor and gl_FragData invariant should succeed.
|
||||
fail-if = (os == 'linux') || (os == 'mac')
|
||||
fail-if = (os == 'mac')
|
||||
|
||||
########################################################################
|
||||
# "tst-linux{32,64}-spot-NNN" Slaves:
|
||||
|
|
|
@ -184,7 +184,16 @@ Clipboard::GetClipboardLog()
|
|||
return gClipboardLog;
|
||||
}
|
||||
|
||||
bool
|
||||
/* static */ bool
|
||||
Clipboard::ReadTextEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
nsIPrincipal* prin = nsContentUtils::SubjectPrincipal(aCx);
|
||||
return IsTestingPrefEnabled() ||
|
||||
prin->GetIsAddonOrExpandedAddonPrincipal() ||
|
||||
prin->GetIsSystemPrincipal();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Clipboard::IsTestingPrefEnabled()
|
||||
{
|
||||
static bool sPrefCached = false;
|
||||
|
|
|
@ -45,6 +45,12 @@ public:
|
|||
|
||||
static LogModule* GetClipboardLog();
|
||||
|
||||
// Check if the Clipboard.readText API should be enabled for this context.
|
||||
// This API is only enabled for Extension and System contexts, as there is no
|
||||
// way to request the required permission for web content. If the clipboard
|
||||
// API testing pref is enabled, ReadText is enabled for web content for
|
||||
// testing purposes.
|
||||
static bool ReadTextEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
@ -53,7 +59,7 @@ private:
|
|||
// Checks if dom.events.testing.asyncClipboard pref is enabled.
|
||||
// The aforementioned pref allows automated tests to bypass the security checks when writing to
|
||||
// or reading from the clipboard.
|
||||
bool IsTestingPrefEnabled();
|
||||
static bool IsTestingPrefEnabled();
|
||||
|
||||
already_AddRefed<Promise> ReadHelper(JSContext* aCx, nsIPrincipal& aSubjectPrincipal,
|
||||
ClipboardReadType aClipboardReadType, ErrorResult& aRv);
|
||||
|
|
|
@ -1555,6 +1555,12 @@ StartMacOSContentSandbox()
|
|||
#endif
|
||||
}
|
||||
|
||||
// If the sandbox is already enabled, there's nothing more to do here.
|
||||
if (Preferences::GetBool("security.sandbox.content.mac.earlyinit") &&
|
||||
!recordreplay::IsRecordingOrReplaying()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsAutoCString appPath;
|
||||
if (!nsMacUtilsImpl::GetAppPath(appPath)) {
|
||||
MOZ_CRASH("Error resolving child process app path");
|
||||
|
|
|
@ -2742,15 +2742,6 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority)
|
|||
// of value to take effect.
|
||||
shouldSandbox = IsContentSandboxEnabled();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// If the sandbox was initialized during content process
|
||||
// startup, we must not send the SetProcessSandbox message.
|
||||
// If early startup was pref'd off or the process is a
|
||||
// middleman process, send SetProcessSandbox now.
|
||||
shouldSandbox = shouldSandbox &&
|
||||
(!sEarlySandboxInit || IsRecordingOrReplaying());
|
||||
#endif
|
||||
|
||||
#ifdef XP_LINUX
|
||||
if (shouldSandbox) {
|
||||
MOZ_ASSERT(!mSandboxBroker);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://www.w3.org/TR/geolocation-API
|
||||
* https://w3c.github.io/clipboard-apis/
|
||||
*
|
||||
* Copyright © 2018 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
|
@ -15,8 +15,9 @@
|
|||
interface Clipboard : EventTarget {
|
||||
[Pref="dom.events.asyncClipboard.dataTransfer", Throws, NeedsSubjectPrincipal]
|
||||
Promise<DataTransfer> read();
|
||||
[Throws, NeedsSubjectPrincipal]
|
||||
[Func="Clipboard::ReadTextEnabled", Throws, NeedsSubjectPrincipal]
|
||||
Promise<DOMString> readText();
|
||||
|
||||
[Pref="dom.events.asyncClipboard.dataTransfer", Throws, NeedsSubjectPrincipal]
|
||||
Promise<void> write(DataTransfer data);
|
||||
[Throws, NeedsSubjectPrincipal]
|
||||
|
|
|
@ -97,7 +97,6 @@ static const char* const sExtensionNames[] = {
|
|||
"GL_ARB_framebuffer_object",
|
||||
"GL_ARB_framebuffer_sRGB",
|
||||
"GL_ARB_geometry_shader4",
|
||||
"GL_ARB_gpu_shader5",
|
||||
"GL_ARB_half_float_pixel",
|
||||
"GL_ARB_instanced_arrays",
|
||||
"GL_ARB_internalformat_query",
|
||||
|
@ -140,7 +139,6 @@ static const char* const sExtensionNames[] = {
|
|||
"GL_EXT_framebuffer_object",
|
||||
"GL_EXT_framebuffer_sRGB",
|
||||
"GL_EXT_gpu_shader4",
|
||||
"GL_EXT_gpu_shader5",
|
||||
"GL_EXT_multisampled_render_to_texture",
|
||||
"GL_EXT_occlusion_query_boolean",
|
||||
"GL_EXT_packed_depth_stencil",
|
||||
|
@ -174,7 +172,6 @@ static const char* const sExtensionNames[] = {
|
|||
"GL_NV_fence",
|
||||
"GL_NV_framebuffer_blit",
|
||||
"GL_NV_geometry_program4",
|
||||
"GL_NV_gpu_shader5",
|
||||
"GL_NV_half_float",
|
||||
"GL_NV_instanced_arrays",
|
||||
"GL_NV_primitive_restart",
|
||||
|
@ -381,10 +378,6 @@ GLContext::LoadFeatureSymbols(const char* prefix, bool trygl, const SymLoadStruc
|
|||
bool
|
||||
GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
|
||||
{
|
||||
// see bug 929506 comment 29. wglGetProcAddress requires a current context.
|
||||
if (!MakeCurrent(true))
|
||||
return false;
|
||||
|
||||
mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
|
||||
|
||||
const SymLoadStruct coreSymbols[] = {
|
||||
|
@ -521,6 +514,10 @@ GLContext::InitWithPrefixImpl(const char* prefix, bool trygl)
|
|||
|
||||
////////////////
|
||||
|
||||
if (!MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string versionStr = (const char*)fGetString(LOCAL_GL_VERSION);
|
||||
if (versionStr.find("OpenGL ES") == 0) {
|
||||
mProfile = ContextProfile::OpenGLES;
|
||||
|
@ -2054,9 +2051,11 @@ GLContext::MarkDestroyed()
|
|||
mBlitHelper = nullptr;
|
||||
mReadTexImageHelper = nullptr;
|
||||
|
||||
mIsDestroyed = true;
|
||||
if (!MakeCurrent()) {
|
||||
NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
|
||||
}
|
||||
|
||||
mSymbols = {};
|
||||
(void)MakeCurrent(true); // Clear current context.
|
||||
}
|
||||
|
||||
#ifdef MOZ_GL_DEBUG
|
||||
|
@ -2942,14 +2941,16 @@ GetBytesPerTexel(GLenum format, GLenum type)
|
|||
}
|
||||
|
||||
bool
|
||||
GLContext::MakeCurrent(const bool aForce) const
|
||||
GLContext::MakeCurrent(bool aForce) const
|
||||
{
|
||||
if (MOZ_LIKELY( !aForce & !IsDestroyed() )) {
|
||||
bool isCurrent = false;
|
||||
if (MOZ_UNLIKELY( IsDestroyed() ))
|
||||
return false;
|
||||
|
||||
if (MOZ_LIKELY( !aForce )) {
|
||||
bool isCurrent;
|
||||
if (mUseTLSIsCurrent) {
|
||||
isCurrent = (sCurrentContext.get() == reinterpret_cast<uintptr_t>(this));
|
||||
}
|
||||
if (MOZ_UNLIKELY( !isCurrent )) {
|
||||
} else {
|
||||
isCurrent = IsCurrentImpl();
|
||||
}
|
||||
if (MOZ_LIKELY( isCurrent )) {
|
||||
|
@ -2958,10 +2959,8 @@ GLContext::MakeCurrent(const bool aForce) const
|
|||
}
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY( !MakeCurrentImpl() )) {
|
||||
ClearGetCurrentContextTLS();
|
||||
if (!MakeCurrentImpl())
|
||||
return false;
|
||||
}
|
||||
|
||||
sCurrentContext.set(reinterpret_cast<uintptr_t>(this));
|
||||
return true;
|
||||
|
|
|
@ -103,7 +103,6 @@ enum class GLFeature {
|
|||
get_query_object_i64v,
|
||||
get_query_object_iv,
|
||||
gpu_shader4,
|
||||
gpu_shader5,
|
||||
instanced_arrays,
|
||||
instanced_non_arrays,
|
||||
internalformat_query,
|
||||
|
@ -201,10 +200,6 @@ public:
|
|||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(GLContext)
|
||||
static MOZ_THREAD_LOCAL(uintptr_t) sCurrentContext;
|
||||
|
||||
static void ClearGetCurrentContextTLS() {
|
||||
sCurrentContext.set(0);
|
||||
}
|
||||
|
||||
bool mImplicitMakeCurrent = false;
|
||||
bool mUseTLSIsCurrent;
|
||||
|
||||
|
@ -346,7 +341,6 @@ public:
|
|||
protected:
|
||||
bool mIsOffscreen;
|
||||
mutable bool mContextLost = false;
|
||||
bool mIsDestroyed = false;
|
||||
|
||||
/**
|
||||
* mVersion store the OpenGL's version, multiplied by 100. For example, if
|
||||
|
@ -404,7 +398,6 @@ public:
|
|||
ARB_framebuffer_object,
|
||||
ARB_framebuffer_sRGB,
|
||||
ARB_geometry_shader4,
|
||||
ARB_gpu_shader5,
|
||||
ARB_half_float_pixel,
|
||||
ARB_instanced_arrays,
|
||||
ARB_internalformat_query,
|
||||
|
@ -447,7 +440,6 @@ public:
|
|||
EXT_framebuffer_object,
|
||||
EXT_framebuffer_sRGB,
|
||||
EXT_gpu_shader4,
|
||||
EXT_gpu_shader5,
|
||||
EXT_multisampled_render_to_texture,
|
||||
EXT_occlusion_query_boolean,
|
||||
EXT_packed_depth_stencil,
|
||||
|
@ -481,7 +473,6 @@ public:
|
|||
NV_fence,
|
||||
NV_framebuffer_blit,
|
||||
NV_geometry_program4,
|
||||
NV_gpu_shader5,
|
||||
NV_half_float,
|
||||
NV_instanced_arrays,
|
||||
NV_primitive_restart,
|
||||
|
@ -3383,7 +3374,8 @@ public:
|
|||
virtual void ReleaseSurface() {}
|
||||
|
||||
bool IsDestroyed() const {
|
||||
return mIsDestroyed;
|
||||
// MarkDestroyed will mark all these as null.
|
||||
return mSymbols.fUseProgram == nullptr;
|
||||
}
|
||||
|
||||
GLContext* GetSharedContext() { return mSharedContext; }
|
||||
|
|
|
@ -24,7 +24,7 @@ class GLContextCGL : public GLContext
|
|||
{
|
||||
friend class GLContextProviderCGL;
|
||||
|
||||
NSOpenGLContext* const mContext;
|
||||
NSOpenGLContext* mContext;
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL, override)
|
||||
|
|
|
@ -321,18 +321,6 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
|||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"gpu_shader5",
|
||||
GLVersion::GL4,
|
||||
GLESVersion::NONE,
|
||||
GLContext::Extension_None,
|
||||
{
|
||||
GLContext::ARB_gpu_shader5,
|
||||
GLContext::EXT_gpu_shader5,
|
||||
GLContext::NV_gpu_shader5,
|
||||
GLContext::Extensions_End
|
||||
}
|
||||
},
|
||||
{
|
||||
"instanced_arrays",
|
||||
GLVersion::GL3_3,
|
||||
|
|
|
@ -87,7 +87,6 @@ private:
|
|||
GLXContext mContext;
|
||||
Display* mDisplay;
|
||||
GLXDrawable mDrawable;
|
||||
Maybe<GLXDrawable> mOverrideDrawable;
|
||||
bool mDeleteDrawable;
|
||||
bool mDoubleBuffered;
|
||||
|
||||
|
|
|
@ -76,13 +76,25 @@ GLContextCGL::GLContextCGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
|||
GLContextCGL::~GLContextCGL()
|
||||
{
|
||||
MarkDestroyed();
|
||||
[mContext release];
|
||||
|
||||
if (mContext) {
|
||||
if ([NSOpenGLContext currentContext] == mContext) {
|
||||
// Clear the current context before releasing. If we don't do
|
||||
// this, the next time we call [NSOpenGLContext currentContext],
|
||||
// "invalid context" will be printed to the console.
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
[mContext release];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextCGL::Init()
|
||||
{
|
||||
return InitWithPrefix("gl", true);
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CGLContextObj
|
||||
|
@ -94,11 +106,6 @@ GLContextCGL::GetCGLContext() const
|
|||
bool
|
||||
GLContextCGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (IsDestroyed()) {
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
[mContext makeCurrentContext];
|
||||
MOZ_ASSERT(IsCurrentImpl());
|
||||
|
|
|
@ -32,26 +32,35 @@ GLContextEAGL::GLContextEAGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
|||
|
||||
GLContextEAGL::~GLContextEAGL()
|
||||
{
|
||||
if (MakeCurrent()) {
|
||||
if (mBackbufferFB) {
|
||||
fDeleteFramebuffers(1, &mBackbufferFB);
|
||||
}
|
||||
MakeCurrent();
|
||||
|
||||
if (mBackbufferRB) {
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
}
|
||||
if (mBackbufferFB) {
|
||||
fDeleteFramebuffers(1, &mBackbufferFB);
|
||||
}
|
||||
|
||||
mLayer = nil;
|
||||
if (mBackbufferRB) {
|
||||
fDeleteRenderbuffers(1, &mBackbufferRB);
|
||||
}
|
||||
|
||||
MarkDestroyed();
|
||||
[mContext release];
|
||||
|
||||
if (mLayer) {
|
||||
mLayer = nil;
|
||||
}
|
||||
|
||||
if (mContext) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
[mContext release];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEAGL::Init()
|
||||
{
|
||||
return InitWithPrefix("gl", true);
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -103,11 +112,12 @@ GLContextEAGL::RecreateRB()
|
|||
bool
|
||||
GLContextEAGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (IsDestroyed()) {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
return false;
|
||||
if (mContext) {
|
||||
if(![EAGLContext setCurrentContext:mContext]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return [EAGLContext setCurrentContext:mContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -158,18 +158,19 @@ is_power_of_two(int v)
|
|||
}
|
||||
|
||||
static void
|
||||
DestroySurface(const EGLSurface surf)
|
||||
{
|
||||
if (!surf)
|
||||
return;
|
||||
DestroySurface(EGLSurface oldSurface) {
|
||||
auto* egl = gl::GLLibraryEGL::Get();
|
||||
|
||||
const auto& egl = gl::GLLibraryEGL::Get();
|
||||
|
||||
// TODO: This breaks TLS MakeCurrent caching.
|
||||
MOZ_ALWAYS_TRUE( egl->fDestroySurface(EGL_DISPLAY(), surf) );
|
||||
if (oldSurface != EGL_NO_SURFACE) {
|
||||
// TODO: This breaks TLS MakeCurrent caching.
|
||||
egl->fMakeCurrent(EGL_DISPLAY(),
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
egl->fDestroySurface(EGL_DISPLAY(), oldSurface);
|
||||
#if defined(MOZ_WAYLAND)
|
||||
DeleteWaylandGLSurface(surf);
|
||||
DeleteWaylandGLSurface(oldSurface);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static EGLSurface
|
||||
|
@ -283,7 +284,7 @@ GLContextEGLFactory::Create(EGLNativeWindowType aWindow,
|
|||
surface, &discardFailureId);
|
||||
if (!gl) {
|
||||
gfxCriticalNote << "Failed to create EGLContext!";
|
||||
DestroySurface(surface);
|
||||
mozilla::gl::DestroySurface(surface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -325,9 +326,9 @@ GLContextEGL::~GLContextEGL()
|
|||
#endif
|
||||
|
||||
mEgl->fDestroyContext(EGL_DISPLAY(), mContext);
|
||||
DestroySurface(mSurface);
|
||||
MOZ_ASSERT(!mFallbackSurface || mFallbackSurface != mSurface);
|
||||
DestroySurface(mFallbackSurface);
|
||||
|
||||
mozilla::gl::DestroySurface(mSurface);
|
||||
mozilla::gl::DestroySurface(mFallbackSurface);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -350,7 +351,13 @@ GLContextEGL::Init()
|
|||
SetupLookupFunction();
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
MOZ_ASSERT(IsCurrent());
|
||||
|
||||
bool current = MakeCurrent();
|
||||
if (!current) {
|
||||
gfx::LogFailure(NS_LITERAL_CSTRING(
|
||||
"Couldn't get device attachments for device."));
|
||||
return false;
|
||||
}
|
||||
|
||||
static_assert(sizeof(GLint) >= sizeof(int32_t), "GLint is smaller than int32_t");
|
||||
mMaxTextureImageSize = INT32_MAX;
|
||||
|
@ -401,10 +408,7 @@ GLContextEGL::ReleaseTexImage()
|
|||
}
|
||||
|
||||
void
|
||||
GLContextEGL::SetEGLSurfaceOverride(const EGLSurface surf)
|
||||
{
|
||||
MOZ_ASSERT(!surf || surf != mSurface);
|
||||
|
||||
GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
|
||||
if (Screen()) {
|
||||
/* Blit `draw` to `read` if we need to, before we potentially juggle
|
||||
* `read` around. If we don't, we might attach a different `read`,
|
||||
|
@ -415,21 +419,15 @@ GLContextEGL::SetEGLSurfaceOverride(const EGLSurface surf)
|
|||
}
|
||||
|
||||
mSurfaceOverride = surf;
|
||||
MOZ_ALWAYS_TRUE( MakeCurrent(true) );
|
||||
DebugOnly<bool> ok = MakeCurrent(true);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextEGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (IsDestroyed()) {
|
||||
MOZ_ALWAYS_TRUE( mEgl->fMakeCurrent(EGL_DISPLAY(), nullptr, nullptr, nullptr) );
|
||||
return false;
|
||||
}
|
||||
|
||||
auto surface = mSurface;
|
||||
if (mSurfaceOverride) {
|
||||
surface = mSurfaceOverride;
|
||||
}
|
||||
EGLSurface surface = (mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride
|
||||
: mSurface;
|
||||
if (!surface) {
|
||||
surface = mFallbackSurface;
|
||||
}
|
||||
|
@ -459,8 +457,7 @@ GLContextEGL::IsCurrentImpl() const
|
|||
}
|
||||
|
||||
bool
|
||||
GLContextEGL::RenewSurface(CompositorWidget* const aWidget)
|
||||
{
|
||||
GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
|
||||
if (!mOwnsContext) {
|
||||
return false;
|
||||
}
|
||||
|
@ -482,13 +479,14 @@ GLContextEGL::RenewSurface(CompositorWidget* const aWidget)
|
|||
}
|
||||
|
||||
void
|
||||
GLContextEGL::ReleaseSurface()
|
||||
{
|
||||
if (!mOwnsContext)
|
||||
return;
|
||||
|
||||
DestroySurface(mSurface);
|
||||
mSurface = nullptr;
|
||||
GLContextEGL::ReleaseSurface() {
|
||||
if (mOwnsContext) {
|
||||
mozilla::gl::DestroySurface(mSurface);
|
||||
}
|
||||
if (mSurface == mSurfaceOverride) {
|
||||
mSurfaceOverride = EGL_NO_SURFACE;
|
||||
}
|
||||
mSurface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -587,12 +587,20 @@ GLContextGLX::~GLContextGLX()
|
|||
return;
|
||||
}
|
||||
|
||||
// see bug 659842 comment 76
|
||||
#ifdef DEBUG
|
||||
bool success =
|
||||
#endif
|
||||
mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
|
||||
MOZ_ASSERT(success,
|
||||
"glXMakeCurrent failed to release GL context before we call "
|
||||
"glXDestroyContext!");
|
||||
|
||||
mGLX->fDestroyContext(mDisplay, mContext);
|
||||
|
||||
if (mDeleteDrawable) {
|
||||
mGLX->fDestroyPixmap(mDisplay, mDrawable);
|
||||
}
|
||||
MOZ_ASSERT(!mOverrideDrawable);
|
||||
}
|
||||
|
||||
|
||||
|
@ -621,16 +629,7 @@ GLContextGLX::MakeCurrentImpl() const
|
|||
Unused << XPending(mDisplay);
|
||||
}
|
||||
|
||||
if (IsDestroyed()) {
|
||||
MOZ_ALWAYS_TRUE( mGLX->fMakeCurrent(mDisplay, X11None, nullptr) );
|
||||
return false; // Did not MakeCurrent mContext, but that's what we wanted!
|
||||
}
|
||||
|
||||
auto drawable = mDrawable;
|
||||
if (mOverrideDrawable) {
|
||||
drawable = mOverrideDrawable.ref();
|
||||
}
|
||||
const bool succeeded = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
|
||||
const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
|
||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||
|
||||
if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
|
||||
|
@ -695,18 +694,16 @@ GLContextGLX::GetWSIInfo(nsCString* const out) const
|
|||
bool
|
||||
GLContextGLX::OverrideDrawable(GLXDrawable drawable)
|
||||
{
|
||||
if (Screen()) {
|
||||
if (Screen())
|
||||
Screen()->AssureBlitted();
|
||||
}
|
||||
mOverrideDrawable = Some(drawable);
|
||||
return MakeCurrent(true);
|
||||
Bool result = mGLX->fMakeCurrent(mDisplay, drawable, mContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextGLX::RestoreDrawable()
|
||||
{
|
||||
mOverrideDrawable = Nothing();
|
||||
return MakeCurrent(true);
|
||||
return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
|
||||
}
|
||||
|
||||
GLContextGLX::GLContextGLX(
|
||||
|
|
|
@ -163,6 +163,7 @@ WGLLibrary::EnsureInitialized()
|
|||
|
||||
const auto curCtx = mSymbols.fGetCurrentContext();
|
||||
const auto curDC = mSymbols.fGetCurrentDC();
|
||||
|
||||
if (!mSymbols.fMakeCurrent(mRootDc, mDummyGlrc)) {
|
||||
NS_WARNING("wglMakeCurrent failed");
|
||||
return false;
|
||||
|
@ -298,6 +299,7 @@ GLContextWGL::GLContextWGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
|||
GLContextWGL::~GLContextWGL()
|
||||
{
|
||||
MarkDestroyed();
|
||||
|
||||
(void)sWGLLib.mSymbols.fDeleteContext(mContext);
|
||||
|
||||
if (mPBuffer) {
|
||||
|
@ -316,18 +318,20 @@ GLContextWGL::Init()
|
|||
if (!mDC || !mContext)
|
||||
return false;
|
||||
|
||||
// see bug 929506 comment 29. wglGetProcAddress requires a current context.
|
||||
if (!sWGLLib.mSymbols.fMakeCurrent(mDC, mContext))
|
||||
return false;
|
||||
|
||||
SetupLookupFunction();
|
||||
return InitWithPrefix("gl", true);
|
||||
if (!InitWithPrefix("gl", true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GLContextWGL::MakeCurrentImpl() const
|
||||
{
|
||||
if (IsDestroyed()) {
|
||||
MOZ_ALWAYS_TRUE( sWGLLib.mSymbols.fMakeCurrent(0, 0) );
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
|
||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||
return succeeded;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
setJitCompilerOption("baseline.warmup.trigger", 0);
|
||||
enableGeckoProfiling();
|
||||
try {
|
||||
enableSingleStepProfiling();
|
||||
} catch(e) {
|
||||
quit();
|
||||
}
|
||||
function removeAdd(dbg, g) {
|
||||
dbg.removeDebuggee(g);
|
||||
}
|
||||
function newGlobalDebuggerPair(toggleSeq) {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger;
|
||||
dbg.addDebuggee(g);
|
||||
g.eval("" + function f() {return 100});
|
||||
return [g, dbg];
|
||||
}
|
||||
function testTrap(toggleSeq) {
|
||||
var [g, dbg] = newGlobalDebuggerPair(toggleSeq);
|
||||
dbg.onEnterFrame = function(f) {
|
||||
f.script.setBreakpoint(Symbol.iterator == (this) ^ (this), {
|
||||
hit: function() {
|
||||
toggleSeq(dbg, g);
|
||||
}
|
||||
});
|
||||
};
|
||||
assertEq(g.f(), 100);
|
||||
}
|
||||
testTrap(removeAdd);
|
|
@ -1216,12 +1216,13 @@ InitFromBailout(JSContext* cx, size_t frameNo,
|
|||
// the correct pc offset of the throwing op instead of its
|
||||
// successor (this pc will be used as the BaselineFrame's
|
||||
// override pc).
|
||||
//
|
||||
// Note that we never resume at this pc, it is set for the sake
|
||||
// of frame iterators giving the correct answer.
|
||||
jsbytecode* throwPC = script->offsetToPC(iter.pcOffset());
|
||||
builder.setResumePC(throwPC);
|
||||
nativeCodeForPC = baselineScript->nativeCodeForPC(script, throwPC);
|
||||
|
||||
// Note that we never resume at this pc, it is set for the sake
|
||||
// of frame iterators giving the correct answer.
|
||||
PCMappingSlotInfo unused;
|
||||
nativeCodeForPC = baselineScript->nativeCodeForPC(script, throwPC, &unused);
|
||||
} else {
|
||||
nativeCodeForPC = baselineScript->nativeCodeForPC(script, pc, &slotInfo);
|
||||
}
|
||||
|
@ -1260,7 +1261,7 @@ InitFromBailout(JSContext* cx, size_t frameNo,
|
|||
// resume into the prologue for function scripts.
|
||||
MOZ_ASSERT(fun);
|
||||
MOZ_ASSERT(numUnsynced == 0);
|
||||
opReturnAddr = baselineScript->prologueEntryAddr();
|
||||
opReturnAddr = baselineScript->bailoutPrologueEntryAddr();
|
||||
JitSpew(JitSpew_BaselineBailouts, " Resuming into prologue.");
|
||||
|
||||
// Undo the progress for any loop entry we thought we were skipping
|
||||
|
|
|
@ -63,7 +63,6 @@ BaselineCompiler::BaselineCompiler(JSContext* cx, TempAllocator& alloc, JSScript
|
|||
profilerExitFrameToggleOffset_(),
|
||||
traceLoggerToggleOffsets_(cx),
|
||||
traceLoggerScriptTextIdOffset_(),
|
||||
yieldAndAwaitOffsets_(cx),
|
||||
modifiesArguments_(false)
|
||||
{
|
||||
#ifdef JS_CODEGEN_NONE
|
||||
|
@ -236,20 +235,23 @@ BaselineCompiler::compile()
|
|||
return Method_Error;
|
||||
}
|
||||
|
||||
// Note: There is an extra entry in the bytecode type map for the search hint, see below.
|
||||
// Note: There is an extra entry in the bytecode type map for the search
|
||||
// hint, see below.
|
||||
size_t bytecodeTypeMapEntries = script->nTypeSets() + 1;
|
||||
size_t yieldAndAwaitEntries =
|
||||
script->hasYieldAndAwaitOffsets() ? script->yieldAndAwaitOffsets().size() : 0;
|
||||
UniquePtr<BaselineScript> baselineScript(
|
||||
BaselineScript::New(script, prologueOffset_.offset(),
|
||||
epilogueOffset_.offset(),
|
||||
BaselineScript::New(script, bailoutPrologueOffset_.offset(),
|
||||
debugOsrPrologueOffset_.offset(),
|
||||
debugOsrEpilogueOffset_.offset(),
|
||||
profilerEnterFrameToggleOffset_.offset(),
|
||||
profilerExitFrameToggleOffset_.offset(),
|
||||
postDebugPrologueOffset_.offset(),
|
||||
icEntries_.length(),
|
||||
retAddrEntries_.length(),
|
||||
pcMappingIndexEntries.length(),
|
||||
pcEntries.length(),
|
||||
bytecodeTypeMapEntries,
|
||||
yieldAndAwaitOffsets_.length(),
|
||||
yieldAndAwaitEntries,
|
||||
traceLoggerToggleOffsets_.length()),
|
||||
JS::DeletePolicy<BaselineScript>(cx->runtime()));
|
||||
if (!baselineScript) {
|
||||
|
@ -315,7 +317,8 @@ BaselineCompiler::compile()
|
|||
// searches for the sought entry when queries are in linear order.
|
||||
bytecodeMap[script->nTypeSets()] = 0;
|
||||
|
||||
baselineScript->copyYieldAndAwaitEntries(script, yieldAndAwaitOffsets_);
|
||||
// Compute yield/await native resume addresses.
|
||||
baselineScript->computeYieldAndAwaitNativeOffsets(script);
|
||||
|
||||
if (compileDebugInstrumentation_) {
|
||||
baselineScript->setHasDebugInstrumentation();
|
||||
|
@ -486,7 +489,7 @@ BaselineCompiler::emitPrologue()
|
|||
|
||||
// Record the offset of the prologue, because Ion can bailout before
|
||||
// the env chain is initialized.
|
||||
prologueOffset_ = CodeOffset(masm.currentOffset());
|
||||
bailoutPrologueOffset_ = CodeOffset(masm.currentOffset());
|
||||
|
||||
// When compiling with Debugger instrumentation, set the debuggeeness of
|
||||
// the frame before any operation that can call into the VM.
|
||||
|
@ -525,7 +528,7 @@ BaselineCompiler::emitEpilogue()
|
|||
{
|
||||
// Record the offset of the epilogue, so we can do early return from
|
||||
// Debugger handlers during on-stack recompile.
|
||||
epilogueOffset_ = CodeOffset(masm.currentOffset());
|
||||
debugOsrEpilogueOffset_ = CodeOffset(masm.currentOffset());
|
||||
|
||||
masm.bind(&return_);
|
||||
|
||||
|
@ -800,7 +803,7 @@ BaselineCompiler::emitDebugPrologue()
|
|||
masm.bind(&done);
|
||||
}
|
||||
|
||||
postDebugPrologueOffset_ = CodeOffset(masm.currentOffset());
|
||||
debugOsrPrologueOffset_ = CodeOffset(masm.currentOffset());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -4821,33 +4824,9 @@ BaselineCompiler::emit_JSOP_GENERATOR()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::addYieldAndAwaitOffset()
|
||||
{
|
||||
MOZ_ASSERT(*pc == JSOP_INITIALYIELD || *pc == JSOP_YIELD || *pc == JSOP_AWAIT);
|
||||
|
||||
uint32_t yieldAndAwaitIndex = GET_UINT24(pc);
|
||||
|
||||
while (yieldAndAwaitIndex >= yieldAndAwaitOffsets_.length()) {
|
||||
if (!yieldAndAwaitOffsets_.append(0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static_assert(JSOP_INITIALYIELD_LENGTH == JSOP_YIELD_LENGTH &&
|
||||
JSOP_INITIALYIELD_LENGTH == JSOP_AWAIT_LENGTH,
|
||||
"code below assumes INITIALYIELD and YIELD and AWAIT have same length");
|
||||
yieldAndAwaitOffsets_[yieldAndAwaitIndex] = script->pcToOffset(pc + JSOP_YIELD_LENGTH);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_INITIALYIELD()
|
||||
{
|
||||
if (!addYieldAndAwaitOffset()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
frame.syncStack(0);
|
||||
MOZ_ASSERT(frame.stackDepth() == 1);
|
||||
|
||||
|
@ -4885,10 +4864,6 @@ static const VMFunction NormalSuspendInfo =
|
|||
bool
|
||||
BaselineCompiler::emit_JSOP_YIELD()
|
||||
{
|
||||
if (!addYieldAndAwaitOffset()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store generator in R0.
|
||||
frame.popRegsAndSync(1);
|
||||
|
||||
|
|
|
@ -305,20 +305,17 @@ class BaselineCompiler final
|
|||
NonAssertingLabel return_;
|
||||
NonAssertingLabel postBarrierSlot_;
|
||||
|
||||
// Native code offset right before the scope chain is initialized.
|
||||
CodeOffset prologueOffset_;
|
||||
// Early Ion bailouts will enter at this address. This is after frame
|
||||
// construction and before environment chain is initialized.
|
||||
CodeOffset bailoutPrologueOffset_;
|
||||
|
||||
// Native code offset right before the frame is popped and the method
|
||||
// returned from.
|
||||
CodeOffset epilogueOffset_;
|
||||
// Baseline Debug OSR during prologue will enter at this address. This is
|
||||
// right after where a debug prologue VM call would have returned.
|
||||
CodeOffset debugOsrPrologueOffset_;
|
||||
|
||||
// Native code offset right after debug prologue and epilogue, or
|
||||
// equivalent positions when debug mode is off.
|
||||
CodeOffset postDebugPrologueOffset_;
|
||||
|
||||
// For each INITIALYIELD or YIELD or AWAIT op, this Vector maps the yield
|
||||
// index to the bytecode offset of the next op.
|
||||
Vector<uint32_t> yieldAndAwaitOffsets_;
|
||||
// Baseline Debug OSR during epilogue will enter at this address. This is
|
||||
// right after where a debug epilogue VM call would have returned.
|
||||
CodeOffset debugOsrEpilogueOffset_;
|
||||
|
||||
// Whether any on stack arguments are modified.
|
||||
bool modifiesArguments_;
|
||||
|
@ -482,8 +479,6 @@ class BaselineCompiler final
|
|||
|
||||
MOZ_MUST_USE bool addPCMappingEntry(bool addIndexEntry);
|
||||
|
||||
MOZ_MUST_USE bool addYieldAndAwaitOffset();
|
||||
|
||||
void getEnvironmentCoordinateObject(Register reg);
|
||||
Address getEnvironmentCoordinateAddressFromObject(Register objReg, Register reg);
|
||||
Address getEnvironmentCoordinateAddress(Register reg);
|
||||
|
|
|
@ -457,7 +457,10 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
|
|||
MOZ_ASSERT(frame.baselineFrame()->overridePc() == pc);
|
||||
uint8_t* retAddr;
|
||||
if (cx->runtime()->geckoProfiler().enabled()) {
|
||||
retAddr = bl->nativeCodeForPC(script, pc);
|
||||
// Won't actually jump to this address so we can ignore the
|
||||
// register state in the slot info.
|
||||
PCMappingSlotInfo unused;
|
||||
retAddr = bl->nativeCodeForPC(script, pc, &unused);
|
||||
} else {
|
||||
retAddr = nullptr;
|
||||
}
|
||||
|
@ -544,7 +547,7 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
|
|||
//
|
||||
// We patch a jump directly to the right place in the prologue
|
||||
// after popping the frame reg and checking for forced return.
|
||||
recompInfo->resumeAddr = bl->postDebugPrologueAddr();
|
||||
recompInfo->resumeAddr = bl->debugOsrPrologueEntryAddr();
|
||||
popFrameReg = true;
|
||||
break;
|
||||
|
||||
|
@ -565,7 +568,7 @@ PatchBaselineFramesForDebugMode(JSContext* cx,
|
|||
// We patch a jump directly to the epilogue after popping the
|
||||
// frame reg and checking for forced return.
|
||||
MOZ_ASSERT(kind == RetAddrEntry::Kind::DebugEpilogue);
|
||||
recompInfo->resumeAddr = bl->epilogueEntryAddr();
|
||||
recompInfo->resumeAddr = bl->debugOsrEpilogueEntryAddr();
|
||||
popFrameReg = true;
|
||||
break;
|
||||
}
|
||||
|
@ -1032,7 +1035,7 @@ SyncBaselineDebugModeOSRInfo(BaselineFrame* frame, Value* vp, bool rv)
|
|||
// epilogue.
|
||||
MOZ_ASSERT(R0 == JSReturnOperand);
|
||||
info->valueR0 = frame->returnValue();
|
||||
info->resumeAddr = frame->script()->baselineScript()->epilogueEntryAddr();
|
||||
info->resumeAddr = frame->script()->baselineScript()->debugOsrEpilogueEntryAddr();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5224,10 +5224,13 @@ ICTableSwitch::Compiler::getStub(ICStubSpace* space)
|
|||
void
|
||||
ICTableSwitch::fixupJumpTable(JSScript* script, BaselineScript* baseline)
|
||||
{
|
||||
defaultTarget_ = baseline->nativeCodeForPC(script, (jsbytecode*) defaultTarget_);
|
||||
PCMappingSlotInfo slotInfo;
|
||||
defaultTarget_ = baseline->nativeCodeForPC(script, (jsbytecode*) defaultTarget_, &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
|
||||
for (int32_t i = 0; i < length_; i++) {
|
||||
table_[i] = baseline->nativeCodeForPC(script, (jsbytecode*) table_[i]);
|
||||
table_[i] = baseline->nativeCodeForPC(script, (jsbytecode*) table_[i], &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5530,7 +5533,10 @@ DoRetSubFallback(JSContext* cx, BaselineFrame* frame, ICRetSub_Fallback* stub,
|
|||
JSScript* script = frame->script();
|
||||
uint32_t offset = uint32_t(val.toInt32());
|
||||
|
||||
*resumeAddr = script->baselineScript()->nativeCodeForPC(script, script->offsetToPC(offset));
|
||||
PCMappingSlotInfo slotInfo;
|
||||
*resumeAddr = script->baselineScript()->nativeCodeForPC(script, script->offsetToPC(offset),
|
||||
&slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
|
||||
if (stub->numOptimizedStubs() >= ICRetSub_Fallback::MAX_OPTIMIZED_STUBS) {
|
||||
return true;
|
||||
|
|
|
@ -61,43 +61,6 @@ ICStubSpace::freeAllAfterMinorGC(Zone* zone)
|
|||
}
|
||||
}
|
||||
|
||||
BaselineScript::BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset)
|
||||
: method_(nullptr),
|
||||
templateEnv_(nullptr),
|
||||
fallbackStubSpace_(),
|
||||
dependentWasmImports_(nullptr),
|
||||
prologueOffset_(prologueOffset),
|
||||
epilogueOffset_(epilogueOffset),
|
||||
profilerEnterToggleOffset_(profilerEnterToggleOffset),
|
||||
profilerExitToggleOffset_(profilerExitToggleOffset),
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
# ifdef DEBUG
|
||||
traceLoggerScriptsEnabled_(false),
|
||||
traceLoggerEngineEnabled_(false),
|
||||
# endif
|
||||
traceLoggerScriptEvent_(),
|
||||
#endif
|
||||
postDebugPrologueOffset_(postDebugPrologueOffset),
|
||||
flags_(0),
|
||||
icEntriesOffset_(0),
|
||||
icEntries_(0),
|
||||
pcMappingIndexOffset_(0),
|
||||
pcMappingIndexEntries_(0),
|
||||
pcMappingOffset_(0),
|
||||
pcMappingSize_(0),
|
||||
bytecodeTypeMapOffset_(0),
|
||||
yieldEntriesOffset_(0),
|
||||
traceLoggerToggleOffsetsOffset_(0),
|
||||
numTraceLoggerToggleOffsets_(0),
|
||||
inlinedBytecodeLength_(0),
|
||||
maxInliningDepth_(UINT8_MAX),
|
||||
pendingBuilder_(nullptr),
|
||||
controlFlowGraph_(nullptr)
|
||||
{ }
|
||||
|
||||
static bool
|
||||
CheckFrame(InterpreterFrame* fp)
|
||||
{
|
||||
|
@ -194,7 +157,9 @@ jit::EnterBaselineAtBranch(JSContext* cx, InterpreterFrame* fp, jsbytecode* pc)
|
|||
BaselineScript* baseline = fp->script()->baselineScript();
|
||||
|
||||
EnterJitData data(cx);
|
||||
data.jitcode = baseline->nativeCodeForPC(fp->script(), pc);
|
||||
PCMappingSlotInfo slotInfo;
|
||||
data.jitcode = baseline->nativeCodeForPC(fp->script(), pc, &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
|
||||
// Skip debug breakpoint/trap handler, the interpreter already handled it
|
||||
// for the current op.
|
||||
|
@ -382,10 +347,11 @@ jit::CanEnterBaselineMethod(JSContext* cx, RunState& state)
|
|||
|
||||
BaselineScript*
|
||||
BaselineScript::New(JSScript* jsscript,
|
||||
uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t bailoutPrologueOffset,
|
||||
uint32_t debugOsrPrologueOffset,
|
||||
uint32_t debugOsrEpilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset,
|
||||
size_t icEntries,
|
||||
size_t retAddrEntries,
|
||||
size_t pcMappingIndexEntries, size_t pcMappingSize,
|
||||
|
@ -422,9 +388,11 @@ BaselineScript::New(JSScript* jsscript,
|
|||
if (!script) {
|
||||
return nullptr;
|
||||
}
|
||||
new (script) BaselineScript(prologueOffset, epilogueOffset,
|
||||
profilerEnterToggleOffset, profilerExitToggleOffset,
|
||||
postDebugPrologueOffset);
|
||||
new (script) BaselineScript(bailoutPrologueOffset,
|
||||
debugOsrPrologueOffset,
|
||||
debugOsrEpilogueOffset,
|
||||
profilerEnterToggleOffset,
|
||||
profilerExitToggleOffset);
|
||||
|
||||
size_t offsetCursor = sizeof(BaselineScript);
|
||||
MOZ_ASSERT(offsetCursor == AlignBytes(sizeof(BaselineScript), DataAlignment));
|
||||
|
@ -812,14 +780,25 @@ BaselineScript::retAddrEntryFromReturnAddress(uint8_t* returnAddr)
|
|||
}
|
||||
|
||||
void
|
||||
BaselineScript::copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets)
|
||||
BaselineScript::computeYieldAndAwaitNativeOffsets(JSScript* script)
|
||||
{
|
||||
uint8_t** entries = yieldEntryList();
|
||||
|
||||
for (size_t i = 0; i < yieldAndAwaitOffsets.length(); i++) {
|
||||
uint32_t offset = yieldAndAwaitOffsets[i];
|
||||
entries[i] = nativeCodeForPC(script, script->offsetToPC(offset));
|
||||
if (!script->hasYieldAndAwaitOffsets()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Translate pcOffset to BaselineScript native address. This may return
|
||||
// nullptr if compiler decided code was unreachable.
|
||||
auto computeNative = [this,script](uint32_t pcOffset) {
|
||||
PCMappingSlotInfo slotInfo;
|
||||
uint8_t* nativeCode = maybeNativeCodeForPC(script, script->offsetToPC(pcOffset), &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
|
||||
return nativeCode;
|
||||
};
|
||||
|
||||
mozilla::Span<uint32_t> pcOffsets = script->yieldAndAwaitOffsets();
|
||||
uint8_t** nativeOffsets = yieldEntryList();
|
||||
std::transform(pcOffsets.begin(), pcOffsets.end(), nativeOffsets, computeNative);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -881,95 +860,91 @@ BaselineScript::copyPCMappingIndexEntries(const PCMappingIndexEntry* entries)
|
|||
}
|
||||
|
||||
uint8_t*
|
||||
BaselineScript::nativeCodeForPC(JSScript* script, jsbytecode* pc, PCMappingSlotInfo* slotInfo)
|
||||
BaselineScript::maybeNativeCodeForPC(JSScript* script, jsbytecode* pc, PCMappingSlotInfo* slotInfo)
|
||||
{
|
||||
MOZ_ASSERT_IF(script->hasBaselineScript(), script->baselineScript() == this);
|
||||
|
||||
uint32_t pcOffset = script->pcToOffset(pc);
|
||||
|
||||
// Look for the first PCMappingIndexEntry with pc > the pc we are
|
||||
// interested in.
|
||||
uint32_t i = 1;
|
||||
for (; i < numPCMappingIndexEntries(); i++) {
|
||||
if (pcMappingIndexEntry(i).pcOffset > pcOffset) {
|
||||
// Find PCMappingIndexEntry containing pc. They are in ascedending order
|
||||
// with the start of one entry being the end of the previous entry. Find
|
||||
// first entry where pcOffset < endOffset.
|
||||
uint32_t i = 0;
|
||||
for (; (i + 1) < numPCMappingIndexEntries(); i++) {
|
||||
uint32_t endOffset = pcMappingIndexEntry(i + 1).pcOffset;
|
||||
if (pcOffset < endOffset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// The previous entry contains the current pc.
|
||||
MOZ_ASSERT(i > 0);
|
||||
i--;
|
||||
|
||||
PCMappingIndexEntry& entry = pcMappingIndexEntry(i);
|
||||
MOZ_ASSERT(pcOffset >= entry.pcOffset);
|
||||
|
||||
CompactBufferReader reader(pcMappingReader(i));
|
||||
jsbytecode* curPC = script->offsetToPC(entry.pcOffset);
|
||||
uint32_t nativeOffset = entry.nativeOffset;
|
||||
MOZ_ASSERT(reader.more());
|
||||
|
||||
jsbytecode* curPC = script->offsetToPC(entry.pcOffset);
|
||||
uint32_t curNativeOffset = entry.nativeOffset;
|
||||
MOZ_ASSERT(script->containsPC(curPC));
|
||||
MOZ_ASSERT(curPC <= pc);
|
||||
|
||||
while (reader.more()) {
|
||||
// If the high bit is set, the native offset relative to the
|
||||
// previous pc != 0 and comes next.
|
||||
uint8_t b = reader.readByte();
|
||||
if (b & 0x80) {
|
||||
nativeOffset += reader.readUnsigned();
|
||||
curNativeOffset += reader.readUnsigned();
|
||||
}
|
||||
|
||||
if (curPC == pc) {
|
||||
if (slotInfo) {
|
||||
*slotInfo = PCMappingSlotInfo(b & ~0x80);
|
||||
}
|
||||
return method_->raw() + nativeOffset;
|
||||
*slotInfo = PCMappingSlotInfo(b & 0x7F);
|
||||
return method_->raw() + curNativeOffset;
|
||||
}
|
||||
|
||||
curPC += GetBytecodeLength(curPC);
|
||||
}
|
||||
|
||||
MOZ_CRASH("No native code for this pc");
|
||||
// Code was not generated for this PC because BaselineCompiler believes it
|
||||
// is unreachable.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
jsbytecode*
|
||||
BaselineScript::approximatePcForNativeAddress(JSScript* script, uint8_t* nativeAddress)
|
||||
{
|
||||
MOZ_ASSERT(script->baselineScript() == this);
|
||||
MOZ_ASSERT(nativeAddress >= method_->raw());
|
||||
MOZ_ASSERT(nativeAddress < method_->raw() + method_->instructionsSize());
|
||||
MOZ_ASSERT(containsCodeAddress(nativeAddress));
|
||||
|
||||
uint32_t nativeOffset = nativeAddress - method_->raw();
|
||||
MOZ_ASSERT(nativeOffset < method_->instructionsSize());
|
||||
|
||||
// Look for the first PCMappingIndexEntry with native offset > the native offset we are
|
||||
// interested in.
|
||||
uint32_t i = 1;
|
||||
for (; i < numPCMappingIndexEntries(); i++) {
|
||||
if (pcMappingIndexEntry(i).nativeOffset > nativeOffset) {
|
||||
// The native code address can occur before the start of ops. Associate
|
||||
// those with start of bytecode.
|
||||
if (nativeOffset < pcMappingIndexEntry(0).nativeOffset) {
|
||||
return script->code();
|
||||
}
|
||||
|
||||
// Find corresponding PCMappingIndexEntry for native offset. They are in
|
||||
// ascedending order with the start of one entry being the end of the
|
||||
// previous entry. Find first entry where nativeOffset < endOffset.
|
||||
uint32_t i = 0;
|
||||
for (; (i + 1) < numPCMappingIndexEntries(); i++) {
|
||||
uint32_t endOffset = pcMappingIndexEntry(i + 1).nativeOffset;
|
||||
if (nativeOffset < endOffset) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Go back an entry to search forward from.
|
||||
MOZ_ASSERT(i > 0);
|
||||
i--;
|
||||
|
||||
PCMappingIndexEntry& entry = pcMappingIndexEntry(i);
|
||||
MOZ_ASSERT(nativeOffset >= entry.nativeOffset);
|
||||
|
||||
CompactBufferReader reader(pcMappingReader(i));
|
||||
MOZ_ASSERT(reader.more());
|
||||
|
||||
jsbytecode* curPC = script->offsetToPC(entry.pcOffset);
|
||||
uint32_t curNativeOffset = entry.nativeOffset;
|
||||
|
||||
MOZ_ASSERT(script->containsPC(curPC));
|
||||
|
||||
// The native code address can occur before the start of ops.
|
||||
// Associate those with bytecode offset 0.
|
||||
if (curNativeOffset > nativeOffset) {
|
||||
return script->code();
|
||||
}
|
||||
|
||||
jsbytecode* lastPC = curPC;
|
||||
while (true) {
|
||||
while (reader.more()) {
|
||||
// If the high bit is set, the native offset relative to the
|
||||
// previous pc != 0 and comes next.
|
||||
uint8_t b = reader.readByte();
|
||||
|
@ -985,15 +960,12 @@ BaselineScript::approximatePcForNativeAddress(JSScript* script, uint8_t* nativeA
|
|||
return lastPC;
|
||||
}
|
||||
|
||||
// The native address may lie in-between the last delta-entry in
|
||||
// a pcMappingIndexEntry, and the next pcMappingIndexEntry.
|
||||
if (!reader.more()) {
|
||||
return curPC;
|
||||
}
|
||||
|
||||
lastPC = curPC;
|
||||
curPC += GetBytecodeLength(curPC);
|
||||
}
|
||||
|
||||
// Associate all addresses at end of PCMappingIndexEntry with lastPC.
|
||||
return lastPC;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -65,6 +65,9 @@ class PCMappingSlotInfo
|
|||
return PCMappingSlotInfo(2 | (topSlotLoc << 2) | (nextSlotLoc) << 4);
|
||||
}
|
||||
|
||||
inline bool isStackSynced() const {
|
||||
return numUnsynced() == 0;
|
||||
}
|
||||
inline unsigned numUnsynced() const {
|
||||
return slotInfo_ & 0x3;
|
||||
}
|
||||
|
@ -229,30 +232,35 @@ class RetAddrEntry
|
|||
}
|
||||
};
|
||||
|
||||
struct BaselineScript
|
||||
struct BaselineScript final
|
||||
{
|
||||
private:
|
||||
// Code pointer containing the actual method.
|
||||
HeapPtr<JitCode*> method_;
|
||||
HeapPtr<JitCode*> method_ = nullptr;
|
||||
|
||||
// For functions with a call object, template objects to use for the call
|
||||
// object and decl env object (linked via the call object's enclosing
|
||||
// scope).
|
||||
HeapPtr<EnvironmentObject*> templateEnv_;
|
||||
HeapPtr<EnvironmentObject*> templateEnv_ = nullptr;
|
||||
|
||||
// Allocated space for fallback stubs.
|
||||
FallbackICStubSpace fallbackStubSpace_;
|
||||
FallbackICStubSpace fallbackStubSpace_ = {};
|
||||
|
||||
// If non-null, the list of wasm::Modules that contain an optimized call
|
||||
// directly to this script.
|
||||
Vector<DependentWasmImport>* dependentWasmImports_;
|
||||
Vector<DependentWasmImport>* dependentWasmImports_ = nullptr;
|
||||
|
||||
// Native code offset right before the scope chain is initialized.
|
||||
uint32_t prologueOffset_;
|
||||
// Early Ion bailouts will enter at this address. This is after frame
|
||||
// construction and before environment chain is initialized.
|
||||
uint32_t bailoutPrologueOffset_;
|
||||
|
||||
// Native code offset right before the frame is popped and the method
|
||||
// returned from.
|
||||
uint32_t epilogueOffset_;
|
||||
// Baseline Debug OSR during prologue will enter at this address. This is
|
||||
// right after where a debug prologue VM call would have returned.
|
||||
uint32_t debugOsrPrologueOffset_;
|
||||
|
||||
// Baseline Debug OSR during epilogue will enter at this address. This is
|
||||
// right after where a debug epilogue VM call would have returned.
|
||||
uint32_t debugOsrEpilogueOffset_;
|
||||
|
||||
// The offsets for the toggledJump instructions for profiler instrumentation.
|
||||
uint32_t profilerEnterToggleOffset_;
|
||||
|
@ -261,20 +269,12 @@ struct BaselineScript
|
|||
// The offsets and event used for Tracelogger toggling.
|
||||
#ifdef JS_TRACE_LOGGING
|
||||
# ifdef DEBUG
|
||||
bool traceLoggerScriptsEnabled_;
|
||||
bool traceLoggerEngineEnabled_;
|
||||
bool traceLoggerScriptsEnabled_ = false;
|
||||
bool traceLoggerEngineEnabled_ = false;
|
||||
# endif
|
||||
TraceLoggerEvent traceLoggerScriptEvent_;
|
||||
TraceLoggerEvent traceLoggerScriptEvent_ = {};
|
||||
#endif
|
||||
|
||||
// Native code offsets right after the debug prologue VM call returns, or
|
||||
// would have returned. This offset is recorded even when debug mode is
|
||||
// off to aid on-stack debug mode recompilation.
|
||||
//
|
||||
// We don't need one for the debug epilogue because that always happens
|
||||
// right before the epilogue, so we just use the epilogue offset.
|
||||
uint32_t postDebugPrologueOffset_;
|
||||
|
||||
public:
|
||||
enum Flag {
|
||||
// Flag set by JSScript::argumentsOptimizationFailed. Similar to
|
||||
|
@ -308,60 +308,68 @@ struct BaselineScript
|
|||
};
|
||||
|
||||
private:
|
||||
uint32_t flags_;
|
||||
uint32_t flags_ = 0;
|
||||
|
||||
private:
|
||||
void trace(JSTracer* trc);
|
||||
|
||||
uint32_t icEntriesOffset_;
|
||||
uint32_t icEntries_;
|
||||
uint32_t icEntriesOffset_ = 0;
|
||||
uint32_t icEntries_ = 0;
|
||||
|
||||
uint32_t retAddrEntriesOffset_;
|
||||
uint32_t retAddrEntries_;
|
||||
uint32_t retAddrEntriesOffset_ = 0;
|
||||
uint32_t retAddrEntries_ = 0;
|
||||
|
||||
uint32_t pcMappingIndexOffset_;
|
||||
uint32_t pcMappingIndexEntries_;
|
||||
uint32_t pcMappingIndexOffset_ = 0;
|
||||
uint32_t pcMappingIndexEntries_ = 0;
|
||||
|
||||
uint32_t pcMappingOffset_;
|
||||
uint32_t pcMappingSize_;
|
||||
uint32_t pcMappingOffset_ = 0;
|
||||
uint32_t pcMappingSize_ = 0;
|
||||
|
||||
// List mapping indexes of bytecode type sets to the offset of the opcode
|
||||
// they correspond to, for use by TypeScript::BytecodeTypes.
|
||||
uint32_t bytecodeTypeMapOffset_;
|
||||
uint32_t bytecodeTypeMapOffset_ = 0;
|
||||
|
||||
// For generator scripts, we store the native code address for each yield
|
||||
// instruction.
|
||||
uint32_t yieldEntriesOffset_;
|
||||
uint32_t yieldEntriesOffset_ = 0;
|
||||
|
||||
// By default tracelogger is disabled. Therefore we disable the logging code
|
||||
// by default. We store the offsets we must patch to enable the logging.
|
||||
uint32_t traceLoggerToggleOffsetsOffset_;
|
||||
uint32_t numTraceLoggerToggleOffsets_;
|
||||
uint32_t traceLoggerToggleOffsetsOffset_ = 0;
|
||||
uint32_t numTraceLoggerToggleOffsets_ = 0;
|
||||
|
||||
// The total bytecode length of all scripts we inlined when we Ion-compiled
|
||||
// this script. 0 if Ion did not compile this script or if we didn't inline
|
||||
// anything.
|
||||
uint16_t inlinedBytecodeLength_;
|
||||
uint16_t inlinedBytecodeLength_ = 0;
|
||||
|
||||
// The max inlining depth where we can still inline all functions we inlined
|
||||
// when we Ion-compiled this script. This starts as UINT8_MAX, since we have
|
||||
// no data yet, and won't affect inlining heuristics in that case. The value
|
||||
// is updated when we Ion-compile this script. See makeInliningDecision for
|
||||
// more info.
|
||||
uint8_t maxInliningDepth_;
|
||||
uint8_t maxInliningDepth_ = UINT8_MAX;
|
||||
|
||||
// An ion compilation that is ready, but isn't linked yet.
|
||||
IonBuilder *pendingBuilder_;
|
||||
IonBuilder *pendingBuilder_ = nullptr;
|
||||
|
||||
ControlFlowGraph* controlFlowGraph_;
|
||||
ControlFlowGraph* controlFlowGraph_ = nullptr;
|
||||
|
||||
// Use BaselineScript::New to create new instances. It will properly
|
||||
// allocate trailing objects.
|
||||
BaselineScript(uint32_t bailoutPrologueOffset,
|
||||
uint32_t debugOsrPrologueOffset,
|
||||
uint32_t debugOsrEpilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset)
|
||||
: bailoutPrologueOffset_(bailoutPrologueOffset),
|
||||
debugOsrPrologueOffset_(debugOsrPrologueOffset),
|
||||
debugOsrEpilogueOffset_(debugOsrEpilogueOffset),
|
||||
profilerEnterToggleOffset_(profilerEnterToggleOffset),
|
||||
profilerExitToggleOffset_(profilerExitToggleOffset)
|
||||
{ }
|
||||
|
||||
public:
|
||||
// Do not call directly, use BaselineScript::New. This is public for cx->new_.
|
||||
BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset);
|
||||
|
||||
~BaselineScript() {
|
||||
// The contents of the fallback stub space are removed and freed
|
||||
// separately after the next minor GC. See BaselineScript::Destroy.
|
||||
|
@ -369,10 +377,11 @@ struct BaselineScript
|
|||
}
|
||||
|
||||
static BaselineScript* New(JSScript* jsscript,
|
||||
uint32_t prologueOffset, uint32_t epilogueOffset,
|
||||
uint32_t bailoutPrologueOffset,
|
||||
uint32_t debugOsrPrologueOffset,
|
||||
uint32_t debugOsrEpilogueOffset,
|
||||
uint32_t profilerEnterToggleOffset,
|
||||
uint32_t profilerExitToggleOffset,
|
||||
uint32_t postDebugPrologueOffset,
|
||||
size_t icEntries,
|
||||
size_t retAddrEntries,
|
||||
size_t pcMappingIndexEntries, size_t pcMappingSize,
|
||||
|
@ -443,25 +452,14 @@ struct BaselineScript
|
|||
return flags_ & USES_ENVIRONMENT_CHAIN;
|
||||
}
|
||||
|
||||
uint32_t prologueOffset() const {
|
||||
return prologueOffset_;
|
||||
uint8_t* bailoutPrologueEntryAddr() const {
|
||||
return method_->raw() + bailoutPrologueOffset_;
|
||||
}
|
||||
uint8_t* prologueEntryAddr() const {
|
||||
return method_->raw() + prologueOffset_;
|
||||
uint8_t* debugOsrPrologueEntryAddr() const {
|
||||
return method_->raw() + debugOsrPrologueOffset_;
|
||||
}
|
||||
|
||||
uint32_t epilogueOffset() const {
|
||||
return epilogueOffset_;
|
||||
}
|
||||
uint8_t* epilogueEntryAddr() const {
|
||||
return method_->raw() + epilogueOffset_;
|
||||
}
|
||||
|
||||
uint32_t postDebugPrologueOffset() const {
|
||||
return postDebugPrologueOffset_;
|
||||
}
|
||||
uint8_t* postDebugPrologueAddr() const {
|
||||
return method_->raw() + postDebugPrologueOffset_;
|
||||
uint8_t* debugOsrEpilogueEntryAddr() const {
|
||||
return method_->raw() + debugOsrEpilogueOffset_;
|
||||
}
|
||||
|
||||
ICEntry* icEntryList() {
|
||||
|
@ -532,7 +530,9 @@ struct BaselineScript
|
|||
|
||||
void adoptFallbackStubs(FallbackICStubSpace* stubSpace);
|
||||
|
||||
void copyYieldAndAwaitEntries(JSScript* script, Vector<uint32_t>& yieldAndAwaitOffsets);
|
||||
// Copy yieldAndAwaitOffsets list from |script| and convert the pcOffsets
|
||||
// to native addresses in the Baseline code.
|
||||
void computeYieldAndAwaitNativeOffsets(JSScript* script);
|
||||
|
||||
PCMappingIndexEntry& pcMappingIndexEntry(size_t index);
|
||||
CompactBufferReader pcMappingReader(size_t indexEntry);
|
||||
|
@ -544,8 +544,15 @@ struct BaselineScript
|
|||
void copyPCMappingIndexEntries(const PCMappingIndexEntry* entries);
|
||||
void copyPCMappingEntries(const CompactBufferWriter& entries);
|
||||
|
||||
uint8_t* nativeCodeForPC(JSScript* script, jsbytecode* pc,
|
||||
PCMappingSlotInfo* slotInfo = nullptr);
|
||||
// Baseline JIT may not generate code for unreachable bytecode which
|
||||
// results in mapping returning nullptr.
|
||||
uint8_t* maybeNativeCodeForPC(JSScript* script, jsbytecode* pc, PCMappingSlotInfo* slotInfo);
|
||||
uint8_t* nativeCodeForPC(JSScript* script, jsbytecode* pc, PCMappingSlotInfo* slotInfo)
|
||||
{
|
||||
uint8_t* native = maybeNativeCodeForPC(script, pc, slotInfo);
|
||||
MOZ_ASSERT(native);
|
||||
return native;
|
||||
}
|
||||
|
||||
// Return the bytecode offset for a given native code address. Be careful
|
||||
// when using this method: we don't emit code for some bytecode ops, so
|
||||
|
|
|
@ -667,8 +667,10 @@ JSJitProfilingFrameIterator::fixBaselineReturnAddress()
|
|||
// the stack. We have the actual jsbytecode* stashed on the frame itself;
|
||||
// translate that into the Baseline code address.
|
||||
if (jsbytecode* override = bl->maybeOverridePc()) {
|
||||
PCMappingSlotInfo slotInfo;
|
||||
JSScript* script = bl->script();
|
||||
returnAddressToFp_ = script->baselineScript()->nativeCodeForPC(script, override);
|
||||
returnAddressToFp_ = script->baselineScript()->nativeCodeForPC(script, override, &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -764,6 +766,7 @@ JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
|||
fp_ = ((uint8_t*) stubFrame->reverseSavedFramePtr())
|
||||
+ jit::BaselineFrame::FramePointerOffset;
|
||||
type_ = FrameType::BaselineJS;
|
||||
fixBaselineReturnAddress();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -785,6 +788,7 @@ JSJitProfilingFrameIterator::moveToNextFrame(CommonFrameLayout* frame)
|
|||
fp_ = ((uint8_t*) stubFrame->reverseSavedFramePtr())
|
||||
+ jit::BaselineFrame::FramePointerOffset;
|
||||
type_ = FrameType::BaselineJS;
|
||||
fixBaselineReturnAddress();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -439,8 +439,10 @@ ProcessTryNotesBaseline(JSContext* cx, const JSJitFrameIter& frame, EnvironmentI
|
|||
script->resetWarmUpCounter();
|
||||
|
||||
// Resume at the start of the catch block.
|
||||
PCMappingSlotInfo slotInfo;
|
||||
rfe->kind = ResumeFromException::RESUME_CATCH;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc);
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc, &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -450,9 +452,11 @@ ProcessTryNotesBaseline(JSContext* cx, const JSJitFrameIter& frame, EnvironmentI
|
|||
break;
|
||||
}
|
||||
|
||||
PCMappingSlotInfo slotInfo;
|
||||
SettleOnTryNote(cx, tn, frame, ei, rfe, pc);
|
||||
rfe->kind = ResumeFromException::RESUME_FINALLY;
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc);
|
||||
rfe->target = script->baselineScript()->nativeCodeForPC(script, *pc, &slotInfo);
|
||||
MOZ_ASSERT(slotInfo.isStackSynced());
|
||||
// Drop the exception instead of leaking cross compartment data.
|
||||
if (!cx->getPendingException(MutableHandleValue::fromMarkedLocation(&rfe->exception))) {
|
||||
rfe->exception = UndefinedValue();
|
||||
|
|
|
@ -18,8 +18,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=912322
|
|||
ok(f in SpecialPowers.wrap(document), f + " should be available to chrome via Xray");
|
||||
}
|
||||
|
||||
var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
// Test window.controllers.
|
||||
is(typeof window.controllers, 'undefined', "controllers should not be available to content");
|
||||
if (AppConstants.RELEASE_OR_BETA) {
|
||||
is(typeof window.controllers, 'object', "shimmed controllers should be available to content in beta and release");
|
||||
} else {
|
||||
is(typeof window.controllers, 'undefined', "controllers should not be available to content in Nightly");
|
||||
}
|
||||
is(typeof SpecialPowers.wrap(window).controllers, 'object', "controllers should be available over Xray");
|
||||
|
||||
</script>
|
||||
|
|
|
@ -154,17 +154,25 @@ function readAltContent(request, buffer)
|
|||
|
||||
cc.getOriginalInputStream({
|
||||
onInputStreamReady: function(aInputStream) {
|
||||
executeSoon(function() {
|
||||
// We expect the async stream length to match the expected content.
|
||||
// If the test times out, it's probably because of this.
|
||||
let originalData = read_stream(aInputStream, responseContent.length);
|
||||
Assert.equal(originalData, responseContent);
|
||||
requestAgain();
|
||||
});
|
||||
executeSoon(() => readOriginalInputStream(aInputStream));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function readOriginalInputStream(aInputStream)
|
||||
{
|
||||
// We expect the async stream length to match the expected content.
|
||||
// If the test times out, it's probably because of this.
|
||||
try {
|
||||
let originalData = read_stream(aInputStream, responseContent.length);
|
||||
Assert.equal(originalData, responseContent);
|
||||
requestAgain();
|
||||
} catch (e) {
|
||||
equal(e.result, Cr.NS_BASE_STREAM_WOULD_BLOCK);
|
||||
executeSoon(() => readOriginalInputStream(aInputStream));
|
||||
}
|
||||
}
|
||||
|
||||
function requestAgain()
|
||||
{
|
||||
shouldPassRevalidation = false;
|
||||
|
|
|
@ -1,9 +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/.
|
||||
|
||||
#### Cloud Storage Downloads
|
||||
|
||||
# NOTE (saveFilesToCloudStorage): %S is replaced by a service name (Dropbox, Google Drive)
|
||||
# String below is hardcoded for en-US and not localized
|
||||
saveFilesToCloudStorage=Save files to %S
|
Загрузка…
Ссылка в новой задаче