зеркало из https://github.com/mozilla/gecko-dev.git
Merge autoland to mozilla-central a=merge
This commit is contained in:
Коммит
1015fc2548
|
@ -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(
|
|||
}
|
||||
}
|
||||
|
||||
innerOffset -= text->GetChildOffset(childIdx);
|
||||
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 = [
|
||||
|
@ -1911,157 +1911,110 @@
|
|||
words: ["Army.", "Army."],
|
||||
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
|
||||
{ style: "These are my awards, Mother. From Army.",
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["Army.", "Army.", "I deceived you, mom."],
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["Army.", "Army.", "I deceived you, mom."],
|
||||
words: ["Army.", ""],
|
||||
element: ["AXStaticText", "These are my awards, Mother. From Army."] },
|
||||
{ style: "I deceived you, ",
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["I deceived you, mom.",
|
||||
"I deceived you, mom.",
|
||||
"I deceived you, mom."],
|
||||
{ style: "I ",
|
||||
paragraph: "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, ",
|
||||
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, ",
|
||||
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,"],
|
||||
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."],
|
||||
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: [",", " "],
|
||||
element: ["AXStaticText", ", mom."] },
|
||||
{ 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."],
|
||||
words: ["mom.", "mom."],
|
||||
element: ["AXStaticText", " mom."] },
|
||||
{ style: " mom.",
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["I deceived you, mom.",
|
||||
"I deceived you, mom.",
|
||||
"I deceived you, 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: ["mom.", "mom."],
|
||||
element: ["AXStaticText", " mom."] },
|
||||
{ style: " mom.",
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["I deceived you, mom.",
|
||||
"I deceived you, mom.",
|
||||
"I deceived you, 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: ["mom.", "mom."],
|
||||
element: ["AXStaticText", " mom."] },
|
||||
{ style: " mom.",
|
||||
paragraph: "I deceived you, mom.",
|
||||
lines: ["I deceived you, mom.",
|
||||
"I deceived you, mom.",
|
||||
"I deceived you, 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: ["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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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&>kWidget,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());
|
||||
}
|
||||
SkUniqueCFRef<CTFontDescriptorRef> desc(CTFontCopyFontDescriptor(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,7 +13,8 @@
|
|||
#include "frontend/ModuleSharedContext.h"
|
||||
#include "vm/FunctionFlags.h" // js::FunctionFlags
|
||||
#include "vm/GeneratorAndAsyncKind.h" // js::GeneratorKind, js::FunctionAsyncKind
|
||||
#include "vm/StencilEnums.h" // ImmutableScriptFlagsEnum
|
||||
#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
|
||||
#include "jit/Registers.h" // js::jit::MachineState
|
||||
#include "js/TypeDecls.h" // jsbytecode
|
||||
|
||||
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,
|
||||
ICState::Mode mode) {
|
||||
MOZ_ASSERT(type == JSJitInfo::Getter || type == JSJitInfo::Setter);
|
||||
static bool CanAttachDOMCall(JSContext* cx, JSJitInfo::OpType type,
|
||||
JSObject* obj, JSFunction* fun,
|
||||
ICState::Mode mode) {
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче