Merge inbound to mozilla-central. a=merge

This commit is contained in:
Gurzau Raul 2018-03-29 00:55:16 +03:00
Родитель c6706798ae 9fdad4e863
Коммит d117255a14
111 изменённых файлов: 2175 добавлений и 1508 удалений

Просмотреть файл

@ -51,7 +51,6 @@ var whitelist = [
{file: "chrome://pippki/content/load_device.xul"},
// Add-on compat
{file: "chrome://global/content/XPCNativeWrapper.js"},
{file: "chrome://global/locale/brand.dtd"},
// The l10n build system can't package string files only for some platforms.

Просмотреть файл

@ -1,9 +1,9 @@
This is the debugger.html project output.
See https://github.com/devtools-html/debugger.html
Version 28.0
Version 29.0
Comparison: https://github.com/devtools-html/debugger.html/compare/release-28...release-27
Comparison: https://github.com/devtools-html/debugger.html/compare/release-28...release-29
Packages:
- babel-plugin-transform-es2015-modules-commonjs @6.26.0

Просмотреть файл

@ -1218,6 +1218,7 @@ html[dir="rtl"] .tree-node img.arrow {
.sources-list {
flex: 1;
display: flex;
overflow: hidden;
}
.sources-list .tree:focus {
@ -3982,6 +3983,10 @@ html .welcomebox .toggle-button-end.collapsed {
border-bottom: 1px solid var(--theme-splitter-color);
}
.result-list.small li {
justify-content: space-between;
}
.result-list li:hover {
background: var(--theme-tab-toolbar-background);
}

Просмотреть файл

@ -5405,6 +5405,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
*/
exports.getPauseReason = getPauseReason;
exports.getPauseCommand = getPauseCommand;
exports.isStepping = isStepping;
exports.isPaused = isPaused;
exports.getPreviousPauseFrameLocation = getPreviousPauseFrameLocation;
@ -5414,6 +5415,7 @@ exports.getIsWaitingOnBreak = getIsWaitingOnBreak;
exports.getShouldPauseOnExceptions = getShouldPauseOnExceptions;
exports.getShouldIgnoreCaughtExceptions = getShouldIgnoreCaughtExceptions;
exports.getCanRewind = getCanRewind;
exports.getExtra = getExtra;
exports.getFrames = getFrames;
exports.getGeneratedFrameScope = getGeneratedFrameScope;
exports.getOriginalFrameScope = getOriginalFrameScope;
@ -5435,6 +5437,7 @@ var _prefs = __webpack_require__(226);
var _sources = __webpack_require__(1369);
const createPauseState = exports.createPauseState = () => ({
extra: {},
why: null,
isWaitingOnBreak: false,
frames: undefined,
@ -5449,7 +5452,7 @@ const createPauseState = exports.createPauseState = () => ({
shouldIgnoreCaughtExceptions: _prefs.prefs.ignoreCaughtExceptions,
canRewind: false,
debuggeeUrl: "",
command: "",
command: null,
previousLocation: null
});
@ -5495,7 +5498,7 @@ function update(state = createPauseState(), action) {
case "ADD_SCOPES":
{
const { frame, status, value } = action;
const { frame, extra, status, value } = action;
const selectedFrameId = frame.id;
const generated = _extends({}, state.frameScopes.generated, {
@ -5505,6 +5508,7 @@ function update(state = createPauseState(), action) {
}
});
return _extends({}, state, {
extra: extra,
frameScopes: _extends({}, state.frameScopes, {
generated
})
@ -5578,7 +5582,7 @@ function update(state = createPauseState(), action) {
return action.status === "start" ? _extends({}, state, emptyPauseState, {
command: action.command,
previousLocation: buildPreviousLocation(state, action)
}) : _extends({}, state, { command: "" });
}) : _extends({}, state, { command: null });
}
case "RESUME":
@ -5588,7 +5592,7 @@ function update(state = createPauseState(), action) {
case "EVALUATE_EXPRESSION":
return _extends({}, state, {
command: action.status === "start" ? "expression" : ""
command: action.status === "start" ? "expression" : null
});
case "NAVIGATE":
@ -5635,8 +5639,12 @@ function getPauseReason(state) {
return state.pause.why;
}
function getPauseCommand(state) {
return state.pause && state.pause.command;
}
function isStepping(state) {
return ["stepIn", "stepOver", "stepOut"].includes(state.pause.command);
return ["stepIn", "stepOver", "stepOut"].includes(getPauseCommand(state));
}
function isPaused(state) {
@ -5671,6 +5679,10 @@ function getCanRewind(state) {
return state.pause.canRewind;
}
function getExtra(state) {
return state.pause.extra;
}
function getFrames(state) {
return state.pause.frames;
}
@ -6388,16 +6400,14 @@ exports.setPausePoints = setPausePoints;
var _selectors = __webpack_require__(3590);
var _pause = __webpack_require__(1639);
var _setInScopeLines = __webpack_require__(1781);
var _parser = __webpack_require__(1365);
var _promise = __webpack_require__(1653);
/* 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/>. */
function setSourceMetaData(sourceId) {
return async ({ dispatch, getState }) => {
const source = (0, _selectors.getSource)(getState(), sourceId);
@ -6414,7 +6424,9 @@ function setSourceMetaData(sourceId) {
}
});
};
}
} /* 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/>. */
function setSymbols(sourceId) {
return async ({ dispatch, getState }) => {
@ -6429,6 +6441,10 @@ function setSymbols(sourceId) {
[_promise.PROMISE]: (0, _parser.getSymbols)(source.id)
});
if ((0, _selectors.isPaused)(getState())) {
await dispatch((0, _pause.mapFrames)());
}
await dispatch(setPausePoints(sourceId));
await dispatch(setSourceMetaData(sourceId));
};
@ -7712,45 +7728,16 @@ module.exports = {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.containsPosition = containsPosition;
exports.findClosestScope = findClosestScope;
exports.getASTLocation = getASTLocation;
exports.findScopeByName = findScopeByName;
var _parser = __webpack_require__(1365);
function containsPosition(a, b) {
const startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column;
const endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column;
var _ast = __webpack_require__(1638);
return startsBefore && endsAfter;
} /* 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/>. */
function findClosestScope(functions, location) {
return functions.reduce((found, currNode) => {
if (currNode.name === "anonymous" || !containsPosition(currNode.location, {
line: location.line,
column: location.column || 0
})) {
return found;
}
if (!found) {
return currNode;
}
if (found.location.start.line > currNode.location.start.line) {
return found;
}
if (found.location.start.line === currNode.location.start.line && found.location.start.column > currNode.location.start.column) {
return found;
}
return currNode;
}, null);
}
/* 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/>. */
function getASTLocation(source, symbols, location) {
if (source.isWasm || !symbols || symbols.loading) {
@ -7759,7 +7746,7 @@ function getASTLocation(source, symbols, location) {
const functions = [...symbols.functions];
const scope = findClosestScope(functions, location);
const scope = (0, _ast.findClosestFunction)(functions, location);
if (scope) {
// we only record the line, but at some point we may
// also do column offsets
@ -21930,7 +21917,7 @@ var _clipboard = __webpack_require__(1388);
var _function = __webpack_require__(1597);
var _astBreakpointLocation = __webpack_require__(1416);
var _ast = __webpack_require__(1638);
var _editor = __webpack_require__(1358);
@ -22138,8 +22125,8 @@ exports.default = (0, _reactRedux.connect)(state => {
selectedSource,
hasPrettyPrint: !!(0, _selectors.getPrettySource)(state, selectedSource.get("id")),
contextMenu: (0, _selectors.getContextMenu)(state),
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), (0, _selectors.getSymbols)(state, selectedSource.toJS())),
getFunctionLocation: line => (0, _astBreakpointLocation.findClosestScope)((0, _selectors.getSymbols)(state, selectedSource.toJS()).functions, {
getFunctionText: line => (0, _function.findFunctionText)(line, selectedSource.toJS(), (0, _selectors.getSymbols)(state, selectedSource)),
getFunctionLocation: line => (0, _ast.findClosestFunction)((0, _selectors.getSymbols)(state, selectedSource).functions, {
line,
column: Infinity
})
@ -22167,7 +22154,7 @@ Object.defineProperty(exports, "__esModule", {
});
exports.findFunctionText = findFunctionText;
var _astBreakpointLocation = __webpack_require__(1416);
var _ast = __webpack_require__(1638);
var _indentation = __webpack_require__(1438);
@ -22176,7 +22163,10 @@ var _indentation = __webpack_require__(1438);
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
function findFunctionText(line, source, symbols) {
const func = (0, _astBreakpointLocation.findClosestScope)(symbols.functions, { line, column: Infinity });
const func = (0, _ast.findClosestFunction)(symbols.functions, {
line,
column: Infinity
});
if (!func) {
return null;
}
@ -22471,6 +22461,10 @@ var _BreakpointsDropdown = __webpack_require__(1790);
var _BreakpointsDropdown2 = _interopRequireDefault(_BreakpointsDropdown);
var _FrameworkComponent = __webpack_require__(3623);
var _FrameworkComponent2 = _interopRequireDefault(_FrameworkComponent);
var _ChromeScopes = __webpack_require__(1610);
var _ChromeScopes2 = _interopRequireDefault(_ChromeScopes);
@ -22483,11 +22477,9 @@ __webpack_require__(1342);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* 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/>. */
const Scopes = _prefs.features.chromeScopes ? _ChromeScopes2.default : _Scopes3.default;
const Scopes = _prefs.features.chromeScopes ? _ChromeScopes2.default : _Scopes3.default; /* 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/>. */
function debugBtn(onClick, type, className, tooltip) {
return _react2.default.createElement(
@ -22558,6 +22550,20 @@ class SecondaryPanes extends _react.Component {
};
}
getComponentItem() {
const { extra: { react } } = this.props;
return {
header: react.displayName,
className: "component-pane",
component: _react2.default.createElement(_FrameworkComponent2.default, null),
opened: _prefs.prefs.componentVisible,
onToggle: opened => {
_prefs.prefs.componentVisible = opened;
}
};
}
getWatchItem() {
return {
header: L10N.getStr("watchExpressions.header"),
@ -22625,7 +22631,7 @@ class SecondaryPanes extends _react.Component {
}
getStartItems() {
const { workers } = this.props;
const { extra, workers } = this.props;
const items = [];
if (this.props.horizontal) {
@ -22640,7 +22646,12 @@ class SecondaryPanes extends _react.Component {
if (this.props.hasFrames) {
items.push(this.getCallStackItem());
if (this.props.horizontal) {
if (extra && extra.react) {
items.push(this.getComponentItem());
}
items.push(this.getScopeItem());
}
}
@ -22661,7 +22672,7 @@ class SecondaryPanes extends _react.Component {
}
getEndItems() {
const { workers } = this.props;
const { extra, workers } = this.props;
let items = [];
@ -22675,6 +22686,10 @@ class SecondaryPanes extends _react.Component {
items.push(this.getWatchItem());
if (extra && extra.react) {
items.push(this.getComponentItem());
}
if (this.props.hasFrames) {
items = [...items, this.getScopeItem()];
}
@ -22728,6 +22743,7 @@ SecondaryPanes.contextTypes = {
};
exports.default = (0, _reactRedux.connect)(state => ({
extra: (0, _selectors.getExtra)(state),
hasFrames: !!(0, _selectors.getTopFrame)(state),
breakpoints: (0, _selectors.getBreakpoints)(state),
breakpointsDisabled: (0, _selectors.getBreakpointsDisabled)(state),
@ -26375,6 +26391,8 @@ Object.defineProperty(exports, "__esModule", {
});
exports.findBestMatchExpression = findBestMatchExpression;
exports.findEmptyLines = findEmptyLines;
exports.containsPosition = containsPosition;
exports.findClosestFunction = findClosestFunction;
var _lodash = __webpack_require__(2);
@ -26410,6 +26428,37 @@ function findEmptyLines(selectedSource, pausePoints) {
return (0, _lodash.without)(sourceLines, ...breakpointLines);
}
function containsPosition(a, b) {
const startsBefore = a.start.line < b.line || a.start.line === b.line && a.start.column <= b.column;
const endsAfter = a.end.line > b.line || a.end.line === b.line && a.end.column >= b.column;
return startsBefore && endsAfter;
}
function findClosestFunction(functions, location) {
return functions.reduce((found, currNode) => {
if (currNode.name === "anonymous" || !containsPosition(currNode.location, {
line: location.line,
column: location.column || 0
})) {
return found;
}
if (!found) {
return currNode;
}
if (found.location.start.line > currNode.location.start.line) {
return found;
}
if (found.location.start.line === currNode.location.start.line && found.location.start.column > currNode.location.start.column) {
return found;
}
return currNode;
}, null);
}
/***/ }),
/***/ 1639:
@ -27179,7 +27228,10 @@ class QuickOpenModal extends _react.Component {
let results = functions;
if (this.isVariableQuery()) {
results = variables;
} else {
results = results.filter(result => result.title !== "anonymous");
}
if (query === "@" || query === "#") {
return this.setState({ results });
}
@ -27595,8 +27647,14 @@ var _selectors = __webpack_require__(3590);
var _mapScopes = __webpack_require__(1634);
var _preview = __webpack_require__(1786);
var _promise = __webpack_require__(1653);
/* 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/>. */
function fetchScopes() {
return async function ({ dispatch, getState, client, sourceMaps }) {
const frame = (0, _selectors.getSelectedFrame)(getState());
@ -27604,17 +27662,18 @@ function fetchScopes() {
return;
}
const extra = await dispatch((0, _preview.getExtra)("this;", frame.this, frame));
const scopes = dispatch({
type: "ADD_SCOPES",
frame,
extra,
[_promise.PROMISE]: client.getFrameScopes(frame)
});
await dispatch((0, _mapScopes.mapScopes)(scopes, frame));
};
} /* 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/>. */
}
/***/ }),
@ -30168,6 +30227,7 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < argument
* 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/>. */
exports.getExtra = getExtra;
exports.updatePreview = updatePreview;
exports.setPreview = setPreview;
exports.clearPreview = clearPreview;
@ -30242,6 +30302,14 @@ function isInvalidTarget(target) {
return invalidTarget || invalidToken || invaildType;
}
function getExtra(expression, result, selectedFrame) {
return async ({ dispatch, getState, client, sourceMaps }) => {
const extra = await getExtraProps(expression, result, expr => client.evaluateInFrame(selectedFrame.id, expr));
return extra;
};
}
function updatePreview(target, editor) {
return ({ dispatch, getState, client, sourceMaps }) => {
const tokenPos = (0, _editor.getTokenLocation)(editor.codeMirror, target);
@ -30322,7 +30390,7 @@ function setPreview(expression, location, tokenPos, cursorPos) {
return;
}
const extra = await getExtraProps(expression, result, expr => client.evaluateInFrame(selectedFrame.id, expr));
const extra = await dispatch(getExtra(expression, result, selectedFrame));
return {
expression,
@ -30750,27 +30818,61 @@ function isDocumentReady(selectedSource, selectedLocation) {
return selectedLocation && (0, _source.isLoaded)(selectedSource) && (0, _sourceDocuments.hasDocument)(selectedLocation.sourceId);
}
class HighlightLine extends _react.PureComponent {
class HighlightLine extends _react.Component {
constructor(...args) {
var _temp;
return _temp = super(...args), this.isStepping = false, this.previousEditorLine = null, _temp;
}
shouldComponentUpdate(nextProps) {
const { selectedLocation, selectedSource } = nextProps;
return this.shouldSetHighlightLine(selectedLocation, selectedSource);
}
shouldSetHighlightLine(selectedLocation, selectedSource) {
const { sourceId, line } = selectedLocation;
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
if (!isDocumentReady(selectedSource, selectedLocation)) {
return false;
}
if (this.isStepping && editorLine === this.previousEditorLine) {
return false;
}
return true;
}
componentDidUpdate(prevProps) {
const { selectedLocation, selectedFrame, selectedSource } = this.props;
const {
pauseCommand,
selectedLocation,
selectedFrame,
selectedSource
} = this.props;
if (pauseCommand) {
this.isStepping = true;
}
this.clearHighlightLine(prevProps.selectedLocation, prevProps.selectedSource);
this.setHighlightLine(selectedLocation, selectedFrame, selectedSource);
}
setHighlightLine(selectedLocation, selectedFrame, selectedSource) {
if (!isDocumentReady(selectedSource, selectedLocation)) {
const { sourceId, line } = selectedLocation;
if (!this.shouldSetHighlightLine(selectedLocation, selectedSource)) {
return;
}
const { sourceId, line } = selectedLocation;
this.isStepping = false;
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
this.previousEditorLine = editorLine;
if (!line || isDebugLine(selectedFrame, selectedLocation)) {
return;
}
const editorLine = (0, _editor.toEditorLine)(sourceId, line);
const doc = (0, _sourceDocuments.getDocument)(sourceId);
doc.addLineClass(editorLine, "line", "highlight-line");
}
@ -30793,6 +30895,7 @@ class HighlightLine extends _react.PureComponent {
exports.HighlightLine = HighlightLine;
exports.default = (0, _reactRedux.connect)(state => ({
pauseCommand: (0, _selectors.getPauseCommand)(state),
selectedFrame: (0, _selectors.getVisibleSelectedFrame)(state),
selectedLocation: (0, _selectors.getSelectedLocation)(state),
selectedSource: (0, _selectors.getSelectedSource)(state)
@ -31581,10 +31684,13 @@ Object.defineProperty(exports, "__esModule", {
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
exports.updateFrameLocation = updateFrameLocation;
exports.mapDisplayNames = mapDisplayNames;
exports.mapFrames = mapFrames;
var _selectors = __webpack_require__(3590);
var _ast = __webpack_require__(1638);
function updateFrameLocation(frame, sourceMaps) {
return sourceMaps.getOriginalLocation(frame.location).then(loc => _extends({}, frame, {
location: loc,
@ -31600,12 +31706,32 @@ function updateFrameLocations(frames, sourceMaps) {
return Promise.all(frames.map(frame => updateFrameLocation(frame, sourceMaps)));
}
function mapDisplayNames(frames, getState) {
return frames.map(frame => {
const source = (0, _selectors.getSource)(getState(), frame.location.sourceId);
const symbols = (0, _selectors.getSymbols)(getState(), source);
if (!symbols || !symbols.functions) {
return frame;
}
const originalFunction = (0, _ast.findClosestFunction)(symbols.functions, frame.location);
if (!originalFunction) {
return frame;
}
const originalDisplayName = originalFunction.name;
return _extends({}, frame, { originalDisplayName });
});
}
/**
* Map call stack frame locations to original locations.
* Map call stack frame locations and display names to originals.
* e.g.
* 1. When the debuggee pauses
* 2. When a source is pretty printed
*
* 3. When symbols are loaded
* @memberof actions/pause
* @static
*/
@ -31616,7 +31742,8 @@ function mapFrames() {
return;
}
const mappedFrames = await updateFrameLocations(frames, sourceMaps);
let mappedFrames = await updateFrameLocations(frames, sourceMaps);
mappedFrames = mapDisplayNames(mappedFrames, getState);
dispatch({
type: "MAP_FRAMES",
@ -33926,6 +34053,7 @@ if (isDevelopment()) {
pref("devtools.debugger.ignore-caught-exceptions", false);
pref("devtools.debugger.call-stack-visible", true);
pref("devtools.debugger.scopes-visible", true);
pref("devtools.debugger.component-visible", true);
pref("devtools.debugger.workers-visible", true);
pref("devtools.debugger.expressions-visible", true);
pref("devtools.debugger.breakpoints-visible", true);
@ -33968,6 +34096,7 @@ const prefs = new PrefsHelper("devtools", {
ignoreCaughtExceptions: ["Bool", "debugger.ignore-caught-exceptions"],
callStackVisible: ["Bool", "debugger.call-stack-visible"],
scopesVisible: ["Bool", "debugger.scopes-visible"],
componentVisible: ["Bool", "debugger.component-visible"],
workersVisible: ["Bool", "debugger.workers-visible"],
breakpointsVisible: ["Bool", "debugger.breakpoints-visible"],
expressionsVisible: ["Bool", "debugger.expressions-visible"],
@ -37221,9 +37350,22 @@ function annotateBabelAsyncFrames(frames) {
// Receives an array of frames and looks for babel async
// call stack groups.
function getBabelFrameIndexes(frames) {
const startIndexes = getFrameIndices(frames, (displayName, url) => url.match(/regenerator-runtime/i) && displayName === "tryCatch");
const startIndexes = frames.reduce((accumulator, frame, index) => {
if ((0, _getFrameUrl.getFrameUrl)(frame).match(/regenerator-runtime/i) && frame.displayName === "tryCatch") {
return [...accumulator, index];
}
return accumulator;
}, []);
const endIndexes = getFrameIndices(frames, (displayName, url) => displayName === "_asyncToGenerator/<" || url.match(/_microtask/i) && displayName === "flush");
const endIndexes = frames.reduce((accumulator, frame, index) => {
if ((0, _getFrameUrl.getFrameUrl)(frame).match(/_microtask/i) && frame.displayName === "flush") {
return [...accumulator, index];
}
if (frame.displayName === "_asyncToGenerator/<") {
return [...accumulator, index + 1];
}
return accumulator;
}, []);
if (startIndexes.length != endIndexes.length || startIndexes.length === 0) {
return frames;
@ -37235,10 +37377,6 @@ function getBabelFrameIndexes(frames) {
return (0, _lodash.flatMap)((0, _lodash.zip)(startIndexes, endIndexes), ([startIndex, endIndex]) => (0, _lodash.range)(startIndex, endIndex + 1));
}
function getFrameIndices(frames, predicate) {
return frames.reduce((accumulator, frame, index) => predicate(frame.displayName, (0, _getFrameUrl.getFrameUrl)(frame)) ? [...accumulator, index] : accumulator, []);
}
/***/ }),
/***/ 3609:
@ -37402,7 +37540,8 @@ function mapDisplayNames(frame, library) {
}
function formatDisplayName(frame, { shouldMapDisplayName = true } = {}) {
let { displayName, library } = frame;
let { displayName, originalDisplayName, library } = frame;
displayName = originalDisplayName || displayName;
if (library && shouldMapDisplayName) {
displayName = mapDisplayNames(frame, library);
}
@ -38306,6 +38445,111 @@ function formatPausePoints(text, nodes) {
/***/ }),
/***/ 3623:
/***/ (function(module, exports, __webpack_require__) {
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _react = __webpack_require__(0);
var _react2 = _interopRequireDefault(_react);
var _redux = __webpack_require__(3593);
var _reactRedux = __webpack_require__(3592);
var _actions = __webpack_require__(1354);
var _actions2 = _interopRequireDefault(_actions);
var _firefox = __webpack_require__(1500);
var _selectors = __webpack_require__(3590);
var _devtoolsReps = __webpack_require__(1408);
var _preview = __webpack_require__(1807);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/* 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/>. */
const { createNode, getChildren } = _devtoolsReps.ObjectInspectorUtils.node;
const { loadItemProperties } = _devtoolsReps.ObjectInspectorUtils.loadProperties;
class FrameworkComponent extends _react.PureComponent {
async componentWillMount() {
const expression = "this;";
const { selectedFrame, setPopupObjectProperties } = this.props;
const value = selectedFrame.this;
const root = createNode(null, expression, expression, { value });
const properties = await loadItemProperties(root, _firefox.createObjectClient);
if (properties) {
setPopupObjectProperties(value, properties);
}
}
renderReactComponent() {
const { selectedFrame, popupObjectProperties } = this.props;
const expression = "this;";
const value = selectedFrame.this;
const root = {
name: expression,
path: expression,
contents: { value }
};
const loadedRootProperties = popupObjectProperties[value.actor];
let roots = getChildren({
item: root,
loadedProperties: new Map([[root.path, loadedRootProperties]])
});
roots = roots.filter(r => ["state", "props"].includes(r.name));
return _react2.default.createElement(
"div",
{ className: "pane framework-component" },
_react2.default.createElement(_devtoolsReps.ObjectInspector, {
roots: roots,
autoExpandAll: false,
autoExpandDepth: 0,
disableWrap: true,
disabledFocus: true,
dimTopLevelWindow: true,
createObjectClient: grip => (0, _firefox.createObjectClient)(grip)
})
);
}
render() {
const { selectedFrame } = this.props;
if ((0, _preview.isReactComponent)(selectedFrame.this)) {
return this.renderReactComponent();
}
return null;
}
}
exports.default = (0, _reactRedux.connect)(state => {
return {
selectedFrame: (0, _selectors.getSelectedFrame)(state),
popupObjectProperties: (0, _selectors.getAllPopupObjectProperties)(state)
};
}, dispatch => (0, _redux.bindActionCreators)(_actions2.default, dispatch))(FrameworkComponent);
/***/ }),
/***/ 363:
/***/ (function(module, exports) {

Просмотреть файл

@ -997,10 +997,7 @@ function _parse(code, opts) {
const sourceOptions = {
generated: {
tokens: true,
plugins: [
"objectRestSpread"
]
tokens: true
},
original: {
sourceType: "unambiguous",
@ -40565,4 +40562,4 @@ module.exports = listCacheHas;
/***/ })
/******/ });
});
});

Просмотреть файл

@ -29,6 +29,7 @@ pref("devtools.debugger.ui.variables-searchbox-visible", false);
pref("devtools.debugger.ui.framework-grouping-on", true);
pref("devtools.debugger.call-stack-visible", true);
pref("devtools.debugger.scopes-visible", true);
pref("devtools.debugger.component-visible", true);
pref("devtools.debugger.workers-visible", true);
pref("devtools.debugger.breakpoints-visible", true);
pref("devtools.debugger.expressions-visible", true);

Просмотреть файл

@ -123,6 +123,17 @@ StructuredCloneCallbacksFreeTransfer(uint32_t aTag,
aExtraData);
}
bool
StructuredCloneCallbacksCanTransfer(JSContext* aCx,
JS::Handle<JSObject*> aObject,
void* aClosure)
{
StructuredCloneHolderBase* holder =
static_cast<StructuredCloneHolderBase*>(aClosure);
MOZ_ASSERT(holder);
return holder->CustomCanTransferHandler(aCx, aObject);
}
void
StructuredCloneCallbacksError(JSContext* aCx,
uint32_t aErrorId)
@ -138,7 +149,8 @@ const JSStructuredCloneCallbacks StructuredCloneHolder::sCallbacks = {
StructuredCloneCallbacksError,
StructuredCloneCallbacksReadTransfer,
StructuredCloneCallbacksWriteTransfer,
StructuredCloneCallbacksFreeTransfer
StructuredCloneCallbacksFreeTransfer,
StructuredCloneCallbacksCanTransfer,
};
// StructuredCloneHolderBase class
@ -240,6 +252,13 @@ StructuredCloneHolderBase::CustomFreeTransferHandler(uint32_t aTag,
MOZ_CRASH("Nothing to free.");
}
bool
StructuredCloneHolderBase::CustomCanTransferHandler(JSContext* aCx,
JS::Handle<JSObject*> aObj)
{
return false;
}
// StructuredCloneHolder class
StructuredCloneHolder::StructuredCloneHolder(CloningSupport aSupportsCloning,
@ -1221,6 +1240,10 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
*aExtraData = mPortIdentifiers.Length();
MessagePortIdentifier* identifier = mPortIdentifiers.AppendElement();
if (!port->CanBeCloned()) {
return false;
}
port->CloneAndDisentangle(*identifier);
*aTag = SCTAG_DOM_MAP_MESSAGEPORT;
@ -1237,6 +1260,10 @@ StructuredCloneHolder::CustomWriteTransferHandler(JSContext* aCx,
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(canvas);
if (canvas->IsNeutered()) {
return false;
}
*aExtraData = 0;
*aTag = SCTAG_DOM_CANVAS;
*aOwnership = JS::SCTAG_TMO_CUSTOM;
@ -1314,6 +1341,42 @@ StructuredCloneHolder::CustomFreeTransferHandler(uint32_t aTag,
}
}
bool
StructuredCloneHolder::CustomCanTransferHandler(JSContext* aCx,
JS::Handle<JSObject*> aObj)
{
if (!mSupportsTransferring) {
return false;
}
JS::Rooted<JSObject*> obj(aCx, aObj);
{
MessagePort* port = nullptr;
nsresult rv = UNWRAP_OBJECT(MessagePort, &obj, port);
if (NS_SUCCEEDED(rv)) {
return true;
}
if (mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) {
OffscreenCanvas* canvas = nullptr;
rv = UNWRAP_OBJECT(OffscreenCanvas, &obj, canvas);
if (NS_SUCCEEDED(rv)) {
return true;
}
ImageBitmap* bitmap = nullptr;
rv = UNWRAP_OBJECT(ImageBitmap, &obj, bitmap);
if (NS_SUCCEEDED(rv)) {
return true;
}
}
}
return false;
}
bool
StructuredCloneHolder::TakeTransferredPortsAsSequence(Sequence<OwningNonNull<mozilla::dom::MessagePort>>& aPorts)
{

Просмотреть файл

@ -88,6 +88,10 @@ public:
void* aContent,
uint64_t aExtraData);
virtual bool
CustomCanTransferHandler(JSContext* aCx,
JS::Handle<JSObject*> aObj);
// These methods are what you should use to read/write data.
// Execute the serialization of aValue using the Structured Clone Algorithm.
@ -283,6 +287,9 @@ public:
void* aContent,
uint64_t aExtraData) override;
virtual bool CustomCanTransferHandler(JSContext* aCx,
JS::Handle<JSObject*> aObj) override;
// These 2 static methods are useful to read/write fully serializable objects.
// They can be used by custom StructuredCloneHolderBase classes to
// serialize objects such as ImageData, CryptoKey, RTCCertificate, etc.

Просмотреть файл

@ -613,9 +613,11 @@ public:
}
/**
* This method returns the owner doc if the node is in the
* composed document (as defined in the Shadow DOM spec), otherwise
* it returns null.
* This method returns the owner document if the node is connected to it
* (as defined in the DOM spec), otherwise it returns null.
* In other words, returns non-null even in the case the node is in
* Shadow DOM, if there is a possibly shadow boundary crossing path from
* the node to its owner document.
*/
nsIDocument* GetComposedDoc() const
{

Просмотреть файл

@ -700,7 +700,8 @@ GetAddInfoCallback(JSContext* aCx, void* aClosure)
nullptr /* reportError */,
nullptr /* readTransfer */,
nullptr /* writeTransfer */,
nullptr /* freeTransfer */
nullptr /* freeTransfer */,
nullptr /* canTransfer */
};
MOZ_ASSERT(aCx);
@ -1323,6 +1324,7 @@ IDBObjectStore::DeserializeValue(JSContext* aCx,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
};
@ -1496,6 +1498,7 @@ private:
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
};
@ -1609,6 +1612,7 @@ private:
nullptr,
nullptr,
nullptr,
nullptr,
nullptr
};

Просмотреть файл

@ -204,6 +204,7 @@ MessagePort::MessagePort(nsIGlobalObject* aGlobal)
, mInnerID(0)
, mMessageQueueEnabled(false)
, mIsKeptAlive(false)
, mHasBeenTransferredOrClosed(false)
{
MOZ_ASSERT(aGlobal);
@ -501,6 +502,7 @@ MessagePort::Dispatch()
void
MessagePort::Close()
{
mHasBeenTransferredOrClosed = true;
CloseInternal(true /* aSoftly */);
}
@ -725,6 +727,9 @@ void
MessagePort::CloneAndDisentangle(MessagePortIdentifier& aIdentifier)
{
MOZ_ASSERT(mIdentifier);
MOZ_ASSERT(!mHasBeenTransferredOrClosed);
mHasBeenTransferredOrClosed = true;
// We can clone a port that has already been transfered. In this case, on the
// otherside will have a neutered port. Here we set neutered to true so that

Просмотреть файл

@ -74,6 +74,11 @@ public:
void UnshippedEntangle(MessagePort* aEntangledPort);
bool CanBeCloned() const
{
return !mHasBeenTransferredOrClosed;
}
void CloneAndDisentangle(MessagePortIdentifier& aIdentifier);
void CloseForced();
@ -182,6 +187,12 @@ private:
bool mMessageQueueEnabled;
bool mIsKeptAlive;
// mHasBeenTransferredOrClosed is used to know if this port has been manually
// closed or transferred via postMessage. Note that if the entangled port is
// closed, this port is closed as well (see mState) but, just because close()
// has not been called directly, by spec, this port can still be transferred.
bool mHasBeenTransferredOrClosed;
};
} // namespace dom

Просмотреть файл

@ -240,6 +240,13 @@ public:
RefPtr<FilterNode> filter = mFilter;
if (mFilter->GetBackendType() == FilterBackend::FILTER_BACKEND_CAPTURE) {
filter = static_cast<FilterNodeCapture*>(filter.get())->Validate(aDT);
// This can happen if the FilterNodeCapture is unable to create a
// backing FilterNode on the target backend. Normally this would be
// handled by the painting code, but here there's not much we can do.
if (!filter) {
return;
}
}
aDT->DrawFilter(filter, mSourceRect, mDestPoint, mOptions);
}

Просмотреть файл

@ -202,6 +202,8 @@ uint32_t ConvertValue(FilterType aType, uint32_t aAttribute, uint32_t aValue)
aValue = D2DFilterCompositionMode(aValue);
}
break;
default:
break;
}
return aValue;
@ -218,6 +220,8 @@ void ConvertValue(FilterType aType, uint32_t aAttribute, IntSize &aValue)
aValue.height += 1;
}
break;
default:
break;
}
}
@ -441,6 +445,8 @@ GetD2D1PropForAttribute(FilterType aType, uint32_t aIndex)
CONVERT_PROP(CROP_RECT, CROP_PROP_RECT);
}
break;
default:
break;
}
return UINT32_MAX;
@ -457,6 +463,8 @@ GetD2D1PropsForIntSize(FilterType aType, uint32_t aIndex, UINT32 *aPropWidth, UI
return true;
}
break;
default:
break;
}
return false;
}
@ -514,6 +522,8 @@ static inline REFCLSID GetCLDIDForFilterType(FilterType aType)
return CLSID_D2D1Premultiply;
case FilterType::UNPREMULTIPLY:
return CLSID_D2D1UnPremultiply;
default:
break;
}
return GUID_NULL;
}

Просмотреть файл

@ -865,7 +865,7 @@ SourceSurfaceImage::GetTextureClient(KnowsCompositor* aForwarder)
}
// Remove the speculatively added entry.
mTextureClients.Remove(aForwarder->GetSerial());
entry.OrRemove();
return nullptr;
}

Просмотреть файл

@ -867,7 +867,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
apzc = insertResult.first->second;
PrintAPZCInfo(aLayer, apzc);
}
APZCTM_LOG("Found APZC %p for layer %p with identifiers %" PRId64 " %" PRId64 "\n", apzc, aLayer.GetLayer(), guid.mLayersId, guid.mScrollId);
APZCTM_LOG("Found APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n",
apzc, aLayer.GetLayer(), uint64_t(guid.mLayersId), guid.mScrollId);
// If we haven't encountered a layer already with the same metrics, then we need to
// do the full reuse-or-make-an-APZC algorithm, which is contained inside the block
@ -938,7 +939,8 @@ APZCTreeManager::PrepareNodeForLayer(const ScrollNode& aLayer,
node->SetLastChild(nullptr);
}
APZCTM_LOG("Using APZC %p for layer %p with identifiers %" PRId64 " %" PRId64 "\n", apzc, aLayer.GetLayer(), aLayersId, aMetrics.GetScrollId());
APZCTM_LOG("Using APZC %p for layer %p with identifiers %" PRIx64 " %" PRId64 "\n",
apzc, aLayer.GetLayer(), uint64_t(aLayersId), aMetrics.GetScrollId());
apzc->NotifyLayersUpdated(aLayer.Metadata(), aState.mIsFirstPaint,
aLayersId == aState.mOriginatingLayersId);
@ -1087,7 +1089,7 @@ APZCTreeManager::FlushApzRepaints(LayersId aLayersId)
// Previously, paints were throttled and therefore this method was used to
// ensure any pending paints were flushed. Now, paints are flushed
// immediately, so it is safe to simply send a notification now.
APZCTM_LOG("Flushing repaints for layers id 0x%" PRIx64 "\n", aLayersId);
APZCTM_LOG("Flushing repaints for layers id 0x%" PRIx64 "\n", uint64_t(aLayersId));
RefPtr<GeckoContentController> controller = GetContentController(aLayersId);
MOZ_ASSERT(controller);
controller->DispatchToRepaintThread(

Просмотреть файл

@ -675,15 +675,9 @@ PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
}
if (!scrollAncestor) {
MOZ_ASSERT(false); // If you hit this, please file a bug with STR.
// Attempt some sort of graceful handling based on a theory as to why we
// reach this point...
// If we get here, the document element is non-null, valid, but doesn't have
// a displayport. It's possible that the init code in ChromeProcessController
// failed for some reason, or the document element got swapped out at some
// later time. In this case let's try to set a displayport on the document
// element again and bail out on this operation.
// This can happen if the document element gets swapped out after ChromeProcessController
// runs InitializeRootDisplayport. In this case let's try to set a displayport again and
// bail out on this operation.
APZCCH_LOG("Widget %p's document element %p didn't have a displayport\n",
aWidget, dpElement.get());
APZCCallbackHelper::InitializeRootDisplayport(aRootFrame->PresShell());

Просмотреть файл

@ -108,7 +108,6 @@ WebRenderLayerManager::DoDestroy(bool aIsSync)
if (WrBridge()) {
// Just clear ImageKeys, they are deleted during WebRenderAPI destruction.
mImageKeysToDeleteLater.Clear();
mImageKeysToDelete.Clear();
// CompositorAnimations are cleared by WebRenderBridgeParent.
mDiscardedCompositorAnimationsIds.Clear();
@ -298,7 +297,6 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
resourceUpdates.DeleteImage(key);
}
mImageKeysToDelete.Clear();
mImageKeysToDelete.SwapElements(mImageKeysToDeleteLater);
WrBridge()->RemoveExpiredFontKeys(resourceUpdates);
@ -406,20 +404,16 @@ WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
void
WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
{
mImageKeysToDeleteLater.AppendElement(key);
mImageKeysToDelete.AppendElement(key);
}
void
WebRenderLayerManager::DiscardImages()
{
wr::IpcResourceUpdateQueue resources(WrBridge());
for (const auto& key : mImageKeysToDeleteLater) {
resources.DeleteImage(key);
}
for (const auto& key : mImageKeysToDelete) {
resources.DeleteImage(key);
}
mImageKeysToDeleteLater.Clear();
mImageKeysToDelete.Clear();
WrBridge()->UpdateResources(resources);
}
@ -462,7 +456,6 @@ WebRenderLayerManager::DiscardLocalImages()
// Removes images but doesn't tell the parent side about them
// This is useful in empty / failed transactions where we created
// image keys but didn't tell the parent about them yet.
mImageKeysToDeleteLater.Clear();
mImageKeysToDelete.Clear();
}

Просмотреть файл

@ -175,11 +175,6 @@ private:
private:
nsIWidget* MOZ_NON_OWNING_REF mWidget;
nsTArray<wr::ImageKey> mImageKeysToDelete;
// TODO - This is needed because we have some code that creates image keys
// and enqueues them for deletion right away which is bad not only because
// of poor texture cache usage, but also because images end up deleted before
// they are used. This should hopfully be temporary.
nsTArray<wr::ImageKey> mImageKeysToDeleteLater;
// Set of compositor animation ids for which there are active animations (as
// of the last transaction) on the compositor side.

Просмотреть файл

@ -31,6 +31,8 @@
#define fopen(path,mode) hnjFopen(path,mode)
#define fclose(file) hnjFclose(file)
#define fgets(buf,count,file) hnjFgets(buf,count,file)
#define feof(file) hnjFeof(file)
#define fgetc(file) hnjFgetc(file)
typedef struct hnjFile_ hnjFile;
@ -44,6 +46,10 @@ int hnjFclose(hnjFile* f);
char* hnjFgets(char* s, int n, hnjFile* f);
int hnjFeof(hnjFile* f);
int hnjFgetc(hnjFile* f);
#ifdef __cplusplus
}
#endif

Просмотреть файл

@ -22,6 +22,7 @@ struct hnjFile_ {
char mBuffer[BUFSIZE];
uint32_t mCurPos;
uint32_t mLimit;
bool mEOF;
};
// replacement for fopen()
@ -58,6 +59,7 @@ hnjFopen(const char* aURISpec, const char* aMode)
f->mStream = instream;
f->mCurPos = 0;
f->mLimit = 0;
f->mEOF = false;
return f;
}
@ -79,6 +81,27 @@ hnjFclose(hnjFile* f)
return result;
}
// replacement for fgetc()
int
hnjFgetc(hnjFile* f)
{
if (f->mCurPos >= f->mLimit) {
f->mCurPos = 0;
nsresult rv = f->mStream->Read(f->mBuffer, BUFSIZE, &f->mLimit);
if (NS_FAILED(rv)) {
f->mLimit = 0;
}
if (f->mLimit == 0) {
f->mEOF = true;
return EOF;
}
}
return f->mBuffer[f->mCurPos++];
}
// replacement for fgets()
// (not a full reimplementation, but sufficient for libhyphen's needs)
char*
@ -88,24 +111,15 @@ hnjFgets(char* s, int n, hnjFile* f)
int i = 0;
while (i < n - 1) {
if (f->mCurPos < f->mLimit) {
char c = f->mBuffer[f->mCurPos++];
s[i++] = c;
if (c == '\n' || c == '\r') {
break;
}
continue;
int c = hnjFgetc(f);
if (c == EOF) {
break;
}
f->mCurPos = 0;
s[i++] = c;
nsresult rv = f->mStream->Read(f->mBuffer, BUFSIZE, &f->mLimit);
if (NS_FAILED(rv)) {
f->mLimit = 0;
return nullptr;
}
if (f->mLimit == 0) {
if (c == '\n' || c == '\r') {
break;
}
}
@ -117,3 +131,9 @@ hnjFgets(char* s, int n, hnjFile* f)
s[i] = '\0'; // null-terminate the returned string
return s;
}
int
hnjFeof(hnjFile* f)
{
return f->mEOF ? EOF : 0;
}

Просмотреть файл

@ -438,11 +438,25 @@ for (k = 0; k < 2; k++) {
}
if (k == 0 || nextlevel) {
while (fgets (buf, sizeof(buf), f) != NULL) {
while (fgets(buf, sizeof(buf), f) != NULL) {
/* discard lines that don't fit in buffer */
if (!feof(f) && strchr(buf, '\n') == NULL) {
int c;
while ((c = fgetc(f)) != '\n' && c != EOF);
/* issue warning if not a comment */
if (buf[0] != '%') {
fprintf(stderr, "Warning: skipping too long pattern (more than %lu chars)\n", sizeof(buf));
}
continue;
}
if (strncmp(buf, "NEXTLEVEL", 9) == 0) {
nextlevel = 1;
break;
} else if (buf[0] != '%') hnj_hyphen_load_line(buf, dict[k], hashtab);
nextlevel = 1;
break;
} else if (buf[0] != '%') {
hnj_hyphen_load_line(buf, dict[k], hashtab);
}
}
} else if (k == 1) {
/* default first level: hyphen and ASCII apostrophe */

Просмотреть файл

@ -295,6 +295,14 @@ typedef bool (*TransferStructuredCloneOp)(JSContext* cx,
typedef void (*FreeTransferStructuredCloneOp)(uint32_t tag, JS::TransferableOwnership ownership,
void* content, uint64_t extraData, void* closure);
/**
* Called when the transferring objects are checked. If this function returns false, the
* serialization ends throwing a DataCloneError exception.
*/
typedef bool (*CanTransferStructuredCloneOp)(JSContext* cx,
JS::Handle<JSObject*> obj,
void* closure);
struct JSStructuredCloneCallbacks {
ReadStructuredCloneOp read;
WriteStructuredCloneOp write;
@ -302,6 +310,7 @@ struct JSStructuredCloneCallbacks {
ReadTransferStructuredCloneOp readTransfer;
TransferStructuredCloneOp writeTransfer;
FreeTransferStructuredCloneOp freeTransfer;
CanTransferStructuredCloneOp canTransfer;
};
enum OwnTransferablePolicy {

Просмотреть файл

@ -38,7 +38,6 @@ namespace JS {
\
_(GetElem_TypedObject) \
_(GetElem_Dense) \
_(GetElem_TypedStatic) \
_(GetElem_TypedArray) \
_(GetElem_String) \
_(GetElem_Arguments) \
@ -47,7 +46,6 @@ namespace JS {
_(GetElem_InlineCache) \
\
_(SetElem_TypedObject) \
_(SetElem_TypedStatic) \
_(SetElem_TypedArray) \
_(SetElem_Dense) \
_(SetElem_Arguments) \
@ -123,8 +121,6 @@ namespace JS {
_(OperandNotStringOrNumber) \
_(OperandNotSimpleArith) \
_(OperandNotEasilyCoercibleToString) \
_(StaticTypedArrayUint32) \
_(StaticTypedArrayCantComputeMask) \
_(OutOfBounds) \
_(GetElemStringNotCached) \
_(NonNativeReceiver) \

Просмотреть файл

@ -188,9 +188,13 @@ function GetModuleNamespace(module)
// Step 1
assert(IsModule(module), "GetModuleNamespace called with non-module");
// Until issue https://github.com/tc39/ecma262/issues/1155 is resolved,
// violate the spec here and throw if called on an errored module.
if (module.status === MODULE_STATUS_EVALUATED_ERROR)
throw GetModuleEvaluationError(module);
// Steps 2-3
assert(module.status !== MODULE_STATUS_UNINSTANTIATED &&
module.status !== MODULE_STATUS_EVALUATED_ERROR,
assert(module.status !== MODULE_STATUS_UNINSTANTIATED,
"Bad module state in GetModuleNamespace");
// Step 4

Просмотреть файл

@ -1755,32 +1755,6 @@ obj_getOwnPropertySymbols(JSContext* cx, unsigned argc, Value* vp)
args.rval());
}
/* ES6 draft rev 32 (2015 Feb 2) 19.1.2.4: Object.defineProperty(O, P, Attributes) */
bool
js::obj_defineProperty(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
// Steps 1-3.
RootedObject obj(cx);
if (!GetFirstArgumentAsObject(cx, args, "Object.defineProperty", &obj))
return false;
RootedId id(cx);
if (!ToPropertyKey(cx, args.get(1), &id))
return false;
// Steps 4-5.
Rooted<PropertyDescriptor> desc(cx);
if (!ToPropertyDescriptor(cx, args.get(2), true, &desc))
return false;
// Steps 6-8.
if (!DefineProperty(cx, obj, id, desc))
return false;
args.rval().setObject(*obj);
return true;
}
/* ES5 15.2.3.7: Object.defineProperties(O, Properties) */
static bool
obj_defineProperties(JSContext* cx, unsigned argc, Value* vp)

Просмотреть файл

@ -22,9 +22,6 @@ namespace js {
MOZ_MUST_USE bool
obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
PlainObject*
ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind = GenericObject,
HandleObjectGroup group = nullptr);
@ -33,29 +30,21 @@ PlainObject*
ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj);
// Object methods exposed so they can be installed in the self-hosting global.
MOZ_MUST_USE bool
obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
MOZ_MUST_USE bool
obj_create(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_defineProperty(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_getOwnPropertyNames(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_getPrototypeOf(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_isExtensible(JSContext* cx, unsigned argc, JS::Value* vp);
MOZ_MUST_USE bool
obj_toString(JSContext* cx, unsigned argc, JS::Value* vp);
JSString*
ObjectClassToString(JSContext* cx, HandleObject obj);
// Exposed so SelfHosting.cpp can use it in the OwnPropertyKeys intrinsic
MOZ_MUST_USE bool
GetOwnPropertyKeys(JSContext* cx, HandleObject obj, unsigned flags, JS::MutableHandleValue rval);

Просмотреть файл

@ -8,7 +8,7 @@ function ObjectGetOwnPropertyDescriptors(O) {
var obj = ToObject(O);
// Step 2.
var keys = OwnPropertyKeys(obj);
var keys = std_Reflect_ownKeys(obj);
// Step 3.
var descriptors = {};

Просмотреть файл

@ -87,8 +87,8 @@ js::Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp)
// ES2018 draft rev c164be80f7ea91de5526b33d54e5c9321ed03d3f
// 26.1.10 Reflect.ownKeys ( target )
static bool
Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp)
bool
js::Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);

Просмотреть файл

@ -24,6 +24,9 @@ Reflect_getPrototypeOf(JSContext* cx, unsigned argc, Value* vp);
extern MOZ_MUST_USE bool
Reflect_isExtensible(JSContext* cx, unsigned argc, Value* vp);
extern MOZ_MUST_USE bool
Reflect_ownKeys(JSContext* cx, unsigned argc, Value* vp);
}
#endif /* builtin_Reflect_h */

Просмотреть файл

@ -219,67 +219,78 @@ function GetInternalError(msg) {
// To be used when a function is required but calling it shouldn't do anything.
function NullFunction() {}
// Object Rest/Spread Properties proposal
// Abstract operation: CopyDataProperties (target, source, excluded)
function CopyDataProperties(target, source, excluded) {
// ES2019 draft rev 4c2df13f4194057f09b920ee88712e5a70b1a556
// 7.3.23 CopyDataProperties (target, source, excludedItems)
function CopyDataProperties(target, source, excludedItems) {
// Step 1.
assert(IsObject(target), "target is an object");
// Step 2.
assert(IsObject(excluded), "excluded is an object");
assert(IsObject(excludedItems), "excludedItems is an object");
// Steps 3, 6.
// Steps 3 and 7.
if (source === undefined || source === null)
return;
// Step 4.a.
source = ToObject(source);
// Step 4.b.
var keys = OwnPropertyKeys(source);
// Step 4.
var from = ToObject(source);
// Step 5.
var keys = CopyDataPropertiesOrGetOwnKeys(target, from, excludedItems);
// Return if we copied all properties in native code.
if (keys === null)
return;
// Step 6.
for (var index = 0; index < keys.length; index++) {
var key = keys[index];
// We abbreviate this by calling propertyIsEnumerable which is faster
// and returns false for not defined properties.
if (!hasOwn(key, excluded) && callFunction(std_Object_propertyIsEnumerable, source, key))
_DefineDataProperty(target, key, source[key]);
if (!hasOwn(key, excludedItems) &&
callFunction(std_Object_propertyIsEnumerable, from, key))
{
_DefineDataProperty(target, key, from[key]);
}
}
// Step 6 (Return).
// Step 7 (Return).
}
// Object Rest/Spread Properties proposal
// Abstract operation: CopyDataProperties (target, source, excluded)
// ES2019 draft rev 4c2df13f4194057f09b920ee88712e5a70b1a556
// 7.3.23 CopyDataProperties (target, source, excludedItems)
function CopyDataPropertiesUnfiltered(target, source) {
// Step 1.
assert(IsObject(target), "target is an object");
// Step 2 (Not applicable).
// Steps 3, 6.
// Steps 3 and 7.
if (source === undefined || source === null)
return;
// Step 4.a.
source = ToObject(source);
// Step 4.b.
var keys = OwnPropertyKeys(source);
// Step 4.
var from = ToObject(source);
// Step 5.
var keys = CopyDataPropertiesOrGetOwnKeys(target, from, null);
// Return if we copied all properties in native code.
if (keys === null)
return;
// Step 6.
for (var index = 0; index < keys.length; index++) {
var key = keys[index];
// We abbreviate this by calling propertyIsEnumerable which is faster
// and returns false for not defined properties.
if (callFunction(std_Object_propertyIsEnumerable, source, key))
_DefineDataProperty(target, key, source[key]);
if (callFunction(std_Object_propertyIsEnumerable, from, key))
_DefineDataProperty(target, key, from[key]);
}
// Step 6 (Return).
// Step 7 (Return).
}
/*************************************** Testing functions ***************************************/

Просмотреть файл

@ -5489,20 +5489,7 @@ BytecodeEmitter::setOrEmitSetFunName(ParseNode* maybeFun, HandleAtom name,
// Function doesn't have 'name' property at this point.
// Set function's name at compile time.
JSFunction* fun = maybeFun->pn_funbox->function();
// Single node can be emitted multiple times if it appears in
// array destructuring default. If function already has a name,
// just return.
if (fun->hasInferredName()) {
#ifdef DEBUG
RootedFunction rootedFun(cx, fun);
JSAtom* funName = NameToFunctionName(cx, name, prefixKind);
if (!funName)
return false;
MOZ_ASSERT(funName == rootedFun->inferredName());
#endif
return true;
}
MOZ_ASSERT(!fun->hasInferredName());
fun->setInferredName(name);
return true;

Просмотреть файл

@ -1290,9 +1290,11 @@ FoldElement(JSContext* cx, ParseNode** nodePtr, PerHandlerParser<FullParseHandle
// Optimization 2: We have something like expr[3.14]. The number
// isn't an array index, so it converts to a string ("3.14"),
// enabling optimization 3 below.
JSAtom* atom = ToAtom<NoGC>(cx, DoubleValue(number));
if (!atom)
JSAtom* atom = NumberToAtom(cx, number);
if (!atom) {
cx->recoverFromOutOfMemory();
return false;
}
name = atom->asPropertyName();
}
}

Просмотреть файл

@ -9309,14 +9309,6 @@ GeneralParser<ParseHandler, CharT>::arrayInitializer(YieldHandling yieldHandling
return literal;
}
static JSAtom*
DoubleToAtom(JSContext* cx, double value)
{
// This is safe because doubles can not be moved.
Value tmp = DoubleValue(value);
return ToAtom<CanGC>(cx, HandleValue::fromMarkedLocation(&tmp));
}
template <class ParseHandler, typename CharT>
typename ParseHandler::Node
GeneralParser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
@ -9374,7 +9366,7 @@ GeneralParser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
Node propName;
switch (ltok) {
case TokenKind::Number:
propAtom.set(DoubleToAtom(context, anyChars.currentToken().number()));
propAtom.set(NumberToAtom(context, anyChars.currentToken().number()));
if (!propAtom.get())
return null();
propName = newNumber(anyChars.currentToken());
@ -9438,7 +9430,7 @@ GeneralParser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
uint32_t index;
if (propAtom->isIndex(&index)) {
propAtom.set(DoubleToAtom(context, index));
propAtom.set(NumberToAtom(context, index));
if (!propAtom.get())
return null();
return handler.newNumber(index, NoDecimal, pos());
@ -9448,7 +9440,7 @@ GeneralParser<ParseHandler, CharT>::propertyName(YieldHandling yieldHandling,
if (tt == TokenKind::Number) {
tokenStream.consumeKnownToken(TokenKind::Number);
propAtom.set(DoubleToAtom(context, anyChars.currentToken().number()));
propAtom.set(NumberToAtom(context, anyChars.currentToken().number()));
if (!propAtom.get())
return null();
return newNumber(anyChars.currentToken());

Просмотреть файл

@ -9,6 +9,7 @@ GeckoProgram('fuzz-tests', linkage=None)
UNIFIED_SOURCES += [
'testExample.cpp',
'tests.cpp',
'testStructuredCloneReader.cpp',
]
if CONFIG['JS_BUILD_BINAST']:

Просмотреть файл

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* 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 "mozilla/ScopeExit.h"
#include "jsapi.h"
#include "fuzz-tests/tests.h"
#include "vm/Interpreter.h"
#include "vm/JSContext-inl.h"
using namespace js;
// These are defined and pre-initialized by the harness (in tests.cpp).
extern JS::PersistentRootedObject gGlobal;
extern JSContext* gCx;
static int
testStructuredCloneReaderInit(int *argc, char ***argv) {
return 0;
}
static int
testStructuredCloneReaderFuzz(const uint8_t* buf, size_t size) {
auto gcGuard = mozilla::MakeScopeExit([&] {
JS::PrepareForFullGC(gCx);
JS::GCForReason(gCx, GC_NORMAL, JS::gcreason::API);
});
if (!size) return 0;
// Make sure to pad the buffer to a multiple of kSegmentAlignment
const size_t kSegmentAlignment = 8;
size_t buf_size = JS_ROUNDUP(size, kSegmentAlignment);
auto clonebuf = MakeUnique<JSStructuredCloneData>(0, 0, buf_size);
if (!clonebuf || !clonebuf->Init(buf_size, buf_size)) {
ReportOutOfMemory(gCx);
return 0;
}
// Initialize with zeros, including padding, then copy buffer
memset(clonebuf->Start(), '\0', buf_size);
js_memcpy(clonebuf->Start(), buf, size);
JS::StructuredCloneScope scope = JS::StructuredCloneScope::DifferentProcess;
RootedValue deserialized(gCx);
if (!JS_ReadStructuredClone(gCx, *clonebuf,
JS_STRUCTURED_CLONE_VERSION,
scope,
&deserialized, nullptr, nullptr))
{
return 0;
}
/* If we succeeded in deserializing, we should try to reserialize the data.
This has two main advantages:
1) It tests parts of the serializer as well.
2) The deserialized data is actually used, making it more likely to detect
further memory-related problems.
Tests show that this also doesn't cause a serious performance penalty.
*/
mozilla::Maybe<JSAutoStructuredCloneBuffer> clonebufOut;
JS::CloneDataPolicy policy;
clonebufOut.emplace(scope, nullptr, nullptr);
if (!clonebufOut->write(gCx, deserialized, UndefinedHandleValue, policy))
return 0;
return 0;
}
MOZ_FUZZING_INTERFACE_RAW(
testStructuredCloneReaderInit,
testStructuredCloneReaderFuzz,
StructuredCloneReader
);

Просмотреть файл

@ -0,0 +1,21 @@
// Overview:
// - The outer function is an IIFE which gets marked as a singleton.
// - The |o[index]| inner function is then also marked as a singleton.
// - The |o[index]| inner function has a dynamic name from a computed property name.
// - The |self| inner function uses |Function.prototype.caller| to reinvoke the outer function.
//
// When we reinvoke outer, we end up cloning a previously reused, i.e. non-cloned,
// function which triggered an assertion in js::SetFunctionNameIfNoOwnName().
(function(index) {
var o = {
[index]: function() {}
};
// Reinvoke the IIFE through |Function.prototype.caller|.
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -0,0 +1,25 @@
// Overview:
// - The outer function is an IIFE which gets marked as a singleton.
// - The |o[index]| inner function is then also marked as a singleton.
// - The |o[index]| inner function has a dynamic name from a computed property name.
// - The |self| inner function uses |Function.prototype.caller| to reinvoke the outer function.
//
// When we reinvoke outer, we end up cloning a previously reused, i.e. non-cloned,
// function which triggered an assertion in js::SetFunctionNameIfNoOwnName().
(function(index) {
var o = {
[index]: function() {}
};
// Accessing |.name| sets the resolved-name flag, which triggered yet
// another assertion when compared to bug1448582-1.js
assertEq(o[index].name, String(index));
// Reinvoke the IIFE through |Function.prototype.caller|.
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -0,0 +1,22 @@
// Overview:
// - The outer function is an IIFE which gets marked as a singleton.
// - The |fn| inner function is then also marked as a singleton.
// - The |self| inner function uses |Function.prototype.caller| to reinvoke the outer function.
//
// When we reinvoke outer, we end up cloning a previously reused, i.e. non-cloned,
// function.
(function(index) {
var fn = function() {};
// Accessing |.name| sets the resolved-name flag, which should not be
// copied over to the function clone.
assertEq(fn.name, "fn");
// Reinvoke the IIFE through |Function.prototype.caller|.
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -0,0 +1,22 @@
// Overview:
// - The outer function is an IIFE which gets marked as a singleton.
// - The |fn| inner function is then also marked as a singleton.
// - The |self| inner function uses |Function.prototype.caller| to reinvoke the outer function.
//
// When we reinvoke outer, we end up cloning a previously reused, i.e. non-cloned,
// function.
(function(index) {
var fn = function(a) {};
// Accessing |.length| sets the resolved-length flag, which should not be
// copied over to the function clone.
assertEq(fn.length, 1);
// Reinvoke the IIFE through |Function.prototype.caller|.
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -0,0 +1,133 @@
// Repeat 1448582-{1,3,4}.js for classes.
(function(index) {
// Does not assert.
var c = class { constructor(){} };
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
(function(index) {
var c = class { constructor(){} };
// Accessing |.name| sets the resolved-name flag, which should not be
// copied over to the function clone.
assertEq(c.name, "c");
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
(function(index) {
var c = class { constructor(a){} };
// Accessing |.length| sets the resolved-length flag, which should not be
// copied over to the function clone.
assertEq(c.length, 1);
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
// Repeat 1448582-{3,4}.js for generator functions.
(function(index) {
function* f() {}
// Accessing |.name| sets the resolved-name flag, which should not be
// copied over to the function clone.
assertEq(f.name, "f");
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
(function(index) {
function* f(a) {}
// Accessing |.length| sets the resolved-length flag, which should not be
// copied over to the function clone.
assertEq(f.length, 1);
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
// Repeat 1448582-{3,4}.js for async functions.
(function(index) {
async function f() {}
// Accessing |.name| sets the resolved-name flag, which should not be
// copied over to the function clone.
assertEq(f.name, "f");
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
(function(index) {
async function f(a) {}
// Accessing |.length| sets the resolved-length flag, which should not be
// copied over to the function clone.
assertEq(f.length, 1);
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
// Repeat 1448582-{3,4}.js for async generator functions.
(function(index) {
async function* f() {}
// Accessing |.name| sets the resolved-name flag, which should not be
// copied over to the function clone.
assertEq(f.name, "f");
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);
(function(index) {
async function* f(a) {}
// Accessing |.length| sets the resolved-length flag, which should not be
// copied over to the function clone.
assertEq(f.length, 1);
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -0,0 +1,27 @@
// Overview:
// - The outer function is an IIFE which gets marked as a singleton.
// - The |o[index]| inner function is then also marked as a singleton.
// - The |o[index]| inner function has a dynamic name from a computed property name.
// - The |self| inner function uses |Function.prototype.caller| to reinvoke the outer function.
(function(index) {
var o = {
[index]: class {
constructor() {}
// Prevent adding an inferred name at index = 1 by creating a
// static method named "name".
static [(index === 0 ? "not-name" : "name")]() {}
}
}
// At index = 0 the class will get the inferred name "0".
// At index = 1 the class should have no inferred name.
assertEq(displayName(o[index]), index === 0 ? "0" : "");
if (index === 0) {
(function self() {
self.caller(1);
})();
}
})(0);

Просмотреть файл

@ -10,7 +10,8 @@ function tryCreateUnboxedObject() {
for (var i = 0; i < 1000; ++i) {
obj = new Unboxed();
}
if (unboxedObjectsEnabled())
assertEq(isUnboxedObject(obj), true);
return obj;
}

Просмотреть файл

@ -0,0 +1,44 @@
load(libdir + "asserts.js");
function Unboxed() {
this.a = 0;
this.b = true;
}
function tryCreateUnboxedObject() {
var obj;
for (var i = 0; i < 1000; ++i) {
obj = new Unboxed();
}
if (unboxedObjectsEnabled())
assertEq(isUnboxedObject(obj), true);
return obj;
}
function basic() {
var unboxed = tryCreateUnboxedObject();
var {...target} = unboxed;
assertDeepEq(target, {a: 0, b: true});
var {a, c, ...target} = unboxed;
assertDeepEq(a, 0);
assertDeepEq(c, undefined);
assertDeepEq(target, {b: true});
}
function expando() {
var unboxed = tryCreateUnboxedObject();
unboxed.c = 3.5;
var {...target} = unboxed;
assertDeepEq(target, {a: 0, b: true, c: 3.5});
var {a, d, ...target} = unboxed;
assertDeepEq(a, 0);
assertDeepEq(d, undefined);
assertDeepEq(target, {b: true, c: 3.5});
}
basic();
expando();

Просмотреть файл

@ -0,0 +1,90 @@
function test() {
var from, to;
// From values.
from = {x: 1, y: 2};
({...to} = from);
assertEq(to.y, 2);
var z;
from = {x: 1, y: 2};
({x: z, ...to} = from);
assertEq(z, 1);
assertEq(to.y, 2);
// From getter.
var c = 7;
from = {x: 1, get y() { return ++c; }};
({...to} = from);
assertEq(c, 8);
assertEq(to.y, 8);
from = {x: 1, get y() { return ++c; }};
({y: z, ...to} = from);
assertEq(c, 9);
assertEq(z, 9);
assertEq(to.y, undefined);
// Array with dense elements.
from = [1, 2, 3];
({...to} = from);
assertEq(to[2], 3);
assertEq("length" in to, false);
from = [1, 2, 3];
({2: z, ...to} = from);
assertEq(z, 3);
assertEq(to[2], undefined);
assertEq(to[0], 1);
assertEq("length" in to, false);
// Object with sparse elements and symbols.
from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3};
({...to} = from);
assertEq(to[1234567], 2);
assertEq(Object.keys(to).toString(), "1234560,1234567,x,z");
assertEq(to[Symbol.iterator], 5);
from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3};
({[Symbol.iterator]: z, ...to} = from);
assertEq(to[1234567], 2);
assertEq(Object.keys(to).toString(), "1234560,1234567,x,z");
assertEq(to[Symbol.iterator], undefined);
assertEq(z, 5);
// Typed array.
from = new Int32Array([1, 2, 3]);
({...to} = from);
assertEq(to[1], 2);
from = new Int32Array([1, 2, 3]);
({1: z, ...to} = from);
assertEq(z, 2);
assertEq(to[1], undefined);
assertEq(to[2], 3);
// Primitive string.
from = "foo";
({...to} = from);
assertEq(to[0], "f");
from = "foo";
({0: z, ...to} = from);
assertEq(z, "f");
assertEq(to[0], undefined);
assertEq(to[1], "o");
// String object.
from = new String("bar");
({...to} = from);
assertEq(to[2], "r");
from = new String("bar");
({1: z, ...to} = from);
assertEq(z, "a");
assertEq(to[1], undefined);
assertEq(to[2], "r");
}
test();
test();
test();

Просмотреть файл

@ -0,0 +1,40 @@
load(libdir + "asserts.js");
function Unboxed() {
this.a = 0;
this.b = true;
}
function tryCreateUnboxedObject() {
var obj;
for (var i = 0; i < 1000; ++i) {
obj = new Unboxed();
}
if (unboxedObjectsEnabled())
assertEq(isUnboxedObject(obj), true);
return obj;
}
function basic() {
var unboxed = tryCreateUnboxedObject();
var target = {...unboxed};
assertDeepEq(target, {a: 0, b: true});
target = {a: 1, c: 3, ...unboxed};
assertDeepEq(target, {a: 0, c: 3, b: true});
}
function expando() {
var unboxed = tryCreateUnboxedObject();
unboxed.c = 3.5;
var target = {...unboxed};
assertDeepEq(target, {a: 0, b: true, c: 3.5});
target = {a: 1, d: 3, ...unboxed};
assertDeepEq(target, {a: 0, d: 3, b: true, c: 3.5});
}
basic();
expando();

Просмотреть файл

@ -0,0 +1,49 @@
function test() {
var from, to;
// From values.
from = {x: 1, y: 2};
to = {...from};
assertEq(to.y, 2);
to = {...from, ...from};
assertEq(to.y, 2);
// From getter.
var c = 7;
from = {x: 1, get y() { return ++c; }};
to = {...from};
assertEq(to.y, 8);
to = {...from, ...from};
assertEq(to.y, 10);
// Array with dense elements.
from = [1, 2, 3];
to = {...from};
assertEq(to[2], 3);
assertEq("length" in to, false);
// Object with sparse elements and symbols.
from = {x: 1, 1234567: 2, 1234560: 3, [Symbol.iterator]: 5, z: 3};
to = {...from};
assertEq(to[1234567], 2);
assertEq(Object.keys(to).toString(), "1234560,1234567,x,z");
assertEq(to[Symbol.iterator], 5);
// Typed array.
from = new Int32Array([1, 2, 3]);
to = {...from};
assertEq(to[1], 2);
// Primitive string.
from = "foo";
to = {...from};
assertEq(to[0], "f");
// String object.
from = new String("bar");
to = {...from};
assertEq(to[2], "r");
}
test();
test();
test();

Просмотреть файл

@ -0,0 +1,35 @@
// Test performing GetModuleNamespace on an errored module.
class MyError {}
function assertThrowsMyError(f)
{
let caught = false;
try {
f();
} catch (e) {
caught = true;
assertEq(e.constructor, MyError);
}
assertEq(caught, true);
}
let moduleRepo = {};
setModuleResolveHook(function(module, specifier) {
return moduleRepo[specifier];
});
moduleRepo["a"] = parseModule(`
throw new MyError();
`);
let c = moduleRepo["c"] = parseModule(`
import "a";
`);
c.declarationInstantiation();
assertThrowsMyError(() => c.evaluation());
let b = moduleRepo['b'] = parseModule(`
import * as ns0 from 'a'
`);
assertThrowsMyError(() => b.declarationInstantiation());

Просмотреть файл

@ -32,4 +32,27 @@ new WebAssembly.Module(wasmTextToBinary(`
unreachable
)
)
`))
`));
new WebAssembly.Module(wasmTextToBinary(`
(module
(global $g (mut i32) (i32.const 42))
(func (param $i i32)
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_global $g
get_local $i
set_global $g
unreachable
)
)
`));

Просмотреть файл

@ -123,8 +123,6 @@ GetObject(const MDefinition* ins)
object = ins->getOperand(0);
break;
case MDefinition::Opcode::GetPropertyCache:
case MDefinition::Opcode::LoadTypedArrayElementStatic:
case MDefinition::Opcode::StoreTypedArrayElementStatic:
case MDefinition::Opcode::GetDOMProperty:
case MDefinition::Opcode::GetDOMMember:
case MDefinition::Opcode::Call:

Просмотреть файл

@ -1380,9 +1380,11 @@ BaselineCacheIRCompiler::emitStoreDenseElement()
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Bounds check.
// Bounds check. Unfortunately we don't have more registers available on
// x86, so use InvalidReg and emit slightly slower code on x86.
Register spectreTemp = InvalidReg;
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, failure->label());
// Hole check.
BaseObjectElementIndex element(scratch, index);
@ -1471,18 +1473,30 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
ObjectElements::FROZEN),
failure->label());
// We don't have enough registers on x86 so use InvalidReg. This will emit
// slightly less efficient code on x86.
Register spectreTemp = InvalidReg;
if (handleAdd) {
// Fail if index > initLength.
masm.branch32(Assembler::Below, initLength, index, failure->label());
// Bounds check.
Label capacityOk, outOfBounds;
masm.spectreBoundsCheck32(index, initLength, spectreTemp, &outOfBounds);
masm.jump(&capacityOk);
// If we're out-of-bounds, only handle the index == initLength case.
masm.bind(&outOfBounds);
masm.branch32(Assembler::NotEqual, initLength, index, failure->label());
// If index < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Label allocElement;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, index, &capacityOk);
masm.spectreBoundsCheck32(index, capacity, spectreTemp, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
masm.bind(&allocElement);
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
@ -1510,7 +1524,7 @@ BaselineCacheIRCompiler::emitStoreDenseElementHole()
// the type update code doesn't read uninitialized memory.
} else {
// Fail if index >= initLength.
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, failure->label());
}
// Check if we have to convert a double element.
@ -1595,10 +1609,9 @@ BaselineCacheIRCompiler::emitArrayPush()
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.load32(Address(scratch, ObjectElements::offsetOfLength()), scratchLength);
BaseObjectElementIndex element(scratch, scratchLength);
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
Address elementsInitLength(scratch, ObjectElements::offsetOfInitializedLength());
Address elementsLength(scratch, ObjectElements::offsetOfLength());
Address elementsFlags(scratch, ObjectElements::offsetOfFlags());
// Check for copy-on-write or frozen elements.
@ -1608,16 +1621,19 @@ BaselineCacheIRCompiler::emitArrayPush()
failure->label());
// Fail if length != initLength.
masm.branch32(Assembler::NotEqual, initLength, scratchLength, failure->label());
masm.load32(elementsInitLength, scratchLength);
masm.branch32(Assembler::NotEqual, elementsLength, scratchLength, failure->label());
// If scratchLength < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Label capacityOk, allocElement;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, scratchLength, &capacityOk);
masm.spectreBoundsCheck32(scratchLength, capacity, InvalidReg, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
masm.bind(&allocElement);
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
@ -1672,12 +1688,12 @@ BaselineCacheIRCompiler::emitArrayPush()
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Increment initLength and length.
Address length(scratch, ObjectElements::offsetOfLength());
masm.add32(Imm32(1), initLength);
masm.load32(length, scratchLength);
masm.add32(Imm32(1), length);
masm.add32(Imm32(1), elementsInitLength);
masm.load32(elementsLength, scratchLength);
masm.add32(Imm32(1), elementsLength);
// Store the value.
BaseObjectElementIndex element(scratch, scratchLength);
masm.storeValue(val, element);
emitPostBarrierElement(obj, val, scratch, scratchLength);
@ -1708,7 +1724,11 @@ BaselineCacheIRCompiler::emitStoreTypedElement()
// Bounds check.
Label done;
LoadTypedThingLength(masm, layout, obj, scratch1);
masm.branch32(Assembler::BelowOrEqual, scratch1, index, handleOOB ? &done : failure->label());
// Unfortunately we don't have more registers available on x86, so use
// InvalidReg and emit slightly slower code on x86.
Register spectreTemp = InvalidReg;
masm.spectreBoundsCheck32(index, scratch1, spectreTemp, handleOOB ? &done : failure->label());
// Load the elements vector.
LoadTypedThingData(masm, layout, obj, scratch1);

Просмотреть файл

@ -6858,16 +6858,24 @@ CodeGenerator::visitArrayLength(LArrayLength* lir)
masm.load32(length, ToRegister(lir->output()));
}
static void
SetLengthFromIndex(MacroAssembler& masm, const LAllocation* index, const Address& length)
{
if (index->isConstant()) {
masm.store32(Imm32(ToInt32(index) + 1), length);
} else {
Register newLength = ToRegister(index);
masm.add32(Imm32(1), newLength);
masm.store32(newLength, length);
masm.sub32(Imm32(1), newLength);
}
}
void
CodeGenerator::visitSetArrayLength(LSetArrayLength* lir)
{
Address length(ToRegister(lir->elements()), ObjectElements::offsetOfLength());
RegisterOrInt32Constant newLength = ToRegisterOrInt32Constant(lir->index());
masm.inc32(&newLength);
masm.store32(newLength, length);
// Restore register value if it is used/captured after.
masm.dec32(&newLength);
SetLengthFromIndex(masm, lir->index(), length);
}
template <class OrderedHashTable>
@ -8898,12 +8906,7 @@ void
CodeGenerator::visitSetInitializedLength(LSetInitializedLength* lir)
{
Address initLength(ToRegister(lir->elements()), ObjectElements::offsetOfInitializedLength());
RegisterOrInt32Constant index = ToRegisterOrInt32Constant(lir->index());
masm.inc32(&index);
masm.store32(index, initLength);
// Restore register value if it is used/captured after.
masm.dec32(&index);
SetLengthFromIndex(masm, lir->index(), initLength);
}
void
@ -9223,18 +9226,18 @@ CodeGenerator::emitStoreElementHoleT(T* lir)
addOutOfLineCode(ool, lir->mir());
Register elements = ToRegister(lir->elements());
const LAllocation* index = lir->index();
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
Register index = ToRegister(lir->index());
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
Address initLength(elements, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, ool->entry());
if (lir->mir()->needsBarrier())
emitPreBarrier(elements, index, 0);
emitPreBarrier(elements, lir->index(), 0);
masm.bind(ool->rejoinStore());
emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
elements, index, 0);
elements, lir->index(), 0);
masm.bind(ool->rejoin());
}
@ -9256,21 +9259,18 @@ CodeGenerator::emitStoreElementHoleV(T* lir)
addOutOfLineCode(ool, lir->mir());
Register elements = ToRegister(lir->elements());
const LAllocation* index = lir->index();
Register index = ToRegister(lir->index());
const ValueOperand value = ToValue(lir, T::Value);
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
Address initLength(elements, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, key, ool->entry());
masm.spectreBoundsCheck32(index, initLength, spectreTemp, ool->entry());
if (lir->mir()->needsBarrier())
emitPreBarrier(elements, index, 0);
emitPreBarrier(elements, lir->index(), 0);
masm.bind(ool->rejoinStore());
if (index->isConstant())
masm.storeValue(value, Address(elements, ToInt32(index) * sizeof(js::Value)));
else
masm.storeValue(value, BaseIndex(elements, ToRegister(index), TimesEight));
masm.storeValue(value, BaseIndex(elements, index, TimesEight));
masm.bind(ool->rejoin());
}
@ -9362,6 +9362,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
const LAllocation* index;
MIRType valueType;
ConstantOrRegister value;
Register spectreTemp;
if (ins->isStoreElementHoleV()) {
LStoreElementHoleV* store = ins->toStoreElementHoleV();
@ -9370,6 +9371,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LStoreElementHoleV::Value));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else if (ins->isFallibleStoreElementV()) {
LFallibleStoreElementV* store = ins->toFallibleStoreElementV();
object = ToRegister(store->object());
@ -9377,6 +9379,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
index = store->index();
valueType = store->mir()->value()->type();
value = TypedOrValueRegister(ToValue(store, LFallibleStoreElementV::Value));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else if (ins->isStoreElementHoleT()) {
LStoreElementHoleT* store = ins->toStoreElementHoleT();
object = ToRegister(store->object());
@ -9387,6 +9390,7 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
} else { // ins->isFallibleStoreElementT()
LFallibleStoreElementT* store = ins->toFallibleStoreElementT();
object = ToRegister(store->object());
@ -9397,39 +9401,42 @@ CodeGenerator::visitOutOfLineStoreElementHole(OutOfLineStoreElementHole* ool)
value = ConstantOrRegister(store->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(valueType, ToAnyRegister(store->value()));
spectreTemp = ToTempRegisterOrInvalid(store->spectreTemp());
}
RegisterOrInt32Constant key = ToRegisterOrInt32Constant(index);
Register indexReg = ToRegister(index);
// If index == initializedLength, try to bump the initialized length inline.
// If index > initializedLength, call a stub. Note that this relies on the
// condition flags sticking from the incoming branch.
// Also note: this branch does not need Spectre mitigations, doing that for
// the capacity check below is sufficient.
Label callStub;
#if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
// Had to reimplement for MIPS because there are no flags.
Address initLength(elements, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, key, &callStub);
masm.branch32(Assembler::NotEqual, initLength, indexReg, &callStub);
#else
masm.j(Assembler::NotEqual, &callStub);
#endif
// Check array capacity.
masm.branch32(Assembler::BelowOrEqual, Address(elements, ObjectElements::offsetOfCapacity()),
key, &callStub);
masm.spectreBoundsCheck32(indexReg, Address(elements, ObjectElements::offsetOfCapacity()),
spectreTemp, &callStub);
// Update initialized length. The capacity guard above ensures this won't overflow,
// due to MAX_DENSE_ELEMENTS_COUNT.
masm.inc32(&key);
masm.store32(key, Address(elements, ObjectElements::offsetOfInitializedLength()));
masm.add32(Imm32(1), indexReg);
masm.store32(indexReg, Address(elements, ObjectElements::offsetOfInitializedLength()));
// Update length if length < initializedLength.
Label dontUpdate;
masm.branch32(Assembler::AboveOrEqual, Address(elements, ObjectElements::offsetOfLength()),
key, &dontUpdate);
masm.store32(key, Address(elements, ObjectElements::offsetOfLength()));
indexReg, &dontUpdate);
masm.store32(indexReg, Address(elements, ObjectElements::offsetOfLength()));
masm.bind(&dontUpdate);
masm.dec32(&key);
masm.sub32(Imm32(1), indexReg);
if ((ins->isStoreElementHoleT() || ins->isFallibleStoreElementT()) &&
valueType != MIRType::Double)
@ -9560,13 +9567,13 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
// VM call if a write barrier is necessary.
masm.branchTestNeedsIncrementalBarrier(Assembler::NonZero, ool->entry());
// Load elements and length, and VM call if length != initializedLength.
RegisterOrInt32Constant key = RegisterOrInt32Constant(lengthTemp);
// Load elements and initializedLength, and VM call if
// length != initializedLength.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), lengthTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfInitializedLength()), lengthTemp);
Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
Address lengthAddr(elementsTemp, ObjectElements::offsetOfLength());
masm.branch32(Assembler::NotEqual, lengthAddr, lengthTemp, ool->entry());
// Test for length != 0. On zero length either take a VM call or generate
// an undefined value, depending on whether the call is known to produce
@ -9590,7 +9597,7 @@ CodeGenerator::emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, R
masm.branchTest32(Assembler::Zero, lengthTemp, lengthTemp, ool->entry());
}
masm.dec32(&key);
masm.sub32(Imm32(1), lengthTemp);
if (mir->mode() == MArrayPopShift::Pop) {
BaseIndex addr(elementsTemp, lengthTemp, TimesEight);
@ -9658,28 +9665,27 @@ static const VMFunction ArrayPushDenseInfo =
void
CodeGenerator::emitArrayPush(LInstruction* lir, Register obj,
const ConstantOrRegister& value, Register elementsTemp, Register length)
const ConstantOrRegister& value, Register elementsTemp, Register length,
Register spectreTemp)
{
OutOfLineCode* ool = oolCallVM(ArrayPushDenseInfo, lir, ArgList(obj, value), StoreRegisterTo(length));
RegisterOrInt32Constant key = RegisterOrInt32Constant(length);
// Load elements and length.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), elementsTemp);
masm.load32(Address(elementsTemp, ObjectElements::offsetOfLength()), length);
// Guard length == initializedLength.
Address initLength(elementsTemp, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, key, ool->entry());
masm.branch32(Assembler::NotEqual, initLength, length, ool->entry());
// Guard length < capacity.
Address capacity(elementsTemp, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::BelowOrEqual, capacity, key, ool->entry());
masm.spectreBoundsCheck32(length, capacity, spectreTemp, ool->entry());
// Do the store.
masm.storeConstantOrRegister(value, BaseIndex(elementsTemp, length, TimesEight));
masm.inc32(&key);
masm.add32(Imm32(1), length);
// Update length and initialized length.
masm.store32(length, Address(elementsTemp, ObjectElements::offsetOfLength()));
@ -9695,7 +9701,8 @@ CodeGenerator::visitArrayPushV(LArrayPushV* lir)
Register elementsTemp = ToRegister(lir->temp());
Register length = ToRegister(lir->output());
ConstantOrRegister value = TypedOrValueRegister(ToValue(lir, LArrayPushV::Value));
emitArrayPush(lir, obj, value, elementsTemp, length);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
}
void
@ -9709,7 +9716,8 @@ CodeGenerator::visitArrayPushT(LArrayPushT* lir)
value = ConstantOrRegister(lir->value()->toConstant()->toJSValue());
else
value = TypedOrValueRegister(lir->mir()->value()->type(), ToAnyRegister(lir->value()));
emitArrayPush(lir, obj, value, elementsTemp, length);
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
emitArrayPush(lir, obj, value, elementsTemp, length, spectreTemp);
}
typedef JSObject* (*ArraySliceDenseFn)(JSContext*, HandleObject, int32_t, int32_t, HandleObject);
@ -11820,42 +11828,20 @@ CodeGenerator::visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole* lir)
Scalar::Type arrayType = lir->mir()->arrayType();
int width = Scalar::byteSize(arrayType);
const LAllocation* index = lir->index();
Register index = ToRegister(lir->index());
const LAllocation* length = lir->length();
Register spectreTemp = ToTempRegisterOrInvalid(lir->spectreTemp());
bool guardLength = true;
if (index->isConstant() && length->isConstant()) {
uint32_t idx = ToInt32(index);
uint32_t len = ToInt32(length);
if (idx >= len)
return;
guardLength = false;
}
Label skip;
if (index->isConstant()) {
uint32_t idx = ToInt32(index);
if (guardLength) {
if (length->isRegister())
masm.branch32(Assembler::BelowOrEqual, ToRegister(length), Imm32(idx), &skip);
else
masm.branch32(Assembler::BelowOrEqual, ToAddress(length), Imm32(idx), &skip);
}
Address dest(elements, idx * width);
StoreToTypedArray(masm, arrayType, value, dest);
} else {
Register idxReg = ToRegister(index);
MOZ_ASSERT(guardLength);
if (length->isConstant())
masm.branch32(Assembler::AboveOrEqual, idxReg, Imm32(ToInt32(length)), &skip);
else if (length->isRegister())
masm.branch32(Assembler::BelowOrEqual, ToRegister(length), idxReg, &skip);
else
masm.branch32(Assembler::BelowOrEqual, ToAddress(length), idxReg, &skip);
BaseIndex dest(elements, ToRegister(index), ScaleFromElemWidth(width));
StoreToTypedArray(masm, arrayType, value, dest);
}
if (guardLength)
masm.bind(&skip);
if (length->isRegister())
masm.spectreBoundsCheck32(index, ToRegister(length), spectreTemp, &skip);
else
masm.spectreBoundsCheck32(index, ToAddress(length), spectreTemp, &skip);
BaseIndex dest(elements, index, ScaleFromElemWidth(width));
StoreToTypedArray(masm, arrayType, value, dest);
masm.bind(&skip);
}
void

Просмотреть файл

@ -163,7 +163,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
void emitArrayPopShift(LInstruction* lir, const MArrayPopShift* mir, Register obj,
Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
void emitArrayPush(LInstruction* lir, Register obj,
const ConstantOrRegister& value, Register elementsTemp, Register length);
const ConstantOrRegister& value, Register elementsTemp, Register length,
Register spectreTemp);
void emitRest(LInstruction* lir, Register array, Register numActuals,
Register temp0, Register temp1, unsigned numFormals,

Просмотреть файл

@ -1681,7 +1681,7 @@ TypeAnalyzer::adjustInputs(MDefinition* def)
return true;
MInstruction* ins = def->toInstruction();
TypePolicy* policy = ins->typePolicy();
const TypePolicy* policy = ins->typePolicy();
if (policy && !policy->adjustInputs(alloc(), ins))
return false;
return true;

Просмотреть файл

@ -7801,11 +7801,6 @@ IonBuilder::jsop_getelem()
if (emitted)
return Ok();
trackOptimizationAttempt(TrackedStrategy::GetElem_TypedStatic);
MOZ_TRY(getElemTryTypedStatic(&emitted, obj, index));
if (emitted)
return Ok();
trackOptimizationAttempt(TrackedStrategy::GetElem_TypedArray);
MOZ_TRY(getElemTryTypedArray(&emitted, obj, index));
if (emitted)
@ -8229,102 +8224,6 @@ IonBuilder::getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index)
return Ok();
}
AbortReasonOr<JSObject*>
IonBuilder::getStaticTypedArrayObject(MDefinition* obj, MDefinition* index)
{
Scalar::Type arrayType;
if (!ElementAccessIsTypedArray(constraints(), obj, index, &arrayType)) {
trackOptimizationOutcome(TrackedOutcome::AccessNotTypedArray);
return nullptr;
}
if (!LIRGenerator::allowStaticTypedArrayAccesses()) {
trackOptimizationOutcome(TrackedOutcome::Disabled);
return nullptr;
}
bool hasExtraIndexedProperty;
MOZ_TRY_VAR(hasExtraIndexedProperty, ElementAccessHasExtraIndexedProperty(this, obj));
if (hasExtraIndexedProperty) {
trackOptimizationOutcome(TrackedOutcome::ProtoIndexedProps);
return nullptr;
}
if (!obj->resultTypeSet()) {
trackOptimizationOutcome(TrackedOutcome::NoTypeInfo);
return nullptr;
}
JSObject* tarrObj = obj->resultTypeSet()->maybeSingleton();
if (!tarrObj) {
trackOptimizationOutcome(TrackedOutcome::NotSingleton);
return nullptr;
}
TypeSet::ObjectKey* tarrKey = TypeSet::ObjectKey::get(tarrObj);
if (tarrKey->unknownProperties()) {
trackOptimizationOutcome(TrackedOutcome::UnknownProperties);
return nullptr;
}
return tarrObj;
}
AbortReasonOr<Ok>
IonBuilder::getElemTryTypedStatic(bool* emitted, MDefinition* obj, MDefinition* index)
{
MOZ_ASSERT(*emitted == false);
JSObject* tarrObj;
MOZ_TRY_VAR(tarrObj, getStaticTypedArrayObject(obj, index));
if (!tarrObj)
return Ok();
// LoadTypedArrayElementStatic currently treats uint32 arrays as int32.
Scalar::Type viewType = tarrObj->as<TypedArrayObject>().type();
if (viewType == Scalar::Uint32) {
trackOptimizationOutcome(TrackedOutcome::StaticTypedArrayUint32);
return Ok();
}
MDefinition* ptr = convertShiftToMaskForStaticTypedArray(index, viewType);
if (!ptr)
return Ok();
// Emit LoadTypedArrayElementStatic.
if (tarrObj->is<TypedArrayObject>()) {
TypeSet::ObjectKey* tarrKey = TypeSet::ObjectKey::get(tarrObj);
tarrKey->watchStateChangeForTypedArrayData(constraints());
}
obj->setImplicitlyUsedUnchecked();
index->setImplicitlyUsedUnchecked();
MLoadTypedArrayElementStatic* load = MLoadTypedArrayElementStatic::New(alloc(), tarrObj, ptr);
current->add(load);
current->push(load);
// The load is infallible if an undefined result will be coerced to the
// appropriate numeric type if the read is out of bounds. The truncation
// analysis picks up some of these cases, but is incomplete with respect
// to others. For now, sniff the bytecode for simple patterns following
// the load which guarantee a truncation or numeric conversion.
if (viewType == Scalar::Float32 || viewType == Scalar::Float64) {
jsbytecode* next = pc + JSOP_GETELEM_LENGTH;
if (*next == JSOP_POS)
load->setInfallible();
} else {
jsbytecode* next = pc + JSOP_GETELEM_LENGTH;
if (*next == JSOP_ZERO && *(next + JSOP_ZERO_LENGTH) == JSOP_BITOR)
load->setInfallible();
}
trackOptimizationSuccess();
*emitted = true;
return Ok();
}
AbortReasonOr<Ok>
IonBuilder::getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index)
{
@ -8787,50 +8686,6 @@ IonBuilder::addTypedArrayLengthAndData(MDefinition* obj,
}
}
MDefinition*
IonBuilder::convertShiftToMaskForStaticTypedArray(MDefinition* id,
Scalar::Type viewType)
{
trackOptimizationOutcome(TrackedOutcome::StaticTypedArrayCantComputeMask);
// No shifting is necessary if the typed array has single byte elements.
if (TypedArrayShift(viewType) == 0)
return id;
// If the index is an already shifted constant, undo the shift to get the
// absolute offset being accessed.
if (MConstant* idConst = id->maybeConstantValue()) {
if (idConst->type() == MIRType::Int32) {
int32_t index = idConst->toInt32();
MConstant* offset = MConstant::New(alloc(), Int32Value(index << TypedArrayShift(viewType)));
current->add(offset);
return offset;
}
}
if (!id->isRsh() || id->isEffectful())
return nullptr;
MConstant* shiftAmount = id->toRsh()->rhs()->maybeConstantValue();
if (!shiftAmount || shiftAmount->type() != MIRType::Int32)
return nullptr;
if (uint32_t(shiftAmount->toInt32()) != TypedArrayShift(viewType))
return nullptr;
// Instead of shifting, mask off the low bits of the index so that
// a non-scaled access on the typed array can be performed.
MConstant* mask = MConstant::New(alloc(), Int32Value(~((1 << shiftAmount->toInt32()) - 1)));
MBitAnd* ptr = MBitAnd::New(alloc(), id->getOperand(0), mask);
ptr->infer(nullptr, nullptr);
MOZ_ASSERT(!ptr->isEffectful());
current->add(mask);
current->add(ptr);
return ptr;
}
AbortReasonOr<Ok>
IonBuilder::jsop_getelem_typed(MDefinition* obj, MDefinition* index,
Scalar::Type arrayType)
@ -8933,11 +8788,6 @@ IonBuilder::jsop_setelem()
}
if (!forceInlineCaches()) {
trackOptimizationAttempt(TrackedStrategy::SetElem_TypedStatic);
MOZ_TRY(setElemTryTypedStatic(&emitted, object, index, value));
if (emitted)
return Ok();
trackOptimizationAttempt(TrackedStrategy::SetElem_TypedArray);
MOZ_TRY(setElemTryTypedArray(&emitted, object, index, value));
if (emitted)
@ -9074,54 +8924,6 @@ IonBuilder::setElemTryScalarElemOfTypedObject(bool* emitted,
return setPropTryScalarTypedObjectValue(emitted, obj, indexAsByteOffset, elemType, value);
}
AbortReasonOr<Ok>
IonBuilder::setElemTryTypedStatic(bool* emitted, MDefinition* object,
MDefinition* index, MDefinition* value)
{
MOZ_ASSERT(*emitted == false);
JSObject* tarrObj;
MOZ_TRY_VAR(tarrObj, getStaticTypedArrayObject(object, index));
if (!tarrObj)
return Ok();
SharedMem<void*> viewData = tarrObj->as<TypedArrayObject>().viewDataEither();
if (tarrObj->zone()->group()->nursery().isInside(viewData))
return Ok();
Scalar::Type viewType = tarrObj->as<TypedArrayObject>().type();
MDefinition* ptr = convertShiftToMaskForStaticTypedArray(index, viewType);
if (!ptr)
return Ok();
// Emit StoreTypedArrayElementStatic.
if (tarrObj->is<TypedArrayObject>()) {
TypeSet::ObjectKey* tarrKey = TypeSet::ObjectKey::get(tarrObj);
tarrKey->watchStateChangeForTypedArrayData(constraints());
}
object->setImplicitlyUsedUnchecked();
index->setImplicitlyUsedUnchecked();
// Clamp value to [0, 255] for Uint8ClampedArray.
MDefinition* toWrite = value;
if (viewType == Scalar::Uint8Clamped) {
toWrite = MClampToUint8::New(alloc(), value);
current->add(toWrite->toInstruction());
}
MInstruction* store = MStoreTypedArrayElementStatic::New(alloc(), tarrObj, ptr, toWrite);
current->add(store);
current->push(value);
MOZ_TRY(resumeAfter(store));
trackOptimizationSuccess();
*emitted = true;
return Ok();
}
AbortReasonOr<Ok>
IonBuilder::setElemTryTypedArray(bool* emitted, MDefinition* object,
MDefinition* index, MDefinition* value)

Просмотреть файл

@ -209,9 +209,6 @@ class IonBuilder
MInstruction*
addGuardReceiverPolymorphic(MDefinition* obj, const BaselineInspector::ReceiverVector& receivers);
MDefinition* convertShiftToMaskForStaticTypedArray(MDefinition* id,
Scalar::Type viewType);
bool invalidatedIdempotentCache();
bool hasStaticEnvironmentObject(JSObject** pcall);
@ -391,15 +388,12 @@ class IonBuilder
const LinearSum& byteOffset,
ReferenceTypeDescr::Type type,
PropertyName* name);
AbortReasonOr<JSObject*> getStaticTypedArrayObject(MDefinition* obj, MDefinition* index);
// jsop_setelem() helpers.
AbortReasonOr<Ok> setElemTryTypedArray(bool* emitted, MDefinition* object,
MDefinition* index, MDefinition* value);
AbortReasonOr<Ok> setElemTryTypedObject(bool* emitted, MDefinition* obj,
MDefinition* index, MDefinition* value);
AbortReasonOr<Ok> setElemTryTypedStatic(bool* emitted, MDefinition* object,
MDefinition* index, MDefinition* value);
AbortReasonOr<Ok> initOrSetElemTryDense(bool* emitted, MDefinition* object,
MDefinition* index, MDefinition* value,
bool writeHole);
@ -425,7 +419,6 @@ class IonBuilder
// jsop_getelem() helpers.
AbortReasonOr<Ok> getElemTryDense(bool* emitted, MDefinition* obj, MDefinition* index);
AbortReasonOr<Ok> getElemTryGetProp(bool* emitted, MDefinition* obj, MDefinition* index);
AbortReasonOr<Ok> getElemTryTypedStatic(bool* emitted, MDefinition* obj, MDefinition* index);
AbortReasonOr<Ok> getElemTryTypedArray(bool* emitted, MDefinition* obj, MDefinition* index);
AbortReasonOr<Ok> getElemTryTypedObject(bool* emitted, MDefinition* obj, MDefinition* index);
AbortReasonOr<Ok> getElemTryString(bool* emitted, MDefinition* obj, MDefinition* index);

Просмотреть файл

@ -1901,7 +1901,8 @@ IonCacheIRCompiler::emitStoreDenseElement()
Register index = allocator.useRegister(masm, reader.int32OperandId());
ConstantOrRegister val = allocator.useConstantOrRegister(masm, reader.valOperandId());
AutoScratchRegister scratch(allocator, masm);
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -1910,20 +1911,20 @@ IonCacheIRCompiler::emitStoreDenseElement()
EmitCheckPropertyTypes(masm, typeCheckInfo_, obj, val, *liveRegs_, failure->label());
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
// Bounds check.
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
Address initLength(scratch1, ObjectElements::offsetOfInitializedLength());
masm.spectreBoundsCheck32(index, initLength, scratch2, failure->label());
// Hole check.
BaseObjectElementIndex element(scratch, index);
BaseObjectElementIndex element(scratch1, index);
masm.branchTestMagic(Assembler::Equal, element, failure->label());
EmitPreBarrier(masm, element, MIRType::Value);
EmitStoreDenseElement(masm, val, scratch, element);
EmitStoreDenseElement(masm, val, scratch1, element);
if (needsPostBarrier())
emitPostBarrierElement(obj, val, scratch, index);
emitPostBarrierElement(obj, val, scratch1, index);
return true;
}
@ -1939,7 +1940,8 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
// track this.
reader.readBool();
AutoScratchRegister scratch(allocator, masm);
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -1947,45 +1949,51 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
EmitCheckPropertyTypes(masm, typeCheckInfo_, obj, val, *liveRegs_, failure->label());
// Load obj->elements in scratch.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
// Load obj->elements in scratch1.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
BaseObjectElementIndex element(scratch, index);
Address initLength(scratch1, ObjectElements::offsetOfInitializedLength());
BaseObjectElementIndex element(scratch1, index);
Label inBounds, doStore;
masm.branch32(Assembler::Above, initLength, index, &inBounds);
Label inBounds, outOfBounds;
Register spectreTemp = scratch2;
masm.spectreBoundsCheck32(index, initLength, spectreTemp, &outOfBounds);
masm.jump(&inBounds);
masm.bind(&outOfBounds);
masm.branch32(Assembler::NotEqual, initLength, index, failure->label());
// If index < capacity, we can add a dense element inline. If not we
// need to allocate more elements.
Label capacityOk;
Address capacity(scratch, ObjectElements::offsetOfCapacity());
masm.branch32(Assembler::Above, capacity, index, &capacityOk);
Label capacityOk, allocElement;
Address capacity(scratch1, ObjectElements::offsetOfCapacity());
masm.spectreBoundsCheck32(index, capacity, spectreTemp, &allocElement);
masm.jump(&capacityOk);
// Check for non-writable array length. We only have to do this if
// index >= capacity.
Address elementsFlags(scratch, ObjectElements::offsetOfFlags());
masm.bind(&allocElement);
Address elementsFlags(scratch1, ObjectElements::offsetOfFlags());
masm.branchTest32(Assembler::NonZero, elementsFlags,
Imm32(ObjectElements::NONWRITABLE_ARRAY_LENGTH),
failure->label());
LiveRegisterSet save(GeneralRegisterSet::Volatile(), liveVolatileFloatRegs());
save.takeUnchecked(scratch);
save.takeUnchecked(scratch1);
masm.PushRegsInMask(save);
masm.setupUnalignedABICall(scratch);
masm.loadJSContext(scratch);
masm.passABIArg(scratch);
masm.setupUnalignedABICall(scratch1);
masm.loadJSContext(scratch1);
masm.passABIArg(scratch1);
masm.passABIArg(obj);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, NativeObject::addDenseElementDontReportOOM));
masm.mov(ReturnReg, scratch);
masm.mov(ReturnReg, scratch1);
masm.PopRegsInMask(save);
masm.branchIfFalseBool(scratch, failure->label());
masm.branchIfFalseBool(scratch1, failure->label());
// Load the reallocated elements pointer.
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch1);
masm.bind(&capacityOk);
@ -1994,12 +2002,13 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
// If length is now <= index, increment length too.
Label skipIncrementLength;
Address length(scratch, ObjectElements::offsetOfLength());
Address length(scratch1, ObjectElements::offsetOfLength());
masm.branch32(Assembler::Above, length, index, &skipIncrementLength);
masm.add32(Imm32(1), length);
masm.bind(&skipIncrementLength);
// Skip EmitPreBarrier as the memory is uninitialized.
Label doStore;
masm.jump(&doStore);
masm.bind(&inBounds);
@ -2007,9 +2016,9 @@ IonCacheIRCompiler::emitStoreDenseElementHole()
EmitPreBarrier(masm, element, MIRType::Value);
masm.bind(&doStore);
EmitStoreDenseElement(masm, val, scratch, element);
EmitStoreDenseElement(masm, val, scratch1, element);
if (needsPostBarrier())
emitPostBarrierElement(obj, val, scratch, index);
emitPostBarrierElement(obj, val, scratch1, index);
return true;
}
@ -2032,10 +2041,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
bool handleOOB = reader.readBool();
AutoScratchRegister scratch1(allocator, masm);
Maybe<AutoScratchRegister> scratch2;
if (arrayType != Scalar::Float32 && arrayType != Scalar::Float64)
scratch2.emplace(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
@ -2044,7 +2050,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
// Bounds check.
Label done;
LoadTypedThingLength(masm, layout, obj, scratch1);
masm.branch32(Assembler::BelowOrEqual, scratch1, index, handleOOB ? &done : failure->label());
masm.spectreBoundsCheck32(index, scratch1, scratch2, handleOOB ? &done : failure->label());
// Load the elements vector.
LoadTypedThingData(masm, layout, obj, scratch1);
@ -2066,7 +2072,7 @@ IonCacheIRCompiler::emitStoreTypedElement()
return false;
masm.storeToTypedFloatArray(arrayType, maybeTempDouble, dest);
} else {
Register valueToStore = scratch2.ref();
Register valueToStore = scratch2;
if (arrayType == Scalar::Uint8Clamped) {
if (!masm.clampConstantOrRegisterToUint8(cx_, val, maybeTempDouble, valueToStore,
failure->label()))

Просмотреть файл

@ -3419,6 +3419,18 @@ LIRGenerator::visitStoreElement(MStoreElement* ins)
}
}
static bool
BoundsCheckNeedsSpectreTemp()
{
// On x86, spectreBoundsCheck32 can emit better code if it has a scratch
// register and index masking is enabled.
#ifdef JS_CODEGEN_X86
return JitOptions.spectreIndexMasking;
#else
return false;
#endif
}
void
LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
{
@ -3427,18 +3439,21 @@ LIRGenerator::visitStoreElementHole(MStoreElementHole* ins)
const LUse object = useRegister(ins->object());
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegisterOrConstant(ins->index());
const LAllocation index = useRegister(ins->index());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()));
lir = new(alloc()) LStoreElementHoleV(object, elements, index, useBox(ins->value()),
spectreTemp);
break;
default:
{
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
lir = new(alloc()) LStoreElementHoleT(object, elements, index, value);
lir = new(alloc()) LStoreElementHoleT(object, elements, index, value, spectreTemp);
break;
}
}
@ -3455,16 +3470,20 @@ LIRGenerator::visitFallibleStoreElement(MFallibleStoreElement* ins)
const LUse object = useRegister(ins->object());
const LUse elements = useRegister(ins->elements());
const LAllocation index = useRegisterOrConstant(ins->index());
const LAllocation index = useRegister(ins->index());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
LInstruction* lir;
switch (ins->value()->type()) {
case MIRType::Value:
lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()));
lir = new(alloc()) LFallibleStoreElementV(object, elements, index, useBox(ins->value()),
spectreTemp);
break;
default:
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value);
lir = new(alloc()) LFallibleStoreElementT(object, elements, index, value,
spectreTemp);
break;
}
@ -3563,10 +3582,13 @@ LIRGenerator::visitArrayPush(MArrayPush* ins)
LUse object = useRegister(ins->object());
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
switch (ins->value()->type()) {
case MIRType::Value:
{
LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp());
LArrayPushV* lir = new(alloc()) LArrayPushV(object, useBox(ins->value()), temp(),
spectreTemp);
define(lir, ins);
assignSafepoint(lir, ins);
break;
@ -3575,7 +3597,7 @@ LIRGenerator::visitArrayPush(MArrayPush* ins)
default:
{
const LAllocation value = useRegisterOrNonDoubleConstant(ins->value());
LArrayPushT* lir = new(alloc()) LArrayPushT(object, value, temp());
LArrayPushT* lir = new(alloc()) LArrayPushT(object, value, temp(), spectreTemp);
define(lir, ins);
assignSafepoint(lir, ins);
break;
@ -3730,18 +3752,6 @@ LIRGenerator::visitLoadTypedArrayElementHole(MLoadTypedArrayElementHole* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitLoadTypedArrayElementStatic(MLoadTypedArrayElementStatic* ins)
{
LLoadTypedArrayElementStatic* lir =
new(alloc()) LLoadTypedArrayElementStatic(useRegisterAtStart(ins->ptr()));
// In case of out of bounds, may bail out, or may jump to ool code.
if (ins->fallible())
assignSnapshot(lir, Bailout_BoundsCheck);
define(lir, ins);
}
void
LIRGenerator::visitStoreUnboxedScalar(MStoreUnboxedScalar* ins)
{
@ -3801,16 +3811,19 @@ LIRGenerator::visitStoreTypedArrayElementHole(MStoreTypedArrayElementHole* ins)
}
LUse elements = useRegister(ins->elements());
LAllocation length = useAnyOrConstant(ins->length());
LAllocation index = useRegisterOrConstant(ins->index());
LAllocation value;
LAllocation length = useAny(ins->length());
LAllocation index = useRegister(ins->index());
// For byte arrays, the value has to be in a byte register on x86.
LAllocation value;
if (ins->isByteWrite())
value = useByteOpRegisterOrNonDoubleConstant(ins->value());
else
value = useRegisterOrNonDoubleConstant(ins->value());
add(new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value), ins);
LDefinition spectreTemp = BoundsCheckNeedsSpectreTemp() ? temp() : LDefinition::BogusTemp();
auto* lir =
new(alloc()) LStoreTypedArrayElementHole(elements, length, index, value, spectreTemp);
add(lir, ins);
}
void

Просмотреть файл

@ -5771,41 +5771,6 @@ InlinePropertyTable::appendRoots(MRootList& roots) const
return true;
}
SharedMem<void*>
MLoadTypedArrayElementStatic::base() const
{
return someTypedArray_->as<TypedArrayObject>().viewDataEither();
}
size_t
MLoadTypedArrayElementStatic::length() const
{
return someTypedArray_->as<TypedArrayObject>().byteLength();
}
bool
MLoadTypedArrayElementStatic::congruentTo(const MDefinition* ins) const
{
if (!ins->isLoadTypedArrayElementStatic())
return false;
const MLoadTypedArrayElementStatic* other = ins->toLoadTypedArrayElementStatic();
if (offset() != other->offset())
return false;
if (needsBoundsCheck() != other->needsBoundsCheck())
return false;
if (accessType() != other->accessType())
return false;
if (base() != other->base())
return false;
return congruentIfOperandsEqual(other);
}
SharedMem<void*>
MStoreTypedArrayElementStatic::base() const
{
return someTypedArray_->as<TypedArrayObject>().viewDataEither();
}
bool
MGetPropertyCache::allowDoubleResult() const
{
@ -5815,12 +5780,6 @@ MGetPropertyCache::allowDoubleResult() const
return resultTypeSet()->hasType(TypeSet::DoubleType());
}
size_t
MStoreTypedArrayElementStatic::length() const
{
return someTypedArray_->as<TypedArrayObject>().byteLength();
}
MDefinition::AliasType
MGetPropertyPolymorphic::mightAlias(const MDefinition* store) const
{

Просмотреть файл

@ -1218,7 +1218,7 @@ class MInstruction
// Instructions needing to hook into type analysis should return a
// TypePolicy.
virtual TypePolicy* typePolicy() = 0;
virtual const TypePolicy* typePolicy() = 0;
virtual MIRType typePolicySpecialization() = 0;
};
@ -1230,7 +1230,7 @@ class MInstruction
#define INSTRUCTION_HEADER(opcode) \
INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(opcode) \
virtual TypePolicy* typePolicy() override; \
virtual const TypePolicy* typePolicy() override; \
virtual MIRType typePolicySpecialization() override;
#define ALLOW_CLONE(typename) \
@ -7938,7 +7938,7 @@ class MPhi final
public:
INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(Phi)
virtual TypePolicy* typePolicy();
virtual const TypePolicy* typePolicy();
virtual MIRType typePolicySpecialization();
MPhi(TempAllocator& alloc, MIRType resultType)
@ -10586,73 +10586,6 @@ class MLoadTypedArrayElementHole
ALLOW_CLONE(MLoadTypedArrayElementHole)
};
// Load a value fallibly or infallibly from a statically known typed array.
class MLoadTypedArrayElementStatic
: public MUnaryInstruction,
public ConvertToInt32Policy<0>::Data
{
MLoadTypedArrayElementStatic(JSObject* someTypedArray, MDefinition* ptr,
int32_t offset = 0, bool needsBoundsCheck = true)
: MUnaryInstruction(classOpcode, ptr), someTypedArray_(someTypedArray), offset_(offset),
needsBoundsCheck_(needsBoundsCheck), fallible_(true)
{
int type = accessType();
if (type == Scalar::Float32)
setResultType(MIRType::Float32);
else if (type == Scalar::Float64)
setResultType(MIRType::Double);
else
setResultType(MIRType::Int32);
}
CompilerObject someTypedArray_;
// An offset to be encoded in the load instruction - taking advantage of the
// addressing modes. This is only non-zero when the access is proven to be
// within bounds.
int32_t offset_;
bool needsBoundsCheck_;
bool fallible_;
public:
INSTRUCTION_HEADER(LoadTypedArrayElementStatic)
TRIVIAL_NEW_WRAPPERS
Scalar::Type accessType() const {
return someTypedArray_->as<TypedArrayObject>().type();
}
SharedMem<void*> base() const;
size_t length() const;
MDefinition* ptr() const { return getOperand(0); }
int32_t offset() const { return offset_; }
void setOffset(int32_t offset) { offset_ = offset; }
bool congruentTo(const MDefinition* ins) const override;
AliasSet getAliasSet() const override {
return AliasSet::Load(AliasSet::UnboxedElement);
}
bool needsBoundsCheck() const { return needsBoundsCheck_; }
void setNeedsBoundsCheck(bool v) { needsBoundsCheck_ = v; }
bool fallible() const {
return fallible_;
}
void setInfallible() {
fallible_ = false;
}
void computeRange(TempAllocator& alloc) override;
bool needTruncation(TruncateKind kind) override;
bool canProduceFloat32() const override { return accessType() == Scalar::Float32; }
void collectRangeInfoPreTrunc() override;
bool appendRoots(MRootList& roots) const override {
return roots.append(someTypedArray_);
}
};
// Base class for MIR ops that write unboxed scalar values.
class StoreUnboxedScalarBase
{
@ -10812,60 +10745,6 @@ class MStoreTypedArrayElementHole
ALLOW_CLONE(MStoreTypedArrayElementHole)
};
// Store a value infallibly to a statically known typed array.
class MStoreTypedArrayElementStatic :
public MBinaryInstruction,
public StoreUnboxedScalarBase,
public StoreTypedArrayElementStaticPolicy::Data
{
MStoreTypedArrayElementStatic(JSObject* someTypedArray, MDefinition* ptr, MDefinition* v,
int32_t offset = 0, bool needsBoundsCheck = true)
: MBinaryInstruction(classOpcode, ptr, v),
StoreUnboxedScalarBase(someTypedArray->as<TypedArrayObject>().type()),
someTypedArray_(someTypedArray),
offset_(offset), needsBoundsCheck_(needsBoundsCheck)
{}
CompilerObject someTypedArray_;
// An offset to be encoded in the store instruction - taking advantage of the
// addressing modes. This is only non-zero when the access is proven to be
// within bounds.
int32_t offset_;
bool needsBoundsCheck_;
public:
INSTRUCTION_HEADER(StoreTypedArrayElementStatic)
TRIVIAL_NEW_WRAPPERS
Scalar::Type accessType() const {
return writeType();
}
SharedMem<void*> base() const;
size_t length() const;
MDefinition* ptr() const { return getOperand(0); }
MDefinition* value() const { return getOperand(1); }
bool needsBoundsCheck() const { return needsBoundsCheck_; }
void setNeedsBoundsCheck(bool v) { needsBoundsCheck_ = v; }
int32_t offset() const { return offset_; }
void setOffset(int32_t offset) { offset_ = offset; }
AliasSet getAliasSet() const override {
return AliasSet::Store(AliasSet::UnboxedElement);
}
TruncateKind operandTruncateKind(size_t index) const override;
bool canConsumeFloat32(MUse* use) const override {
return use == getUseFor(1) && accessType() == Scalar::Float32;
}
void collectRangeInfoPreTrunc() override;
bool appendRoots(MRootList& roots) const override {
return roots.append(someTypedArray_);
}
};
// Compute an "effective address", i.e., a compound computation of the form:
// base + index * scale + displacement
class MEffectiveAddress

Просмотреть файл

@ -332,52 +332,9 @@ MacroAssembler::addPtr(ImmPtr imm, Register dest)
addPtr(ImmWord(uintptr_t(imm.value)), dest);
}
void
MacroAssembler::inc32(RegisterOrInt32Constant* key)
{
if (key->isRegister())
add32(Imm32(1), key->reg());
else
key->bumpConstant(1);
}
void
MacroAssembler::dec32(RegisterOrInt32Constant* key)
{
if (key->isRegister())
add32(Imm32(-1), key->reg());
else
key->bumpConstant(-1);
}
// ===============================================================
// Branch functions
void
MacroAssembler::branch32(Condition cond, Register length, const RegisterOrInt32Constant& key,
Label* label)
{
branch32Impl(cond, length, key, label);
}
void
MacroAssembler::branch32(Condition cond, const Address& length, const RegisterOrInt32Constant& key,
Label* label)
{
branch32Impl(cond, length, key, label);
}
template <typename T>
void
MacroAssembler::branch32Impl(Condition cond, const T& length, const RegisterOrInt32Constant& key,
Label* label)
{
if (key.isRegister())
branch32(cond, length, key.reg(), label);
else
branch32(cond, length, Imm32(key.constant()), label);
}
template <class L>
void
MacroAssembler::branchIfFalseBool(Register reg, L label)

Просмотреть файл

@ -820,11 +820,8 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void divFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
inline void divDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
inline void inc32(RegisterOrInt32Constant* key);
inline void inc64(AbsoluteAddress dest) PER_ARCH;
inline void dec32(RegisterOrInt32Constant* key);
inline void neg32(Register reg) PER_SHARED_ARCH;
inline void neg64(Register64 reg) DEFINED_ON(x86, x64, arm, mips32, mips64);
@ -938,13 +935,9 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void branch32(Condition cond, Register lhs, Register rhs, L label) PER_SHARED_ARCH;
template <class L>
inline void branch32(Condition cond, Register lhs, Imm32 rhs, L label) PER_SHARED_ARCH;
inline void branch32(Condition cond, Register length, const RegisterOrInt32Constant& key,
Label* label);
inline void branch32(Condition cond, const Address& lhs, Register rhs, Label* label) PER_SHARED_ARCH;
inline void branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label) PER_SHARED_ARCH;
inline void branch32(Condition cond, const Address& length, const RegisterOrInt32Constant& key,
Label* label);
inline void branch32(Condition cond, const AbsoluteAddress& lhs, Register rhs, Label* label)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
@ -1278,11 +1271,6 @@ class MacroAssembler : public MacroAssemblerSpecific
private:
// Implementation for branch* methods.
template <typename T>
inline void branch32Impl(Condition cond, const T& length, const RegisterOrInt32Constant& key,
Label* label);
template <typename T, typename S, typename L>
inline void branchPtrImpl(Condition cond, const T& lhs, const S& rhs, L label)
DEFINED_ON(x86_shared);
@ -1362,12 +1350,20 @@ class MacroAssembler : public MacroAssemblerSpecific
// Performs a bounds check and zeroes the index register if out-of-bounds
// (to mitigate Spectre).
inline void spectreBoundsCheck32(Register index, Register length, Register scratch,
private:
inline void spectreBoundsCheck32(Register index, const Operand& length, Register maybeScratch,
Label* failure)
DEFINED_ON(arm, arm64, mips_shared, x86_shared);
inline void spectreBoundsCheck32(Register index, const Address& length, Register scratch,
DEFINED_ON(x86);
public:
inline void spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
DEFINED_ON(arm, arm64, mips_shared, x86_shared);
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
inline void spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
DEFINED_ON(arm, arm64, mips_shared, x86, x64);
// ========================================================================
// Canonicalization primitives.
@ -2121,14 +2117,6 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void storeCallResultValue(TypedOrValueRegister dest);
using MacroAssemblerSpecific::store32;
void store32(const RegisterOrInt32Constant& key, const Address& dest) {
if (key.isRegister())
store32(key.reg(), dest);
else
store32(Imm32(key.constant()), dest);
}
template <typename T>
void guardedCallPreBarrier(const T& address, MIRType type) {
Label done;

Просмотреть файл

@ -1801,16 +1801,6 @@ MLoadUnboxedScalar::computeRange(TempAllocator& alloc)
setRange(GetTypedArrayRange(alloc, readType()));
}
void
MLoadTypedArrayElementStatic::computeRange(TempAllocator& alloc)
{
// We don't currently use MLoadTypedArrayElementStatic for uint32, so we
// don't have to worry about it returning a value outside our type.
MOZ_ASSERT(someTypedArray_->as<TypedArrayObject>().type() != Scalar::Uint32);
setRange(GetTypedArrayRange(alloc, someTypedArray_->as<TypedArrayObject>().type()));
}
void
MArrayLength::computeRange(TempAllocator& alloc)
{
@ -2672,18 +2662,6 @@ MToDouble::truncate()
}
}
bool
MLoadTypedArrayElementStatic::needTruncation(TruncateKind kind)
{
// IndirectTruncate not possible, since it returns 'undefined'
// upon out of bounds read. Doing arithmetic on 'undefined' gives wrong
// results. So only set infallible if explicitly truncated.
if (kind == Truncate)
setInfallible();
return false;
}
bool
MLimitedTruncate::needTruncation(TruncateKind kind)
{
@ -2804,13 +2782,6 @@ MStoreTypedArrayElementHole::operandTruncateKind(size_t index) const
return index == 3 && isIntegerWrite() ? Truncate : NoTruncate;
}
MDefinition::TruncateKind
MStoreTypedArrayElementStatic::operandTruncateKind(size_t index) const
{
// An integer store truncates the stored value.
return index == 1 && isIntegerWrite() ? Truncate : NoTruncate;
}
MDefinition::TruncateKind
MDiv::operandTruncateKind(size_t index) const
{
@ -3268,36 +3239,6 @@ MLoadElementHole::collectRangeInfoPreTrunc()
}
}
void
MLoadTypedArrayElementStatic::collectRangeInfoPreTrunc()
{
Range range(ptr());
if (range.hasInt32LowerBound() && range.hasInt32UpperBound()) {
int64_t offset = this->offset();
int64_t lower = range.lower() + offset;
int64_t upper = range.upper() + offset;
int64_t length = this->length();
if (lower >= 0 && upper < length)
setNeedsBoundsCheck(false);
}
}
void
MStoreTypedArrayElementStatic::collectRangeInfoPreTrunc()
{
Range range(ptr());
if (range.hasInt32LowerBound() && range.hasInt32UpperBound()) {
int64_t offset = this->offset();
int64_t lower = range.lower() + offset;
int64_t upper = range.upper() + offset;
int64_t length = this->length();
if (lower >= 0 && upper < length)
setNeedsBoundsCheck(false);
}
}
void
MClz::collectRangeInfoPreTrunc()
{

Просмотреть файл

@ -282,41 +282,6 @@ class ConstantOrRegister
}
};
struct RegisterOrInt32Constant {
bool isRegister_;
union {
Register reg_;
int32_t constant_;
};
explicit RegisterOrInt32Constant(Register reg)
: isRegister_(true), reg_(reg)
{ }
explicit RegisterOrInt32Constant(int32_t index)
: isRegister_(false), constant_(index)
{ }
inline void bumpConstant(int diff) {
MOZ_ASSERT(!isRegister_);
constant_ += diff;
}
inline Register reg() const {
MOZ_ASSERT(isRegister_);
return reg_;
}
inline int32_t constant() const {
MOZ_ASSERT(!isRegister_);
return constant_;
}
inline bool isRegister() const {
return isRegister_;
}
inline bool isConstant() const {
return !isRegister_;
}
};
template <typename T>
class TypedRegisterSet
{

Просмотреть файл

@ -66,7 +66,7 @@ BoxInputsPolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
ArithPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MIRType specialization = ins->typePolicySpecialization();
if (specialization == MIRType::None)
@ -121,7 +121,7 @@ AllDoublePolicy::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
MOZ_ASSERT(def->isCompare());
MCompare* compare = def->toCompare();
@ -269,7 +269,7 @@ ComparePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
}
bool
SameValuePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
SameValuePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
MOZ_ASSERT(def->isSameValue());
MSameValue* sameValue = def->toSameValue();
@ -300,7 +300,7 @@ SameValuePolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
}
bool
TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
MTypeBarrier* ins = def->toTypeBarrier();
MIRType inputType = ins->getOperand(0)->type();
@ -355,7 +355,7 @@ TypeBarrierPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
}
bool
TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MDefinition* op = ins->getOperand(0);
switch (op->type()) {
@ -386,7 +386,7 @@ TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
BitwisePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
BitwisePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MIRType specialization = ins->typePolicySpecialization();
if (specialization == MIRType::None)
@ -413,7 +413,7 @@ BitwisePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
PowPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
PowPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MIRType specialization = ins->typePolicySpecialization();
MOZ_ASSERT(specialization == MIRType::Int32 ||
@ -586,7 +586,7 @@ template bool Float32Policy<2>::staticAdjustInputs(TempAllocator& alloc, MInstru
template <unsigned Op>
bool
FloatingPointPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* def)
FloatingPointPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
MIRType policyType = def->typePolicySpecialization();
if (policyType == MIRType::Double)
@ -594,7 +594,7 @@ FloatingPointPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* def)
return Float32Policy<Op>::staticAdjustInputs(alloc, def);
}
template bool FloatingPointPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* def);
template bool FloatingPointPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* def) const;
template <unsigned Op>
bool
@ -611,16 +611,16 @@ template bool NoFloatPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstru
template <unsigned FirstOp>
bool
NoFloatPolicyAfter<FirstOp>::adjustInputs(TempAllocator& alloc, MInstruction* def)
NoFloatPolicyAfter<FirstOp>::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
for (size_t op = FirstOp, e = def->numOperands(); op < e; op++)
EnsureOperandNotFloat32(alloc, def, op);
return true;
}
template bool NoFloatPolicyAfter<0>::adjustInputs(TempAllocator& alloc, MInstruction* def);
template bool NoFloatPolicyAfter<1>::adjustInputs(TempAllocator& alloc, MInstruction* def);
template bool NoFloatPolicyAfter<2>::adjustInputs(TempAllocator& alloc, MInstruction* def);
template bool NoFloatPolicyAfter<0>::adjustInputs(TempAllocator& alloc, MInstruction* def) const;
template bool NoFloatPolicyAfter<1>::adjustInputs(TempAllocator& alloc, MInstruction* def) const;
template bool NoFloatPolicyAfter<2>::adjustInputs(TempAllocator& alloc, MInstruction* def) const;
template <unsigned Op>
bool
@ -856,7 +856,7 @@ template bool
SimdSameAsReturnedTypePolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
bool
SimdAllPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
SimdAllPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
for (unsigned i = 0, e = ins->numOperands(); i < e; i++)
MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
@ -865,17 +865,17 @@ SimdAllPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
template <unsigned Op>
bool
SimdPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* ins)
SimdPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MOZ_ASSERT(ins->typePolicySpecialization() == ins->getOperand(Op)->type());
return true;
}
template bool
SimdPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* ins);
SimdPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* ins) const;
bool
SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MSimdGeneralShuffle* s = ins->toSimdGeneralShuffle();
@ -899,7 +899,7 @@ SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
SimdSelectPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
SimdSelectPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
// First input is the mask, which has to be a boolean.
MOZ_ASSERT(IsBooleanSimdType(ins->getOperand(0)->type()));
@ -912,7 +912,7 @@ SimdSelectPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MCall* call = ins->toCall();
@ -936,7 +936,7 @@ CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
CallSetElementPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
CallSetElementPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
// The first operand should be an object.
if (!SingleObjectPolicy::staticAdjustInputs(alloc, ins))
@ -953,7 +953,7 @@ CallSetElementPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
InstanceOfPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def)
InstanceOfPolicy::adjustInputs(TempAllocator& alloc, MInstruction* def) const
{
// Box first operand if it isn't object
if (def->getOperand(0)->type() != MIRType::Object)
@ -1054,7 +1054,7 @@ StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc, MInstruction* i
}
bool
StoreUnboxedScalarPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
StoreUnboxedScalarPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
if (!SingleObjectPolicy::staticAdjustInputs(alloc, ins))
return false;
@ -1067,7 +1067,7 @@ StoreUnboxedScalarPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
StoreTypedArrayHolePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
StoreTypedArrayHolePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MStoreTypedArrayElementHole* store = ins->toStoreTypedArrayElementHole();
MOZ_ASSERT(store->elements()->type() == MIRType::Elements);
@ -1078,16 +1078,7 @@ StoreTypedArrayHolePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
StoreTypedArrayElementStaticPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
{
MStoreTypedArrayElementStatic* store = ins->toStoreTypedArrayElementStatic();
return ConvertToInt32Policy<0>::staticAdjustInputs(alloc, ins) &&
StoreUnboxedScalarPolicy::adjustValueInput(alloc, ins, store->accessType(), store->value(), 1);
}
bool
StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
if (!ObjectPolicy<0>::staticAdjustInputs(alloc, ins))
return false;
@ -1128,7 +1119,7 @@ StoreUnboxedObjectOrNullPolicy::adjustInputs(TempAllocator& alloc, MInstruction*
}
bool
StoreUnboxedStringPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
StoreUnboxedStringPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
if (!ObjectPolicy<0>::staticAdjustInputs(alloc, ins))
return false;
@ -1155,7 +1146,7 @@ StoreUnboxedStringPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MDefinition* in = ins->toClampToUint8()->input();
@ -1173,7 +1164,7 @@ ClampPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
}
bool
FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const
{
MOZ_ASSERT(ins->numOperands() == 1);
MIRType inputType = ins->getOperand(0)->type();
@ -1266,7 +1257,6 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
_(SimdAllPolicy) \
_(SimdSelectPolicy) \
_(SimdShufflePolicy) \
_(StoreTypedArrayElementStaticPolicy) \
_(StoreTypedArrayHolePolicy) \
_(StoreUnboxedScalarPolicy) \
_(StoreUnboxedObjectOrNullPolicy) \
@ -1352,10 +1342,10 @@ namespace jit {
//
// This Macro use __VA_ARGS__ to account for commas of template parameters.
#define DEFINE_TYPE_POLICY_SINGLETON_INSTANCES_(...) \
TypePolicy * \
const TypePolicy* \
__VA_ARGS__::Data::thisTypePolicy() \
{ \
static __VA_ARGS__ singletonType; \
static constexpr __VA_ARGS__ singletonType; \
return &singletonType; \
}
@ -1388,7 +1378,7 @@ thisTypeSpecialization()
// inherited from the TypePolicy::Data structure, or a member inherited from
// NoTypePolicy if the MIR instruction has no type policy.
#define DEFINE_MIR_TYPEPOLICY_MEMBERS_(op) \
TypePolicy * \
const TypePolicy* \
js::jit::M##op::typePolicy() \
{ \
return M##op::thisTypePolicy(); \

Просмотреть файл

@ -32,7 +32,7 @@ class TypePolicy
// * If untyped, optionally ask the input to try and specialize its value.
// * Replace the operand with a conversion instruction.
// * Insert an unconditional deoptimization (no conversion possible).
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) = 0;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const = 0;
};
struct TypeSpecializationData
@ -56,13 +56,13 @@ struct TypeSpecializationData
#define EMPTY_DATA_ \
struct Data \
{ \
static TypePolicy* thisTypePolicy(); \
static const TypePolicy* thisTypePolicy(); \
}
#define INHERIT_DATA_(DATA_TYPE) \
struct Data : public DATA_TYPE \
{ \
static TypePolicy* thisTypePolicy(); \
static const TypePolicy* thisTypePolicy(); \
}
#define SPECIALIZATION_DATA_ INHERIT_DATA_(TypeSpecializationData)
@ -72,7 +72,7 @@ class NoTypePolicy
public:
struct Data
{
static TypePolicy* thisTypePolicy() {
static const TypePolicy* thisTypePolicy() {
return nullptr;
}
};
@ -83,7 +83,7 @@ class BoxInputsPolicy final : public TypePolicy
public:
SPECIALIZATION_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -92,7 +92,7 @@ class ArithPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
class AllDoublePolicy final : public TypePolicy
@ -100,7 +100,7 @@ class AllDoublePolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -109,21 +109,21 @@ class BitwisePolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
class ComparePolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
class SameValuePolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
// Policy for MTest instructions.
@ -131,21 +131,21 @@ class TestPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class TypeBarrierPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class CallPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
// Policy for MPow. First operand Double; second Double or Int32.
@ -153,7 +153,7 @@ class PowPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
// Expect a string for operand Op. If the input is a Value, it is unboxed.
@ -163,7 +163,7 @@ class StringPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -175,7 +175,7 @@ class ConvertToStringPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -187,7 +187,7 @@ class BooleanPolicy final : private TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -199,7 +199,7 @@ class UnboxedInt32Policy final : private TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -211,7 +211,7 @@ class ConvertToInt32Policy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -223,7 +223,7 @@ class TruncateToInt32Policy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -235,7 +235,7 @@ class DoublePolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -247,7 +247,7 @@ class Float32Policy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -259,7 +259,7 @@ class FloatingPointPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
template <unsigned Op>
@ -268,7 +268,7 @@ class NoFloatPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -280,7 +280,7 @@ class NoFloatPolicyAfter final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
// Box objects or strings as an input to a ToDouble instruction.
@ -289,7 +289,7 @@ class ToDoublePolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -300,7 +300,7 @@ class ToInt32Policy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -311,7 +311,7 @@ class ToStringPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -322,7 +322,7 @@ class ObjectPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -339,7 +339,7 @@ class SimdScalarPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override {
return staticAdjustInputs(alloc, def);
}
};
@ -348,7 +348,7 @@ class SimdAllPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
template <unsigned Op>
@ -356,21 +356,21 @@ class SimdPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class SimdSelectPolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class SimdShufflePolicy final : public TypePolicy
{
public:
SPECIALIZATION_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
// SIMD value-type policy, use the returned type of the instruction to determine
@ -381,7 +381,7 @@ class SimdSameAsReturnedTypePolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -392,7 +392,7 @@ class BoxPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -404,7 +404,7 @@ class BoxExceptPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -416,7 +416,7 @@ class CacheIdPolicy final : public TypePolicy
public:
EMPTY_DATA_;
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -442,7 +442,7 @@ class MixPolicy final : public TypePolicy
static MOZ_MUST_USE bool staticAdjustInputs(TempAllocator& alloc, MInstruction* ins) {
return MixPolicy::staticAdjustInputsHelper<Policies...>(alloc, ins);
}
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override {
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override {
return staticAdjustInputs(alloc, ins);
}
};
@ -451,7 +451,7 @@ class CallSetElementPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
// First operand will be boxed to a Value (except for an object)
@ -460,11 +460,10 @@ class InstanceOfPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
class StoreTypedArrayHolePolicy;
class StoreTypedArrayElementStaticPolicy;
class StoreUnboxedScalarPolicy : public TypePolicy
{
@ -474,39 +473,31 @@ class StoreUnboxedScalarPolicy : public TypePolicy
int valueOperand);
friend class StoreTypedArrayHolePolicy;
friend class StoreTypedArrayElementStaticPolicy;
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class StoreTypedArrayHolePolicy final : public StoreUnboxedScalarPolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
};
class StoreTypedArrayElementStaticPolicy final : public StoreUnboxedScalarPolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class StoreUnboxedObjectOrNullPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
class StoreUnboxedStringPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* def) const override;
};
// Accepts integers and doubles. Everything else is boxed.
@ -514,14 +505,14 @@ class ClampPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
class FilterTypeSetPolicy final : public TypePolicy
{
public:
EMPTY_DATA_;
virtual MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
MOZ_MUST_USE bool adjustInputs(TempAllocator& alloc, MInstruction* ins) const override;
};
#undef SPECIALIZATION_DATA_

Просмотреть файл

@ -1766,18 +1766,6 @@ CodeGeneratorARM::generateInvalidateEpilogue()
masm.assumeUnreachable("Should have returned directly to its caller instead of here.");
}
void
CodeGenerator::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
CodeGenerator::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
CodeGenerator::visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir)
{

Просмотреть файл

@ -784,12 +784,6 @@ LIRGeneratorARM::lowerTruncateFToInt32(MTruncateToInt32* ins)
define(new(alloc()) LTruncateFToInt32(useRegister(opd), LDefinition::BogusTemp()), ins);
}
void
LIRGenerator::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
LIRGenerator::visitAtomicExchangeTypedArrayElement(MAtomicExchangeTypedArrayElement* ins)
{

Просмотреть файл

@ -2194,37 +2194,31 @@ MacroAssembler::spectreZeroRegister(Condition cond, Register, Register dest)
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length);
MOZ_ASSERT(length != scratch);
MOZ_ASSERT(index != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
MOZ_ASSERT(length != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
branch32(Assembler::BelowOrEqual, length, index, failure);
if (JitOptions.spectreIndexMasking)
ma_mov(scratch, index, LeaveCC, Assembler::BelowOrEqual);
ma_mov(Imm32(0), index, Assembler::BelowOrEqual);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length.base);
MOZ_ASSERT(length.base != scratch);
MOZ_ASSERT(index != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
MOZ_ASSERT(length.base != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
branch32(Assembler::BelowOrEqual, length, index, failure);
if (JitOptions.spectreIndexMasking)
ma_mov(scratch, index, LeaveCC, Assembler::BelowOrEqual);
ma_mov(Imm32(0), index, Assembler::BelowOrEqual);
}
// ========================================================================

Просмотреть файл

@ -568,18 +568,6 @@ getBase(U* mir)
return InvalidReg;
}
void
CodeGenerator::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
{
MOZ_CRASH("CodeGenerator::visitLoadTypedArrayElementStatic");
}
void
CodeGenerator::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("CodeGenerator::visitStoreTypedArrayElementStatic");
}
void
CodeGenerator::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
{

Просмотреть файл

@ -280,12 +280,6 @@ LIRGeneratorARM64::lowerTruncateFToInt32(MTruncateToInt32* ins)
MOZ_CRASH("lowerTruncateFToInt32");
}
void
LIRGenerator::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
LIRGenerator::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins)
{

Просмотреть файл

@ -1875,12 +1875,12 @@ MacroAssembler::spectreZeroRegister(Condition cond, Register, Register dest)
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length);
MOZ_ASSERT(length != scratch);
MOZ_ASSERT(index != scratch);
MOZ_ASSERT(length != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
branch32(Assembler::BelowOrEqual, length, index, failure);
@ -1889,12 +1889,12 @@ MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register s
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length.base);
MOZ_ASSERT(length.base != scratch);
MOZ_ASSERT(index != scratch);
MOZ_ASSERT(length.base != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
branch32(Assembler::BelowOrEqual, length, index, failure);

Просмотреть файл

@ -1800,18 +1800,6 @@ CodeGeneratorMIPSShared::generateInvalidateEpilogue()
masm.assumeUnreachable("Should have returned directly to its caller instead of here.");
}
void
CodeGenerator::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
CodeGenerator::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
class js::jit::OutOfLineTableSwitch : public OutOfLineCodeBase<CodeGeneratorMIPSShared>
{
MTableSwitch* mir_;

Просмотреть файл

@ -557,12 +557,6 @@ LIRGenerator::visitSubstr(MSubstr* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
LIRGenerator::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins)
{

Просмотреть файл

@ -1017,7 +1017,7 @@ MacroAssembler::test32MovePtr(Condition cond, const Address& addr, Imm32 mask, R
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
{
MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);
@ -1025,7 +1025,7 @@ MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register s
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register scratch,
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
{
MOZ_RELEASE_ASSERT(!JitOptions.spectreIndexMasking);

Просмотреть файл

@ -184,14 +184,6 @@ ToAnyRegister(const LDefinition* def)
return ToAnyRegister(def->output());
}
static inline RegisterOrInt32Constant
ToRegisterOrInt32Constant(const LAllocation* a)
{
if (a->isConstant())
return RegisterOrInt32Constant(ToInt32(a));
return RegisterOrInt32Constant(ToRegister(a));
}
static inline ValueOperand
ToOutValue(LInstruction* ins)
{

Просмотреть файл

@ -6440,19 +6440,21 @@ class LStoreElementT : public LInstructionHelper<0, 3, 0>
};
// Like LStoreElementV, but supports indexes >= initialized length.
class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
{
public:
LIR_HEADER(StoreElementHoleV)
LStoreElementHoleV(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LBoxAllocation& value)
const LAllocation& index, const LBoxAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
setTemp(0, spectreTemp);
}
static const size_t Value = 3;
@ -6469,22 +6471,27 @@ class LStoreElementHoleV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
const LAllocation* index() {
return getOperand(2);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementT, but supports indexes >= initialized length.
class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
class LStoreElementHoleT : public LInstructionHelper<0, 4, 1>
{
public:
LIR_HEADER(StoreElementHoleT)
LStoreElementHoleT(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LAllocation& value)
const LAllocation& index, const LAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
setTemp(0, spectreTemp);
}
const MStoreElementHole* mir() const {
@ -6502,22 +6509,27 @@ class LStoreElementHoleT : public LInstructionHelper<0, 4, 0>
const LAllocation* value() {
return getOperand(3);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementV, but can just ignore assignment (for eg. frozen objects)
class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 1>
{
public:
LIR_HEADER(FallibleStoreElementV)
LFallibleStoreElementV(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LBoxAllocation& value)
const LAllocation& index, const LBoxAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setBoxOperand(Value, value);
setTemp(0, spectreTemp);
}
static const size_t Value = 3;
@ -6534,22 +6546,27 @@ class LFallibleStoreElementV : public LInstructionHelper<0, 3 + BOX_PIECES, 0>
const LAllocation* index() {
return getOperand(2);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
// Like LStoreElementT, but can just ignore assignment (for eg. frozen objects)
class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
class LFallibleStoreElementT : public LInstructionHelper<0, 4, 1>
{
public:
LIR_HEADER(FallibleStoreElementT)
LFallibleStoreElementT(const LAllocation& object, const LAllocation& elements,
const LAllocation& index, const LAllocation& value)
const LAllocation& index, const LAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, elements);
setOperand(2, index);
setOperand(3, value);
setTemp(0, spectreTemp);
}
const MFallibleStoreElement* mir() const {
@ -6567,6 +6584,9 @@ class LFallibleStoreElementT : public LInstructionHelper<0, 4, 0>
const LAllocation* value() {
return getOperand(3);
}
const LDefinition* spectreTemp() {
return getTemp(0);
}
};
class LStoreUnboxedPointer : public LInstructionHelper<0, 3, 0>
@ -6681,17 +6701,19 @@ class LArrayPopShiftT : public LInstructionHelper<1, 1, 2>
}
};
class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 2>
{
public:
LIR_HEADER(ArrayPushV)
LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp)
LArrayPushV(const LAllocation& object, const LBoxAllocation& value, const LDefinition& temp,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setBoxOperand(Value, value);
setTemp(0, temp);
setTemp(1, spectreTemp);
}
static const size_t Value = 1;
@ -6705,19 +6727,24 @@ class LArrayPushV : public LInstructionHelper<1, 1 + BOX_PIECES, 1>
const LDefinition* temp() {
return getTemp(0);
}
const LDefinition* spectreTemp() {
return getTemp(1);
}
};
class LArrayPushT : public LInstructionHelper<1, 2, 1>
class LArrayPushT : public LInstructionHelper<1, 2, 2>
{
public:
LIR_HEADER(ArrayPushT)
LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp)
LArrayPushT(const LAllocation& object, const LAllocation& value, const LDefinition& temp,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, object);
setOperand(1, value);
setTemp(0, temp);
setTemp(1, spectreTemp);
}
const MArrayPush* mir() const {
@ -6732,6 +6759,9 @@ class LArrayPushT : public LInstructionHelper<1, 2, 1>
const LDefinition* temp() {
return getTemp(0);
}
const LDefinition* spectreTemp() {
return getTemp(1);
}
};
class LArraySlice : public LCallInstructionHelper<1, 3, 2>
@ -6854,23 +6884,6 @@ class LLoadTypedArrayElementHole : public LInstructionHelper<BOX_PIECES, 2, 1>
}
};
class LLoadTypedArrayElementStatic : public LInstructionHelper<1, 1, 0>
{
public:
LIR_HEADER(LoadTypedArrayElementStatic);
explicit LLoadTypedArrayElementStatic(const LAllocation& ptr)
: LInstructionHelper(classOpcode)
{
setOperand(0, ptr);
}
MLoadTypedArrayElementStatic* mir() const {
return mir_->toLoadTypedArrayElementStatic();
}
const LAllocation* ptr() {
return getOperand(0);
}
};
class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0>
{
public:
@ -6899,19 +6912,21 @@ class LStoreUnboxedScalar : public LInstructionHelper<0, 3, 0>
}
};
class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 0>
class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 1>
{
public:
LIR_HEADER(StoreTypedArrayElementHole)
LStoreTypedArrayElementHole(const LAllocation& elements, const LAllocation& length,
const LAllocation& index, const LAllocation& value)
const LAllocation& index, const LAllocation& value,
const LDefinition& spectreTemp)
: LInstructionHelper(classOpcode)
{
setOperand(0, elements);
setOperand(1, length);
setOperand(2, index);
setOperand(3, value);
setTemp(0, spectreTemp);
}
const MStoreTypedArrayElementHole* mir() const {
@ -6929,26 +6944,8 @@ class LStoreTypedArrayElementHole : public LInstructionHelper<0, 4, 0>
const LAllocation* value() {
return getOperand(3);
}
};
class LStoreTypedArrayElementStatic : public LInstructionHelper<0, 2, 0>
{
public:
LIR_HEADER(StoreTypedArrayElementStatic);
LStoreTypedArrayElementStatic(const LAllocation& ptr, const LAllocation& value)
: LInstructionHelper(classOpcode)
{
setOperand(0, ptr);
setOperand(1, value);
}
MStoreTypedArrayElementStatic* mir() const {
return mir_->toStoreTypedArrayElementStatic();
}
const LAllocation* ptr() {
return getOperand(0);
}
const LAllocation* value() {
return getOperand(1);
const LDefinition* spectreTemp() {
return getTemp(0);
}
};

Просмотреть файл

@ -290,11 +290,6 @@ class LIRGeneratorShared
static bool allowTypedElementHoleCheck() {
return false;
}
// Whether to generate typed array accesses on statically known objects.
static bool allowStaticTypedArrayAccesses() {
return false;
}
};
} // namespace jit

Просмотреть файл

@ -382,18 +382,6 @@ CodeGenerator::visitWasmUint32ToFloat32(LWasmUint32ToFloat32* lir)
masm.convertUInt32ToFloat32(ToRegister(lir->input()), ToFloatRegister(lir->output()));
}
void
CodeGenerator::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
CodeGenerator::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
CodeGeneratorX64::wasmStore(const wasm::MemoryAccessDesc& access, const LAllocation* value,
Operand dstAddr)

Просмотреть файл

@ -416,12 +416,6 @@ LIRGenerator::visitSubstr(MSubstr* ins)
assignSafepoint(lir, ins);
}
void
LIRGenerator::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
{
MOZ_CRASH("NYI");
}
void
LIRGenerator::visitRandom(MRandom* ins)
{

Просмотреть файл

@ -852,6 +852,50 @@ MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest)
cmovCCq(cond, Operand(src), dest);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length);
MOZ_ASSERT(length != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
ScratchRegisterScope scratch(*this);
MOZ_ASSERT(index != scratch);
MOZ_ASSERT(length != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
cmp32(index, length);
j(Assembler::AboveOrEqual, failure);
if (JitOptions.spectreIndexMasking)
cmovCCl(Assembler::AboveOrEqual, scratch, index);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length.base);
MOZ_ASSERT(length.base != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
ScratchRegisterScope scratch(*this);
MOZ_ASSERT(index != scratch);
MOZ_ASSERT(length.base != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
cmp32(index, Operand(length));
j(Assembler::AboveOrEqual, failure);
if (JitOptions.spectreIndexMasking)
cmovCCl(Assembler::AboveOrEqual, scratch, index);
}
// ========================================================================
// Truncate floating point.

Просмотреть файл

@ -1118,42 +1118,6 @@ MacroAssembler::spectreZeroRegister(Condition cond, Register scratch, Register d
spectreMovePtr(cond, scratch, dest);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register scratch,
Label* failure)
{
MOZ_ASSERT(index != length);
MOZ_ASSERT(length != scratch);
MOZ_ASSERT(index != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
cmp32(index, length);
j(Assembler::AboveOrEqual, failure);
if (JitOptions.spectreIndexMasking)
cmovCCl(Assembler::AboveOrEqual, scratch, index);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register scratch,
Label* failure)
{
MOZ_ASSERT(index != length.base);
MOZ_ASSERT(length.base != scratch);
MOZ_ASSERT(index != scratch);
if (JitOptions.spectreIndexMasking)
move32(Imm32(0), scratch);
cmp32(index, Operand(length));
j(Assembler::AboveOrEqual, failure);
if (JitOptions.spectreIndexMasking)
cmovCCl(Assembler::AboveOrEqual, scratch, index);
}
// ========================================================================
// Canonicalization primitives.
void

Просмотреть файл

@ -259,55 +259,6 @@ CodeGenerator::visitWasmUint32ToFloat32(LWasmUint32ToFloat32* lir)
masm.convertUInt32ToFloat32(temp, output);
}
void
CodeGenerator::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
{
const MLoadTypedArrayElementStatic* mir = ins->mir();
Scalar::Type accessType = mir->accessType();
MOZ_ASSERT_IF(accessType == Scalar::Float32, mir->type() == MIRType::Float32);
Register ptr = ToRegister(ins->ptr());
AnyRegister out = ToAnyRegister(ins->output());
OutOfLineLoadTypedArrayOutOfBounds* ool = nullptr;
uint32_t offset = mir->offset();
if (mir->needsBoundsCheck()) {
MOZ_ASSERT(offset == 0);
if (!mir->fallible()) {
ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(out, accessType);
addOutOfLineCode(ool, ins->mir());
}
masm.cmpPtr(ptr, ImmWord(mir->length()));
if (ool)
masm.j(Assembler::AboveOrEqual, ool->entry());
else
bailoutIf(Assembler::AboveOrEqual, ins->snapshot());
}
Operand srcAddr(ptr, int32_t(mir->base().asValue()) + int32_t(offset));
switch (accessType) {
case Scalar::Int8: masm.movsblWithPatch(srcAddr, out.gpr()); break;
case Scalar::Uint8Clamped:
case Scalar::Uint8: masm.movzblWithPatch(srcAddr, out.gpr()); break;
case Scalar::Int16: masm.movswlWithPatch(srcAddr, out.gpr()); break;
case Scalar::Uint16: masm.movzwlWithPatch(srcAddr, out.gpr()); break;
case Scalar::Int32:
case Scalar::Uint32: masm.movlWithPatch(srcAddr, out.gpr()); break;
case Scalar::Float32: masm.vmovssWithPatch(srcAddr, out.fpu()); break;
case Scalar::Float64: masm.vmovsdWithPatch(srcAddr, out.fpu()); break;
default: MOZ_CRASH("Unexpected type");
}
if (accessType == Scalar::Float64)
masm.canonicalizeDouble(out.fpu());
if (accessType == Scalar::Float32)
masm.canonicalizeFloat(out.fpu());
if (ool)
masm.bind(ool->rejoin());
}
template <typename T>
void
CodeGeneratorX86::emitWasmLoad(T* ins)
@ -420,55 +371,6 @@ CodeGenerator::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
masm.bind(ool->rejoin());
}
void
CodeGenerator::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
{
MStoreTypedArrayElementStatic* mir = ins->mir();
Scalar::Type accessType = mir->accessType();
Register ptr = ToRegister(ins->ptr());
const LAllocation* value = ins->value();
canonicalizeIfDeterministic(accessType, value);
uint32_t offset = mir->offset();
MOZ_ASSERT_IF(mir->needsBoundsCheck(), offset == 0);
Label rejoin;
if (mir->needsBoundsCheck()) {
MOZ_ASSERT(offset == 0);
masm.cmpPtr(ptr, ImmWord(mir->length()));
masm.j(Assembler::AboveOrEqual, &rejoin);
}
Operand dstAddr(ptr, int32_t(mir->base().asValue()) + int32_t(offset));
switch (accessType) {
case Scalar::Int8:
case Scalar::Uint8Clamped:
case Scalar::Uint8:
masm.movbWithPatch(ToRegister(value), dstAddr);
break;
case Scalar::Int16:
case Scalar::Uint16:
masm.movwWithPatch(ToRegister(value), dstAddr);
break;
case Scalar::Int32:
case Scalar::Uint32:
masm.movlWithPatch(ToRegister(value), dstAddr);
break;
case Scalar::Float32:
masm.vmovssWithPatch(ToFloatRegister(value), dstAddr);
break;
case Scalar::Float64:
masm.vmovsdWithPatch(ToFloatRegister(value), dstAddr);
break;
default:
MOZ_CRASH("unexpected type");
}
if (rejoin.used())
masm.bind(&rejoin);
}
void
CodeGenerator::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins)
{

Просмотреть файл

@ -469,30 +469,6 @@ LIRGenerator::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins)
add(lir, ins);
}
void
LIRGenerator::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins)
{
// The code generated for StoreTypedArrayElementStatic is identical to that
// for AsmJSStoreHeap, and the same concerns apply.
LStoreTypedArrayElementStatic* lir;
switch (ins->accessType()) {
case Scalar::Int8: case Scalar::Uint8:
case Scalar::Uint8Clamped:
lir = new(alloc()) LStoreTypedArrayElementStatic(useRegister(ins->ptr()),
useFixed(ins->value(), eax));
break;
case Scalar::Int16: case Scalar::Uint16:
case Scalar::Int32: case Scalar::Uint32:
case Scalar::Float32: case Scalar::Float64:
lir = new(alloc()) LStoreTypedArrayElementStatic(useRegisterAtStart(ins->ptr()),
useRegisterAtStart(ins->value()));
break;
default: MOZ_CRASH("unexpected array type");
}
add(lir, ins);
}
void
LIRGenerator::visitWasmCompareExchangeHeap(MWasmCompareExchangeHeap* ins)
{

Просмотреть файл

@ -60,9 +60,6 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
static bool allowTypedElementHoleCheck() {
return true;
}
static bool allowStaticTypedArrayAccesses() {
return true;
}
};
typedef LIRGeneratorX86 LIRGeneratorSpecific;

Просмотреть файл

@ -1041,6 +1041,64 @@ MacroAssembler::spectreMovePtr(Condition cond, Register src, Register dest)
cmovCCl(cond, Operand(src), dest);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Operand& length, Register maybeScratch,
Label* failure)
{
Label failurePopValue;
bool pushedValue = false;
if (JitOptions.spectreIndexMasking) {
if (maybeScratch == InvalidReg) {
push(Imm32(0));
pushedValue = true;
} else {
move32(Imm32(0), maybeScratch);
}
}
cmp32(index, length);
j(Assembler::AboveOrEqual, pushedValue ? &failurePopValue : failure);
if (JitOptions.spectreIndexMasking) {
if (maybeScratch == InvalidReg) {
Label done;
cmovCCl(Assembler::AboveOrEqual, Operand(StackPointer, 0), index);
lea(Operand(StackPointer, sizeof(void*)), StackPointer);
jump(&done);
bind(&failurePopValue);
lea(Operand(StackPointer, sizeof(void*)), StackPointer);
jump(failure);
bind(&done);
} else {
cmovCCl(Assembler::AboveOrEqual, maybeScratch, index);
}
}
}
void
MacroAssembler::spectreBoundsCheck32(Register index, Register length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length);
MOZ_ASSERT(length != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
spectreBoundsCheck32(index, Operand(length), maybeScratch, failure);
}
void
MacroAssembler::spectreBoundsCheck32(Register index, const Address& length, Register maybeScratch,
Label* failure)
{
MOZ_ASSERT(index != length.base);
MOZ_ASSERT(length.base != maybeScratch);
MOZ_ASSERT(index != maybeScratch);
spectreBoundsCheck32(index, Operand(length), maybeScratch, failure);
}
// ========================================================================
// Truncate floating point.

Просмотреть файл

@ -49,15 +49,31 @@ if not CONFIG['JS_DISABLE_SHELL']:
TEST_DIRS += ['jsapi-tests', 'tests', 'gdb']
if CONFIG['FUZZING_INTERFACES']:
if CONFIG['LIBFUZZER']:
# Add trace-pc coverage for libfuzzer
CFLAGS += ['-fsanitize-coverage=trace-pc-guard']
CXXFLAGS += ['-fsanitize-coverage=trace-pc-guard']
TEST_DIRS += [
'fuzz-tests',
]
if CONFIG['FUZZING_INTERFACES'] and CONFIG['LIBFUZZER']:
# In addition to regular coverage provided by trace-pc-guard,
# LibFuzzer can use trace-cmp to instrument various compare instructions.
# Only use this feature on source files that do a lot of constant
# comparisons that would otherwise be hard to guess by LibFuzzer,
# as it comes with a larger overhead (requires -use_value_profile=1).
libfuzzer_flags = ['-fsanitize-coverage=trace-pc-guard']
libfuzzer_flags_cmp = ['-fsanitize-coverage=trace-pc-guard', '-fsanitize-coverage=trace-cmp']
# Any files that are targeted by LibFuzzer should be added here so they can
# be built with the necessary instrumentation flags, rather than just building
# the whole JS engine with instrumentation, to reduce the amount of noise.
SOURCES += [
'vm/StructuredClone.cpp',
]
SOURCES['vm/StructuredClone.cpp'].flags += libfuzzer_flags_cmp
else:
UNIFIED_SOURCES += [
'vm/StructuredClone.cpp',
]
CONFIGURE_SUBST_FILES += [
'devtools/rootAnalysis/Makefile',
]
@ -374,7 +390,6 @@ UNIFIED_SOURCES += [
'vm/Stack.cpp',
'vm/Stopwatch.cpp',
'vm/StringType.cpp',
'vm/StructuredClone.cpp',
'vm/SymbolType.cpp',
'vm/TaggedProto.cpp',
'vm/Time.cpp',
@ -697,9 +712,9 @@ if CONFIG['JS_BUILD_BINAST']:
# Instrument BinAST files for fuzzing as we have a fuzzing target for BinAST.
if CONFIG['FUZZING_INTERFACES'] and CONFIG['LIBFUZZER']:
SOURCES['frontend/BinSource.cpp'].flags += ['-fsanitize-coverage=trace-pc-guard']
SOURCES['frontend/BinToken.cpp'].flags += ['-fsanitize-coverage=trace-pc-guard']
SOURCES['frontend/BinTokenReaderTester.cpp'].flags += ['-fsanitize-coverage=trace-pc-guard']
SOURCES['frontend/BinSource.cpp'].flags += libfuzzer_flags_cmp
SOURCES['frontend/BinToken.cpp'].flags += libfuzzer_flags_cmp
SOURCES['frontend/BinTokenReaderTester.cpp'].flags += libfuzzer_flags_cmp
# Wasm code should use WASM_HUGE_MEMORY instead of JS_CODEGEN_X64
# so that it is easy to use the huge-mapping optimization for other

Просмотреть файл

@ -21,16 +21,6 @@ GetFunctionNameBytes(JSContext* cx, JSFunction* fun, JSAutoByteString* bytes)
return js_anonymous_str;
}
static inline JSObject*
SkipEnvironmentObjects(JSObject* env)
{
if (!env)
return nullptr;
while (env->is<EnvironmentObject>())
env = &env->as<EnvironmentObject>().enclosingEnvironment();
return env;
}
inline bool
CanReuseFunctionForClone(JSContext* cx, HandleFunction fun)
{
@ -68,7 +58,6 @@ CloneFunctionObjectIfNotSingleton(JSContext* cx, HandleFunction fun, HandleObjec
* the function's script.
*/
if (CanReuseFunctionForClone(cx, fun)) {
RootedObject obj(cx, SkipEnvironmentObjects(parent));
ObjectOpResult succeeded;
if (proto && !SetPrototype(cx, fun, proto, succeeded))
return nullptr;

Просмотреть файл

@ -2033,6 +2033,16 @@ js::NewScriptedFunction(JSContext* cx, unsigned nargs,
}
#ifdef DEBUG
static JSObject*
SkipEnvironmentObjects(JSObject* env)
{
if (!env)
return nullptr;
while (env->is<EnvironmentObject>())
env = &env->as<EnvironmentObject>().enclosingEnvironment();
return env;
}
static bool
NewFunctionEnvironmentIsWellFormed(JSContext* cx, HandleObject env)
{
@ -2137,7 +2147,17 @@ NewFunctionClone(JSContext* cx, HandleFunction fun, NewObjectKind newKind,
return nullptr;
RootedFunction clone(cx, &cloneobj->as<JSFunction>());
uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
// JSFunction::HAS_INFERRED_NAME can be set at compile-time and at
// runtime. In the latter case we should actually clear the flag before
// cloning the function, but since we can't differentiate between both
// cases here, we'll end up with a momentarily incorrect function name.
// This will be fixed up in SetFunctionNameIfNoOwnName(), which should
// happen through JSOP_SETFUNNAME directly after JSOP_LAMBDA.
constexpr uint16_t NonCloneableFlags = JSFunction::EXTENDED |
JSFunction::RESOLVED_LENGTH |
JSFunction::RESOLVED_NAME;
uint16_t flags = fun->flags() & ~NonCloneableFlags;
if (allocKind == AllocKind::FUNCTION_EXTENDED)
flags |= JSFunction::EXTENDED;
@ -2311,6 +2331,31 @@ SymbolToFunctionName(JSContext* cx, JS::Symbol* symbol, FunctionPrefixKind prefi
return sb.finishAtom();
}
static JSAtom*
NameToFunctionName(JSContext* cx, HandleValue name, FunctionPrefixKind prefixKind)
{
MOZ_ASSERT(name.isString() || name.isNumber());
if (prefixKind == FunctionPrefixKind::None)
return ToAtom<CanGC>(cx, name);
JSString* nameStr = ToString(cx, name);
if (!nameStr)
return nullptr;
StringBuffer sb(cx);
if (prefixKind == FunctionPrefixKind::Get) {
if (!sb.append("get "))
return nullptr;
} else {
if (!sb.append("set "))
return nullptr;
}
if (!sb.append(nameStr))
return nullptr;
return sb.finishAtom();
}
/*
* Return an atom for use as the name of a builtin method with the given
* property id.
@ -2325,6 +2370,8 @@ JSAtom*
js::IdToFunctionName(JSContext* cx, HandleId id,
FunctionPrefixKind prefixKind /* = FunctionPrefixKind::None */)
{
MOZ_ASSERT(JSID_IS_STRING(id) || JSID_IS_SYMBOL(id) || JSID_IS_INT(id));
// No prefix fastpath.
if (JSID_IS_ATOM(id) && prefixKind == FunctionPrefixKind::None)
return JSID_TO_ATOM(id);
@ -2335,33 +2382,9 @@ js::IdToFunctionName(JSContext* cx, HandleId id,
if (JSID_IS_SYMBOL(id))
return SymbolToFunctionName(cx, JSID_TO_SYMBOL(id), prefixKind);
RootedValue idv(cx, IdToValue(id));
RootedAtom name(cx, ToAtom<CanGC>(cx, idv));
if (!name)
return nullptr;
// Step 5.
return NameToFunctionName(cx, name, prefixKind);
}
JSAtom*
js::NameToFunctionName(JSContext* cx, HandleAtom name,
FunctionPrefixKind prefixKind /* = FunctionPrefixKind::None */)
{
if (prefixKind == FunctionPrefixKind::None)
return name;
StringBuffer sb(cx);
if (prefixKind == FunctionPrefixKind::Get) {
if (!sb.append("get "))
return nullptr;
} else {
if (!sb.append("set "))
return nullptr;
}
if (!sb.append(name))
return nullptr;
return sb.finishAtom();
RootedValue idv(cx, IdToValue(id));
return NameToFunctionName(cx, idv, prefixKind);
}
bool
@ -2370,6 +2393,14 @@ js::SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue na
{
MOZ_ASSERT(name.isString() || name.isSymbol() || name.isNumber());
// An inferred name may already be set if this function is a clone of a
// singleton function. Clear the inferred name in all cases, even if we
// end up not adding a new inferred name if |fun| is a class constructor.
if (fun->hasInferredName()) {
MOZ_ASSERT(fun->isSingleton());
fun->clearInferredName();
}
if (fun->isClassConstructor()) {
// A class may have static 'name' method or accessor.
if (fun->contains(cx, cx->names().name))
@ -2379,20 +2410,20 @@ js::SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue na
MOZ_ASSERT(!fun->containsPure(cx->names().name));
}
JSAtom* funNameAtom;
if (name.isSymbol()) {
funNameAtom = SymbolToFunctionName(cx, name.toSymbol(), prefixKind);
} else {
RootedAtom nameAtom(cx, ToAtom<CanGC>(cx, name));
if (!nameAtom)
return false;
funNameAtom = NameToFunctionName(cx, nameAtom, prefixKind);
}
if (!funNameAtom)
JSAtom* funName = name.isSymbol()
? SymbolToFunctionName(cx, name.toSymbol(), prefixKind)
: NameToFunctionName(cx, name, prefixKind);
if (!funName)
return false;
// RESOLVED_NAME shouldn't yet be set, at least as long as we don't
// support the "static public fields" or "decorators" proposal.
// These two proposals allow to access class constructors before
// JSOP_SETFUNNAME is executed, which means user code may have set the
// RESOLVED_NAME flag when we reach this point.
MOZ_ASSERT(!fun->hasResolvedName());
fun->setInferredName(funNameAtom);
fun->setInferredName(funName);
return true;
}

Просмотреть файл

@ -61,7 +61,8 @@ class JSFunction : public js::NativeObject
BOUND_FUN = 0x0008, /* function was created with Function.prototype.bind. */
WASM_OPTIMIZED = 0x0010, /* asm.js/wasm function that has a jit entry */
HAS_GUESSED_ATOM = 0x0020, /* function had no explicit name, but a
name was guessed for it anyway */
name was guessed for it anyway. See
atom_ for more info about this flag. */
HAS_BOUND_FUNCTION_NAME_PREFIX = 0x0020, /* bound functions reuse the HAS_GUESSED_ATOM
flag to track if atom_ already contains the
"bound " function name prefix */
@ -72,7 +73,8 @@ class JSFunction : public js::NativeObject
decompilable nor constructible. */
HAS_INFERRED_NAME = 0x0100, /* function had no explicit name, but a name was
set by SetFunctionName at compile time or
SetFunctionNameIfNoOwnName at runtime. */
SetFunctionNameIfNoOwnName at runtime. See
atom_ for more info about this flag. */
INTERPRETED_LAZY = 0x0200, /* function is interpreted but doesn't have a script yet */
RESOLVED_LENGTH = 0x0400, /* f.length has been resolved (see fun_resolve). */
RESOLVED_NAME = 0x0800, /* f.name has been resolved (see fun_resolve). */
@ -141,7 +143,42 @@ class JSFunction : public js::NativeObject
} s;
} scripted;
} u;
js::GCPtrAtom atom_; /* name for diagnostics and decompiling */
// The |atom_| field can have different meanings depending on the function
// type and flags. It is used for diagnostics, decompiling, and
//
// 1. If the function is not a bound function:
// a. If HAS_GUESSED_ATOM is not set, to store the initial value of the
// "name" property of functions. But also see RESOLVED_NAME.
// b. If HAS_GUESSED_ATOM is set, |atom_| is only used for diagnostics,
// but must not be used for the "name" property.
// c. If HAS_INFERRED_NAME is set, the function wasn't given an explicit
// name in the source text, e.g. |function fn(){}|, but instead it
// was inferred based on how the function was defined in the source
// text. The exact name inference rules are defined in the ECMAScript
// specification.
// Name inference can happen at compile-time, for example in
// |var fn = function(){}|, or it can happen at runtime, for example
// in |var o = {[Symbol.iterator]: function(){}}|. When it happens at
// compile-time, the HAS_INFERRED_NAME is set directly in the
// bytecode emitter, when it happens at runtime, the flag is set when
// evaluating the JSOP_SETFUNNAME bytecode.
// d. HAS_GUESSED_ATOM and HAS_INFERRED_NAME cannot both be set.
// e. |atom_| can be null if neither an explicit, nor inferred, nor a
// guessed name was set.
// f. HAS_INFERRED_NAME can be set for cloned singleton function, even
// though the clone shouldn't receive an inferred name. See the
// comments in NewFunctionClone() and SetFunctionNameIfNoOwnName()
// for details.
//
// 2. If the function is a bound function:
// a. To store the initial value of the "name" property.
// b. If HAS_BOUND_FUNCTION_NAME_PREFIX is not set, |atom_| doesn't
// contain the "bound " prefix which is prepended to the "name"
// property of bound functions per ECMAScript.
// c. Bound functions can never have an inferred or guessed name.
// d. |atom_| is never null for bound functions.
js::GCPtrAtom atom_;
public:
/* Call objects must be created for each invocation of this function. */
@ -804,10 +841,6 @@ extern JSAtom*
IdToFunctionName(JSContext* cx, HandleId id,
FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
extern JSAtom*
NameToFunctionName(JSContext* cx, HandleAtom name,
FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
extern bool
SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue name,
FunctionPrefixKind prefixKind);

Просмотреть файл

@ -2382,7 +2382,6 @@ js::SharedScriptData::new_(JSContext* cx, uint32_t codeLength,
entry->codeLength_ = codeLength;
entry->noteLength_ = srcnotesLength;
/*
* Call constructors to initialize the storage that will be accessed as a
* GCPtrAtom array via atoms().
@ -2399,6 +2398,20 @@ js::SharedScriptData::new_(JSContext* cx, uint32_t codeLength,
return entry;
}
inline
js::ScriptBytecodeHasher::Lookup::Lookup(SharedScriptData* data)
: scriptData(data),
hash(mozilla::HashBytes(scriptData->data(), scriptData->dataLength()))
{
scriptData->incRefCount();
}
inline
js::ScriptBytecodeHasher::Lookup::~Lookup()
{
scriptData->decRefCount();
}
bool
JSScript::createScriptData(JSContext* cx, uint32_t codeLength, uint32_t srcnotesLength,
uint32_t natoms)
@ -2415,7 +2428,6 @@ JSScript::createScriptData(JSContext* cx, uint32_t codeLength, uint32_t srcnotes
void
JSScript::freeScriptData()
{
MOZ_ASSERT(scriptData_->refCount() == 1);
scriptData_->decRefCount();
scriptData_ = nullptr;
}
@ -2441,9 +2453,13 @@ JSScript::shareScriptData(JSContext* cx)
MOZ_ASSERT(ssd);
MOZ_ASSERT(ssd->refCount() == 1);
// Calculate the hash before taking the lock. Because the data is reference
// counted, it also will be freed after releasing the lock if necessary.
ScriptBytecodeHasher::Lookup lookup(ssd);
AutoLockScriptData lock(cx->runtime());
ScriptDataTable::AddPtr p = cx->scriptDataTable(lock).lookupForAdd(*ssd);
ScriptDataTable::AddPtr p = cx->scriptDataTable(lock).lookupForAdd(lookup);
if (p) {
MOZ_ASSERT(ssd != *p);
freeScriptData();

Просмотреть файл

@ -856,19 +856,29 @@ class SharedScriptData
struct ScriptBytecodeHasher
{
typedef SharedScriptData Lookup;
class Lookup {
friend struct ScriptBytecodeHasher;
SharedScriptData* scriptData;
HashNumber hash;
public:
explicit Lookup(SharedScriptData* data);
~Lookup();
};
static HashNumber hash(const Lookup& l) {
return mozilla::HashBytes(l.data(), l.dataLength());
return l.hash;
}
static bool match(SharedScriptData* entry, const Lookup& lookup) {
if (entry->natoms() != lookup.natoms())
const SharedScriptData* data = lookup.scriptData;
if (entry->natoms() != data->natoms())
return false;
if (entry->codeLength() != lookup.codeLength())
if (entry->codeLength() != data->codeLength())
return false;
if (entry->numNotes() != lookup.numNotes())
if (entry->numNotes() != data->numNotes())
return false;
return mozilla::PodEqual<uint8_t>(entry->data(), lookup.data(), lookup.dataLength());
return mozilla::PodEqual<uint8_t>(entry->data(), data->data(), data->dataLength());
}
};

Просмотреть файл

@ -9,17 +9,20 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Casting.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/DebugOnly.h"
#include "gc/Marking.h"
#include "js/Value.h"
#include "vm/Debugger.h"
#include "vm/TypedArrayObject.h"
#include "vm/UnboxedObject.h"
#include "gc/Nursery-inl.h"
#include "vm/ArrayObject-inl.h"
#include "vm/EnvironmentObject-inl.h"
#include "vm/JSObject-inl.h"
#include "vm/Shape-inl.h"
#include "vm/UnboxedObject-inl.h"
using namespace js;
@ -1498,8 +1501,8 @@ AddOrChangeProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
return CallAddPropertyHook(cx, obj, id, desc.value());
}
// Version of AddOrChangeProperty optimized for adding a plain data property.
// This function doesn't handle integer ids as we may have to store them in
// Versions of AddOrChangeProperty optimized for adding a plain data property.
// These function doesn't handle integer ids as we may have to store them in
// dense elements.
static MOZ_ALWAYS_INLINE bool
AddDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v)
@ -1518,6 +1521,24 @@ AddDataProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue
return CallAddPropertyHook(cx, obj, id, v);
}
static MOZ_ALWAYS_INLINE bool
AddDataPropertyNonDelegate(JSContext* cx, HandlePlainObject obj, HandleId id, HandleValue v)
{
MOZ_ASSERT(!JSID_IS_INT(id));
MOZ_ASSERT(!obj->isDelegate());
// If we know this is a new property we can call addProperty instead of
// the slower putProperty.
Shape* shape = NativeObject::addEnumerableDataProperty(cx, obj, id);
if (!shape)
return false;
UpdateShapeTypeAndValueForWritableDataProp(cx, obj, shape, id, v);
MOZ_ASSERT(!obj->getClass()->getAddProperty());
return true;
}
static bool IsConfigurable(unsigned attrs) { return (attrs & JSPROP_PERMANENT) == 0; }
static bool IsEnumerable(unsigned attrs) { return (attrs & JSPROP_ENUMERATE) != 0; }
static bool IsWritable(unsigned attrs) { return (attrs & JSPROP_READONLY) == 0; }
@ -2895,3 +2916,143 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
return SuppressDeletedProperty(cx, obj, id);
}
bool
js::CopyDataPropertiesNative(JSContext* cx, HandlePlainObject target, HandleNativeObject from,
HandlePlainObject excludedItems, bool* optimized)
{
MOZ_ASSERT(!target->isDelegate(),
"CopyDataPropertiesNative should only be called during object literal construction"
"which precludes that |target| is the prototype of any other object");
*optimized = false;
// Don't use the fast path if |from| may have extra indexed or lazy
// properties.
if (from->getDenseInitializedLength() > 0 ||
from->isIndexed() ||
from->is<TypedArrayObject>() ||
from->getClass()->getNewEnumerate() ||
from->getClass()->getEnumerate())
{
return true;
}
// Collect all enumerable data properties.
using ShapeVector = GCVector<Shape*, 8>;
Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
RootedShape fromShape(cx, from->lastProperty());
for (Shape::Range<NoGC> r(fromShape); !r.empty(); r.popFront()) {
Shape* shape = &r.front();
jsid id = shape->propid();
MOZ_ASSERT(!JSID_IS_INT(id));
if (!shape->enumerable())
continue;
if (excludedItems && excludedItems->contains(cx, id))
continue;
// Don't use the fast path if |from| contains non-data properties.
//
// This enables two optimizations:
// 1. We don't need to handle the case when accessors modify |from|.
// 2. String and symbol properties can be added in one go.
if (!shape->isDataProperty())
return true;
if (!shapes.append(shape))
return false;
}
*optimized = true;
// If |target| contains no own properties, we can directly call
// addProperty instead of the slower putProperty.
const bool targetHadNoOwnProperties = target->lastProperty()->isEmptyShape();
RootedId key(cx);
RootedValue value(cx);
for (size_t i = shapes.length(); i > 0; i--) {
Shape* shape = shapes[i - 1];
MOZ_ASSERT(shape->isDataProperty());
MOZ_ASSERT(shape->enumerable());
key = shape->propid();
MOZ_ASSERT(!JSID_IS_INT(key));
MOZ_ASSERT(from->isNative());
MOZ_ASSERT(from->lastProperty() == fromShape);
value = from->getSlot(shape->slot());
if (targetHadNoOwnProperties) {
MOZ_ASSERT(!target->contains(cx, key),
"didn't expect to find an existing property");
if (!AddDataPropertyNonDelegate(cx, target, key, value))
return false;
} else {
if (!NativeDefineDataProperty(cx, target, key, value, JSPROP_ENUMERATE))
return false;
}
}
return true;
}
bool
js::CopyDataPropertiesNative(JSContext* cx, HandlePlainObject target,
Handle<UnboxedPlainObject*> from, HandlePlainObject excludedItems,
bool* optimized)
{
MOZ_ASSERT(!target->isDelegate(),
"CopyDataPropertiesNative should only be called during object literal construction"
"which precludes that |target| is the prototype of any other object");
*optimized = false;
// Don't use the fast path for unboxed objects with expandos.
if (from->maybeExpando())
return true;
*optimized = true;
// If |target| contains no own properties, we can directly call
// addProperty instead of the slower putProperty.
const bool targetHadNoOwnProperties = target->lastProperty()->isEmptyShape();
#ifdef DEBUG
RootedObjectGroup fromGroup(cx, from->group());
#endif
RootedId key(cx);
RootedValue value(cx);
const UnboxedLayout& layout = from->layout();
for (size_t i = 0; i < layout.properties().length(); i++) {
const UnboxedLayout::Property& property = layout.properties()[i];
key = NameToId(property.name);
MOZ_ASSERT(!JSID_IS_INT(key));
if (excludedItems && excludedItems->contains(cx, key))
continue;
// Ensure the object stays unboxed.
MOZ_ASSERT(from->group() == fromGroup);
// All unboxed properties are enumerable.
value = from->getValue(property);
if (targetHadNoOwnProperties) {
MOZ_ASSERT(!target->contains(cx, key),
"didn't expect to find an existing property");
if (!AddDataPropertyNonDelegate(cx, target, key, value))
return false;
} else {
if (!NativeDefineDataProperty(cx, target, key, value, JSPROP_ENUMERATE))
return false;
}
}
return true;
}

Просмотреть файл

@ -29,6 +29,7 @@ namespace js {
class Shape;
class TenuringTracer;
class UnboxedPlainObject;
/*
* To really poison a set of values, using 'magic' or 'undefined' isn't good
@ -1607,6 +1608,16 @@ bool IsPackedArray(JSObject* obj);
extern void
AddPropertyTypesAfterProtoChange(JSContext* cx, NativeObject* obj, ObjectGroup* oldGroup);
// Specializations of 7.3.23 CopyDataProperties(...) for NativeObjects.
extern bool
CopyDataPropertiesNative(JSContext* cx, HandlePlainObject target, HandleNativeObject from,
HandlePlainObject excludedItems, bool* optimized);
extern bool
CopyDataPropertiesNative(JSContext* cx, HandlePlainObject target,
Handle<UnboxedPlainObject*> from, HandlePlainObject excludedItems,
bool* optimized);
} // namespace js

Просмотреть файл

@ -262,17 +262,6 @@ intrinsic_SubstringKernel(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_OwnPropertyKeys(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
MOZ_ASSERT(args[0].isObject());
RootedObject obj(cx, &args[0].toObject());
return GetOwnPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
args.rval());
}
static void
ThrowErrorWithType(JSContext* cx, JSExnType type, const CallArgs& args)
{
@ -2159,6 +2148,59 @@ intrinsic_PromiseResolve(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_CopyDataPropertiesOrGetOwnKeys(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 3);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[1].isObject());
MOZ_ASSERT(args[2].isObjectOrNull());
RootedObject target(cx, &args[0].toObject());
RootedObject from(cx, &args[1].toObject());
RootedObject excludedItems(cx, args[2].toObjectOrNull());
if (from->isNative() &&
target->is<PlainObject>() &&
(!excludedItems || excludedItems->is<PlainObject>()))
{
bool optimized;
if (!CopyDataPropertiesNative(cx, target.as<PlainObject>(), from.as<NativeObject>(),
(excludedItems ? excludedItems.as<PlainObject>() : nullptr),
&optimized))
{
return false;
}
if (optimized) {
args.rval().setNull();
return true;
}
}
if (from->is<UnboxedPlainObject>() &&
target->is<PlainObject>() &&
(!excludedItems || excludedItems->is<PlainObject>()))
{
bool optimized;
if (!CopyDataPropertiesNative(cx, target.as<PlainObject>(), from.as<UnboxedPlainObject>(),
(excludedItems ? excludedItems.as<PlainObject>() : nullptr),
&optimized))
{
return false;
}
if (optimized) {
args.rval().setNull();
return true;
}
}
return GetOwnPropertyKeys(cx, from, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS,
args.rval());
}
// The self-hosting global isn't initialized with the normal set of builtins.
// Instead, individual C++-implemented functions that're required by
// self-hosted code are defined as global functions. Accessing these
@ -2205,6 +2247,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("std_Reflect_getPrototypeOf", Reflect_getPrototypeOf, 1,0,
ReflectGetPrototypeOf),
JS_FN("std_Reflect_isExtensible", Reflect_isExtensible, 1,0),
JS_FN("std_Reflect_ownKeys", Reflect_ownKeys, 1,0),
JS_FN("std_Set_has", SetObject::has, 1,0),
JS_FN("std_Set_iterator", SetObject::values, 0,0),
@ -2272,7 +2315,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("CreateModuleSyntaxError", intrinsic_CreateModuleSyntaxError, 4,0),
JS_FN("AssertionFailed", intrinsic_AssertionFailed, 1,0),
JS_FN("DumpMessage", intrinsic_DumpMessage, 1,0),
JS_FN("OwnPropertyKeys", intrinsic_OwnPropertyKeys, 1,0),
JS_FN("MakeDefaultConstructor", intrinsic_MakeDefaultConstructor, 2,0),
JS_FN("_ConstructorForTypedArray", intrinsic_ConstructorForTypedArray, 1,0),
JS_FN("_NameForTypedArray", intrinsic_NameForTypedArray, 1,0),
@ -2284,6 +2326,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_FN("AddContentTelemetry", intrinsic_AddContentTelemetry, 2,0),
JS_FN("_DefineDataProperty", intrinsic_DefineDataProperty, 4,0),
JS_FN("_DefineProperty", intrinsic_DefineProperty, 6,0),
JS_FN("CopyDataPropertiesOrGetOwnKeys", intrinsic_CopyDataPropertiesOrGetOwnKeys, 3,0),
JS_INLINABLE_FN("_IsConstructing", intrinsic_IsConstructing, 0,0,
IntrinsicIsConstructing),

Просмотреть файл

@ -1102,21 +1102,40 @@ JSStructuredCloneWriter::parseTransferable()
return reportDataCloneError(JS_SCERR_TRANSFERABLE);
tObj = &v.toObject();
RootedObject unwrappedObj(cx, CheckedUnwrap(tObj));
if (!unwrappedObj) {
ReportAccessDenied(cx);
return false;
}
// Shared memory cannot be transferred because it is not possible (nor
// desirable) to detach the memory in agents that already hold a
// reference to it.
if (tObj->is<SharedArrayBufferObject>())
if (unwrappedObj->is<SharedArrayBufferObject>())
return reportDataCloneError(JS_SCERR_SHMEM_TRANSFERABLE);
if (tObj->is<WasmMemoryObject>() && tObj->as<WasmMemoryObject>().isShared())
return reportDataCloneError(JS_SCERR_SHMEM_TRANSFERABLE);
else if (unwrappedObj->is<WasmMemoryObject>()) {
if (unwrappedObj->as<WasmMemoryObject>().isShared())
return reportDataCloneError(JS_SCERR_SHMEM_TRANSFERABLE);
}
// External array buffers may be able to be transferred in the future,
// but that is not currently implemented.
if (tObj->is<ArrayBufferObject>() && tObj->as<ArrayBufferObject>().isExternal())
return reportDataCloneError(JS_SCERR_TRANSFERABLE);
else if (unwrappedObj->is<ArrayBufferObject>()) {
if (unwrappedObj->as<ArrayBufferObject>().isExternal())
return reportDataCloneError(JS_SCERR_TRANSFERABLE);
}
else {
if (!callbacks || !callbacks->canTransfer)
return reportDataCloneError(JS_SCERR_TRANSFERABLE);
JSAutoCompartment ac(cx, unwrappedObj);
if (!callbacks->canTransfer(cx, unwrappedObj, closure))
return false;
}
// No duplicates allowed
auto p = transferableObjects.lookupForAdd(tObj);
@ -1686,6 +1705,12 @@ JSStructuredCloneWriter::transferOwnership()
// lend itself well to generic manipulation via proxies.
Rooted<ArrayBufferObject*> arrayBuffer(cx, &CheckedUnwrap(obj)->as<ArrayBufferObject>());
JSAutoCompartment ac(cx, arrayBuffer);
if (arrayBuffer->isDetached()) {
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
return false;
}
size_t nbytes = arrayBuffer->byteLength();
if (arrayBuffer->isWasm() || arrayBuffer->isPreparedForAsmJS()) {

Просмотреть файл

@ -7992,28 +7992,31 @@ BaseCompiler::emitSetGlobal()
const GlobalDesc& global = env_.globals[id];
ScratchI32 tmp(*this);
switch (global.type()) {
case ValType::I32: {
RegI32 rv = popI32();
ScratchI32 tmp(*this);
masm.store32(rv, addressOfGlobalVar(global, tmp));
freeI32(rv);
break;
}
case ValType::I64: {
RegI64 rv = popI64();
ScratchI32 tmp(*this);
masm.store64(rv, addressOfGlobalVar(global, tmp));
freeI64(rv);
break;
}
case ValType::F32: {
RegF32 rv = popF32();
ScratchI32 tmp(*this);
masm.storeFloat32(rv, addressOfGlobalVar(global, tmp));
freeF32(rv);
break;
}
case ValType::F64: {
RegF64 rv = popF64();
ScratchI32 tmp(*this);
masm.storeDouble(rv, addressOfGlobalVar(global, tmp));
freeF64(rv);
break;

Просмотреть файл

@ -23,7 +23,8 @@
*
* CSS_NON_INHERITING_ANON_BOX is used for anon boxes that never inherit style
* from anything. This means all their property values are the initial values
* of those properties.
* of those properties. These ones must come first! Code relies on this.
* If this macro is not defined, it will default to CSS_ANON_BOX.
*
* CSS_WRAPPER_ANON_BOX is used for anon boxes that are used as wrappers around
* other frames during frametree fixup (e.g. table anonymous boxes, ruby
@ -51,13 +52,33 @@
# define DEFINED_CSS_WRAPPER_ANON_BOX
#endif /* CSS_WRAPPER_ANON_BOX */
// ::-moz-text, ::-moz-oof-placeholder, and ::-moz-first-letter-continuation are
// non-elements which no rule will match.
CSS_ANON_BOX(mozText, ":-moz-text")
// placeholder frames for out of flows. Note that :-moz-placeholder is used for
//---------------------------------------------------------------------------
// Non-inheriting ones, which must come first
//---------------------------------------------------------------------------
// Placeholder frames for out of flows. Note that :-moz-placeholder is used for
// the pseudo-element that represents the placeholder text in <input
// placeholder="foo">, so we need a different string here.
CSS_NON_INHERITING_ANON_BOX(oofPlaceholder, ":-moz-oof-placeholder")
// Framesets
CSS_NON_INHERITING_ANON_BOX(horizontalFramesetBorder, ":-moz-hframeset-border")
CSS_NON_INHERITING_ANON_BOX(verticalFramesetBorder, ":-moz-vframeset-border")
CSS_NON_INHERITING_ANON_BOX(framesetBlank, ":-moz-frameset-blank")
CSS_NON_INHERITING_ANON_BOX(tableColGroup, ":-moz-table-column-group")
CSS_NON_INHERITING_ANON_BOX(tableCol, ":-moz-table-column")
CSS_NON_INHERITING_ANON_BOX(pageBreak, ":-moz-pagebreak")
//---------------------------------------------------------------------------
// Other ones
//---------------------------------------------------------------------------
// ::-moz-text, ::-moz-oof-placeholder, and ::-moz-first-letter-continuation are
// non-elements which no rule will match.
CSS_ANON_BOX(mozText, ":-moz-text")
// nsFirstLetterFrames for content outside the ::first-letter.
CSS_ANON_BOX(firstLetterContinuation, ":-moz-first-letter-continuation")
@ -65,31 +86,23 @@ CSS_ANON_BOX(mozBlockInsideInlineWrapper, ":-moz-block-inside-inline-wrapper")
CSS_WRAPPER_ANON_BOX(mozMathMLAnonymousBlock, ":-moz-mathml-anonymous-block")
CSS_ANON_BOX(mozXULAnonymousBlock, ":-moz-xul-anonymous-block")
// Framesets
CSS_NON_INHERITING_ANON_BOX(horizontalFramesetBorder, ":-moz-hframeset-border")
CSS_NON_INHERITING_ANON_BOX(verticalFramesetBorder, ":-moz-vframeset-border")
CSS_ANON_BOX(mozLineFrame, ":-moz-line-frame")
CSS_ANON_BOX(buttonContent, ":-moz-button-content")
CSS_ANON_BOX(cellContent, ":-moz-cell-content")
CSS_ANON_BOX(dropDownList, ":-moz-dropdown-list")
CSS_ANON_BOX(fieldsetContent, ":-moz-fieldset-content")
CSS_NON_INHERITING_ANON_BOX(framesetBlank, ":-moz-frameset-blank")
CSS_ANON_BOX(mozDisplayComboboxControlFrame, ":-moz-display-comboboxcontrol-frame")
CSS_ANON_BOX(htmlCanvasContent, ":-moz-html-canvas-content")
CSS_WRAPPER_ANON_BOX(inlineTable, ":-moz-inline-table")
CSS_WRAPPER_ANON_BOX(table, ":-moz-table")
CSS_WRAPPER_ANON_BOX(tableCell, ":-moz-table-cell")
CSS_NON_INHERITING_ANON_BOX(tableColGroup, ":-moz-table-column-group")
CSS_NON_INHERITING_ANON_BOX(tableCol, ":-moz-table-column")
CSS_ANON_BOX(tableWrapper, ":-moz-table-wrapper")
CSS_WRAPPER_ANON_BOX(tableRowGroup, ":-moz-table-row-group")
CSS_WRAPPER_ANON_BOX(tableRow, ":-moz-table-row")
CSS_ANON_BOX(canvas, ":-moz-canvas")
CSS_NON_INHERITING_ANON_BOX(pageBreak, ":-moz-pagebreak")
CSS_ANON_BOX(page, ":-moz-page")
CSS_ANON_BOX(pageContent, ":-moz-pagecontent")
CSS_ANON_BOX(pageSequence, ":-moz-page-sequence")

Просмотреть файл

@ -39,21 +39,12 @@ MOZ_POP_DISABLE_INTEGRAL_CONSTANT_OVERFLOW_WARNING
#undef CSS_ANON_BOX
static const nsStaticAtomSetup sCSSAnonBoxAtomSetup[] = {
// Put the non-inheriting anon boxes first, so we can index into them easily.
#define CSS_ANON_BOX(name_, value_) /* nothing */
#define CSS_NON_INHERITING_ANON_BOX(name_, value_) \
NS_STATIC_ATOM_SUBCLASS_SETUP( \
mozilla::detail::gCSSAnonBoxAtoms, nsCSSAnonBoxes, name_)
#include "nsCSSAnonBoxList.h"
#undef CSS_NON_INHERITING_ANON_BOX
#undef CSS_ANON_BOX
// Non-inheriting boxes must come first in nsCSSAnonBoxList.h so that
// `NonInheriting` values can index into this array and other similar arrays.
#define CSS_ANON_BOX(name_, value_) \
NS_STATIC_ATOM_SUBCLASS_SETUP( \
mozilla::detail::gCSSAnonBoxAtoms, nsCSSAnonBoxes, name_)
#define CSS_NON_INHERITING_ANON_BOX(name_, value_) /* nothing */
#include "nsCSSAnonBoxList.h"
#undef CSS_NON_INHERITING_ANON_BOX
#undef CSS_ANON_BOX
};
@ -86,10 +77,3 @@ nsCSSAnonBoxes::NonInheritingTypeForPseudoTag(nsAtom* aPseudo)
MOZ_RELEASE_ASSERT(index.isSome());
return static_cast<NonInheriting>(*index);
}
/* static */ nsAtom*
nsCSSAnonBoxes::GetNonInheritingPseudoAtom(NonInheriting aBoxType)
{
MOZ_ASSERT(aBoxType < NonInheriting::_Count);
return *sCSSAnonBoxAtomSetup[static_cast<NonInheritingBase>(aBoxType)].mAtomp;
}

Просмотреть файл

@ -118,10 +118,6 @@ public:
// Get the NonInheriting type for a given pseudo tag. The pseudo tag must
// test true for IsNonInheritingAnonBox.
static NonInheriting NonInheritingTypeForPseudoTag(nsAtom* aPseudo);
// Get the atom for a given non-inheriting anon box type. aBoxType must be <
// NonInheriting::_Count.
static nsAtom* GetNonInheritingPseudoAtom(NonInheriting aBoxType);
};
#endif /* nsCSSAnonBoxes_h___ */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше