Merge autoland to mozilla-central a=merge

This commit is contained in:
Andreea Pavel 2020-10-07 18:45:09 +03:00
Родитель 4e78008f2d f56817ceee
Коммит 1015fc2548
590 изменённых файлов: 45353 добавлений и 6881 удалений

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

@ -171,6 +171,13 @@ int32_t HyperTextIterator::NextLinkOffset() {
}
bool HyperTextIterator::Next() {
if (!mCurrentContainer->Document()->HasLoadState(
DocAccessible::eTreeConstructed)) {
// If the accessible tree is still being constructed the text tree
// is not in a traversable state yet.
return false;
}
if (mCurrentContainer == mEndContainer &&
(mCurrentEndOffset == -1 || mEndOffset <= mCurrentEndOffset)) {
return false;
@ -326,7 +333,7 @@ void HyperTextAccessibleWrap::RightWordAt(int32_t aOffset,
int32_t* aEndOffset) {
TextPoint here(this, aOffset);
TextPoint end = FindTextPoint(aOffset, eDirNext, eSelectWord, eEndWord);
if (!end.mContainer || end < here) {
if (!end.mContainer || end < here || here == end) {
// If we didn't find a word end, or if we wrapped around (bug 1652833),
// return with no result.
return;
@ -334,11 +341,8 @@ void HyperTextAccessibleWrap::RightWordAt(int32_t aOffset,
if ((NativeState() & states::EDITABLE) &&
!(end.mContainer->NativeState() & states::EDITABLE)) {
// The word search crossed an editable boundary. Return the last word of the
// editable root.
return EditableRoot()->LeftWordAt(
nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, aStartContainer,
aStartOffset, aEndContainer, aEndOffset);
// The word search crossed an editable boundary. Return with no result.
return;
}
TextPoint start =
@ -506,7 +510,7 @@ Accessible* HyperTextAccessibleWrap::LeafAtOffset(int32_t aOffset) {
}
child = text->GetChildAt(childIdx);
if (!child || nsAccUtils::MustPrune(child)) {
if (!child || nsAccUtils::MustPrune(text)) {
return text;
}
@ -566,7 +570,19 @@ TextPoint HyperTextAccessibleWrap::FindTextPoint(
}
}
int32_t childOffset = text->GetChildOffset(childIdx);
if (child->IsHyperText() && aDirection == eDirPrevious && childIdx > 0 &&
innerOffset - childOffset == 0) {
// If we are searching backwards, and this is the begining of a
// segment, get the previous sibling so that layout will start
// its search there.
childIdx--;
innerOffset -= text->GetChildOffset(childIdx);
child = text->GetChildAt(childIdx);
} else {
innerOffset -= childOffset;
}
text = child->AsHyperText();
} while (text);

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

@ -100,23 +100,6 @@ static nsDataHashtable<nsUint64HashKey, MOXTextMarkerDelegate*> sDelegates;
}
- (NSString*)moxStringForTextMarkerRange:(id)textMarkerRange {
if (mGeckoDocAccessible.IsAccessible()) {
if (!mGeckoDocAccessible.AsAccessible()->AsDoc()->HasLoadState(
DocAccessible::eTreeConstructed)) {
// If the accessible tree is still being constructed the text tree
// is not in a traversable state yet.
return @"";
}
} else {
if (mGeckoDocAccessible.AsProxy()->State() & states::STALE) {
// In the proxy case we don't have access to load state,
// so we need to use the less granular generic STALE state
// this state also includes DOM unloaded, which isn't ideal.
// Since we really only care if the a11y tree is loaded.
return @"";
}
}
mozilla::a11y::GeckoTextMarkerRange range(mGeckoDocAccessible,
textMarkerRange);
if (!range.IsValid()) {

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

@ -15,7 +15,7 @@
</ul>
<ul style="list-style: none;"><li>Do not order the Skip's Scramble</li></ul>
<p style="width: 1rem">These are my awards, Mother. From Army.</p>
<p>I deceived you, <input> mom.</p>
<p>I <input value="deceived you">, mom.</p>
<script>
"use strict";
window.EXPECTED = [
@ -1915,153 +1915,106 @@
lines: ["Army.", "Army.", "I deceived you, mom."],
words: ["Army.", ""],
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
{ style: "I deceived you, ",
{ style: "I ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["I", " "],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXStaticText", "I "] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: [" ", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", "deceived"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["deceived", " "],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: [" ", "you"],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["you", "you"],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["deceived you", "deceived you", "deceived you"],
words: ["you", "you"],
element: ["AXTextField", "deceived you"] },
{ style: "deceived you",
paragraph: "deceived you",
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["you", ""],
element: ["AXTextField", "deceived you"] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: [" ", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: [",", " "],
element: ["AXStaticText", ", mom."] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: ["you,", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: [", ", "mom."],
element: ["AXStaticText", ", mom."] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: ["you,", "you,"],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: ["you,", "you, mom."],
element: ["AXStaticText", "I deceived you, "] },
{ style: "I deceived you, ",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: ["you,", " "],
element: ["AXStaticText", "I deceived you, "] },
{ style: "",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: [" ", " "],
element: ["AXTextField", ""] },
{ style: " mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
words: [" ", "mom."],
element: ["AXStaticText", " mom."] },
{ style: " mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ style: " mom.",
element: ["AXStaticText", ", mom."] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ style: " mom.",
element: ["AXStaticText", ", mom."] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["mom.", "mom."],
element: ["AXStaticText", " mom."] },
{ style: " mom.",
element: ["AXStaticText", ", mom."] },
{ style: ", mom.",
paragraph: "I deceived you, mom.",
lines: ["I deceived you, mom.",
"I deceived you, mom.",
"I deceived you, mom."],
lines: ["I deceived you, mom.", "I deceived you, mom.", "I deceived you, mom."],
words: ["mom.", ""],
element: ["AXStaticText", " mom."] }];
element: ["AXStaticText", ", mom."] }];
</script>
</body>
</html>

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

@ -75,7 +75,7 @@ skip-if = !e10s # Test only relevant for e10s.
skip-if = (debug && os == 'linux' && bits == 32) #Bug 1455882, disabled on Linux32 for almost permafailing
support-files = file_new_tab_page.html
[browser_new_tab_in_privilegedabout_process_pref.js]
skip-if = !e10s || (os == 'linux' && debug && bits == 64) # Pref and test only relevant for e10s, Bug 1581500.
skip-if = !e10s || (os == 'linux' && debug && bits == 64) || fission # Pref and test only relevant for e10s, Bug 1581500. Bug 1668809
[browser_privilegedmozilla_process_pref.js]
skip-if = !e10s || fission # Pref and test only relevant for e10s.
[browser_newwindow_tabstrip_overflow.js]

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

@ -10084,7 +10084,6 @@ Gecko_IsDocumentBody
?StripTrackingIdentifiers@URLDecorationStripper@mozilla@@SA?AW4nsresult@@PAVnsIURI@@AAV?$nsTSubstring@D@@@Z
??1gfxWindowsNativeDrawing@@QAE@XZ
?RecvAddChild@SHEntryParent@dom@mozilla@@AAE_NPAVPSHEntryParent@23@ABHAB_NPAW4nsresult@@@Z
?SetPrintOptionsBits@nsPrintSettings@@UAG?AW4nsresult@@H@Z
?SetRealmPrincipals@JS@@YAXPAVRealm@1@PAUJSPrincipals@@@Z
?MarkAsBroken@nsHtml5TreeOpExecutor@@UAE?AW4nsresult@@W42@@Z
??$AppendElements@UnsTArrayInfallibleAllocator@@@?$nsTArray_Impl@VPrincipalInfo@ipc@mozilla@@UnsTArrayInfallibleAllocator@@@@IAEPAVPrincipalInfo@ipc@mozilla@@I@Z

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

@ -64,7 +64,7 @@ support-files =
!/docshell/test/navigation/blank.html
fail-if = xorigin
[test_bug385434.html]
skip-if = (xorigin && fission) # Hangs, JavaScript error: http://mochi.test:8888/tests/docshell/test/mochitest/test_bug385434.html?currentTestURL=docshell%2Ftest%2Fmochitest%2Ftest_bug385434.html&closeWhenDone=undefined&showTestReport=true&expected=pass, line 132: NS_ERROR_FAILURE:
skip-if = fission # Hangs, JavaScript error: http://mochi.test:8888/tests/docshell/test/mochitest/test_bug385434.html?currentTestURL=docshell%2Ftest%2Fmochitest%2Ftest_bug385434.html&closeWhenDone=undefined&showTestReport=true&expected=pass, line 132: NS_ERROR_FAILURE:; Bug 1668809
[test_bug387979.html]
[test_bug402210.html]
[test_bug404548.html]

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

@ -1196,9 +1196,15 @@ void nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
return;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JSScript*> script(cx);
script = ScriptPreloader::GetChildSingleton().GetCachedScript(cx, url);
JS::CompileOptions options(cx);
ScriptPreloader::FillCompileOptionsForCachedScript(options);
options.setFileAndLine(url.get(), 1);
options.setNonSyntacticScope(true);
JS::Rooted<JSScript*> script(cx);
script =
ScriptPreloader::GetChildSingleton().GetCachedScript(cx, options, url);
if (!script) {
nsCOMPtr<nsIChannel> channel;
@ -1241,11 +1247,6 @@ void nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
return;
}
JS::CompileOptions options(cx);
options.setFileAndLine(url.get(), 1);
options.setNoScriptRval(true);
options.setNonSyntacticScope(true);
script = JS::Compile(cx, options, srcBuf);
if (!script) {
return;

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

@ -273,7 +273,7 @@ nsresult nsJSUtils::ExecutionContext::Decode(
MOZ_ASSERT(!mWantsReturnValue);
JS::TranscodeResult tr = JS::DecodeScriptMaybeStencil(
mCx, aBytecodeBuf, aCompileOptions, &mScript, aBytecodeIndex);
mCx, aCompileOptions, aBytecodeBuf, &mScript, aBytecodeIndex);
// These errors are external parameters which should be handled before the
// decoding phase, and which are the only reasons why you might want to
// fallback on decoding failures.

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

@ -1626,6 +1626,13 @@ nsresult nsXULPrototypeScript::SerializeOutOfLine(
return rv;
}
void nsXULPrototypeScript::FillCompileOptions(JS::CompileOptions& options) {
// If the script was inline, tell the JS parser to save source for
// Function.prototype.toSource(). If it's out of line, we retrieve the
// source from the files on demand.
options.setSourceIsLazy(mOutOfLine);
}
nsresult nsXULPrototypeScript::Deserialize(
nsIObjectInputStream* aStream, nsXULPrototypeDocument* aProtoDoc,
nsIURI* aDocumentURI,
@ -1647,8 +1654,11 @@ nsresult nsXULPrototypeScript::Deserialize(
}
JSContext* cx = jsapi.cx();
JS::CompileOptions options(cx);
FillCompileOptions(options);
JS::Rooted<JSScript*> newScriptObject(cx);
rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx,
rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx, options,
newScriptObject.address());
NS_ENSURE_SUCCESS(rv, rv);
Set(newScriptObject);
@ -1831,12 +1841,10 @@ nsresult nsXULPrototypeScript::Compile(
// Ok, compile it to create a prototype script object!
JS::CompileOptions options(cx);
FillCompileOptions(options);
options.setIntroductionType(mOutOfLine ? "srcScript" : "inlineScript")
.setFileAndLine(urlspec.get(), mOutOfLine ? 1 : aLineNo);
// If the script was inline, tell the JS parser to save source for
// Function.prototype.toSource(). If it's out of line, we retrieve the
// source from the files on demand.
options.setSourceIsLazy(mOutOfLine);
JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx));
if (aOffThreadReceiver && JS::CanCompileOffThread(cx, options, aTextLength)) {

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

@ -12,6 +12,7 @@
#ifndef nsXULElement_h__
#define nsXULElement_h__
#include "js/CompileOptions.h" // JS::CompileOptions
#include "js/SourceText.h"
#include "js/TracingAPI.h"
#include "mozilla/Attributes.h"
@ -185,6 +186,8 @@ class nsXULPrototypeScript : public nsXULPrototypeNode {
private:
virtual ~nsXULPrototypeScript();
void FillCompileOptions(JS::CompileOptions& options);
public:
virtual nsresult Serialize(
nsIObjectOutputStream* aStream, nsXULPrototypeDocument* aProtoDoc,

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

@ -160,46 +160,16 @@ ScaledFontMac::~ScaledFontMac() {
CGFontRelease(mFont);
}
#define TRUETYPE_TAG(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
bool UnscaledFontMac::CheckForColorGlyphs() {
CFArrayRef tags = CGFontCopyTableTags(mFont);
if (!tags) {
return false;
}
bool hasColorGlyphs = false;
int numTags = (int)CFArrayGetCount(tags);
for (int t = 0; t < numTags; t++) {
uint32_t tag = (uint32_t)(uintptr_t)CFArrayGetValueAtIndex(tags, t);
switch (tag) {
case TRUETYPE_TAG('S', 'V', 'G', ' '):
case TRUETYPE_TAG('C', 'O', 'L', 'R'):
case TRUETYPE_TAG('s', 'b', 'i', 'x'):
hasColorGlyphs = true;
break;
}
}
CFRelease(tags);
return hasColorGlyphs;
}
#ifdef USE_SKIA
SkTypeface* ScaledFontMac::CreateSkTypeface() {
// We don't rely upon style information in the mac font backend, so avoid
// letting the backend try to query that information from the CTFont to
// work around potential bugs.
auto unscaledMac = static_cast<UnscaledFontMac*>(GetUnscaledFont().get());
CTFontSymbolicTraits traits =
unscaledMac->HasColorGlyphs() ? kCTFontColorGlyphsTrait : 0;
SkFontStyle noStyle;
if (mCTFont) {
return SkCreateTypefaceFromCTFont(mCTFont, nullptr, &noStyle, &traits);
return SkCreateTypefaceFromCTFont(mCTFont);
} else {
auto unscaledMac = static_cast<UnscaledFontMac*>(GetUnscaledFont().get());
bool dataFont = unscaledMac->IsDataFont();
CTFontRef fontFace =
CreateCTFontFromCGFontWithVariations(mFont, mSize, !dataFont);
SkTypeface* typeface =
SkCreateTypefaceFromCTFont(fontFace, nullptr, &noStyle, &traits);
SkTypeface* typeface = SkCreateTypefaceFromCTFont(fontFace);
CFRelease(fontFace);
return typeface;
}

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

@ -23,15 +23,7 @@ class UnscaledFontMac final : public UnscaledFont {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(UnscaledFontMac, override)
explicit UnscaledFontMac(CGFontRef aFont, bool aIsDataFont = false)
: mFont(aFont),
mIsDataFont(aIsDataFont),
mHasColorGlyphs(CheckForColorGlyphs()) {
CFRetain(mFont);
}
UnscaledFontMac(CGFontRef aFont, bool aIsDataFont, bool aHasColorGlyphs)
: mFont(aFont),
mIsDataFont(aIsDataFont),
mHasColorGlyphs(aHasColorGlyphs) {
: mFont(aFont), mIsDataFont(aIsDataFont) {
CFRetain(mFont);
}
virtual ~UnscaledFontMac() {
@ -49,8 +41,6 @@ class UnscaledFontMac final : public UnscaledFont {
bool IsDataFont() const { return mIsDataFont; }
bool HasColorGlyphs() const { return mHasColorGlyphs; }
already_AddRefed<ScaledFont> CreateScaledFont(
Float aGlyphSize, const uint8_t* aInstanceData,
uint32_t aInstanceDataLength, const FontVariation* aVariations,
@ -74,12 +64,9 @@ class UnscaledFontMac final : public UnscaledFont {
const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex);
private:
bool CheckForColorGlyphs();
CGFontRef mFont;
CFArrayRef mAxesCache = nullptr; // Cached array of variation axis details
bool mIsDataFont;
bool mHasColorGlyphs;
};
} // namespace gfx

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

@ -0,0 +1,69 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0">
<title>Tests that keyboard arrow keys scroll after zooming in when there was no scrollable overflow before zooming</title>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="apz_test_utils.js"></script>
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
</head>
<body>
<div style="height: 20000px; background-color: green"></div>
<script type="application/javascript">
const utils = SpecialPowers.getDOMWindowUtils(window);
function* test(testDriver) {
is(getResolution(), 1.0, "should not be zoomed (1)");
is(window.scrollX, 0, "shouldn't have scrolled (2)");
is(window.scrollY, 0, "shouldn't have scrolled (3)");
is(visualViewport.pageTop, 0, "shouldn't have scrolled (4)");
is(visualViewport.pageLeft, 0, "shouldn't have scrolled (5)");
// Zoom in
SpecialPowers.getDOMWindowUtils(window).setResolutionAndScaleTo(2.0);
yield waitForApzFlushedRepaints(testDriver);
is(getResolution(), 2.0, "should have zoomed (6)");
is(window.scrollX, 0, "shouldn't have scrolled (7)");
is(window.scrollY, 0, "shouldn't have scrolled (8)");
is(visualViewport.pageTop, 0, "shouldn't have scrolled (9)");
is(visualViewport.pageLeft, 0, "shouldn't have scrolled (10)");
window.synthesizeKey("KEY_ArrowRight");
yield waitForApzFlushedRepaints(testDriver);
is(getResolution(), 2.0, "should be zoomed (11)");
is(window.scrollX, 0, "shouldn't have scrolled (12)");
is(window.scrollY, 0, "shouldn't have scrolled (13)");
is(visualViewport.pageTop, 0, "shouldn't have scrolled (14)");
isnot(visualViewport.pageLeft, 0, "should have scrolled (15)");
window.synthesizeKey("KEY_ArrowDown");
yield waitForApzFlushedRepaints(testDriver);
is(getResolution(), 2.0, "should be zoomed (16)");
is(window.scrollX, 0, "shouldn't have scrolled (17)");
is(window.scrollY, 0, "shouldn't have scrolled (18)");
isnot(visualViewport.pageTop, 0, "should have scrolled (19)");
isnot(visualViewport.pageLeft, 0, "should have scrolled (20)");
// Zoom back out
SpecialPowers.getDOMWindowUtils(window).setResolutionAndScaleTo(1.0);
yield waitForApzFlushedRepaints(testDriver);
is(getResolution(), 1.0, "should not be zoomed (21)");
}
waitUntilApzStable().then(runContinuation(test)).then(subtestDone);
</script>
</body>
</html>

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

@ -45,6 +45,7 @@ var subtests = [
{"file": "helper_visual_scrollbars_pagescroll.html", "prefs": prefs},
{"file": "helper_click_interrupt_animation.html", "prefs": prefs},
{"file": "helper_overflowhidden_zoom.html", "prefs": prefs},
{"file": "helper_zoom_keyboardscroll.html", "prefs": prefs},
];
if (isApzEnabled()) {

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

@ -3,12 +3,12 @@
# First make sure that we are actually drawing scrollbars
skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v.html about:blank
skip-if(!asyncPan) pref(apz.allow_zooming,true) != async-scrollbar-1-v-ref.html about:blank
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,7-8,24-32) fuzzy-if(webrender&&cocoaWidget,23-23,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,7-8,24-32) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
fuzzy-if(Android,0-4,0-5) fuzzy-if(webrender&&gtkWidget,28-28,30-32) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
fuzzy-if(Android,0-6,0-6) fuzzy-if(webrender&&gtkWidget,2-2,19-20) fuzzy-if(webrender&&cocoaWidget,18-18,79-79) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,7-8,24-32) fuzzy-if(webrender&&cocoaWidget,23-23,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
fuzzy-if(Android,0-6,0-6) fuzzy-if(webrender&&gtkWidget,2-2,19-20) fuzzy-if(webrender&&cocoaWidget,17-17,88-88) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
fuzzy-if(Android,0-1,0-2) fuzzy-if(webrender&&gtkWidget,7-8,24-32) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
fuzzy-if(Android,0-14,0-5) fuzzy-if(webrender&&gtkWidget,28-28,30-32) fuzzy-if(webrender&&cocoaWidget,22-22,44-44) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
fuzzy-if(Android,0-8,0-8) fuzzy-if(webrender&&gtkWidget,13-13,32-32) fuzzy-if(webrender&&cocoaWidget,18-18,43-43) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
fuzzy-if(Android,0-8,0-8) fuzzy-if(webrender&&gtkWidget,13-13,32-32) fuzzy-if(webrender&&cocoaWidget,17-17,50-50) skip-if(!asyncPan) pref(apz.allow_zooming,true) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
# compositor, the border-radius ends of the scrollthumb are going to be a little

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

@ -276,13 +276,9 @@ static void DestroyDrawTarget(RefPtr<DrawTarget>& aDT,
// An Azure DrawTarget needs to be locked when it gets nullptr'ed as this is
// when it calls EndDraw. This EndDraw should not execute anything so it
// shouldn't -really- need the lock but the debug layer chokes on this.
#ifdef DEBUG
LockD3DTexture(aTexture.get());
#endif
aDT = nullptr;
#ifdef DEBUG
UnlockD3DTexture(aTexture.get());
#endif
aTexture = nullptr;
}

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

@ -31,9 +31,7 @@
* lifetime of the SkTypeface. This was introduced as a means to work around
* https://crbug.com/413332 .
*/
SK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef, CFTypeRef = NULL,
const SkFontStyle* = nullptr,
const CTFontSymbolicTraits* = nullptr);
SK_API extern SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef, CFTypeRef = NULL);
/**
* Returns the platform-specific CTFontRef handle for a

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

@ -699,12 +699,13 @@ static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc, bool from
class SkTypeface_Mac : public SkTypeface {
public:
SkTypeface_Mac(SkUniqueCFRef<CTFontRef> fontRef, SkUniqueCFRef<CFTypeRef> resourceRef,
const SkFontStyle& fs, bool isFixedPitch, bool hasColorGlyphs,
const SkFontStyle& fs, bool isFixedPitch,
std::unique_ptr<SkStreamAsset> providedData)
: SkTypeface(fs, isFixedPitch)
, fFontRef(std::move(fontRef))
, fOriginatingCFTypeRef(std::move(resourceRef))
, fHasColorGlyphs(hasColorGlyphs)
, fHasColorGlyphs(
SkToBool(CTFontGetSymbolicTraits(fFontRef.get()) & kCTFontColorGlyphsTrait))
, fStream(std::move(providedData))
, fIsFromStream(fStream)
{
@ -765,9 +766,7 @@ static bool find_by_CTFontRef(SkTypeface* cached, void* context) {
/** Creates a typeface, searching the cache if isLocalStream is false. */
static sk_sp<SkTypeface> create_from_CTFontRef(SkUniqueCFRef<CTFontRef> font,
SkUniqueCFRef<CFTypeRef> resource,
std::unique_ptr<SkStreamAsset> providedData,
const SkFontStyle* providedStyle = nullptr,
const CTFontSymbolicTraits* providedTraits = nullptr) {
std::unique_ptr<SkStreamAsset> providedData) {
SkASSERT(font);
const bool isFromStream(providedData);
@ -779,26 +778,13 @@ static sk_sp<SkTypeface> create_from_CTFontRef(SkUniqueCFRef<CTFontRef> font,
}
}
SkFontStyle style;
if (providedStyle) {
style = *providedStyle;
} else {
SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(font.get()));
style = fontstyle_from_descriptor(desc.get(), isFromStream);
}
CTFontSymbolicTraits traits;
if (providedTraits) {
traits = *providedTraits;
} else {
traits = CTFontGetSymbolicTraits(font.get());
}
SkFontStyle style = fontstyle_from_descriptor(desc.get(), isFromStream);
CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font.get());
bool isFixedPitch = SkToBool(traits & kCTFontMonoSpaceTrait);
bool hasColorGlyphs = SkToBool(traits & kCTFontColorGlyphsTrait);
sk_sp<SkTypeface> face(new SkTypeface_Mac(std::move(font), std::move(resource),
style, isFixedPitch, hasColorGlyphs,
std::move(providedData)));
style, isFixedPitch, std::move(providedData)));
if (!isFromStream) {
SkTypefaceCache::Add(face);
}
@ -914,16 +900,14 @@ static sk_sp<SkTypeface> create_from_name(const char familyName[], const SkFontS
/* This function is visible on the outside. It first searches the cache, and if
* not found, returns a new entry (after adding it to the cache).
*/
SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font, CFTypeRef resource,
const SkFontStyle* style,
const CTFontSymbolicTraits* traits) {
SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef font, CFTypeRef resource) {
CFRetain(font);
if (resource) {
CFRetain(resource);
}
return create_from_CTFontRef(SkUniqueCFRef<CTFontRef>(font),
SkUniqueCFRef<CFTypeRef>(resource),
nullptr, style, traits).release();
nullptr).release();
}
static const char* map_css_names(const char* name) {

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

@ -85,8 +85,6 @@ class MacOSFontEntry final : public gfxFontEntry {
static void DestroyBlobFunc(void* aUserData);
bool CheckForColorGlyphs();
CGFontRef
mFontRef; // owning reference to the CGFont, released on destruction

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

@ -266,12 +266,6 @@ nsresult MacOSFontEntry::ReadCMAP(FontInfoData* aFontInfoData) {
return rv;
}
bool MacOSFontEntry::CheckForColorGlyphs() {
return HasFontTable(TRUETYPE_TAG('S', 'V', 'G', ' ')) ||
HasFontTable(TRUETYPE_TAG('C', 'O', 'L', 'R')) ||
HasFontTable(TRUETYPE_TAG('s', 'b', 'i', 'x'));
}
gfxFont* MacOSFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle) {
RefPtr<UnscaledFontMac> unscaledFont(mUnscaledFont);
if (!unscaledFont) {
@ -279,7 +273,7 @@ gfxFont* MacOSFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle) {
if (!baseFont) {
return nullptr;
}
unscaledFont = new UnscaledFontMac(baseFont, mIsDataUserFont, CheckForColorGlyphs());
unscaledFont = new UnscaledFontMac(baseFont, mIsDataUserFont);
mUnscaledFont = unscaledFont;
}

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

@ -1490,8 +1490,18 @@ impl Device {
info!("GL texture cache {:?}, bgra {:?} swizzle {:?}, texture storage {:?}, depth {:?}",
color_formats, bgra_formats, bgra8_sampling_swizzle, texture_storage_usage, depth_format);
let supports_copy_image_sub_data = supports_extension(&extensions, "GL_EXT_copy_image") ||
supports_extension(&extensions, "GL_ARB_copy_image");
// On Mali devices glCopyImageSubData appears to stall the pipeline until any pending
// renders to the source texture have completed. Using an alternative such as
// glBlitFramebuffer is preferable on such devices, so pretend we don't support
// glCopyImageSubData. This was observed on a Mali-T830, but as a precaution we avoid this
// on Mali-G too. See bug 1669494.
let supports_copy_image_sub_data = if renderer_name.starts_with("Mali") {
false
} else {
supports_extension(&extensions, "GL_EXT_copy_image") ||
supports_extension(&extensions, "GL_ARB_copy_image")
};
// Due to a bug on Adreno devices, blitting to an fbo bound to
// a non-0th layer of a texture array is not supported.

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

@ -65,12 +65,13 @@ extern JS_PUBLIC_API TranscodeResult EncodeScript(JSContext* cx,
// Decode JSScript from the buffer.
extern JS_PUBLIC_API TranscodeResult
DecodeScript(JSContext* cx, TranscodeBuffer& buffer,
MutableHandle<JSScript*> scriptp, size_t cursorIndex = 0);
DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
size_t cursorIndex = 0);
extern JS_PUBLIC_API TranscodeResult
DecodeScript(JSContext* cx, const TranscodeRange& range,
MutableHandle<JSScript*> scriptp);
DecodeScript(JSContext* cx, const ReadOnlyCompileOptions& options,
const TranscodeRange& range, MutableHandle<JSScript*> scriptp);
// If js::UseOffThreadParseGlobal is true, decode JSScript from the buffer.
//
@ -79,8 +80,8 @@ DecodeScript(JSContext* cx, const TranscodeRange& range,
//
// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal.
extern JS_PUBLIC_API TranscodeResult DecodeScriptMaybeStencil(
JSContext* cx, TranscodeBuffer& buffer,
const ReadOnlyCompileOptions& options, MutableHandle<JSScript*> scriptp,
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
size_t cursorIndex = 0);
// If js::UseOffThreadParseGlobal is true, decode JSScript from the buffer.
@ -96,8 +97,8 @@ extern JS_PUBLIC_API TranscodeResult DecodeScriptMaybeStencil(
//
// options.useOffThreadParseGlobal should match JS::SetUseOffThreadParseGlobal.
extern JS_PUBLIC_API TranscodeResult DecodeScriptAndStartIncrementalEncoding(
JSContext* cx, TranscodeBuffer& buffer,
const ReadOnlyCompileOptions& options, MutableHandle<JSScript*> scriptp,
JSContext* cx, const ReadOnlyCompileOptions& options,
TranscodeBuffer& buffer, MutableHandle<JSScript*> scriptp,
size_t cursorIndex = 0);
// Finish incremental encoding started by one of:
@ -120,6 +121,17 @@ extern JS_PUBLIC_API bool FinishIncrementalEncoding(JSContext* cx,
Handle<JSScript*> script,
TranscodeBuffer& buffer);
// Check if the compile options and script's flag matches.
//
// JS::DecodeScript* and JS::DecodeOffThreadScript internally check this.
//
// JS::DecodeMultiOffThreadScripts checks some options shared across multiple
// scripts. Caller is responsible for checking each script with this API when
// using the decoded script instead of compiling a new script wiht the given
// options.
extern JS_PUBLIC_API bool CheckCompileOptionsMatch(
const ReadOnlyCompileOptions& options, JSScript* script);
} // namespace JS
#endif /* js_Transcoding_h */

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

@ -51,7 +51,7 @@
#include "jit/Disassemble.h"
#include "jit/InlinableNatives.h"
#include "jit/Ion.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/TrialInlining.h"
#include "js/Array.h" // JS::NewArrayObject
#include "js/ArrayBuffer.h" // JS::{DetachArrayBuffer,GetArrayBufferLengthAndData,NewArrayBufferWithContents}

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

@ -13,6 +13,7 @@
#include "frontend/ModuleSharedContext.h"
#include "vm/FunctionFlags.h" // js::FunctionFlags
#include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
#include "vm/JSScript.h" // js::FillImmutableFlagsFromCompileOptionsForTopLevel, js::FillImmutableFlagsFromCompileOptionsForFunction
#include "vm/StencilEnums.h" // ImmutableScriptFlagsEnum
#include "wasm/AsmJS.h"
#include "wasm/WasmModule.h"
@ -56,14 +57,12 @@ SharedContext::SharedContext(JSContext* cx, Kind kind,
// Initialize the transitive "input" flags. These are applied to all
// SharedContext in this compilation and generally cannot be determined from
// the source text alone.
setFlag(ImmutableFlags::SelfHosted, options.selfHostingMode);
setFlag(ImmutableFlags::ForceStrict, options.forceStrictMode());
setFlag(ImmutableFlags::HasNonSyntacticScope, options.nonSyntacticScope);
// Initialize the non-transistive "input" flags if this is a top-level.
if (isTopLevelContext()) {
setFlag(ImmutableFlags::TreatAsRunOnce, options.isRunOnce);
setFlag(ImmutableFlags::NoScriptRval, options.noScriptRval);
js::FillImmutableFlagsFromCompileOptionsForTopLevel(options,
immutableFlags_);
} else {
js::FillImmutableFlagsFromCompileOptionsForFunction(options,
immutableFlags_);
}
// Initialize the strict flag. This may be updated by the parser as we observe

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

@ -6,6 +6,9 @@
#include "frontend/StencilXdr.h" // StencilXDR
#include "vm/JSScript.h" // js::CheckCompileOptionsMatch
#include "vm/StencilEnums.h" // js::ImmutableScriptFlagsEnum
using namespace js;
using namespace js::frontend;
@ -189,6 +192,17 @@ static XDRResult XDRScriptStencil(XDRState<mode>* xdr, ScriptStencil& stencil) {
MOZ_TRY(xdr->codeUint16(&stencil.nargs));
if (mode == XDR_DECODE) {
MOZ_ASSERT(xdr->hasOptions());
if (!(immutableFlags & uint32_t(ImmutableScriptFlagsEnum::IsFunction))) {
MOZ_ASSERT(!xdr->isMultiDecode());
if (!js::CheckCompileOptionsMatch(xdr->options(),
ImmutableScriptFlags(immutableFlags),
xdr->isMultiDecode())) {
return xdr->fail(JS::TranscodeResult_Failure_WrongCompileOption);
}
}
stencil.immutableFlags = immutableFlags;
if (xdrFlags & (1 << uint8_t(XdrFlags::HasMemberInitializers))) {

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

@ -15,7 +15,6 @@
#include "gc/GCLock.h"
#include "gc/GCProbes.h"
#include "gc/Nursery.h"
#include "jit/JitRealm.h"
#include "threading/CpuCount.h"
#include "util/Poison.h"
#include "vm/JSContext.h"

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

@ -227,6 +227,8 @@
#include "jit/JitCode.h"
#include "jit/JitcodeMap.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitZone.h"
#include "js/Object.h" // JS::GetClass
#include "js/SliceBudget.h"
#include "proxy/DeadObjectProxy.h"

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

@ -17,6 +17,7 @@
#include "gc/ClearEdgesTracer.h"
#include "gc/GCInternals.h"
#include "gc/Marking.h"
#include "jit/JitRuntime.h"
#include "js/HashTable.h"
#include "js/ValueArray.h"
#include "vm/HelperThreadState.h"

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

@ -16,7 +16,7 @@
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/Ion.h"
#include "jit/JitRealm.h"
#include "jit/JitZone.h"
#include "vm/Runtime.h"
#include "wasm/WasmInstance.h"

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

@ -13,6 +13,7 @@
#include "irregexp/imported/special-case.h"
#include "jit/Linker.h"
#include "vm/MatchPairs.h"
#include "vm/Realm.h"
#include "jit/MacroAssembler-inl.h"

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

@ -32,6 +32,7 @@
#include "js/RegExpFlags.h"
#include "js/Value.h"
#include "threading/ExclusiveData.h"
#include "vm/JSContext.h"
#include "vm/MutexIDs.h"
#include "vm/NativeObject.h"
#include "vm/RegExpShared.h"
@ -1091,7 +1092,7 @@ class StackLimitCheck {
// Use this to check for stack-overflows in C++ code.
bool HasOverflowed() {
bool overflowed = !CheckRecursionLimitDontReport(cx_);
bool overflowed = !js::CheckRecursionLimitDontReport(cx_);
#ifdef JS_MORE_DETERMINISTIC
if (overflowed) {
// We don't report overrecursion here, but we throw an exception later
@ -1110,7 +1111,7 @@ class StackLimitCheck {
// Use this to check for stack-overflow when entering runtime from JS code.
bool JsHasOverflowed() {
return !CheckRecursionLimitConservativeDontReport(cx_);
return !js::CheckRecursionLimitConservativeDontReport(cx_);
}
private:

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

@ -0,0 +1,29 @@
function simple() {
var obj = new FakeDOMObject();
for (var i = 0; i < 10; i++) {
assertEq(obj.doFoo(0, 0, 0), 3);
}
}
function wrongThis() {
var obj = new FakeDOMObject();
var wrong = {doFoo: obj.doFoo};
for (var i = 0; i < 100; i++) {
assertEq(obj.doFoo(0, 0), i <= 50 ? 2 : undefined);
if (i == 50) {
obj = wrong;
}
}
}
function spread() {
var obj = new FakeDOMObject();
for (var i = 0; i < 10; i++) {
assertEq(obj.doFoo(...[1, 2, 3, 4]), 4);
}
}
simple();
wrongThis();
spread();

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

@ -0,0 +1,11 @@
function f(x, y) {
return +(-y ? -x : (y ? x : NaN));
}
let arr = [false, {}, {}];
for (let i = 0; i < 9; ++i) {
f(1.1, 2);
}
for (let i = 0; i < arr.length; i++) {
output = f(true, arr[i]);
}
assertEq(output, 1);

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

@ -0,0 +1,27 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* 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 "jit/AutoDetectInvalidation.h"
#include "jit/JitFrames.h"
#include "vm/JSContext.h"
#include "vm/JSScript-inl.h"
namespace js::jit {
AutoDetectInvalidation::AutoDetectInvalidation(JSContext* cx,
MutableHandleValue rval)
: cx_(cx),
ionScript_(GetTopJitJSScript(cx)->ionScript()),
rval_(rval),
disabled_(false) {}
void AutoDetectInvalidation::setReturnOverride() {
cx_->setIonReturnOverride(rval_.get());
}
} // namespace js::jit

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

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_AutoDetectInvalidation_h
#define jit_AutoDetectInvalidation_h
#include "mozilla/Assertions.h"
#include "mozilla/Likely.h"
#include "NamespaceImports.h"
#include "jit/IonScript.h"
#include "js/RootingAPI.h"
#include "js/TypeDecls.h"
namespace js::jit {
class AutoDetectInvalidation {
JSContext* cx_;
IonScript* ionScript_;
MutableHandleValue rval_;
bool disabled_;
void setReturnOverride();
public:
AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval,
IonScript* ionScript)
: cx_(cx), ionScript_(ionScript), rval_(rval), disabled_(false) {
MOZ_ASSERT(ionScript);
}
AutoDetectInvalidation(JSContext* cx, MutableHandleValue rval);
void disable() {
MOZ_ASSERT(!disabled_);
disabled_ = true;
}
bool shouldSetReturnOverride() const {
return !disabled_ && ionScript_->invalidated();
}
~AutoDetectInvalidation() {
if (MOZ_UNLIKELY(shouldSetReturnOverride())) {
setReturnOverride();
}
}
};
} // namespace js::jit
#endif /* jit_AutoDetectInvalidation_h */

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

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_AutoJitContextAlloc_h
#define jit_AutoJitContextAlloc_h
#include "mozilla/Assertions.h"
#include "ds/LifoAlloc.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitContext.h"
namespace js::jit {
class AutoJitContextAlloc {
TempAllocator tempAlloc_;
JitContext* jcx_;
TempAllocator* prevAlloc_;
public:
explicit AutoJitContextAlloc(LifoAlloc* lifoAlloc)
: tempAlloc_(lifoAlloc), jcx_(GetJitContext()), prevAlloc_(jcx_->temp) {
jcx_->temp = &tempAlloc_;
}
~AutoJitContextAlloc() {
MOZ_ASSERT(jcx_->temp == &tempAlloc_);
jcx_->temp = prevAlloc_;
}
};
} // namespace js::jit
#endif /* jit_AutoJitContextAlloc_h */

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

@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_AutoWritableJitCode_h
#define jit_AutoWritableJitCode_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include <stddef.h>
#include "jit/ExecutableAllocator.h"
#include "jit/JitCode.h"
#include "jit/ProcessExecutableMemory.h"
#include "vm/JSContext.h"
#include "vm/Runtime.h"
namespace js::jit {
// This class ensures JIT code is executable on its destruction. Creators
// must call makeWritable(), and not attempt to write to the buffer if it fails.
//
// AutoWritableJitCodeFallible may only fail to make code writable; it cannot
// fail to make JIT code executable (because the creating code has no chance to
// recover from a failed destructor).
class MOZ_RAII AutoWritableJitCodeFallible {
JSRuntime* rt_;
void* addr_;
size_t size_;
public:
AutoWritableJitCodeFallible(JSRuntime* rt, void* addr, size_t size)
: rt_(rt), addr_(addr), size_(size) {
rt_->toggleAutoWritableJitCodeActive(true);
}
AutoWritableJitCodeFallible(void* addr, size_t size)
: AutoWritableJitCodeFallible(TlsContext.get()->runtime(), addr, size) {}
explicit AutoWritableJitCodeFallible(JitCode* code)
: AutoWritableJitCodeFallible(code->runtimeFromMainThread(), code->raw(),
code->bufferSize()) {}
MOZ_MUST_USE bool makeWritable() {
return ExecutableAllocator::makeWritable(addr_, size_);
}
~AutoWritableJitCodeFallible() {
if (!ExecutableAllocator::makeExecutableAndFlushICache(
FlushICacheSpec::LocalThreadOnly, addr_, size_)) {
MOZ_CRASH();
}
rt_->toggleAutoWritableJitCodeActive(false);
}
};
// Infallible variant of AutoWritableJitCodeFallible, ensures writable during
// construction
class MOZ_RAII AutoWritableJitCode : private AutoWritableJitCodeFallible {
public:
AutoWritableJitCode(JSRuntime* rt, void* addr, size_t size)
: AutoWritableJitCodeFallible(rt, addr, size) {
MOZ_RELEASE_ASSERT(makeWritable());
}
AutoWritableJitCode(void* addr, size_t size)
: AutoWritableJitCode(TlsContext.get()->runtime(), addr, size) {}
explicit AutoWritableJitCode(JitCode* code)
: AutoWritableJitCode(code->runtimeFromMainThread(), code->raw(),
code->bufferSize()) {}
};
} // namespace js::jit
#endif /* jit_AutoWritableJitCode_h */

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

@ -10,10 +10,12 @@
#include "jit/BaselineJIT.h"
#include "jit/Ion.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/JSJitFrameIter.h"
#include "jit/Snapshots.h"
#include "vm/JSContext.h"
#include "vm/Stack.h"
#include "vm/TraceLogging.h"
#include "jit/JSJitFrameIter-inl.h"

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

@ -16,12 +16,13 @@
#include "jstypes.h"
#include "jit/IonTypes.h" // js::jit::Bailout{Id,Kind}, js::jit::SnapshotOffset
#include "jit/JSJitFrameIter.h" // js::jit::InlineFrameIterator
#include "jit/Registers.h" // js::jit::MachineState
#include "js/TypeDecls.h" // jsbytecode
#include "vm/Stack.h" // js::AbstractFramePtr
namespace js {
class AbstractFramePtr;
namespace jit {
// [SMDOC] IonMonkey Bailouts
@ -138,8 +139,10 @@ class BailoutStack;
class InvalidationBailoutStack;
class IonScript;
class InlineFrameIterator;
class JitActivation;
class JitActivationIterator;
class JSJitFrameIter;
struct ResumeFromException;
// Must be implemented by each architecture.

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

@ -12,9 +12,11 @@
#include "jit/BaselineFrame.h"
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/CalleeToken.h"
#include "jit/CompileInfo.h"
#include "jit/Ion.h"
#include "jit/IonScript.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/mips32/Simulator-mips32.h"
#include "jit/mips64/Simulator-mips64.h"

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

@ -7,6 +7,8 @@
#include "jit/BaselineCacheIRCompiler.h"
#include "jit/CacheIR.h"
#include "jit/JitRuntime.h"
#include "jit/JitZone.h"
#include "jit/Linker.h"
#include "jit/SharedICHelpers.h"
#include "jit/VMFunctions.h"
@ -3153,6 +3155,18 @@ bool BaselineCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags,
ignoresReturnValue, targetOffset_);
}
bool BaselineCacheIRCompiler::emitCallDOMFunction(ObjOperandId calleeId,
Int32OperandId argcId,
ObjOperandId thisObjId,
CallFlags flags,
uint32_t targetOffset) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Maybe<bool> ignoresReturnValue;
Maybe<uint32_t> targetOffset_ = mozilla::Some(targetOffset);
return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags,
ignoresReturnValue, targetOffset_);
}
#else
bool BaselineCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
Int32OperandId argcId,
@ -3164,6 +3178,17 @@ bool BaselineCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags,
ignoresReturnValue_, targetOffset);
}
bool BaselineCacheIRCompiler::emitCallDOMFunction(ObjOperandId calleeId,
Int32OperandId argcId,
ObjOperandId thisObjId,
CallFlags flags) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Maybe<bool> ignoresReturnValue = mozilla::Some(false);
Maybe<uint32_t> targetOffset;
return emitCallNativeShared(NativeCallType::Native, calleeId, argcId, flags,
ignoresReturnValue, targetOffset);
}
#endif
bool BaselineCacheIRCompiler::emitCallClassHook(ObjOperandId calleeId,

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

@ -10,9 +10,11 @@
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/CalleeToken.h"
#include "jit/FixedList.h"
#include "jit/IonAnalysis.h"
#include "jit/JitcodeMap.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/Linker.h"
#ifdef JS_ION_PERF

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

@ -6,9 +6,12 @@
#include "jit/BaselineDebugModeOSR.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/JitcodeMap.h"
#include "jit/Linker.h"
#include "jit/JitRuntime.h"
#include "jit/JSJitFrameIter.h"
#include "jit/PerfSpewer.h"
#include "jit/JitFrames-inl.h"

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

@ -7,11 +7,13 @@
#ifndef jit_BaselineDebugModeOSR_h
#define jit_BaselineDebugModeOSR_h
#include "mozilla/Attributes.h"
#include "jstypes.h"
#include "debugger/DebugAPI.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineIC.h"
#include "jit/BaselineJIT.h"
#include "jit/JSJitFrameIter.h"
struct JS_PUBLIC_API JSContext;
namespace js {
namespace jit {

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

@ -9,6 +9,7 @@
#include <algorithm>
#include "jit/CalleeToken.h"
#include "jit/JitFrames.h"
#include "vm/Stack.h"

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

@ -24,7 +24,10 @@
#include "jit/BaselineDebugModeOSR.h"
#include "jit/BaselineJIT.h"
#include "jit/InlinableNatives.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/JitZone.h"
#include "jit/Linker.h"
#include "jit/Lowering.h"
#ifdef JS_ION_PERF

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

@ -43,6 +43,7 @@ namespace jit {
class BaselineFrame;
class CacheIRStubInfo;
class ICScript;
class MacroAssembler;
enum class TailCallVMFunctionId;

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

@ -15,10 +15,13 @@
#include "debugger/DebugAPI.h"
#include "gc/FreeOp.h"
#include "gc/PublicIterators.h"
#include "jit/AutoWritableJitCode.h"
#include "jit/BaselineCodeGen.h"
#include "jit/BaselineIC.h"
#include "jit/CalleeToken.h"
#include "jit/CompileInfo.h"
#include "jit/JitCommon.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "js/friend/StackLimits.h" // js::CheckRecursionLimitWithStackPointer
#include "util/Memory.h"
@ -69,6 +72,35 @@ static bool CheckFrame(InterpreterFrame* fp) {
return true;
}
struct EnterJitData {
explicit EnterJitData(JSContext* cx)
: jitcode(nullptr),
osrFrame(nullptr),
calleeToken(nullptr),
maxArgv(nullptr),
maxArgc(0),
numActualArgs(0),
osrNumStackValues(0),
envChain(cx),
result(cx),
constructing(false) {}
uint8_t* jitcode;
InterpreterFrame* osrFrame;
void* calleeToken;
Value* maxArgv;
unsigned maxArgc;
unsigned numActualArgs;
unsigned osrNumStackValues;
RootedObject envChain;
RootedValue result;
bool constructing;
};
static JitExecStatus EnterBaseline(JSContext* cx, EnterJitData& data) {
MOZ_ASSERT(data.osrFrame);
@ -149,8 +181,6 @@ JitExecStatus jit::EnterBaselineInterpreterAtBranch(JSContext* cx,
cx->runtime()->jitRuntime()->baselineInterpreter();
data.jitcode = interp.interpretOpNoDebugTrapAddr().value;
// Note: keep this in sync with SetEnterJitData.
data.osrFrame = fp;
data.osrNumStackValues =
fp->script()->nfixed() + cx->interpreterRegs().stackDepth();

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

@ -14,6 +14,7 @@
#include "ds/LifoAlloc.h"
#include "jit/Bailouts.h"
#include "jit/JitCode.h"
#include "jit/JitContext.h"
#include "jit/shared/Assembler-shared.h"
#include "util/TrailingArray.h"
#include "vm/JSContext.h"

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

@ -6,6 +6,10 @@
#include "jit/BitSet.h"
#include <string.h>
#include "jit/JitAllocPolicy.h"
using namespace js;
using namespace js::jit;

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

@ -7,13 +7,18 @@
#ifndef jit_BitSet_h
#define jit_BitSet_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/MathAlgorithms.h"
#include "jit/JitAllocPolicy.h"
#include <stddef.h>
#include <stdint.h>
namespace js {
namespace jit {
class TempAllocator;
// Provides constant time set insertion and removal, and fast linear
// set operations such as intersection, difference, and union.
// N.B. All set operations must be performed on sets with the same number

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

@ -19,6 +19,7 @@
#include "jit/InlinableNatives.h"
#include "jit/Ion.h" // IsIonEnabled
#include "jit/JitContext.h"
#include "jit/JitRuntime.h"
#include "js/experimental/JitInfo.h" // JSJitInfo
#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration
#include "js/friend/WindowProxy.h" // js::IsWindow, js::IsWindowProxy, js::ToWindowIfWindowProxy
@ -189,8 +190,8 @@ JS::Symbol* CacheIRCloner::getSymbolField(uint32_t stubOffset) {
BaseScript* CacheIRCloner::getBaseScriptField(uint32_t stubOffset) {
return reinterpret_cast<BaseScript*>(readStubWord(stubOffset));
}
uintptr_t CacheIRCloner::getRawWordField(uint32_t stubOffset) {
return reinterpret_cast<uintptr_t>(readStubWord(stubOffset));
uint32_t CacheIRCloner::getRawInt32Field(uint32_t stubOffset) {
return uint32_t(reinterpret_cast<uintptr_t>(readStubWord(stubOffset)));
}
const void* CacheIRCloner::getRawPointerField(uint32_t stubOffset) {
return reinterpret_cast<const void*>(readStubWord(stubOffset));
@ -1079,10 +1080,12 @@ static void EmitCallGetterResult(JSContext* cx, CacheIRWriter& writer,
EmitCallGetterResultNoGuards(cx, writer, obj, holder, shape, receiverId);
}
static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
JSObject* obj, HandleShape shape,
static bool CanAttachDOMCall(JSContext* cx, JSJitInfo::OpType type,
JSObject* obj, JSFunction* fun,
ICState::Mode mode) {
MOZ_ASSERT(type == JSJitInfo::Getter || type == JSJitInfo::Setter);
MOZ_ASSERT(type == JSJitInfo::Getter || type == JSJitInfo::Setter ||
type == JSJitInfo::Method);
if (!JitOptions.warpBuilder) {
return false;
}
@ -1091,9 +1094,6 @@ static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
return false;
}
Value v =
type == JSJitInfo::Getter ? shape->getterValue() : shape->setterValue();
JSFunction* fun = &v.toObject().as<JSFunction>();
if (!fun->hasJitInfo()) {
return false;
}
@ -1109,7 +1109,11 @@ static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
}
const JSClass* clasp = obj->getClass();
if (!clasp->isDOMClass() || clasp->isProxy()) {
if (!clasp->isDOMClass()) {
return false;
}
if (type != JSJitInfo::Method && clasp->isProxy()) {
return false;
}
@ -1118,6 +1122,18 @@ static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
return instanceChecker(clasp, jitInfo->protoID, jitInfo->depth);
}
static bool CanAttachDOMGetterSetter(JSContext* cx, JSJitInfo::OpType type,
JSObject* obj, HandleShape shape,
ICState::Mode mode) {
MOZ_ASSERT(type == JSJitInfo::Getter || type == JSJitInfo::Setter);
Value v =
type == JSJitInfo::Getter ? shape->getterValue() : shape->setterValue();
JSFunction* fun = &v.toObject().as<JSFunction>();
return CanAttachDOMCall(cx, type, obj, fun, mode);
}
static void EmitCallDOMGetterResultNoGuards(CacheIRWriter& writer, Shape* shape,
ObjOperandId objId) {
JSFunction* getter = &shape->getterValue().toObject().as<JSFunction>();
@ -9631,10 +9647,32 @@ AttachDecision CallIRGenerator::tryAttachCallNative(HandleFunction calleeFunc) {
writer.loadArgumentDynamicSlot(ArgumentKind::Callee, argcId, flags);
ObjOperandId calleeObjId = writer.guardToObject(calleeValId);
if (isSpecialized) {
// DOM calls need an additional guard so only try optimizing the first stub.
// Can only optimize normal (non-spread) calls.
if (isFirstStub_ && !isSpread && thisval_.isObject() &&
CanAttachDOMCall(cx_, JSJitInfo::Method, &thisval_.toObject(), calleeFunc,
mode_)) {
MOZ_ASSERT(!isConstructing, "DOM functions are not constructors");
// Guard that |this| is an object.
ValOperandId thisValId =
writer.loadArgumentDynamicSlot(ArgumentKind::This, argcId, flags);
ObjOperandId thisObjId = writer.guardToObject(thisValId);
// Guard on the |this| class to make sure it's the right instance.
writer.guardAnyClass(thisObjId, thisval_.toObject().getClass());
// Ensure callee matches this stub's callee
writer.guardSpecificFunction(calleeObjId, calleeFunc);
writer.callDOMFunction(calleeObjId, argcId, thisObjId, calleeFunc, flags);
trackAttached("CallDOM");
} else if (isSpecialized) {
// Ensure callee matches this stub's callee
writer.guardSpecificFunction(calleeObjId, calleeFunc);
writer.callNativeFunction(calleeObjId, argcId, op_, calleeFunc, flags);
trackAttached("CallNative");
} else {
// Guard that object is a native function
writer.guardClass(calleeObjId, GuardClassKind::JSFunction);
@ -9648,22 +9686,18 @@ AttachDecision CallIRGenerator::tryAttachCallNative(HandleFunction calleeFunc) {
writer.guardNotClassConstructor(calleeObjId);
}
writer.callAnyNativeFunction(calleeObjId, argcId, flags);
trackAttached("CallAnyNative");
}
writer.typeMonitorResult();
cacheIRStubKind_ = BaselineCacheIRStubKind::Monitored;
if (templateObj) {
MOZ_ASSERT(isSpecialized);
writer.metaNativeTemplateObject(calleeFunc, templateObj);
}
cacheIRStubKind_ = BaselineCacheIRStubKind::Monitored;
if (isSpecialized) {
trackAttached("Call native func");
} else {
trackAttached("Call any native func");
}
return AttachDecision::Attach;
}

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

@ -228,7 +228,8 @@ class StubField {
public:
enum class Type : uint8_t {
// These fields take up a single word.
RawWord,
RawInt32,
RawPointer,
Shape,
ObjectGroup,
JSObject,
@ -621,11 +622,11 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
MOZ_ASSERT(script);
addStubField(uintptr_t(script), StubField::Type::BaseScript);
}
void writeRawWordField(uintptr_t word) {
addStubField(word, StubField::Type::RawWord);
void writeRawInt32Field(uint32_t val) {
addStubField(val, StubField::Type::RawInt32);
}
void writeRawPointerField(const void* ptr) {
addStubField(uintptr_t(ptr), StubField::Type::RawWord);
addStubField(uintptr_t(ptr), StubField::Type::RawPointer);
}
void writeIdField(jsid id) {
addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
@ -938,6 +939,18 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter {
#endif
}
void callDOMFunction(ObjOperandId calleeId, Int32OperandId argc,
ObjOperandId thisObjId, HandleFunction calleeFunc,
CallFlags flags) {
#ifdef JS_SIMULATOR
void* rawPtr = JS_FUNC_TO_DATA_PTR(void*, calleeFunc->native());
void* redirected = Simulator::RedirectNativeFunction(rawPtr, Args_General3);
callDOMFunction_(calleeId, argc, thisObjId, flags, redirected);
#else
callDOMFunction_(calleeId, argc, thisObjId, flags);
#endif
}
void callAnyNativeFunction(ObjOperandId calleeId, Int32OperandId argc,
CallFlags flags) {
MOZ_ASSERT(!flags.isSameRealm());
@ -1207,7 +1220,7 @@ class MOZ_RAII CacheIRCloner {
PropertyName* getPropertyNameField(uint32_t stubOffset);
JS::Symbol* getSymbolField(uint32_t stubOffset);
BaseScript* getBaseScriptField(uint32_t stubOffset);
uintptr_t getRawWordField(uint32_t stubOffset);
uint32_t getRawInt32Field(uint32_t stubOffset);
const void* getRawPointerField(uint32_t stubOffset);
jsid getIdField(uint32_t stubOffset);
const Value getValueField(uint32_t stubOffset);

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

@ -23,8 +23,12 @@
#include "jit/BaselineCacheIRCompiler.h"
#include "jit/IonCacheIRCompiler.h"
#include "jit/IonIC.h"
#include "jit/JitRuntime.h"
#include "jit/JitZone.h"
#include "jit/SharedICHelpers.h"
#include "jit/SharedICRegisters.h"
#include "jit/TemplateObject.h"
#include "jit/VMFunctions.h"
#include "js/friend/DOMProxy.h" // JS::ExpandoAndGeneration
#include "js/friend/XrayJitInfo.h" // js::jit::GetXrayJitInfo
#include "js/ScalarType.h" // js::Scalar::Type
@ -1107,7 +1111,8 @@ void CacheIRWriter::copyStubData(uint8_t* dest) const {
for (const StubField& field : stubFields_) {
switch (field.type()) {
case StubField::Type::RawWord:
case StubField::Type::RawInt32:
case StubField::Type::RawPointer:
*destWords = field.asWord();
break;
case StubField::Type::Shape:
@ -1154,7 +1159,8 @@ void jit::TraceCacheIRStub(JSTracer* trc, T* stub,
while (true) {
StubField::Type fieldType = stubInfo->fieldType(field);
switch (fieldType) {
case StubField::Type::RawWord:
case StubField::Type::RawInt32:
case StubField::Type::RawPointer:
case StubField::Type::RawInt64:
case StubField::Type::DOMExpandoGeneration:
break;
@ -2006,7 +2012,7 @@ bool CacheIRCompiler::emitGuardDynamicSlotIsSpecificObject(
}
// Guard on the expected object.
StubFieldOffset slot(slotOffset, StubField::Type::RawWord);
StubFieldOffset slot(slotOffset, StubField::Type::RawInt32);
masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), scratch1);
emitLoadStubField(slot, scratch2);
BaseObjectSlotIndex expectedSlot(scratch1, scratch2);
@ -5391,7 +5397,7 @@ bool CacheIRCompiler::emitStoreTypedObjectScalarProperty(
Scalar::Type type, uint32_t rhsId) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Register obj = allocator.useRegister(masm, objId);
StubFieldOffset offset(offsetOffset, StubField::Type::RawWord);
StubFieldOffset offset(offsetOffset, StubField::Type::RawInt32);
AutoAvailableFloatRegister floatScratch0(*this, FloatReg0);
@ -5473,7 +5479,7 @@ bool CacheIRCompiler::emitLoadTypedObjectResult(ObjOperandId objId,
AutoScratchRegister scratch1(allocator, masm);
AutoScratchRegister scratch2(allocator, masm);
StubFieldOffset offset(offsetOffset, StubField::Type::RawWord);
StubFieldOffset offset(offsetOffset, StubField::Type::RawInt32);
// Allocate BigInt if needed. The code after this should be infallible.
Maybe<Register> bigInt;
@ -5572,7 +5578,7 @@ bool CacheIRCompiler::emitStoreFixedSlotUndefinedResult(ObjOperandId objId,
Register obj = allocator.useRegister(masm, objId);
ValueOperand val = allocator.useValueRegister(masm, rhsId);
StubFieldOffset offset(offsetOffset, StubField::Type::RawWord);
StubFieldOffset offset(offsetOffset, StubField::Type::RawInt32);
emitLoadStubField(offset, scratch);
BaseIndex slot(obj, scratch, TimesOne);
@ -6963,7 +6969,10 @@ void CacheIRCompiler::emitLoadStubFieldConstant(StubFieldOffset val,
case StubField::Type::JSObject:
masm.movePtr(ImmGCPtr(objectStubField(val.getOffset())), dest);
break;
case StubField::Type::RawWord:
case StubField::Type::RawPointer:
masm.movePtr(ImmPtr(pointerStubField(val.getOffset())), dest);
break;
case StubField::Type::RawInt32:
masm.move32(Imm32(int32StubField(val.getOffset())), dest);
break;
default:
@ -6987,6 +6996,7 @@ void CacheIRCompiler::emitLoadStubField(StubFieldOffset val, Register dest) {
Address load(ICStubReg, stubDataOffset_ + val.getOffset());
switch (val.getStubFieldType()) {
case StubField::Type::RawPointer:
case StubField::Type::Shape:
case StubField::Type::ObjectGroup:
case StubField::Type::JSObject:
@ -6995,7 +7005,7 @@ void CacheIRCompiler::emitLoadStubField(StubFieldOffset val, Register dest) {
case StubField::Type::Id:
masm.loadPtr(load, dest);
break;
case StubField::Type::RawWord:
case StubField::Type::RawInt32:
masm.load32(load, dest);
break;
default:
@ -7007,7 +7017,7 @@ void CacheIRCompiler::emitLoadStubField(StubFieldOffset val, Register dest) {
Address CacheIRCompiler::emitAddressFromStubField(StubFieldOffset val,
Register base) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
MOZ_ASSERT(val.getStubFieldType() == StubField::Type::RawWord);
MOZ_ASSERT(val.getStubFieldType() == StubField::Type::RawInt32);
if (stubFieldPolicy_ == StubFieldPolicy::Constant) {
int32_t offset = int32StubField(val.getOffset());
@ -7239,7 +7249,7 @@ bool CacheIRCompiler::emitLoadInt32Constant(uint32_t valOffset,
Int32OperandId resultId) {
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Register reg = allocator.defineRegister(masm, resultId);
StubFieldOffset val(valOffset, StubField::Type::RawWord);
StubFieldOffset val(valOffset, StubField::Type::RawInt32);
emitLoadStubField(val, reg);
return true;
}

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

@ -23,6 +23,8 @@ namespace jit {
class BaselineCacheIRCompiler;
class IonCacheIRCompiler;
enum class ICStubEngine : uint8_t;
// [SMDOC] CacheIR Value Representation and Tracking
//
// While compiling an IC stub the CacheIR compiler needs to keep track of the
@ -852,11 +854,11 @@ class MOZ_RAII CacheIRCompiler {
}
int32_t int32StubField(uint32_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return readStubWord(offset, StubField::Type::RawWord);
return readStubWord(offset, StubField::Type::RawInt32);
}
uint32_t uint32StubField(uint32_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return readStubWord(offset, StubField::Type::RawWord);
return readStubWord(offset, StubField::Type::RawInt32);
}
Shape* shapeStubField(uint32_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
@ -888,15 +890,19 @@ class MOZ_RAII CacheIRCompiler {
}
JS::Compartment* compartmentStubField(uint32_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return (JS::Compartment*)readStubWord(offset, StubField::Type::RawWord);
return (JS::Compartment*)readStubWord(offset, StubField::Type::RawPointer);
}
const JSClass* classStubField(uintptr_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return (const JSClass*)readStubWord(offset, StubField::Type::RawWord);
return (const JSClass*)readStubWord(offset, StubField::Type::RawPointer);
}
const void* proxyHandlerStubField(uintptr_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return (const void*)readStubWord(offset, StubField::Type::RawWord);
return (const void*)readStubWord(offset, StubField::Type::RawPointer);
}
const void* pointerStubField(uintptr_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);
return (const void*)readStubWord(offset, StubField::Type::RawPointer);
}
jsid idStubField(uint32_t offset) {
MOZ_ASSERT(stubFieldPolicy_ == StubFieldPolicy::Constant);

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

@ -437,7 +437,7 @@
args:
fun: ObjId
expected: ObjectField
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: GuardFunctionScript
shared: false
@ -447,7 +447,7 @@
args:
obj: ObjId
expected: BaseScriptField
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: GuardSpecificAtom
shared: false
@ -605,7 +605,7 @@
args:
obj: ObjId
expected: ObjId
slot: RawWordField
slot: RawInt32Field
- name: GuardNoAllocationMetadataBuilder
shared: true
@ -825,7 +825,7 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
- name: StoreDynamicSlot
@ -834,7 +834,7 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
- name: AddAndStoreFixedSlot
@ -843,7 +843,7 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
changeGroup: BoolImm
newGroup: GroupField
@ -855,7 +855,7 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
changeGroup: BoolImm
newGroup: GroupField
@ -867,12 +867,12 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
changeGroup: BoolImm
newGroup: GroupField
newShape: ShapeField
numNewSlots: RawWordField
numNewSlots: RawInt32Field
- name: StoreTypedObjectReferenceProperty
shared: false
@ -880,7 +880,7 @@
cost_estimate: 6
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
layout: TypedThingLayoutImm
type: ReferenceTypeImm
rhs: ValId
@ -891,7 +891,7 @@
cost_estimate: 2
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
layout: TypedThingLayoutImm
type: ScalarTypeImm
rhs: RawId
@ -967,7 +967,7 @@
transpile: true
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
rhs: ValId
- name: IsObjectResult
@ -1461,7 +1461,7 @@
setter: ObjectField
rhs: ValId
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallScriptedSetter
shared: false
@ -1473,7 +1473,7 @@
setter: ObjectField
rhs: ValId
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallInlinedSetter
shared: false
@ -1486,7 +1486,7 @@
rhs: ValId
icScript: RawPointerField
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallDOMSetter
shared: false
@ -1585,6 +1585,20 @@
ignoresReturnValue: BoolImm
#endif
- name: CallDOMFunction
shared: false
transpile: true
cost_estimate: 4
custom_writer: true
args:
callee: ObjId
argc: Int32Id
thisObj: ObjId
flags: CallFlagsImm
#ifdef JS_SIMULATOR
target: RawPointerField
#endif
- name: CallClassHook
shared: false
transpile: false
@ -1625,7 +1639,7 @@
cost_estimate: 1
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
- name: LoadFixedSlotTypedResult
shared: false
@ -1633,7 +1647,7 @@
cost_estimate: 1
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
type: ValueTypeImm
- name: LoadDynamicSlotResult
@ -1642,7 +1656,7 @@
cost_estimate: 1
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
- name: LoadTypedObjectResult
shared: true
@ -1652,7 +1666,7 @@
obj: ObjId
layout: TypedThingLayoutImm
typeDescr: ByteImm
offset: RawWordField
offset: RawInt32Field
- name: LoadDenseElementResult
shared: true
@ -1860,7 +1874,7 @@
cost_estimate: 1
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
- name: LoadEnvironmentDynamicSlotResult
shared: false
@ -1868,7 +1882,7 @@
cost_estimate: 1
args:
obj: ObjId
offset: RawWordField
offset: RawInt32Field
- name: LoadObjectResult
shared: true
@ -1921,7 +1935,7 @@
receiver: ValId
getter: ObjectField
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallInlinedGetterResult
shared: false
@ -1933,7 +1947,7 @@
getter: ObjectField
icScript: RawPointerField
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallNativeGetterResult
shared: false
@ -1944,7 +1958,7 @@
receiver: ValId
getter: ObjectField
sameRealm: BoolImm
nargsAndFlags: RawWordField
nargsAndFlags: RawInt32Field
- name: CallDOMGetterResult
shared: false
@ -2022,7 +2036,7 @@
transpile: true
cost_estimate: 1
args:
val: RawWordField
val: RawInt32Field
result: Int32Id
- name: LoadBooleanConstant

66
js/src/jit/CalleeToken.h Normal file
Просмотреть файл

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_CalleeToken_h
#define jit_CalleeToken_h
#include "mozilla/Assertions.h"
#include <stdint.h>
#include "js/TypeDecls.h"
class JS_PUBLIC_API JSTracer;
namespace js::jit {
using CalleeToken = void*;
enum CalleeTokenTag {
CalleeToken_Function = 0x0, // untagged
CalleeToken_FunctionConstructing = 0x1,
CalleeToken_Script = 0x2
};
// Any CalleeToken with this bit set must be CalleeToken_Script.
static const uintptr_t CalleeTokenScriptBit = CalleeToken_Script;
static const uintptr_t CalleeTokenMask = ~uintptr_t(0x3);
static inline CalleeTokenTag GetCalleeTokenTag(CalleeToken token) {
CalleeTokenTag tag = CalleeTokenTag(uintptr_t(token) & 0x3);
MOZ_ASSERT(tag <= CalleeToken_Script);
return tag;
}
static inline CalleeToken CalleeToToken(JSFunction* fun, bool constructing) {
CalleeTokenTag tag =
constructing ? CalleeToken_FunctionConstructing : CalleeToken_Function;
return CalleeToken(uintptr_t(fun) | uintptr_t(tag));
}
static inline CalleeToken CalleeToToken(JSScript* script) {
return CalleeToken(uintptr_t(script) | uintptr_t(CalleeToken_Script));
}
static inline bool CalleeTokenIsFunction(CalleeToken token) {
CalleeTokenTag tag = GetCalleeTokenTag(token);
return tag == CalleeToken_Function || tag == CalleeToken_FunctionConstructing;
}
static inline bool CalleeTokenIsConstructing(CalleeToken token) {
return GetCalleeTokenTag(token) == CalleeToken_FunctionConstructing;
}
static inline JSFunction* CalleeTokenToFunction(CalleeToken token) {
MOZ_ASSERT(CalleeTokenIsFunction(token));
return (JSFunction*)(uintptr_t(token) & CalleeTokenMask);
}
static inline JSScript* CalleeTokenToScript(CalleeToken token) {
MOZ_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script);
return (JSScript*)(uintptr_t(token) & CalleeTokenMask);
}
CalleeToken TraceCalleeToken(JSTracer* trc, CalleeToken token);
} /* namespace js::jit */
#endif /* jit_CalleeToken_h */

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

@ -38,6 +38,8 @@
#include "jit/IonOptimizationLevels.h"
#include "jit/IonScript.h"
#include "jit/JitcodeMap.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/Linker.h"
#include "jit/Lowering.h"

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

@ -7,7 +7,11 @@
#ifndef jit_Compactbuffer_h
#define jit_Compactbuffer_h
#include "jit/IonTypes.h"
#include "mozilla/Assertions.h"
#include <stddef.h>
#include <stdint.h>
#include "js/AllocPolicy.h"
#include "js/Vector.h"

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

@ -9,7 +9,7 @@
#include "gc/GC.h"
#include "gc/Heap.h"
#include "jit/Ion.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "vm/Realm-inl.h"

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

@ -7,9 +7,38 @@
#ifndef jit_CompileWrappers_h
#define jit_CompileWrappers_h
#include "vm/JSContext.h"
#include <stdint.h>
#include "js/TypeDecls.h"
struct JSAtomState;
namespace mozilla::non_crypto {
class XorShift128PlusRNG;
}
namespace JS {
enum class TraceKind;
}
namespace js {
class GeckoProfilerRuntime;
class GlobalObject;
struct JSDOMCallbacks;
class PropertyName;
class StaticStrings;
struct WellKnownSymbols;
using DOMCallbacks = struct JSDOMCallbacks;
namespace gc {
enum class AllocKind : uint8_t;
class FreeSpan;
} // namespace gc
namespace jit {
class JitRuntime;
@ -61,10 +90,10 @@ class CompileRuntime {
};
class CompileZone {
Zone* zone();
JS::Zone* zone();
public:
static CompileZone* get(Zone* zone);
static CompileZone* get(JS::Zone* zone);
CompileRuntime* runtime();
bool isAtomsZone();

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

@ -7,6 +7,7 @@
#include "jit/EdgeCaseAnalysis.h"
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
using namespace js;

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

@ -7,11 +7,12 @@
#ifndef jit_EdgeCaseAnalysis_h
#define jit_EdgeCaseAnalysis_h
#include "jit/MIRGenerator.h"
#include "mozilla/Attributes.h"
namespace js {
namespace jit {
class MIRGenerator;
class MIRGraph;
class EdgeCaseAnalysis {

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

@ -8,6 +8,7 @@
#include "jit/IonAnalysis.h"
#include "jit/MIR.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "util/CheckedArithmetic.h"

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

@ -7,11 +7,12 @@
#ifndef jit_EffectiveAddressAnalysis_h
#define jit_EffectiveAddressAnalysis_h
#include "jit/MIRGenerator.h"
#include "mozilla/Attributes.h"
namespace js {
namespace jit {
class MIRGenerator;
class MIRGraph;
class EffectiveAddressAnalysis {

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

@ -28,7 +28,6 @@
#include "jit/ExecutableAllocator.h"
#include "gc/Zone.h"
#include "jit/JitRealm.h"
#include "js/MemoryMetrics.h"
#include "util/Poison.h"

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

@ -7,12 +7,14 @@
#ifndef jit_FoldLinearArithConstants_h
#define jit_FoldLinearArithConstants_h
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
#include "mozilla/Attributes.h"
namespace js {
namespace jit {
class MIRGenerator;
class MIRGraph;
MOZ_MUST_USE bool FoldLinearArithConstants(MIRGenerator* mir, MIRGraph& graph);
} /* namespace jit */

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

@ -79,7 +79,7 @@ arg_writer_info = {
'PropertyNameField': ('PropertyName*', 'writeStringField'),
'SymbolField': ('JS::Symbol*', 'writeSymbolField'),
'BaseScriptField': ('BaseScript*', 'writeBaseScriptField'),
'RawWordField': ('uintptr_t', 'writeRawWordField'),
'RawInt32Field': ('uint32_t', 'writeRawInt32Field'),
'RawPointerField': ('const void*', 'writeRawPointerField'),
'IdField': ('jsid', 'writeIdField'),
'ValueField': ('const Value&', 'writeValueField'),
@ -177,7 +177,7 @@ arg_reader_info = {
'PropertyNameField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'SymbolField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'BaseScriptField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'RawWordField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'RawInt32Field': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'RawPointerField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'IdField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
'ValueField': ('uint32_t', 'Offset', 'reader.stubOffset()'),
@ -261,7 +261,7 @@ arg_spewer_method = {
'PropertyNameField': 'spewField',
'SymbolField': 'spewField',
'BaseScriptField': 'spewField',
'RawWordField': 'spewField',
'RawInt32Field': 'spewField',
'RawPointerField': 'spewField',
'IdField': 'spewField',
'ValueField': 'spewField',
@ -395,7 +395,7 @@ arg_length = {
'PropertyNameField': 1,
'SymbolField': 1,
'BaseScriptField': 1,
'RawWordField': 1,
'RawInt32Field': 1,
'RawPointerField': 1,
'DOMExpandoGenerationField': 1,
'IdField': 1,

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

@ -18,6 +18,7 @@
#include "gc/PublicIterators.h"
#include "jit/AliasAnalysis.h"
#include "jit/AlignmentMaskAnalysis.h"
#include "jit/AutoWritableJitCode.h"
#include "jit/BacktrackingAllocator.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineInspector.h"
@ -37,7 +38,9 @@
#include "jit/JitcodeMap.h"
#include "jit/JitCommon.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/JitZone.h"
#include "jit/LICM.h"
#include "jit/Linker.h"
#include "jit/LIR.h"

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

@ -49,8 +49,6 @@ MethodStatus CanEnterIon(JSContext* cx, RunState& state);
MethodStatus Recompile(JSContext* cx, HandleScript script, bool force);
struct EnterJitData;
// Walk the stack and invalidate active Ion frames for the invalid scripts.
void Invalidate(TypeZone& types, JSFreeOp* fop,
const RecompileInfoVector& invalid, bool resetUses = true,

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

@ -24,6 +24,7 @@
#include "vm/PlainObject.h" // js::PlainObject
#include "vm/RegExpObject.h"
#include "vm/SelfHosting.h"
#include "vm/TypeInference.h"
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/BytecodeUtil-inl.h"

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

@ -11,12 +11,22 @@
#include "mozilla/Attributes.h"
#include <stddef.h>
#include <stdint.h>
#include "jit/IonTypes.h"
#include "jit/JitAllocPolicy.h"
#include "vm/TypeInference.h"
#include "js/TypeDecls.h"
#include "js/Utility.h"
#include "js/Vector.h"
namespace js {
class DPAConstraintInfo;
class GenericPrinter;
class ObjectGroup;
class PlainObject;
class TypeNewScriptInitializer;
namespace jit {
@ -168,8 +178,8 @@ MCompare* ConvertLinearInequality(TempAllocator& alloc, MBasicBlock* block,
const LinearSum& sum);
MOZ_MUST_USE bool AnalyzeNewScriptDefiniteProperties(
JSContext* cx, DPAConstraintInfo& constraintInfo, HandleFunction fun,
ObjectGroup* group, Handle<PlainObject*> baseobj,
JSContext* cx, DPAConstraintInfo& constraintInfo, JS::HandleFunction fun,
ObjectGroup* group, JS::Handle<PlainObject*> baseobj,
Vector<TypeNewScriptInitializer>* initializerList);
MOZ_MUST_USE bool AnalyzeArgumentsUsage(JSContext* cx, JSScript* script);

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

@ -3960,7 +3960,7 @@ IonBuilder::InliningResult IonBuilder::inlineScriptedCall(CallInfo& callInfo,
}
// Capture formals in the outer resume point.
if (!callInfo.pushCallStack(&mirGen_, current)) {
if (!callInfo.pushCallStack(current)) {
return abort(AbortReason::Alloc);
}
@ -4793,7 +4793,7 @@ AbortReasonOr<Ok> IonBuilder::inlineCalls(CallInfo& callInfo,
MBasicBlock* dispatchBlock = current;
callInfo.setImplicitlyUsedUnchecked();
if (!callInfo.pushCallStack(&mirGen_, dispatchBlock)) {
if (!callInfo.pushCallStack(dispatchBlock)) {
return abort(AbortReason::Alloc);
}
@ -5442,7 +5442,7 @@ AbortReasonOr<Ok> IonBuilder::jsop_funcall(uint32_t argc) {
// Save prior call stack in case we need to resolve during bailout
// recovery of inner inlined function. This includes the JSFunction and the
// 'call' native function.
if (!callInfo.savePriorCallStack(&mirGen_, current, argc + 2)) {
if (!callInfo.savePriorCallStack(current, argc + 2)) {
return abort(AbortReason::Alloc);
}
@ -5790,8 +5790,7 @@ AbortReasonOr<Ok> IonBuilder::jsop_funapplyarray(uint32_t argc) {
return pushTypeBarrier(apply, types, BarrierKind::TypeSet);
}
bool CallInfo::savePriorCallStack(MIRGenerator* mir, MBasicBlock* current,
size_t peekDepth) {
bool CallInfo::savePriorCallStack(MBasicBlock* current, size_t peekDepth) {
MOZ_ASSERT(priorArgs_.empty());
if (!priorArgs_.reserve(peekDepth)) {
return false;
@ -5866,7 +5865,7 @@ AbortReasonOr<Ok> IonBuilder::jsop_funapplyarguments(uint32_t argc) {
CallInfo callInfo(alloc(), pc, /* constructing = */ false,
/* ignoresReturnValue = */ BytecodeIsPopped(pc));
if (!callInfo.savePriorCallStack(&mirGen_, current, 4)) {
if (!callInfo.savePriorCallStack(current, 4)) {
return abort(AbortReason::Alloc);
}

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

@ -14,8 +14,8 @@
#include "jsfriendapi.h"
#include "builtin/TypedObject.h"
#include "jit/BaselineInspector.h"
#include "jit/BytecodeAnalysis.h"
#include "jit/IonAnalysis.h"
#include "jit/IonOptimizationLevels.h"
#include "jit/MIR.h"

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

@ -13,6 +13,7 @@
#include "jit/BaselineIC.h"
#include "jit/CacheIRCompiler.h"
#include "jit/IonIC.h"
#include "jit/JitZone.h"
#include "jit/JSJitFrameIter.h"
#include "jit/Linker.h"
#include "jit/SharedICHelpers.h"
@ -57,10 +58,11 @@ IonCacheIRCompiler::IonCacheIRCompiler(
}
template <typename T>
T IonCacheIRCompiler::rawWordStubField(uint32_t offset) {
static_assert(sizeof(T) == sizeof(uintptr_t), "T must have word size");
return (T)readStubWord(offset, StubField::Type::RawWord);
T IonCacheIRCompiler::rawPointerStubField(uint32_t offset) {
static_assert(sizeof(T) == sizeof(uintptr_t), "T must have pointer size");
return (T)readStubWord(offset, StubField::Type::RawPointer);
}
template <typename T>
T IonCacheIRCompiler::rawInt64StubField(uint32_t offset) {
static_assert(sizeof(T) == sizeof(int64_t), "T musthave int64 size");
@ -1049,7 +1051,7 @@ bool IonCacheIRCompiler::emitCallDOMGetterResult(ObjOperandId objId,
Register obj = allocator.useRegister(masm, objId);
const JSJitInfo* info = rawWordStubField<const JSJitInfo*>(jitInfoOffset);
const JSJitInfo* info = rawPointerStubField<const JSJitInfo*>(jitInfoOffset);
allocator.discardStack(masm);
prepareVMCall(masm, save);
@ -1074,7 +1076,7 @@ bool IonCacheIRCompiler::emitCallDOMSetter(ObjOperandId objId,
Register obj = allocator.useRegister(masm, objId);
ValueOperand val = allocator.useValueRegister(masm, rhsId);
const JSJitInfo* info = rawWordStubField<const JSJitInfo*>(jitInfoOffset);
const JSJitInfo* info = rawPointerStubField<const JSJitInfo*>(jitInfoOffset);
allocator.discardStack(masm);
prepareVMCall(masm, save);
@ -2253,7 +2255,7 @@ bool IonCacheIRCompiler::emitGuardAndGetIterator(ObjOperandId objId,
PropertyIteratorObject* iterobj =
&objectStubField(iterOffset)->as<PropertyIteratorObject>();
NativeIterator** enumerators =
rawWordStubField<NativeIterator**>(enumeratorsAddrOffset);
rawPointerStubField<NativeIterator**>(enumeratorsAddrOffset);
Register output = allocator.defineRegister(masm, resultId);
@ -2324,7 +2326,7 @@ bool IonCacheIRCompiler::emitLoadDOMExpandoValueGuardGeneration(
JitSpew(JitSpew_Codegen, "%s", __FUNCTION__);
Register obj = allocator.useRegister(masm, objId);
ExpandoAndGeneration* expandoAndGeneration =
rawWordStubField<ExpandoAndGeneration*>(expandoAndGenerationOffset);
rawPointerStubField<ExpandoAndGeneration*>(expandoAndGenerationOffset);
uint64_t* generationFieldPtr =
expandoGenerationStubFieldPtr(generationOffset);
@ -2504,6 +2506,14 @@ bool IonCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
uint32_t targetOffset) {
MOZ_CRASH("Call ICs not used in ion");
}
bool IonCacheIRCompiler::emitCallDOMFunction(ObjOperandId calleeId,
Int32OperandId argcId,
ObjOperandId thisObjId,
CallFlags flags,
uint32_t targetOffset) {
MOZ_CRASH("Call ICs not used in ion");
}
#else
bool IonCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
Int32OperandId argcId,
@ -2511,6 +2521,13 @@ bool IonCacheIRCompiler::emitCallNativeFunction(ObjOperandId calleeId,
bool ignoresReturnValue) {
MOZ_CRASH("Call ICs not used in ion");
}
bool IonCacheIRCompiler::emitCallDOMFunction(ObjOperandId calleeId,
Int32OperandId argcId,
ObjOperandId thisObjId,
CallFlags flags) {
MOZ_CRASH("Call ICs not used in ion");
}
#endif
bool IonCacheIRCompiler::emitCallClassHook(ObjOperandId calleeId,

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

@ -53,7 +53,7 @@ class MOZ_RAII IonCacheIRCompiler : public CacheIRCompiler {
bool savedLiveRegs_;
template <typename T>
T rawWordStubField(uint32_t offset);
T rawPointerStubField(uint32_t offset);
template <typename T>
T rawInt64StubField(uint32_t offset);

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

@ -7,6 +7,7 @@
#include "jit/IonCompileTask.h"
#include "jit/CodeGenerator.h"
#include "jit/JitRuntime.h"
#include "jit/JitScript.h"
#include "jit/WarpSnapshot.h"
#include "vm/HelperThreadState.h"

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

@ -22,6 +22,7 @@ namespace jit {
class CodeGenerator;
class MRootList;
class WarpSnapshot;
// IonCompileTask represents a single off-thread Ion compilation task.
class IonCompileTask final : public HelperThreadTask,

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

@ -6,8 +6,9 @@
#include "jit/IonIC.h"
#include "jit/AutoDetectInvalidation.h"
#include "jit/CacheIRCompiler.h"
#include "jit/Linker.h"
#include "jit/VMFunctions.h"
#include "util/DiagnosticAssertions.h"
#include "jit/MacroAssembler-inl.h"

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

@ -14,6 +14,7 @@
#include "jstypes.h"
#include "gc/Barrier.h" // HeapPtr{JitCode,Object}, PreBarrieredValue
#include "jit/IonOptimizationLevels.h" // OptimizationLevel
#include "jit/IonTypes.h" // IonCompilationId
#include "jit/JitCode.h" // JitCode

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

@ -8,11 +8,14 @@
#include "jit/BaselineDebugModeOSR.h"
#include "jit/BaselineIC.h"
#include "jit/CalleeToken.h"
#include "jit/IonScript.h"
#include "jit/JitcodeMap.h"
#include "jit/JitFrames.h"
#include "jit/JitRuntime.h"
#include "jit/JitScript.h"
#include "jit/Safepoints.h"
#include "jit/VMFunctions.h"
#include "js/friend/DumpFunctions.h" // js::DumpObject, js::DumpValue
#include "vm/JSScript-inl.h"

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

@ -23,8 +23,6 @@ class ArgumentsObject;
namespace jit {
using CalleeToken = void*;
enum class FrameType {
// A JS frame is analogous to a js::InterpreterFrame, representing one
// scripted function activation. IonJS frames are used by the optimizing

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

@ -7,9 +7,10 @@
#include "jit/Jit.h"
#include "jit/BaselineJIT.h"
#include "jit/CalleeToken.h"
#include "jit/Ion.h"
#include "jit/JitCommon.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "js/friend/StackLimits.h" // js::CheckRecursionLimit
#include "vm/Interpreter.h"

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

@ -7,17 +7,21 @@
#ifndef jit_JitAllocPolicy_h
#define jit_JitAllocPolicy_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
#include "mozilla/OperatorNewExtensions.h"
#include "mozilla/TemplateLib.h"
#include <algorithm>
#include <stddef.h>
#include <string.h>
#include <type_traits>
#include <utility>
#include "ds/LifoAlloc.h"
#include "jit/InlineList.h"
#include "jit/JitContext.h"
#include "vm/JSContext.h"
#include "js/Utility.h"
namespace js {
namespace jit {
@ -122,25 +126,6 @@ class JitAllocPolicy {
}
};
class AutoJitContextAlloc {
TempAllocator tempAlloc_;
JitContext* jcx_;
TempAllocator* prevAlloc_;
public:
explicit AutoJitContextAlloc(JSContext* cx)
: tempAlloc_(&cx->tempLifoAlloc()),
jcx_(GetJitContext()),
prevAlloc_(jcx_->temp) {
jcx_->temp = &tempAlloc_;
}
~AutoJitContextAlloc() {
MOZ_ASSERT(jcx_->temp == &tempAlloc_);
jcx_->temp = prevAlloc_;
}
};
struct TempObject {
inline void* operator new(size_t nbytes,
TempAllocator::Fallible view) noexcept(true) {

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

@ -6,77 +6,32 @@
#include "jit/JitContext.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Assertions.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/Unused.h"
#include "gc/FreeOp.h"
#include "gc/Marking.h"
#include "gc/PublicIterators.h"
#include "jit/AliasAnalysis.h"
#include "jit/AlignmentMaskAnalysis.h"
#include "jit/BacktrackingAllocator.h"
#include "jit/BaselineFrame.h"
#include "jit/BaselineInspector.h"
#include "jit/BaselineJIT.h"
#include <stdlib.h>
#include "jit/CacheIRSpewer.h"
#include "jit/CodeGenerator.h"
#include "jit/EdgeCaseAnalysis.h"
#include "jit/EffectiveAddressAnalysis.h"
#include "jit/FoldLinearArithConstants.h"
#include "jit/InstructionReordering.h"
#include "jit/IonAnalysis.h"
#include "jit/IonBuilder.h"
#include "jit/IonIC.h"
#include "jit/IonOptimizationLevels.h"
#include "jit/JitcodeMap.h"
#include "jit/JitCommon.h"
#include "jit/JitRealm.h"
#include "jit/CompileWrappers.h"
#include "jit/JitCode.h"
#include "jit/JitOptions.h"
#include "jit/JitSpewer.h"
#include "jit/LICM.h"
#include "jit/Linker.h"
#include "jit/LIR.h"
#include "jit/Lowering.h"
#include "jit/MacroAssembler.h"
#include "jit/PerfSpewer.h"
#include "jit/RangeAnalysis.h"
#include "jit/ScalarReplacement.h"
#include "jit/Sink.h"
#include "jit/ValueNumbering.h"
#include "jit/WasmBCE.h"
#include "js/Printf.h"
#include "js/UniquePtr.h"
#include "util/Memory.h"
#include "util/Windows.h"
#include "vm/HelperThreads.h"
#include "vm/Realm.h"
#include "vm/TraceLogging.h"
#ifdef MOZ_VTUNE
# include "vtune/VTuneWrapper.h"
#endif
#include "debugger/DebugAPI-inl.h"
#include "gc/GC-inl.h"
#include "jit/JitFrames-inl.h"
#include "jit/MacroAssembler-inl.h"
#include "jit/shared/Lowering-shared-inl.h"
#include "vm/EnvironmentObject-inl.h"
#include "vm/GeckoProfiler-inl.h"
#include "vm/JSObject-inl.h"
#include "vm/JSScript-inl.h"
#include "vm/Realm-inl.h"
#include "vm/Stack-inl.h"
#include "js/HeapAPI.h"
#include "vm/JSContext.h"
#if defined(ANDROID)
# include <sys/system_properties.h>
#endif
using mozilla::DebugOnly;
using namespace js;
using namespace js::jit;
namespace js::jit {
class TempAllocator;
}
// Assert that JitCode is gc::Cell aligned.
static_assert(sizeof(JitCode) % gc::CellAlignBytes == 0);

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

@ -19,7 +19,7 @@
#include "jit/Ion.h"
#include "jit/IonScript.h"
#include "jit/JitcodeMap.h"
#include "jit/JitRealm.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "jit/PcScriptCache.h"
#include "jit/Recover.h"

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

@ -9,6 +9,7 @@
#include <stdint.h> // uintptr_t
#include "jit/CalleeToken.h"
#include "jit/JSJitFrameIter.h"
#include "vm/JSContext.h"
#include "vm/JSFunction.h"
@ -19,50 +20,6 @@ namespace jit {
struct SafepointSlotEntry;
struct VMFunctionData;
enum CalleeTokenTag {
CalleeToken_Function = 0x0, // untagged
CalleeToken_FunctionConstructing = 0x1,
CalleeToken_Script = 0x2
};
// Any CalleeToken with this bit set must be CalleeToken_Script.
static const uintptr_t CalleeTokenScriptBit = CalleeToken_Script;
static const uintptr_t CalleeTokenMask = ~uintptr_t(0x3);
static inline CalleeTokenTag GetCalleeTokenTag(CalleeToken token) {
CalleeTokenTag tag = CalleeTokenTag(uintptr_t(token) & 0x3);
MOZ_ASSERT(tag <= CalleeToken_Script);
return tag;
}
static inline CalleeToken CalleeToToken(JSFunction* fun, bool constructing) {
CalleeTokenTag tag =
constructing ? CalleeToken_FunctionConstructing : CalleeToken_Function;
return CalleeToken(uintptr_t(fun) | uintptr_t(tag));
}
static inline CalleeToken CalleeToToken(JSScript* script) {
return CalleeToken(uintptr_t(script) | uintptr_t(CalleeToken_Script));
}
static inline bool CalleeTokenIsFunction(CalleeToken token) {
CalleeTokenTag tag = GetCalleeTokenTag(token);
return tag == CalleeToken_Function || tag == CalleeToken_FunctionConstructing;
}
static inline bool CalleeTokenIsConstructing(CalleeToken token) {
return GetCalleeTokenTag(token) == CalleeToken_FunctionConstructing;
}
static inline JSFunction* CalleeTokenToFunction(CalleeToken token) {
MOZ_ASSERT(CalleeTokenIsFunction(token));
return (JSFunction*)(uintptr_t(token) & CalleeTokenMask);
}
static inline JSScript* CalleeTokenToScript(CalleeToken token) {
MOZ_ASSERT(GetCalleeTokenTag(token) == CalleeToken_Script);
return (JSScript*)(uintptr_t(token) & CalleeTokenMask);
}
static inline bool CalleeTokenIsModuleScript(CalleeToken token) {
CalleeTokenTag tag = GetCalleeTokenTag(token);
return tag == CalleeToken_Script && CalleeTokenToScript(token)->isModule();
}
static inline JSScript* ScriptFromCalleeToken(CalleeToken token) {
switch (GetCalleeTokenTag(token)) {
case CalleeToken_Script:
@ -852,8 +809,6 @@ class InvalidationBailoutStack {
void GetPcScript(JSContext* cx, JSScript** scriptRes, jsbytecode** pcRes);
CalleeToken TraceCalleeToken(JSTracer* trc, CalleeToken token);
// Baseline requires one slot for this/argument type checks.
static const uint32_t MinJITStackSize = 1;

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

@ -7,567 +7,42 @@
#ifndef jit_JitRealm_h
#define jit_JitRealm_h
#include "mozilla/Array.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/MemoryReporting.h"
#include <utility>
#include <stddef.h>
#include <stdint.h>
#include "builtin/TypedObject.h"
#include "jit/BaselineICList.h"
#include "jit/BaselineJIT.h"
#include "jit/CompileInfo.h"
#include "jit/ICStubSpace.h"
#include "jit/JitCode.h"
#include "jit/JitFrames.h"
#include "jit/shared/Assembler-shared.h"
#include "gc/Barrier.h"
#include "gc/ZoneAllocator.h"
#include "js/GCHashTable.h"
#include "js/Value.h"
#include "vm/Stack.h"
#include "js/RootingAPI.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
namespace js {
MOZ_COLD void ReportOutOfMemory(JSContext* cx);
namespace jit {
class FrameSizeClass;
struct VMFunctionData;
class JitCode;
enum class TailCallVMFunctionId;
enum class VMFunctionId;
struct EnterJitData {
explicit EnterJitData(JSContext* cx)
: jitcode(nullptr),
osrFrame(nullptr),
calleeToken(nullptr),
maxArgv(nullptr),
maxArgc(0),
numActualArgs(0),
osrNumStackValues(0),
envChain(cx),
result(cx),
constructing(false) {}
uint8_t* jitcode;
InterpreterFrame* osrFrame;
void* calleeToken;
Value* maxArgv;
unsigned maxArgc;
unsigned numActualArgs;
unsigned osrNumStackValues;
RootedObject envChain;
RootedValue result;
bool constructing;
};
enum class BaselineICFallbackKind {
#define DEF_ENUM_KIND(kind) kind,
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_ENUM_KIND)
#undef DEF_ENUM_KIND
Count
};
enum class BailoutReturnKind {
GetProp,
GetPropSuper,
SetProp,
GetElem,
GetElemSuper,
Call,
New,
Count
};
// Class storing code and offsets for all Baseline IC fallback trampolines. This
// is stored in JitRuntime and generated when creating the JitRuntime.
class BaselineICFallbackCode {
JitCode* code_ = nullptr;
using OffsetArray =
mozilla::EnumeratedArray<BaselineICFallbackKind,
BaselineICFallbackKind::Count, uint32_t>;
OffsetArray offsets_ = {};
// Keep track of offset into various baseline stubs' code at return
// point from called script.
using BailoutReturnArray =
mozilla::EnumeratedArray<BailoutReturnKind, BailoutReturnKind::Count,
uint32_t>;
BailoutReturnArray bailoutReturnOffsets_ = {};
public:
BaselineICFallbackCode() = default;
BaselineICFallbackCode(const BaselineICFallbackCode&) = delete;
void operator=(const BaselineICFallbackCode&) = delete;
void initOffset(BaselineICFallbackKind kind, uint32_t offset) {
offsets_[kind] = offset;
}
void initCode(JitCode* code) { code_ = code; }
void initBailoutReturnOffset(BailoutReturnKind kind, uint32_t offset) {
bailoutReturnOffsets_[kind] = offset;
}
TrampolinePtr addr(BaselineICFallbackKind kind) const {
return TrampolinePtr(code_->raw() + offsets_[kind]);
}
uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
return code_->raw() + bailoutReturnOffsets_[kind];
}
};
enum class ArgumentsRectifierKind { Normal, TrialInlining };
enum class DebugTrapHandlerKind { Interpreter, Compiler, Count };
using EnterJitCode = void (*)(void*, unsigned int, Value*, InterpreterFrame*,
CalleeToken, JSObject*, size_t, Value*);
class JitcodeGlobalTable;
class JitRuntime {
private:
friend class JitRealm;
MainThreadData<uint64_t> nextCompilationId_{0};
// Buffer for OSR from baseline to Ion. To avoid holding on to this for too
// long it's also freed in EnterBaseline and EnterJit (after returning from
// JIT code).
MainThreadData<js::UniquePtr<uint8_t>> ionOsrTempData_{nullptr};
// Shared exception-handler tail.
WriteOnceData<uint32_t> exceptionTailOffset_{0};
// Shared post-bailout-handler tail.
WriteOnceData<uint32_t> bailoutTailOffset_{0};
// Shared profiler exit frame tail.
WriteOnceData<uint32_t> profilerExitFrameTailOffset_{0};
// Trampoline for entering JIT code.
WriteOnceData<uint32_t> enterJITOffset_{0};
// Vector mapping frame class sizes to bailout tables.
struct BailoutTable {
uint32_t startOffset;
uint32_t size;
BailoutTable(uint32_t startOffset, uint32_t size)
: startOffset(startOffset), size(size) {}
};
typedef Vector<BailoutTable, 4, SystemAllocPolicy> BailoutTableVector;
WriteOnceData<BailoutTableVector> bailoutTables_;
// Generic bailout table; used if the bailout table overflows.
WriteOnceData<uint32_t> bailoutHandlerOffset_{0};
// Argument-rectifying thunks, in the case of insufficient arguments passed
// to a function call site. The return offset is used to rebuild stack frames
// when bailing out.
WriteOnceData<uint32_t> argumentsRectifierOffset_{0};
WriteOnceData<uint32_t> trialInliningArgumentsRectifierOffset_{0};
WriteOnceData<uint32_t> argumentsRectifierReturnOffset_{0};
// Thunk that invalides an (Ion compiled) caller on the Ion stack.
WriteOnceData<uint32_t> invalidatorOffset_{0};
// Thunk that calls the GC pre barrier.
WriteOnceData<uint32_t> valuePreBarrierOffset_{0};
WriteOnceData<uint32_t> stringPreBarrierOffset_{0};
WriteOnceData<uint32_t> objectPreBarrierOffset_{0};
WriteOnceData<uint32_t> shapePreBarrierOffset_{0};
WriteOnceData<uint32_t> objectGroupPreBarrierOffset_{0};
// Thunk to call malloc/free.
WriteOnceData<uint32_t> freeStubOffset_{0};
// Thunk called to finish compilation of an IonScript.
WriteOnceData<uint32_t> lazyLinkStubOffset_{0};
// Thunk to enter the interpreter from JIT code.
WriteOnceData<uint32_t> interpreterStubOffset_{0};
// Thunk to convert the value in R0 to int32 if it's a double.
// Note: this stub treats -0 as +0 and may clobber R1.scratchReg().
WriteOnceData<uint32_t> doubleToInt32ValueStubOffset_{0};
// Thunk used by the debugger for breakpoint and step mode.
mozilla::EnumeratedArray<DebugTrapHandlerKind, DebugTrapHandlerKind::Count,
WriteOnceData<JitCode*>>
debugTrapHandlers_;
// BaselineInterpreter state.
BaselineInterpreter baselineInterpreter_;
// Code for trampolines and VMFunction wrappers.
WriteOnceData<JitCode*> trampolineCode_{nullptr};
// Maps VMFunctionId to the offset of the wrapper code in trampolineCode_.
using VMWrapperOffsets = Vector<uint32_t, 0, SystemAllocPolicy>;
VMWrapperOffsets functionWrapperOffsets_;
// Maps TailCallVMFunctionId to the offset of the wrapper code in
// trampolineCode_.
VMWrapperOffsets tailCallFunctionWrapperOffsets_;
MainThreadData<BaselineICFallbackCode> baselineICFallbackCode_;
// Global table of jitcode native address => bytecode address mappings.
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_{nullptr};
#ifdef DEBUG
// The number of possible bailing places encountered before forcefully bailing
// in that place if the counter reaches zero. Note that zero also means
// inactive.
MainThreadData<uint32_t> ionBailAfterCounter_{0};
// Whether the bailAfter mechanism is enabled. Used to avoid generating the
// Ion code instrumentation for ionBailAfterCounter_ if the testing function
// isn't used.
MainThreadData<bool> ionBailAfterEnabled_{false};
#endif
// Number of Ion compilations which were finished off thread and are
// waiting to be lazily linked. This is only set while holding the helper
// thread state lock, but may be read from at other times.
typedef mozilla::Atomic<size_t, mozilla::SequentiallyConsistent>
NumFinishedOffThreadTasksType;
NumFinishedOffThreadTasksType numFinishedOffThreadTasks_{0};
// List of Ion compilation waiting to get linked.
using IonCompileTaskList = mozilla::LinkedList<js::jit::IonCompileTask>;
MainThreadData<IonCompileTaskList> ionLazyLinkList_;
MainThreadData<size_t> ionLazyLinkListSize_{0};
// Counter used to help dismbiguate stubs in CacheIR
MainThreadData<uint64_t> disambiguationId_{0};
#ifdef DEBUG
// Flag that can be set from JIT code to indicate it's invalid to call
// arbitrary JS code in a particular region. This is checked in RunScript.
MainThreadData<uint32_t> disallowArbitraryCode_{false};
#endif
bool generateTrampolines(JSContext* cx);
bool generateBaselineICFallbackCode(JSContext* cx);
void generateLazyLinkStub(MacroAssembler& masm);
void generateInterpreterStub(MacroAssembler& masm);
void generateDoubleToInt32ValueStub(MacroAssembler& masm);
void generateProfilerExitFrameTailStub(MacroAssembler& masm,
Label* profilerExitTail);
void generateExceptionTailStub(MacroAssembler& masm, void* handler,
Label* profilerExitTail);
void generateBailoutTailStub(MacroAssembler& masm, Label* bailoutTail);
void generateEnterJIT(JSContext* cx, MacroAssembler& masm);
void generateArgumentsRectifier(MacroAssembler& masm,
ArgumentsRectifierKind kind);
BailoutTable generateBailoutTable(MacroAssembler& masm, Label* bailoutTail,
uint32_t frameClass);
void generateBailoutHandler(MacroAssembler& masm, Label* bailoutTail);
void generateInvalidator(MacroAssembler& masm, Label* bailoutTail);
uint32_t generatePreBarrier(JSContext* cx, MacroAssembler& masm,
MIRType type);
void generateFreeStub(MacroAssembler& masm);
JitCode* generateDebugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
bool generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
uint32_t* wrapperOffset);
template <typename IdT>
bool generateVMWrappers(JSContext* cx, MacroAssembler& masm,
VMWrapperOffsets& offsets);
bool generateVMWrappers(JSContext* cx, MacroAssembler& masm);
bool generateTLEventVM(MacroAssembler& masm, const VMFunctionData& f,
bool enter);
inline bool generateTLEnterVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ true);
}
inline bool generateTLExitVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ false);
}
uint32_t startTrampolineCode(MacroAssembler& masm);
TrampolinePtr trampolineCode(uint32_t offset) const {
MOZ_ASSERT(offset > 0);
MOZ_ASSERT(offset < trampolineCode_->instructionsSize());
return TrampolinePtr(trampolineCode_->raw() + offset);
}
public:
JitRuntime() = default;
~JitRuntime();
MOZ_MUST_USE bool initialize(JSContext* cx);
static void TraceAtomZoneRoots(JSTracer* trc,
const js::AutoAccessAtomsZone& access);
static MOZ_MUST_USE bool MarkJitcodeGlobalTableIteratively(GCMarker* marker);
static void TraceWeakJitcodeGlobalTable(JSRuntime* rt, JSTracer* trc);
const BaselineICFallbackCode& baselineICFallbackCode() const {
return baselineICFallbackCode_.ref();
}
IonCompilationId nextCompilationId() {
return IonCompilationId(nextCompilationId_++);
}
#ifdef DEBUG
bool disallowArbitraryCode() const { return disallowArbitraryCode_; }
void clearDisallowArbitraryCode() { disallowArbitraryCode_ = false; }
const void* addressOfDisallowArbitraryCode() const {
return &disallowArbitraryCode_.refNoCheck();
}
#endif
uint8_t* allocateIonOsrTempData(size_t size);
void freeIonOsrTempData();
TrampolinePtr getVMWrapper(VMFunctionId funId) const {
MOZ_ASSERT(trampolineCode_);
return trampolineCode(functionWrapperOffsets_[size_t(funId)]);
}
TrampolinePtr getVMWrapper(TailCallVMFunctionId funId) const {
MOZ_ASSERT(trampolineCode_);
return trampolineCode(tailCallFunctionWrapperOffsets_[size_t(funId)]);
}
JitCode* debugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
BaselineInterpreter& baselineInterpreter() { return baselineInterpreter_; }
TrampolinePtr getGenericBailoutHandler() const {
return trampolineCode(bailoutHandlerOffset_);
}
TrampolinePtr getExceptionTail() const {
return trampolineCode(exceptionTailOffset_);
}
TrampolinePtr getBailoutTail() const {
return trampolineCode(bailoutTailOffset_);
}
TrampolinePtr getProfilerExitFrameTail() const {
return trampolineCode(profilerExitFrameTailOffset_);
}
TrampolinePtr getBailoutTable(const FrameSizeClass& frameClass) const;
uint32_t getBailoutTableSize(const FrameSizeClass& frameClass) const;
TrampolinePtr getArgumentsRectifier(
ArgumentsRectifierKind kind = ArgumentsRectifierKind::Normal) const {
if (kind == ArgumentsRectifierKind::TrialInlining) {
return trampolineCode(trialInliningArgumentsRectifierOffset_);
}
return trampolineCode(argumentsRectifierOffset_);
}
TrampolinePtr getArgumentsRectifierReturnAddr() const {
return trampolineCode(argumentsRectifierReturnOffset_);
}
TrampolinePtr getInvalidationThunk() const {
return trampolineCode(invalidatorOffset_);
}
EnterJitCode enterJit() const {
return JS_DATA_TO_FUNC_PTR(EnterJitCode,
trampolineCode(enterJITOffset_).value);
}
TrampolinePtr preBarrier(MIRType type) const {
switch (type) {
case MIRType::Value:
return trampolineCode(valuePreBarrierOffset_);
case MIRType::String:
return trampolineCode(stringPreBarrierOffset_);
case MIRType::Object:
return trampolineCode(objectPreBarrierOffset_);
case MIRType::Shape:
return trampolineCode(shapePreBarrierOffset_);
case MIRType::ObjectGroup:
return trampolineCode(objectGroupPreBarrierOffset_);
default:
MOZ_CRASH();
}
}
TrampolinePtr freeStub() const { return trampolineCode(freeStubOffset_); }
TrampolinePtr lazyLinkStub() const {
return trampolineCode(lazyLinkStubOffset_);
}
TrampolinePtr interpreterStub() const {
return trampolineCode(interpreterStubOffset_);
}
TrampolinePtr getDoubleToInt32ValueStub() const {
return trampolineCode(doubleToInt32ValueStubOffset_);
}
bool hasJitcodeGlobalTable() const { return jitcodeGlobalTable_ != nullptr; }
JitcodeGlobalTable* getJitcodeGlobalTable() {
MOZ_ASSERT(hasJitcodeGlobalTable());
return jitcodeGlobalTable_;
}
bool isProfilerInstrumentationEnabled(JSRuntime* rt) {
return rt->geckoProfiler().enabled();
}
bool isOptimizationTrackingEnabled(JSRuntime* rt) {
return isProfilerInstrumentationEnabled(rt);
}
#ifdef DEBUG
void* addressOfIonBailAfterCounter() { return &ionBailAfterCounter_; }
// Set after how many bailing places we should forcefully bail.
// Zero disables this feature.
void setIonBailAfterCounter(uint32_t after) { ionBailAfterCounter_ = after; }
bool ionBailAfterEnabled() const { return ionBailAfterEnabled_; }
void setIonBailAfterEnabled(bool enabled) { ionBailAfterEnabled_ = enabled; }
#endif
size_t numFinishedOffThreadTasks() const {
return numFinishedOffThreadTasks_;
}
NumFinishedOffThreadTasksType& numFinishedOffThreadTasksRef(
const AutoLockHelperThreadState& locked) {
return numFinishedOffThreadTasks_;
}
IonCompileTaskList& ionLazyLinkList(JSRuntime* rt);
size_t ionLazyLinkListSize() const { return ionLazyLinkListSize_; }
void ionLazyLinkListRemove(JSRuntime* rt, js::jit::IonCompileTask* task);
void ionLazyLinkListAdd(JSRuntime* rt, js::jit::IonCompileTask* task);
uint64_t nextDisambiguationId() { return disambiguationId_++; }
};
enum class CacheKind : uint8_t;
class CacheIRStubInfo;
enum class ICStubEngine : uint8_t {
// Baseline IC, see BaselineIC.h.
Baseline = 0,
// Ion IC, see IonIC.h.
IonIC
};
struct CacheIRStubKey : public DefaultHasher<CacheIRStubKey> {
struct Lookup {
CacheKind kind;
ICStubEngine engine;
const uint8_t* code;
uint32_t length;
Lookup(CacheKind kind, ICStubEngine engine, const uint8_t* code,
uint32_t length)
: kind(kind), engine(engine), code(code), length(length) {}
};
static HashNumber hash(const Lookup& l);
static bool match(const CacheIRStubKey& entry, const Lookup& l);
UniquePtr<CacheIRStubInfo, JS::FreePolicy> stubInfo;
explicit CacheIRStubKey(CacheIRStubInfo* info) : stubInfo(info) {}
CacheIRStubKey(CacheIRStubKey&& other)
: stubInfo(std::move(other.stubInfo)) {}
void operator=(CacheIRStubKey&& other) {
stubInfo = std::move(other.stubInfo);
}
};
template <typename Key>
struct IcStubCodeMapGCPolicy {
static bool traceWeak(JSTracer* trc, Key*, WeakHeapPtrJitCode* value) {
static bool traceWeak(JSTracer* trc, uint32_t*, WeakHeapPtrJitCode* value) {
return TraceWeakEdge(trc, value, "traceWeak");
}
};
class JitZone {
// Allocated space for optimized baseline stubs.
OptimizedICStubSpace optimizedStubSpace_;
// Set of CacheIRStubInfo instances used by Ion stubs in this Zone.
using IonCacheIRStubInfoSet =
HashSet<CacheIRStubKey, CacheIRStubKey, SystemAllocPolicy>;
IonCacheIRStubInfoSet ionCacheIRStubInfoSet_;
// Map CacheIRStubKey to shared JitCode objects.
using BaselineCacheIRStubCodeMap =
GCHashMap<CacheIRStubKey, WeakHeapPtrJitCode, CacheIRStubKey,
SystemAllocPolicy, IcStubCodeMapGCPolicy<CacheIRStubKey>>;
BaselineCacheIRStubCodeMap baselineCacheIRStubCodes_;
// Executable allocator for all code except wasm code.
MainThreadData<ExecutableAllocator> execAlloc_;
public:
void traceWeak(JSTracer* trc);
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
JS::CodeSizes* code, size_t* jitZone,
size_t* baselineStubsOptimized) const;
OptimizedICStubSpace* optimizedStubSpace() { return &optimizedStubSpace_; }
JitCode* getBaselineCacheIRStubCode(const CacheIRStubKey::Lookup& key,
CacheIRStubInfo** stubInfo) {
auto p = baselineCacheIRStubCodes_.lookup(key);
if (p) {
*stubInfo = p->key().stubInfo.get();
return p->value();
}
*stubInfo = nullptr;
return nullptr;
}
MOZ_MUST_USE bool putBaselineCacheIRStubCode(
const CacheIRStubKey::Lookup& lookup, CacheIRStubKey& key,
JitCode* stubCode) {
auto p = baselineCacheIRStubCodes_.lookupForAdd(lookup);
MOZ_ASSERT(!p);
return baselineCacheIRStubCodes_.add(p, std::move(key), stubCode);
}
CacheIRStubInfo* getIonCacheIRStubInfo(const CacheIRStubKey::Lookup& key) {
IonCacheIRStubInfoSet::Ptr p = ionCacheIRStubInfoSet_.lookup(key);
return p ? p->stubInfo.get() : nullptr;
}
MOZ_MUST_USE bool putIonCacheIRStubInfo(const CacheIRStubKey::Lookup& lookup,
CacheIRStubKey& key) {
IonCacheIRStubInfoSet::AddPtr p =
ionCacheIRStubInfoSet_.lookupForAdd(lookup);
MOZ_ASSERT(!p);
return ionCacheIRStubInfoSet_.add(p, std::move(key));
}
void purgeIonCacheIRStubInfo() { ionCacheIRStubInfoSet_.clearAndCompact(); }
ExecutableAllocator& execAlloc() { return execAlloc_.ref(); }
const ExecutableAllocator& execAlloc() const { return execAlloc_.ref(); }
};
class JitRealm {
friend class JitActivation;
// Map ICStub keys to ICStub shared code objects.
using ICStubCodeMap =
GCHashMap<uint32_t, WeakHeapPtrJitCode, DefaultHasher<uint32_t>,
ZoneAllocPolicy, IcStubCodeMapGCPolicy<uint32_t>>;
ZoneAllocPolicy, IcStubCodeMapGCPolicy>;
ICStubCodeMap* stubCodes_;
// The JitRealm stores stubs to concatenate strings inline and perform RegExp
@ -710,64 +185,6 @@ class JitRealm {
size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
};
// Called from Zone::discardJitCode().
void InvalidateAll(JSFreeOp* fop, JS::Zone* zone);
void FinishInvalidation(JSFreeOp* fop, JSScript* script);
// This class ensures JIT code is executable on its destruction. Creators
// must call makeWritable(), and not attempt to write to the buffer if it fails.
//
// AutoWritableJitCodeFallible may only fail to make code writable; it cannot
// fail to make JIT code executable (because the creating code has no chance to
// recover from a failed destructor).
class MOZ_RAII AutoWritableJitCodeFallible {
JSRuntime* rt_;
void* addr_;
size_t size_;
public:
AutoWritableJitCodeFallible(JSRuntime* rt, void* addr, size_t size)
: rt_(rt), addr_(addr), size_(size) {
rt_->toggleAutoWritableJitCodeActive(true);
}
AutoWritableJitCodeFallible(void* addr, size_t size)
: AutoWritableJitCodeFallible(TlsContext.get()->runtime(), addr, size) {}
explicit AutoWritableJitCodeFallible(JitCode* code)
: AutoWritableJitCodeFallible(code->runtimeFromMainThread(), code->raw(),
code->bufferSize()) {}
MOZ_MUST_USE bool makeWritable() {
return ExecutableAllocator::makeWritable(addr_, size_);
}
~AutoWritableJitCodeFallible() {
if (!ExecutableAllocator::makeExecutableAndFlushICache(
FlushICacheSpec::LocalThreadOnly, addr_, size_)) {
MOZ_CRASH();
}
rt_->toggleAutoWritableJitCodeActive(false);
}
};
// Infallible variant of AutoWritableJitCodeFallible, ensures writable during
// construction
class MOZ_RAII AutoWritableJitCode : private AutoWritableJitCodeFallible {
public:
AutoWritableJitCode(JSRuntime* rt, void* addr, size_t size)
: AutoWritableJitCodeFallible(rt, addr, size) {
MOZ_RELEASE_ASSERT(makeWritable());
}
AutoWritableJitCode(void* addr, size_t size)
: AutoWritableJitCode(TlsContext.get()->runtime(), addr, size) {}
explicit AutoWritableJitCode(JitCode* code)
: AutoWritableJitCode(code->runtimeFromMainThread(), code->raw(),
code->bufferSize()) {}
};
} // namespace jit
} // namespace js

449
js/src/jit/JitRuntime.h Normal file
Просмотреть файл

@ -0,0 +1,449 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_JitRuntime_h
#define jit_JitRuntime_h
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/EnumeratedArray.h"
#include "mozilla/LinkedList.h"
#include <stddef.h>
#include <stdint.h>
#include "jstypes.h"
#include "jit/BaselineICList.h"
#include "jit/BaselineJIT.h"
#include "jit/CalleeToken.h"
#include "jit/IonCompileTask.h"
#include "jit/IonTypes.h"
#include "jit/JitCode.h"
#include "jit/shared/Assembler-shared.h"
#include "js/AllocPolicy.h"
#include "js/TypeDecls.h"
#include "js/UniquePtr.h"
#include "js/Vector.h"
#include "threading/ProtectedData.h"
#include "vm/GeckoProfiler.h"
#include "vm/Runtime.h"
class JS_PUBLIC_API JSTracer;
namespace js {
class AutoAccessAtomsZone;
class AutoLockHelperThreadState;
class GCMarker;
namespace jit {
class FrameSizeClass;
class JitRealm;
class Label;
class MacroAssembler;
struct VMFunctionData;
enum class TailCallVMFunctionId;
enum class VMFunctionId;
enum class BaselineICFallbackKind {
#define DEF_ENUM_KIND(kind) kind,
IC_BASELINE_FALLBACK_CODE_KIND_LIST(DEF_ENUM_KIND)
#undef DEF_ENUM_KIND
Count
};
enum class BailoutReturnKind {
GetProp,
GetPropSuper,
SetProp,
GetElem,
GetElemSuper,
Call,
New,
Count
};
// Class storing code and offsets for all Baseline IC fallback trampolines. This
// is stored in JitRuntime and generated when creating the JitRuntime.
class BaselineICFallbackCode {
JitCode* code_ = nullptr;
using OffsetArray =
mozilla::EnumeratedArray<BaselineICFallbackKind,
BaselineICFallbackKind::Count, uint32_t>;
OffsetArray offsets_ = {};
// Keep track of offset into various baseline stubs' code at return
// point from called script.
using BailoutReturnArray =
mozilla::EnumeratedArray<BailoutReturnKind, BailoutReturnKind::Count,
uint32_t>;
BailoutReturnArray bailoutReturnOffsets_ = {};
public:
BaselineICFallbackCode() = default;
BaselineICFallbackCode(const BaselineICFallbackCode&) = delete;
void operator=(const BaselineICFallbackCode&) = delete;
void initOffset(BaselineICFallbackKind kind, uint32_t offset) {
offsets_[kind] = offset;
}
void initCode(JitCode* code) { code_ = code; }
void initBailoutReturnOffset(BailoutReturnKind kind, uint32_t offset) {
bailoutReturnOffsets_[kind] = offset;
}
TrampolinePtr addr(BaselineICFallbackKind kind) const {
return TrampolinePtr(code_->raw() + offsets_[kind]);
}
uint8_t* bailoutReturnAddr(BailoutReturnKind kind) const {
return code_->raw() + bailoutReturnOffsets_[kind];
}
};
enum class ArgumentsRectifierKind { Normal, TrialInlining };
enum class DebugTrapHandlerKind { Interpreter, Compiler, Count };
using EnterJitCode = void (*)(void*, unsigned int, Value*, InterpreterFrame*,
CalleeToken, JSObject*, size_t, Value*);
class JitcodeGlobalTable;
class JitRuntime {
private:
friend class JitRealm;
MainThreadData<uint64_t> nextCompilationId_{0};
// Buffer for OSR from baseline to Ion. To avoid holding on to this for too
// long it's also freed in EnterBaseline and EnterJit (after returning from
// JIT code).
MainThreadData<js::UniquePtr<uint8_t>> ionOsrTempData_{nullptr};
// Shared exception-handler tail.
WriteOnceData<uint32_t> exceptionTailOffset_{0};
// Shared post-bailout-handler tail.
WriteOnceData<uint32_t> bailoutTailOffset_{0};
// Shared profiler exit frame tail.
WriteOnceData<uint32_t> profilerExitFrameTailOffset_{0};
// Trampoline for entering JIT code.
WriteOnceData<uint32_t> enterJITOffset_{0};
// Vector mapping frame class sizes to bailout tables.
struct BailoutTable {
uint32_t startOffset;
uint32_t size;
BailoutTable(uint32_t startOffset, uint32_t size)
: startOffset(startOffset), size(size) {}
};
typedef Vector<BailoutTable, 4, SystemAllocPolicy> BailoutTableVector;
WriteOnceData<BailoutTableVector> bailoutTables_;
// Generic bailout table; used if the bailout table overflows.
WriteOnceData<uint32_t> bailoutHandlerOffset_{0};
// Argument-rectifying thunks, in the case of insufficient arguments passed
// to a function call site. The return offset is used to rebuild stack frames
// when bailing out.
WriteOnceData<uint32_t> argumentsRectifierOffset_{0};
WriteOnceData<uint32_t> trialInliningArgumentsRectifierOffset_{0};
WriteOnceData<uint32_t> argumentsRectifierReturnOffset_{0};
// Thunk that invalides an (Ion compiled) caller on the Ion stack.
WriteOnceData<uint32_t> invalidatorOffset_{0};
// Thunk that calls the GC pre barrier.
WriteOnceData<uint32_t> valuePreBarrierOffset_{0};
WriteOnceData<uint32_t> stringPreBarrierOffset_{0};
WriteOnceData<uint32_t> objectPreBarrierOffset_{0};
WriteOnceData<uint32_t> shapePreBarrierOffset_{0};
WriteOnceData<uint32_t> objectGroupPreBarrierOffset_{0};
// Thunk to call malloc/free.
WriteOnceData<uint32_t> freeStubOffset_{0};
// Thunk called to finish compilation of an IonScript.
WriteOnceData<uint32_t> lazyLinkStubOffset_{0};
// Thunk to enter the interpreter from JIT code.
WriteOnceData<uint32_t> interpreterStubOffset_{0};
// Thunk to convert the value in R0 to int32 if it's a double.
// Note: this stub treats -0 as +0 and may clobber R1.scratchReg().
WriteOnceData<uint32_t> doubleToInt32ValueStubOffset_{0};
// Thunk used by the debugger for breakpoint and step mode.
mozilla::EnumeratedArray<DebugTrapHandlerKind, DebugTrapHandlerKind::Count,
WriteOnceData<JitCode*>>
debugTrapHandlers_;
// BaselineInterpreter state.
BaselineInterpreter baselineInterpreter_;
// Code for trampolines and VMFunction wrappers.
WriteOnceData<JitCode*> trampolineCode_{nullptr};
// Maps VMFunctionId to the offset of the wrapper code in trampolineCode_.
using VMWrapperOffsets = Vector<uint32_t, 0, SystemAllocPolicy>;
VMWrapperOffsets functionWrapperOffsets_;
// Maps TailCallVMFunctionId to the offset of the wrapper code in
// trampolineCode_.
VMWrapperOffsets tailCallFunctionWrapperOffsets_;
MainThreadData<BaselineICFallbackCode> baselineICFallbackCode_;
// Global table of jitcode native address => bytecode address mappings.
UnprotectedData<JitcodeGlobalTable*> jitcodeGlobalTable_{nullptr};
#ifdef DEBUG
// The number of possible bailing places encountered before forcefully bailing
// in that place if the counter reaches zero. Note that zero also means
// inactive.
MainThreadData<uint32_t> ionBailAfterCounter_{0};
// Whether the bailAfter mechanism is enabled. Used to avoid generating the
// Ion code instrumentation for ionBailAfterCounter_ if the testing function
// isn't used.
MainThreadData<bool> ionBailAfterEnabled_{false};
#endif
// Number of Ion compilations which were finished off thread and are
// waiting to be lazily linked. This is only set while holding the helper
// thread state lock, but may be read from at other times.
typedef mozilla::Atomic<size_t, mozilla::SequentiallyConsistent>
NumFinishedOffThreadTasksType;
NumFinishedOffThreadTasksType numFinishedOffThreadTasks_{0};
// List of Ion compilation waiting to get linked.
using IonCompileTaskList = mozilla::LinkedList<js::jit::IonCompileTask>;
MainThreadData<IonCompileTaskList> ionLazyLinkList_;
MainThreadData<size_t> ionLazyLinkListSize_{0};
// Counter used to help dismbiguate stubs in CacheIR
MainThreadData<uint64_t> disambiguationId_{0};
#ifdef DEBUG
// Flag that can be set from JIT code to indicate it's invalid to call
// arbitrary JS code in a particular region. This is checked in RunScript.
MainThreadData<uint32_t> disallowArbitraryCode_{false};
#endif
bool generateTrampolines(JSContext* cx);
bool generateBaselineICFallbackCode(JSContext* cx);
void generateLazyLinkStub(MacroAssembler& masm);
void generateInterpreterStub(MacroAssembler& masm);
void generateDoubleToInt32ValueStub(MacroAssembler& masm);
void generateProfilerExitFrameTailStub(MacroAssembler& masm,
Label* profilerExitTail);
void generateExceptionTailStub(MacroAssembler& masm, void* handler,
Label* profilerExitTail);
void generateBailoutTailStub(MacroAssembler& masm, Label* bailoutTail);
void generateEnterJIT(JSContext* cx, MacroAssembler& masm);
void generateArgumentsRectifier(MacroAssembler& masm,
ArgumentsRectifierKind kind);
BailoutTable generateBailoutTable(MacroAssembler& masm, Label* bailoutTail,
uint32_t frameClass);
void generateBailoutHandler(MacroAssembler& masm, Label* bailoutTail);
void generateInvalidator(MacroAssembler& masm, Label* bailoutTail);
uint32_t generatePreBarrier(JSContext* cx, MacroAssembler& masm,
MIRType type);
void generateFreeStub(MacroAssembler& masm);
JitCode* generateDebugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
bool generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
uint32_t* wrapperOffset);
template <typename IdT>
bool generateVMWrappers(JSContext* cx, MacroAssembler& masm,
VMWrapperOffsets& offsets);
bool generateVMWrappers(JSContext* cx, MacroAssembler& masm);
bool generateTLEventVM(MacroAssembler& masm, const VMFunctionData& f,
bool enter);
inline bool generateTLEnterVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ true);
}
inline bool generateTLExitVM(MacroAssembler& masm, const VMFunctionData& f) {
return generateTLEventVM(masm, f, /* enter = */ false);
}
uint32_t startTrampolineCode(MacroAssembler& masm);
TrampolinePtr trampolineCode(uint32_t offset) const {
MOZ_ASSERT(offset > 0);
MOZ_ASSERT(offset < trampolineCode_->instructionsSize());
return TrampolinePtr(trampolineCode_->raw() + offset);
}
public:
JitRuntime() = default;
~JitRuntime();
MOZ_MUST_USE bool initialize(JSContext* cx);
static void TraceAtomZoneRoots(JSTracer* trc,
const js::AutoAccessAtomsZone& access);
static MOZ_MUST_USE bool MarkJitcodeGlobalTableIteratively(GCMarker* marker);
static void TraceWeakJitcodeGlobalTable(JSRuntime* rt, JSTracer* trc);
const BaselineICFallbackCode& baselineICFallbackCode() const {
return baselineICFallbackCode_.ref();
}
IonCompilationId nextCompilationId() {
return IonCompilationId(nextCompilationId_++);
}
#ifdef DEBUG
bool disallowArbitraryCode() const { return disallowArbitraryCode_; }
void clearDisallowArbitraryCode() { disallowArbitraryCode_ = false; }
const void* addressOfDisallowArbitraryCode() const {
return &disallowArbitraryCode_.refNoCheck();
}
#endif
uint8_t* allocateIonOsrTempData(size_t size);
void freeIonOsrTempData();
TrampolinePtr getVMWrapper(VMFunctionId funId) const {
MOZ_ASSERT(trampolineCode_);
return trampolineCode(functionWrapperOffsets_[size_t(funId)]);
}
TrampolinePtr getVMWrapper(TailCallVMFunctionId funId) const {
MOZ_ASSERT(trampolineCode_);
return trampolineCode(tailCallFunctionWrapperOffsets_[size_t(funId)]);
}
JitCode* debugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
BaselineInterpreter& baselineInterpreter() { return baselineInterpreter_; }
TrampolinePtr getGenericBailoutHandler() const {
return trampolineCode(bailoutHandlerOffset_);
}
TrampolinePtr getExceptionTail() const {
return trampolineCode(exceptionTailOffset_);
}
TrampolinePtr getBailoutTail() const {
return trampolineCode(bailoutTailOffset_);
}
TrampolinePtr getProfilerExitFrameTail() const {
return trampolineCode(profilerExitFrameTailOffset_);
}
TrampolinePtr getBailoutTable(const FrameSizeClass& frameClass) const;
uint32_t getBailoutTableSize(const FrameSizeClass& frameClass) const;
TrampolinePtr getArgumentsRectifier(
ArgumentsRectifierKind kind = ArgumentsRectifierKind::Normal) const {
if (kind == ArgumentsRectifierKind::TrialInlining) {
return trampolineCode(trialInliningArgumentsRectifierOffset_);
}
return trampolineCode(argumentsRectifierOffset_);
}
TrampolinePtr getArgumentsRectifierReturnAddr() const {
return trampolineCode(argumentsRectifierReturnOffset_);
}
TrampolinePtr getInvalidationThunk() const {
return trampolineCode(invalidatorOffset_);
}
EnterJitCode enterJit() const {
return JS_DATA_TO_FUNC_PTR(EnterJitCode,
trampolineCode(enterJITOffset_).value);
}
TrampolinePtr preBarrier(MIRType type) const {
switch (type) {
case MIRType::Value:
return trampolineCode(valuePreBarrierOffset_);
case MIRType::String:
return trampolineCode(stringPreBarrierOffset_);
case MIRType::Object:
return trampolineCode(objectPreBarrierOffset_);
case MIRType::Shape:
return trampolineCode(shapePreBarrierOffset_);
case MIRType::ObjectGroup:
return trampolineCode(objectGroupPreBarrierOffset_);
default:
MOZ_CRASH();
}
}
TrampolinePtr freeStub() const { return trampolineCode(freeStubOffset_); }
TrampolinePtr lazyLinkStub() const {
return trampolineCode(lazyLinkStubOffset_);
}
TrampolinePtr interpreterStub() const {
return trampolineCode(interpreterStubOffset_);
}
TrampolinePtr getDoubleToInt32ValueStub() const {
return trampolineCode(doubleToInt32ValueStubOffset_);
}
bool hasJitcodeGlobalTable() const { return jitcodeGlobalTable_ != nullptr; }
JitcodeGlobalTable* getJitcodeGlobalTable() {
MOZ_ASSERT(hasJitcodeGlobalTable());
return jitcodeGlobalTable_;
}
bool isProfilerInstrumentationEnabled(JSRuntime* rt) {
return rt->geckoProfiler().enabled();
}
bool isOptimizationTrackingEnabled(JSRuntime* rt) {
return isProfilerInstrumentationEnabled(rt);
}
#ifdef DEBUG
void* addressOfIonBailAfterCounter() { return &ionBailAfterCounter_; }
// Set after how many bailing places we should forcefully bail.
// Zero disables this feature.
void setIonBailAfterCounter(uint32_t after) { ionBailAfterCounter_ = after; }
bool ionBailAfterEnabled() const { return ionBailAfterEnabled_; }
void setIonBailAfterEnabled(bool enabled) { ionBailAfterEnabled_ = enabled; }
#endif
size_t numFinishedOffThreadTasks() const {
return numFinishedOffThreadTasks_;
}
NumFinishedOffThreadTasksType& numFinishedOffThreadTasksRef(
const AutoLockHelperThreadState& locked) {
return numFinishedOffThreadTasks_;
}
IonCompileTaskList& ionLazyLinkList(JSRuntime* rt);
size_t ionLazyLinkListSize() const { return ionLazyLinkListSize_; }
void ionLazyLinkListRemove(JSRuntime* rt, js::jit::IonCompileTask* task);
void ionLazyLinkListAdd(JSRuntime* rt, js::jit::IonCompileTask* task);
uint64_t nextDisambiguationId() { return disambiguationId_++; }
};
} // namespace jit
} // namespace js
#endif /* jit_JitRuntime_h */

152
js/src/jit/JitZone.h Normal file
Просмотреть файл

@ -0,0 +1,152 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: set ts=8 sts=2 et sw=2 tw=80:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_JitZone_h
#define jit_JitZone_h
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/HashFunctions.h"
#include "mozilla/MemoryReporting.h"
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "gc/Barrier.h"
#include "jit/ExecutableAllocator.h"
#include "jit/ICStubSpace.h"
#include "js/AllocPolicy.h"
#include "js/GCHashTable.h"
#include "js/HashTable.h"
#include "js/TracingAPI.h"
#include "js/TypeDecls.h"
#include "js/UniquePtr.h"
#include "js/Utility.h"
#include "threading/ProtectedData.h"
namespace JS {
struct CodeSizes;
}
namespace js {
namespace jit {
enum class CacheKind : uint8_t;
class CacheIRStubInfo;
class JitCode;
enum class ICStubEngine : uint8_t {
// Baseline IC, see BaselineIC.h.
Baseline = 0,
// Ion IC, see IonIC.h.
IonIC
};
struct CacheIRStubKey : public DefaultHasher<CacheIRStubKey> {
struct Lookup {
CacheKind kind;
ICStubEngine engine;
const uint8_t* code;
uint32_t length;
Lookup(CacheKind kind, ICStubEngine engine, const uint8_t* code,
uint32_t length)
: kind(kind), engine(engine), code(code), length(length) {}
};
static HashNumber hash(const Lookup& l);
static bool match(const CacheIRStubKey& entry, const Lookup& l);
UniquePtr<CacheIRStubInfo, JS::FreePolicy> stubInfo;
explicit CacheIRStubKey(CacheIRStubInfo* info) : stubInfo(info) {}
CacheIRStubKey(CacheIRStubKey&& other)
: stubInfo(std::move(other.stubInfo)) {}
void operator=(CacheIRStubKey&& other) {
stubInfo = std::move(other.stubInfo);
}
};
struct BaselineCacheIRStubCodeMapGCPolicy {
static bool traceWeak(JSTracer* trc, CacheIRStubKey*,
WeakHeapPtrJitCode* value) {
return TraceWeakEdge(trc, value, "traceWeak");
}
};
class JitZone {
// Allocated space for optimized baseline stubs.
OptimizedICStubSpace optimizedStubSpace_;
// Set of CacheIRStubInfo instances used by Ion stubs in this Zone.
using IonCacheIRStubInfoSet =
HashSet<CacheIRStubKey, CacheIRStubKey, SystemAllocPolicy>;
IonCacheIRStubInfoSet ionCacheIRStubInfoSet_;
// Map CacheIRStubKey to shared JitCode objects.
using BaselineCacheIRStubCodeMap =
GCHashMap<CacheIRStubKey, WeakHeapPtrJitCode, CacheIRStubKey,
SystemAllocPolicy, BaselineCacheIRStubCodeMapGCPolicy>;
BaselineCacheIRStubCodeMap baselineCacheIRStubCodes_;
// Executable allocator for all code except wasm code.
MainThreadData<ExecutableAllocator> execAlloc_;
public:
void traceWeak(JSTracer* trc);
void addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
JS::CodeSizes* code, size_t* jitZone,
size_t* baselineStubsOptimized) const;
OptimizedICStubSpace* optimizedStubSpace() { return &optimizedStubSpace_; }
JitCode* getBaselineCacheIRStubCode(const CacheIRStubKey::Lookup& key,
CacheIRStubInfo** stubInfo) {
auto p = baselineCacheIRStubCodes_.lookup(key);
if (p) {
*stubInfo = p->key().stubInfo.get();
return p->value();
}
*stubInfo = nullptr;
return nullptr;
}
MOZ_MUST_USE bool putBaselineCacheIRStubCode(
const CacheIRStubKey::Lookup& lookup, CacheIRStubKey& key,
JitCode* stubCode) {
auto p = baselineCacheIRStubCodes_.lookupForAdd(lookup);
MOZ_ASSERT(!p);
return baselineCacheIRStubCodes_.add(p, std::move(key), stubCode);
}
CacheIRStubInfo* getIonCacheIRStubInfo(const CacheIRStubKey::Lookup& key) {
IonCacheIRStubInfoSet::Ptr p = ionCacheIRStubInfoSet_.lookup(key);
return p ? p->stubInfo.get() : nullptr;
}
MOZ_MUST_USE bool putIonCacheIRStubInfo(const CacheIRStubKey::Lookup& lookup,
CacheIRStubKey& key) {
IonCacheIRStubInfoSet::AddPtr p =
ionCacheIRStubInfoSet_.lookupForAdd(lookup);
MOZ_ASSERT(!p);
return ionCacheIRStubInfoSet_.add(p, std::move(key));
}
void purgeIonCacheIRStubInfo() { ionCacheIRStubInfoSet_.clearAndCompact(); }
ExecutableAllocator& execAlloc() { return execAlloc_.ref(); }
const ExecutableAllocator& execAlloc() const { return execAlloc_.ref(); }
};
// Called from Zone::discardJitCode().
void InvalidateAll(JSFreeOp* fop, JS::Zone* zone);
void FinishInvalidation(JSFreeOp* fop, JSScript* script);
} // namespace jit
} // namespace js
#endif /* jit_JitZone_h */

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

@ -15,7 +15,8 @@
#include "gc/Marking.h"
#include "gc/Statistics.h"
#include "jit/BaselineJIT.h"
#include "jit/JitRealm.h"
#include "jit/CompileInfo.h"
#include "jit/JitRuntime.h"
#include "jit/JitSpewer.h"
#include "js/Vector.h"
#include "vm/BytecodeLocation.h" // for BytecodeLocation

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

@ -8,7 +8,6 @@
#define jit_JitcodeMap_h
#include "jit/CompactBuffer.h"
#include "jit/CompileInfo.h"
#include "jit/ExecutableAllocator.h"
#include "jit/shared/Assembler-shared.h"
#include "vm/BytecodeLocation.h" // for BytecodeLocation
@ -16,6 +15,8 @@
namespace js {
namespace jit {
class InlineScriptTree;
/*
* The Ion jitcode map implements tables to allow mapping from addresses in ion
* jitcode to the list of (JSScript*, jsbytecode*) pairs that are implicitly

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

@ -7,6 +7,7 @@
#include "jit/Linker.h"
#include "gc/GC.h"
#include "jit/JitZone.h"
#include "util/Memory.h"
#include "gc/StoreBuffer-inl.h"

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

@ -7,17 +7,24 @@
#ifndef jit_Linker_h
#define jit_Linker_h
#include "jit/ExecutableAllocator.h"
#include "jit/JitCode.h"
#include "jit/JitRealm.h"
#include "mozilla/Maybe.h"
#include <stdint.h>
#include "jstypes.h"
#include "jit/AutoWritableJitCode.h"
#include "jit/MacroAssembler.h"
#include "vm/JSContext.h"
#include "vm/Realm.h"
#include "vm/Runtime.h"
struct JS_PUBLIC_API JSContext;
namespace js {
namespace jit {
class MacroAssembler;
class JitCode;
enum class CodeKind : uint8_t;
class Linker {
MacroAssembler& masm;

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

@ -17,6 +17,7 @@
#include "jit/BaselineInspector.h"
#include "jit/InlinableNatives.h"
#include "jit/IonBuilder.h"
#include "jit/JitRealm.h"
#include "jit/Lowering.h"
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
@ -944,7 +945,7 @@ IonBuilder::InliningResult IonBuilder::inlineArrayPush(CallInfo& callInfo) {
// Restore the stack, such that resume points are created with the stack
// as it was before the call.
if (!callInfo.pushPriorCallStack(&mirGen_, current)) {
if (!callInfo.pushPriorCallStack(current)) {
return abort(AbortReason::Alloc);
}
}

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

@ -24,6 +24,7 @@
#include "jit/KnownClass.h"
#include "jit/MIRGraph.h"
#include "jit/RangeAnalysis.h"
#include "jit/VMFunctions.h"
#include "js/Conversions.h"
#include "js/experimental/JitInfo.h" // JSJitInfo, JSTypedMethodJitInfo
#include "js/ScalarType.h" // js::Scalar::Type

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

@ -23,6 +23,7 @@
#include "builtin/ModuleObject.h"
#include "jit/AtomicOp.h"
#include "jit/BaselineIC.h"
#include "jit/CompileInfo.h"
#include "jit/FixedList.h"
#include "jit/InlineList.h"
#include "jit/JitAllocPolicy.h"
@ -6582,11 +6583,17 @@ class MPhi final : public MDefinition,
}
// Use only if capacity has been reserved by reserveLength
void addInput(MDefinition* ins) { inputs_.infallibleEmplaceBack(ins, this); }
void addInput(MDefinition* ins) {
MOZ_ASSERT_IF(JitOptions.warpBuilder && type() != MIRType::Value,
ins->type() == type());
inputs_.infallibleEmplaceBack(ins, this);
}
// Appends a new input to the input vector. May perform reallocation.
// Prefer reserveLength() and addInput() instead, where possible.
MOZ_MUST_USE bool addInputSlow(MDefinition* ins) {
MOZ_ASSERT_IF(JitOptions.warpBuilder && type() != MIRType::Value,
ins->type() == type());
return inputs_.emplaceBack(ins, this);
}

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

@ -10,7 +10,6 @@
#include "mozilla/Maybe.h"
#include "ds/InlineTable.h"
#include "jit/MIRGenerator.h"
#include "jit/MIRGraph.h"
#include "js/Vector.h"
#include "vm/Opcodes.h"
@ -223,8 +222,7 @@ class MOZ_STACK_CLASS CallInfo {
// Before doing any pop to the stack, capture whatever flows into the
// instruction, such that we can restore it later.
MOZ_MUST_USE bool savePriorCallStack(MIRGenerator* mir, MBasicBlock* current,
size_t peekDepth);
MOZ_MUST_USE bool savePriorCallStack(MBasicBlock* current, size_t peekDepth);
void popPriorCallStack(MBasicBlock* current) {
if (priorArgs_.empty()) {
@ -234,10 +232,9 @@ class MOZ_STACK_CLASS CallInfo {
}
}
MOZ_MUST_USE bool pushPriorCallStack(MIRGenerator* mir,
MBasicBlock* current) {
MOZ_MUST_USE bool pushPriorCallStack(MBasicBlock* current) {
if (priorArgs_.empty()) {
return pushCallStack(mir, current);
return pushCallStack(current);
}
for (MDefinition* def : priorArgs_) {
current->push(def);
@ -247,7 +244,7 @@ class MOZ_STACK_CLASS CallInfo {
void popCallStack(MBasicBlock* current) { current->popn(numFormals()); }
MOZ_MUST_USE bool pushCallStack(MIRGenerator* mir, MBasicBlock* current) {
MOZ_MUST_USE bool pushCallStack(MBasicBlock* current) {
// Ensure sufficient space in the slots: needed for inlining from FunApply.
if (apply_) {
uint32_t depth = current->stackDepth() + numFormals();

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

@ -10,24 +10,30 @@
// This file declares the data structures used to build a control-flow graph
// containing MIR.
#include "mozilla/Assertions.h"
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Result.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include "jit/CompileInfo.h"
#include "jit/CompileWrappers.h"
#include "jit/JitAllocPolicy.h"
#include "jit/JitRealm.h"
#include "jit/MIR.h"
#include "jit/JitContext.h"
#include "jit/JitSpewer.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
#endif
#include "jit/RegisterSets.h"
#include "vm/JSContext.h"
#include "vm/Realm.h"
#include "js/Utility.h"
#include "vm/GeckoProfiler.h"
namespace js {
namespace jit {
class JitRuntime;
class MIRGraph;
class OptimizationInfo;

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

@ -6,7 +6,6 @@
#include "jit/MIRGraph.h"
#include "jit/BytecodeAnalysis.h"
#include "jit/Ion.h"
#include "jit/JitSpewer.h"
#include "jit/MIR.h"
@ -1005,22 +1004,25 @@ bool MBasicBlock::addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred,
MDefinition* other = pred->getSlot(i);
if (mine != other) {
MIRType phiType = mine->type();
if (phiType != other->type()) {
phiType = MIRType::Value;
}
// If the current instruction is a phi, and it was created in this
// basic block, then we have already placed this phi and should
// instead append to its operands.
if (mine->isPhi() && mine->block() == this) {
MOZ_ASSERT(predecessors_.length());
MOZ_ASSERT(!mine->hasDefUses(),
"should only change type of newly created phis");
mine->setResultType(phiType);
if (!mine->toPhi()->addInputSlow(other)) {
return false;
}
} else {
// Otherwise, create a new phi node.
MPhi* phi;
if (mine->type() == other->type()) {
phi = MPhi::New(alloc.fallible(), mine->type());
} else {
phi = MPhi::New(alloc.fallible());
}
MPhi* phi = MPhi::New(alloc.fallible(), phiType);
if (!phi) {
return false;
}

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