зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1830727 - Emit JSOp::IsNullOrUndefined for null-or-undefined checks in self-hosted code. r=iain
It's fairly common in the JS spec to check whether a value is null-or-undefined. We already have a bytecode op for this that we can use if we add an `IsNullOrUndefined` intrinsic. This has some minor performance benefits (no Baseline ICs instead of 3 Baseline ICs) and no `Or` or `And` branch, but it also makes our bytecode more compact. This will help with follow-up work to look into inlining more string builtins. Differential Revision: https://phabricator.services.mozilla.com/D176902
This commit is contained in:
Родитель
5c922d8b93
Коммит
5b6cd149a6
|
@ -136,6 +136,7 @@ module.exports = {
|
|||
SetIsInlinableLargeFunction: "readonly",
|
||||
ToNumeric: "readonly",
|
||||
ToString: "readonly",
|
||||
IsNullOrUndefined: "readonly",
|
||||
|
||||
// We've disabled all built-in environments, which also removed
|
||||
// `undefined` from the list of globals. Put it back because it's
|
||||
|
|
|
@ -1024,7 +1024,7 @@ function ArrayFrom(items, mapfn = undefined, thisArg = undefined) {
|
|||
|
||||
// Step 5.
|
||||
// Inlined: GetMethod, step 3.
|
||||
if (usingIterator !== undefined && usingIterator !== null) {
|
||||
if (!IsNullOrUndefined(usingIterator)) {
|
||||
// Inlined: GetMethod, step 4.
|
||||
if (!IsCallable(usingIterator)) {
|
||||
ThrowTypeError(JSMSG_NOT_ITERABLE, DecompileArg(0, items));
|
||||
|
@ -1135,7 +1135,7 @@ function ArrayToLocaleString(locales, options) {
|
|||
|
||||
// Steps 6-7.
|
||||
var R;
|
||||
if (firstElement === undefined || firstElement === null) {
|
||||
if (IsNullOrUndefined(firstElement)) {
|
||||
R = "";
|
||||
} else {
|
||||
#if JS_HAS_INTL_API
|
||||
|
@ -1165,7 +1165,7 @@ function ArrayToLocaleString(locales, options) {
|
|||
|
||||
// Steps 9.a, 9.c-e.
|
||||
R += separator;
|
||||
if (!(nextElement === undefined || nextElement === null)) {
|
||||
if (!IsNullOrUndefined(nextElement)) {
|
||||
#if JS_HAS_INTL_API
|
||||
R += ToString(
|
||||
callContentFunction(
|
||||
|
|
|
@ -37,7 +37,7 @@ async function AsyncIteratorClose(iteratorRecord, value) {
|
|||
// Step 4.
|
||||
const returnMethod = iterator.return;
|
||||
// Step 5.
|
||||
if (returnMethod !== undefined && returnMethod !== null) {
|
||||
if (!IsNullOrUndefined(returnMethod)) {
|
||||
const result = await callContentFunction(returnMethod, iterator);
|
||||
// Step 8.
|
||||
if (!IsObject(result)) {
|
||||
|
@ -74,7 +74,7 @@ function GetAsyncIteratorDirectWrapper(obj) {
|
|||
},
|
||||
async return(value) {
|
||||
const returnMethod = obj.return;
|
||||
if (returnMethod !== undefined && returnMethod !== null) {
|
||||
if (!IsNullOrUndefined(returnMethod)) {
|
||||
return callContentFunction(returnMethod, obj, value);
|
||||
}
|
||||
return { done: true, value };
|
||||
|
|
|
@ -32,7 +32,7 @@ function IteratorClose(iteratorRecord, value) {
|
|||
// Step 4.
|
||||
const returnMethod = iterator.return;
|
||||
// Step 5.
|
||||
if (returnMethod !== undefined && returnMethod !== null) {
|
||||
if (!IsNullOrUndefined(returnMethod)) {
|
||||
const result = callContentFunction(returnMethod, iterator);
|
||||
// Step 8.
|
||||
if (!IsObject(result)) {
|
||||
|
@ -124,7 +124,7 @@ function GetIteratorDirectWrapper(obj) {
|
|||
},
|
||||
return(value) {
|
||||
const returnMethod = obj.return;
|
||||
if (returnMethod !== undefined && returnMethod !== null) {
|
||||
if (!IsNullOrUndefined(returnMethod)) {
|
||||
return callContentFunction(returnMethod, obj, value);
|
||||
}
|
||||
return { done: true, value };
|
||||
|
@ -165,7 +165,7 @@ function IteratorFrom(O) {
|
|||
|
||||
let iteratorRecord;
|
||||
// Step 2.
|
||||
if (usingIterator !== undefined && usingIterator !== null) {
|
||||
if (!IsNullOrUndefined(usingIterator)) {
|
||||
// Step a.
|
||||
// Inline call to GetIterator.
|
||||
const iterator = callContentFunction(usingIterator, O);
|
||||
|
@ -240,7 +240,7 @@ function WrapForValidIteratorReturn(value) {
|
|||
// Inline call to IteratorClose.
|
||||
const iterator = iterated.iterator;
|
||||
const returnMethod = iterator.return;
|
||||
if (returnMethod !== undefined && returnMethod !== null) {
|
||||
if (!IsNullOrUndefined(returnMethod)) {
|
||||
let innerResult = callContentFunction(returnMethod, iterator);
|
||||
if (!IsObject(innerResult)) {
|
||||
ThrowTypeError(JSMSG_OBJECT_REQUIRED, DecompileArg(0, innerResult));
|
||||
|
@ -271,7 +271,7 @@ function WrapForValidIteratorThrow(value) {
|
|||
// Step 4.
|
||||
const throwMethod = iterator.throw;
|
||||
// Step 5.
|
||||
if (throwMethod === undefined || throwMethod === null) {
|
||||
if (IsNullOrUndefined(throwMethod)) {
|
||||
throw value;
|
||||
}
|
||||
// Step 6.
|
||||
|
|
|
@ -29,7 +29,7 @@ function ThrowIncompatibleMethod(name, thisv) {
|
|||
// ES 2016 draft Mar 25, 2016 21.1.3.11.
|
||||
function String_match(regexp) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("match", this);
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,7 @@ function String_match(regexp) {
|
|||
var isPatternString = typeof regexp === "string";
|
||||
if (
|
||||
!(isPatternString && StringProtoHasNoMatch()) &&
|
||||
regexp !== undefined &&
|
||||
regexp !== null
|
||||
!IsNullOrUndefined(regexp)
|
||||
) {
|
||||
// Step 2.a.
|
||||
var matcher = GetMethod(regexp, GetBuiltinSymbol("match"));
|
||||
|
@ -76,19 +75,19 @@ function String_match(regexp) {
|
|||
// String.prototype.matchAll ( regexp )
|
||||
function String_matchAll(regexp) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("matchAll", this);
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
if (regexp !== undefined && regexp !== null) {
|
||||
if (!IsNullOrUndefined(regexp)) {
|
||||
// Steps 2.a-b.
|
||||
if (IsRegExp(regexp)) {
|
||||
// Step 2.b.i.
|
||||
var flags = regexp.flags;
|
||||
|
||||
// Step 2.b.ii.
|
||||
if (flags === undefined || flags === null) {
|
||||
if (IsNullOrUndefined(flags)) {
|
||||
ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
|
||||
}
|
||||
|
||||
|
@ -127,7 +126,7 @@ function String_matchAll(regexp) {
|
|||
*/
|
||||
function String_pad(maxLength, fillString, padEnd) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod(padEnd ? "padEnd" : "padStart", this);
|
||||
}
|
||||
|
||||
|
@ -215,15 +214,14 @@ function Substring(str, from, length) {
|
|||
// ES 2016 draft Mar 25, 2016 21.1.3.14.
|
||||
function String_replace(searchValue, replaceValue) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("replace", this);
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
if (
|
||||
!(typeof searchValue === "string" && StringProtoHasNoReplace()) &&
|
||||
searchValue !== undefined &&
|
||||
searchValue !== null
|
||||
!IsNullOrUndefined(searchValue)
|
||||
) {
|
||||
// Step 2.a.
|
||||
var replacer = GetMethod(searchValue, GetBuiltinSymbol("replace"));
|
||||
|
@ -289,19 +287,19 @@ function String_replace(searchValue, replaceValue) {
|
|||
// String.prototype.replaceAll ( searchValue, replaceValue )
|
||||
function String_replaceAll(searchValue, replaceValue) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("replaceAll", this);
|
||||
}
|
||||
|
||||
// Step 2.
|
||||
if (searchValue !== undefined && searchValue !== null) {
|
||||
if (!IsNullOrUndefined(searchValue)) {
|
||||
// Steps 2.a-b.
|
||||
if (IsRegExp(searchValue)) {
|
||||
// Step 2.b.i.
|
||||
var flags = searchValue.flags;
|
||||
|
||||
// Step 2.b.ii.
|
||||
if (flags === undefined || flags === null) {
|
||||
if (IsNullOrUndefined(flags)) {
|
||||
ThrowTypeError(JSMSG_FLAGS_UNDEFINED_OR_NULL);
|
||||
}
|
||||
|
||||
|
@ -430,7 +428,7 @@ function IsStringSearchOptimizable() {
|
|||
// ES 2016 draft Mar 25, 2016 21.1.3.15.
|
||||
function String_search(regexp) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("search", this);
|
||||
}
|
||||
|
||||
|
@ -438,8 +436,7 @@ function String_search(regexp) {
|
|||
var isPatternString = typeof regexp === "string";
|
||||
if (
|
||||
!(isPatternString && StringProtoHasNoSearch()) &&
|
||||
regexp !== undefined &&
|
||||
regexp !== null
|
||||
!IsNullOrUndefined(regexp)
|
||||
) {
|
||||
// Step 2.a.
|
||||
var searcher = GetMethod(regexp, GetBuiltinSymbol("search"));
|
||||
|
@ -483,7 +480,7 @@ function StringProtoHasNoSplit() {
|
|||
// ES 2016 draft Mar 25, 2016 21.1.3.17.
|
||||
function String_split(separator, limit) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("split", this);
|
||||
}
|
||||
|
||||
|
@ -505,8 +502,7 @@ function String_split(separator, limit) {
|
|||
// Step 2.
|
||||
if (
|
||||
!(typeof separator === "string" && StringProtoHasNoSplit()) &&
|
||||
separator !== undefined &&
|
||||
separator !== null
|
||||
!IsNullOrUndefined(separator)
|
||||
) {
|
||||
// Step 2.a.
|
||||
var splitter = GetMethod(separator, GetBuiltinSymbol("split"));
|
||||
|
@ -559,7 +555,7 @@ function String_split(separator, limit) {
|
|||
// 21.1.3.22 String.prototype.substring ( start, end )
|
||||
function String_substring(start, end) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("substring", this);
|
||||
}
|
||||
|
||||
|
@ -599,7 +595,7 @@ SetIsInlinableLargeFunction(String_substring);
|
|||
// B.2.3.1 String.prototype.substr ( start, length )
|
||||
function String_substr(start, length) {
|
||||
// Steps 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("substr", this);
|
||||
}
|
||||
|
||||
|
@ -645,7 +641,7 @@ SetIsInlinableLargeFunction(String_substr);
|
|||
// Note: String.prototype.concat.length is 1.
|
||||
function String_concat(arg1) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("concat", this);
|
||||
}
|
||||
|
||||
|
@ -683,7 +679,7 @@ function String_concat(arg1) {
|
|||
// 21.1.3.19 String.prototype.slice ( start, end )
|
||||
function String_slice(start, end) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("slice", this);
|
||||
}
|
||||
|
||||
|
@ -724,7 +720,7 @@ SetIsInlinableLargeFunction(String_slice);
|
|||
// 21.1.3.3 String.prototype.codePointAt ( pos )
|
||||
function String_codePointAt(pos) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("codePointAt", this);
|
||||
}
|
||||
|
||||
|
@ -762,7 +758,7 @@ function String_codePointAt(pos) {
|
|||
// 21.1.3.16 String.prototype.repeat ( count )
|
||||
function String_repeat(count) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("repeat", this);
|
||||
}
|
||||
|
||||
|
@ -815,7 +811,7 @@ function String_repeat(count) {
|
|||
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
||||
function String_iterator() {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowTypeError(
|
||||
JSMSG_INCOMPATIBLE_PROTO2,
|
||||
"String",
|
||||
|
@ -886,7 +882,7 @@ var collatorCache = new_Record();
|
|||
*/
|
||||
function String_localeCompare(that) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("localeCompare", this);
|
||||
}
|
||||
|
||||
|
@ -923,7 +919,7 @@ function String_localeCompare(that) {
|
|||
*/
|
||||
function String_toLocaleLowerCase() {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("toLocaleLowerCase", this);
|
||||
}
|
||||
|
||||
|
@ -968,7 +964,7 @@ function String_toLocaleLowerCase() {
|
|||
*/
|
||||
function String_toLocaleUpperCase() {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("toLocaleUpperCase", this);
|
||||
}
|
||||
|
||||
|
@ -1063,7 +1059,7 @@ function String_static_raw(callSite /*, ...substitutions*/) {
|
|||
// String.prototype.at ( index )
|
||||
function String_at(index) {
|
||||
// Step 1.
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("at", this);
|
||||
}
|
||||
|
||||
|
@ -1095,7 +1091,7 @@ function String_at(index) {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.3
|
||||
function String_big() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("big", this);
|
||||
}
|
||||
return "<big>" + ToString(this) + "</big>";
|
||||
|
@ -1103,7 +1099,7 @@ function String_big() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.4
|
||||
function String_blink() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("blink", this);
|
||||
}
|
||||
return "<blink>" + ToString(this) + "</blink>";
|
||||
|
@ -1111,7 +1107,7 @@ function String_blink() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.5
|
||||
function String_bold() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("bold", this);
|
||||
}
|
||||
return "<b>" + ToString(this) + "</b>";
|
||||
|
@ -1119,7 +1115,7 @@ function String_bold() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.6
|
||||
function String_fixed() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("fixed", this);
|
||||
}
|
||||
return "<tt>" + ToString(this) + "</tt>";
|
||||
|
@ -1127,7 +1123,7 @@ function String_fixed() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.9
|
||||
function String_italics() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("italics", this);
|
||||
}
|
||||
return "<i>" + ToString(this) + "</i>";
|
||||
|
@ -1135,7 +1131,7 @@ function String_italics() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.11
|
||||
function String_small() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("small", this);
|
||||
}
|
||||
return "<small>" + ToString(this) + "</small>";
|
||||
|
@ -1143,7 +1139,7 @@ function String_small() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.12
|
||||
function String_strike() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("strike", this);
|
||||
}
|
||||
return "<strike>" + ToString(this) + "</strike>";
|
||||
|
@ -1151,7 +1147,7 @@ function String_strike() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.13
|
||||
function String_sub() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("sub", this);
|
||||
}
|
||||
return "<sub>" + ToString(this) + "</sub>";
|
||||
|
@ -1159,7 +1155,7 @@ function String_sub() {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.14
|
||||
function String_sup() {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("sup", this);
|
||||
}
|
||||
return "<sup>" + ToString(this) + "</sup>";
|
||||
|
@ -1172,7 +1168,7 @@ function EscapeAttributeValue(v) {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.2
|
||||
function String_anchor(name) {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("anchor", this);
|
||||
}
|
||||
var S = ToString(this);
|
||||
|
@ -1181,7 +1177,7 @@ function String_anchor(name) {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.7
|
||||
function String_fontcolor(color) {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("fontcolor", this);
|
||||
}
|
||||
var S = ToString(this);
|
||||
|
@ -1190,7 +1186,7 @@ function String_fontcolor(color) {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.8
|
||||
function String_fontsize(size) {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("fontsize", this);
|
||||
}
|
||||
var S = ToString(this);
|
||||
|
@ -1199,7 +1195,7 @@ function String_fontsize(size) {
|
|||
|
||||
// ES6 draft 2014-04-27 B.2.3.10
|
||||
function String_link(url) {
|
||||
if (this === undefined || this === null) {
|
||||
if (IsNullOrUndefined(this)) {
|
||||
ThrowIncompatibleMethod("link", this);
|
||||
}
|
||||
var S = ToString(this);
|
||||
|
|
|
@ -273,7 +273,7 @@ function TupleJoin(separator) {
|
|||
|
||||
// Steps 3-4
|
||||
var sep = ",";
|
||||
if (separator !== undefined && separator !== null) {
|
||||
if (!IsNullOrUndefined(separator)) {
|
||||
let toString = IsCallable(separator.toString)
|
||||
? separator.toString
|
||||
: std_Object_toString;
|
||||
|
@ -296,7 +296,7 @@ function TupleJoin(separator) {
|
|||
let element = T[k];
|
||||
// Step 7c
|
||||
var next = "";
|
||||
if (element !== undefined && element !== null) {
|
||||
if (!IsNullOrUndefined(element)) {
|
||||
let toString = IsCallable(element.toString)
|
||||
? element.toString
|
||||
: std_Object_toString;
|
||||
|
|
|
@ -108,7 +108,7 @@ function TypedArraySpeciesConstructor(obj) {
|
|||
var s = ctor[GetBuiltinSymbol("species")];
|
||||
|
||||
// Step 6.
|
||||
if (s === undefined || s === null) {
|
||||
if (IsNullOrUndefined(s)) {
|
||||
return ConstructorForTypedArray(obj);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ function GetMethod(V, P) {
|
|||
var func = V[P];
|
||||
|
||||
// Step 3.
|
||||
if (func === undefined || func === null) {
|
||||
if (IsNullOrUndefined(func)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ function SpeciesConstructor(obj, defaultConstructor) {
|
|||
var s = ctor[GetBuiltinSymbol("species")];
|
||||
|
||||
// Step 6.
|
||||
if (s === undefined || s === null) {
|
||||
if (IsNullOrUndefined(s)) {
|
||||
return defaultConstructor;
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ function CopyDataProperties(target, source, excludedItems) {
|
|||
assert(IsObject(excludedItems), "excludedItems is an object");
|
||||
|
||||
// Steps 3 and 7.
|
||||
if (source === undefined || source === null) {
|
||||
if (IsNullOrUndefined(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ function CopyDataPropertiesUnfiltered(target, source) {
|
|||
// Step 2 (Not applicable).
|
||||
|
||||
// Steps 3 and 7.
|
||||
if (source === undefined || source === null) {
|
||||
if (IsNullOrUndefined(source)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -7403,6 +7403,32 @@ bool BytecodeEmitter::emitSelfHostedToString(CallNode* callNode) {
|
|||
return emit1(JSOp::ToString);
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitSelfHostedIsNullOrUndefined(CallNode* callNode) {
|
||||
ListNode* argsList = &callNode->right()->as<ListNode>();
|
||||
|
||||
MOZ_ASSERT(argsList->count() == 1);
|
||||
|
||||
ParseNode* argNode = argsList->head();
|
||||
|
||||
if (!emitTree(argNode)) {
|
||||
// [stack] ARG
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOp::IsNullOrUndefined)) {
|
||||
// [stack] ARG IS_NULL_OR_UNDEF
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOp::Swap)) {
|
||||
// [stack] IS_NULL_OR_UNDEF ARG
|
||||
return false;
|
||||
}
|
||||
if (!emit1(JSOp::Pop)) {
|
||||
// [stack] IS_NULL_OR_UNDEF
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BytecodeEmitter::emitSelfHostedGetBuiltinConstructorOrPrototype(
|
||||
CallNode* callNode, bool isConstructor) {
|
||||
ListNode* argsList = &callNode->right()->as<ListNode>();
|
||||
|
@ -8081,6 +8107,9 @@ bool BytecodeEmitter::emitCallOrNew(CallNode* callNode, ValueUsage valueUsage) {
|
|||
if (calleeName == TaggedParserAtomIndex::WellKnown::SetCanonicalName()) {
|
||||
return emitSelfHostedSetCanonicalName(callNode);
|
||||
}
|
||||
if (calleeName == TaggedParserAtomIndex::WellKnown::IsNullOrUndefined()) {
|
||||
return emitSelfHostedIsNullOrUndefined(callNode);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (calleeName ==
|
||||
TaggedParserAtomIndex::WellKnown::UnsafeGetReservedSlot() ||
|
||||
|
|
|
@ -946,6 +946,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
|
|||
[[nodiscard]] bool emitSelfHostedHasOwn(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedToNumeric(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedToString(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedIsNullOrUndefined(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedGetBuiltinConstructor(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedGetBuiltinPrototype(CallNode* callNode);
|
||||
[[nodiscard]] bool emitSelfHostedGetBuiltinSymbol(CallNode* callNode);
|
||||
|
|
|
@ -295,6 +295,7 @@
|
|||
MACRO_(isExtensible, isExtensible, "isExtensible") \
|
||||
MACRO_(isFinite, isFinite, "isFinite") \
|
||||
MACRO_(isNaN, isNaN, "isNaN") \
|
||||
MACRO_(IsNullOrUndefined, IsNullOrUndefined, "IsNullOrUndefined") \
|
||||
MACRO_(isPrototypeOf, isPrototypeOf, "isPrototypeOf") \
|
||||
MACRO_(isStepStart, isStepStart, "isStepStart") \
|
||||
MACRO_(isSubsetOf, isSubsetOf, "isSubsetOf") \
|
||||
|
|
Загрузка…
Ссылка в новой задаче