StrictNotEq fastpath

Issues: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I8GQOL?from=project-issue
Signed-off-by: liuzhijie <jay.lau2020.work@outlook.com>

Change-Id: I7dfeecec59f49cfe1dd0ee3a44570d7f023a8a75
This commit is contained in:
liuzhijie 2023-11-15 17:09:56 +08:00
parent f4972d28c8
commit fed086b8df
16 changed files with 226 additions and 34 deletions

View File

@ -210,6 +210,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::GREATER_IMM8_V8:
case EcmaOpcode::GREATEREQ_IMM8_V8:
case EcmaOpcode::STRICTEQ_IMM8_V8:
case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
case EcmaOpcode::TONUMERIC_IMM8:
case EcmaOpcode::ISTRUE:
case EcmaOpcode::ISFALSE:

View File

@ -580,6 +580,7 @@ public:
inline GateRef TaggedIsStoreTSHandler(GateRef x);
inline GateRef TaggedIsTransWithProtoHandler(GateRef x);
inline GateRef TaggedIsUndefinedOrNull(GateRef x);
inline GateRef TaggedIsNotUndefinedAndNull(GateRef x);
inline GateRef TaggedIsTrue(GateRef x);
inline GateRef TaggedIsFalse(GateRef x);
inline GateRef TaggedIsNull(GateRef x);

View File

@ -389,6 +389,16 @@ GateRef CircuitBuilder::TaggedIsUndefinedOrNull(GateRef x)
return result;
}
GateRef CircuitBuilder::TaggedIsNotUndefinedAndNull(GateRef x)
{
x = ChangeTaggedPointerToInt64(x);
GateRef heapObjMask = Int64(JSTaggedValue::TAG_HEAPOBJECT_MASK);
GateRef tagSpecial = Int64(JSTaggedValue::TAG_SPECIAL);
GateRef andGate = Int64And(x, heapObjMask);
GateRef result = NotEqual(andGate, tagSpecial);
return result;
}
GateRef CircuitBuilder::TaggedTrue()
{
return GetCircuit()->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_TRUE, GateType::TaggedValue());

View File

@ -44,6 +44,7 @@ namespace panda::ecmascript::kungfu {
V(TYPED_EQ) \
V(TYPED_NOTEQ) \
V(TYPED_STRICTEQ) \
V(TYPED_STRICTNOTEQ) \
V(TYPED_SHL) \
V(TYPED_SHR) \
V(TYPED_ASHR) \

View File

@ -116,12 +116,14 @@ void NumberSpeculativeLowering::VisitTypedBinaryOp(GateRef gate)
}
auto op = acc_.GetTypedBinaryOp(gate);
switch (op) {
case TypedBinOp::TYPED_STRICTEQ: {
VisitStrictEqual(gate);
case TypedBinOp::TYPED_STRICTEQ:
case TypedBinOp::TYPED_STRICTNOTEQ: {
VisitStrictEqualOrStrictNotEqual(gate);
break;
}
case TypedBinOp::TYPED_EQ: {
VisitEqual(gate);
case TypedBinOp::TYPED_EQ:
case TypedBinOp::TYPED_NOTEQ: {
VisitEqualOrNotEqual(gate);
break;
}
default: {
@ -133,21 +135,21 @@ void NumberSpeculativeLowering::VisitTypedBinaryOp(GateRef gate)
}
}
void NumberSpeculativeLowering::VisitEqual(GateRef gate)
void NumberSpeculativeLowering::VisitEqualOrNotEqual(GateRef gate)
{
if (acc_.HasNumberType(gate)) {
VisitNumberBinaryOp(gate);
} else {
VisitUndefinedEq(gate);
VisitUndefinedEqOrUndefinedNotEq(gate);
}
}
void NumberSpeculativeLowering::VisitStrictEqual(GateRef gate)
void NumberSpeculativeLowering::VisitStrictEqualOrStrictNotEqual(GateRef gate)
{
if (acc_.HasNumberType(gate)) {
VisitNumberBinaryOp(gate);
} else {
VisitUndefinedStrictEq(gate);
VisitUndefinedStrictEqOrUndefinedStrictNotEq(gate);
}
}
@ -195,6 +197,10 @@ void NumberSpeculativeLowering::VisitNumberBinaryOp(GateRef gate)
VisitNumberCompare<TypedBinOp::TYPED_STRICTEQ>(gate);
break;
}
case TypedBinOp::TYPED_STRICTNOTEQ: {
VisitNumberCompare<TypedBinOp::TYPED_STRICTNOTEQ>(gate);
break;
}
case TypedBinOp::TYPED_SHL: {
VisitNumberShift<TypedBinOp::TYPED_SHL>(gate);
break;
@ -476,26 +482,39 @@ void NumberSpeculativeLowering::VisitBooleanJump(GateRef gate)
acc_.ReplaceGate(gate, ifBranch, acc_.GetDep(gate), Circuit::NullGate());
}
void NumberSpeculativeLowering::VisitUndefinedStrictEq(GateRef gate)
void NumberSpeculativeLowering::VisitUndefinedStrictEqOrUndefinedStrictNotEq(GateRef gate)
{
ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ);
ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ ||
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTNOTEQ);
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
ASSERT(acc_.IsUndefinedOrNull(left) || acc_.IsUndefinedOrNull(right));
GateRef result = builder_.Equal(left, right);
GateRef result = Circuit::NullGate();
if (acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ) {
result = builder_.Equal(left, right);
} else {
result = builder_.NotEqual(left, right);
}
ASSERT(result != Circuit::NullGate());
acc_.SetMachineType(gate, MachineType::I1);
acc_.SetGateType(gate, GateType::NJSValue());
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
void NumberSpeculativeLowering::VisitUndefinedEq(GateRef gate)
void NumberSpeculativeLowering::VisitUndefinedEqOrUndefinedNotEq(GateRef gate)
{
ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ);
ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ ||
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_NOTEQ);
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
ASSERT(acc_.IsUndefinedOrNull(left) || acc_.IsUndefinedOrNull(right));
GateRef valueGate = acc_.IsUndefinedOrNull(left) ? right : left;
GateRef result = builder_.TaggedIsUndefinedOrNull(valueGate);
GateRef result = Circuit::NullGate();
if (acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ) {
result = builder_.TaggedIsUndefinedOrNull(valueGate);
} else {
result = builder_.TaggedIsNotUndefinedAndNull(valueGate);
}
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), result);
}
@ -730,6 +749,7 @@ GateRef NumberSpeculativeLowering::CompareInts(GateRef left, GateRef right)
condition = builder_.Int32Equal(left, right);
break;
case TypedBinOp::TYPED_NOTEQ:
case TypedBinOp::TYPED_STRICTNOTEQ:
condition = builder_.Int32NotEqual(left, right);
break;
default:
@ -768,6 +788,13 @@ GateRef NumberSpeculativeLowering::CompareDoubles(GateRef left, GateRef right)
condition = builder_.BoolAnd(builder_.BoolAnd(leftNotNan, rightNotNan), doubleEqual);
break;
}
case TypedBinOp::TYPED_STRICTNOTEQ: {
GateRef leftNotNan = builder_.BoolNot(builder_.DoubleIsNAN(left));
GateRef rightNotNan = builder_.BoolNot(builder_.DoubleIsNAN(right));
GateRef doubleEqual = builder_.DoubleNotEqual(left, right);
condition = builder_.BoolAnd(builder_.BoolAnd(leftNotNan, rightNotNan), doubleEqual);
break;
}
default:
break;
}

View File

@ -43,9 +43,9 @@ private:
void VisitTypedConditionJump(GateRef gate);
void VisitConstant(GateRef gate);
void VisitPhi(GateRef gate);
void VisitUndefinedStrictEq(GateRef gate);
void VisitUndefinedEq(GateRef gate);
void VisitEqual(GateRef gate);
void VisitUndefinedStrictEqOrUndefinedStrictNotEq(GateRef gate);
void VisitUndefinedEqOrUndefinedNotEq(GateRef gate);
void VisitEqualOrNotEqual(GateRef gate);
void VisitCallBuiltins(GateRef gate);
void VisitRangeGuard(GateRef gate);
void VisitRangeCheckPredicate(GateRef gate);
@ -70,7 +70,7 @@ private:
void VisitNumberMod(GateRef gate);
void VisitBooleanJump(GateRef gate);
void VisitIsTrueOrFalse(GateRef gate, bool flag);
void VisitStrictEqual(GateRef gate);
void VisitStrictEqualOrStrictNotEqual(GateRef gate);
template<TypedBinOp Op>
void VisitStringCompare(GateRef gate);

View File

@ -160,28 +160,32 @@ GateRef NumberSpeculativeRetype::VisitTypedBinaryOp(GateRef gate)
}
if (acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTEQ &&
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ) {
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_STRICTNOTEQ &&
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_EQ &&
acc_.GetTypedBinaryOp(gate) != TypedBinOp::TYPED_NOTEQ) {
if (acc_.HasPrimitiveNumberType(gate)) {
return VisitNumberBinaryOp(gate);
}
}
return VisitEqualOrStrictEqual(gate);
return VisitEqualCompareOrNotEqualCompare(gate);
}
GateRef NumberSpeculativeRetype::VisitEqualOrStrictEqual(GateRef gate)
GateRef NumberSpeculativeRetype::VisitEqualCompareOrNotEqualCompare(GateRef gate)
{
if (acc_.HasNumberType(gate)) {
return VisitNumberBinaryOp(gate);
} else {
return VisitUndefinedEqOrStrictEq(gate);
return VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(gate);
}
}
GateRef NumberSpeculativeRetype::VisitUndefinedEqOrStrictEq(GateRef gate)
GateRef NumberSpeculativeRetype::VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate)
{
ASSERT(acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTEQ ||
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ);
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_STRICTNOTEQ ||
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_EQ ||
acc_.GetTypedBinaryOp(gate) == TypedBinOp::TYPED_NOTEQ);
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
ASSERT((acc_.IsUndefinedOrNull(left)) || (acc_.IsUndefinedOrNull(right)));
@ -361,7 +365,8 @@ GateRef NumberSpeculativeRetype::VisitNumberBinaryOp(GateRef gate)
case TypedBinOp::TYPED_GREATEREQ:
case TypedBinOp::TYPED_EQ:
case TypedBinOp::TYPED_NOTEQ:
case TypedBinOp::TYPED_STRICTEQ: {
case TypedBinOp::TYPED_STRICTEQ:
case TypedBinOp::TYPED_STRICTNOTEQ: {
return VisitNumberCompare(gate);
}
case TypedBinOp::TYPED_SHL:

View File

@ -64,7 +64,7 @@ private:
GateRef VisitTypedBinaryOp(GateRef gate);
GateRef VisitNumberBinaryOp(GateRef gate);
GateRef VisitStringBinaryOp(GateRef gate);
GateRef VisitUndefinedEqOrStrictEq(GateRef gate);
GateRef VisitUndefinedEqualCompareOrUndefinedNotEqualCompare(GateRef gate);
GateRef VisitTypedUnaryOp(GateRef gate);
GateRef VisitNumberMonocular(GateRef gate);
@ -95,7 +95,7 @@ private:
GateRef VisitIsTrueOrFalse(GateRef gate);
GateRef VisitWithConstantValue(GateRef gate, size_t ignoreIndex);
GateRef VisitIntermediateValue(GateRef gate);
GateRef VisitEqualOrStrictEqual(GateRef gate);
GateRef VisitEqualCompareOrNotEqualCompare(GateRef gate);
GateRef VisitStringCompare(GateRef gate);
GateRef VisitStringAdd(GateRef gate);

View File

@ -185,13 +185,16 @@ void TypeBytecodeLowering::Lower(GateRef gate)
LowerTypedBinOp<TypedBinOp::TYPED_GREATEREQ>(gate);
break;
case EcmaOpcode::EQ_IMM8_V8:
LowerTypedEqOrStrictEq<TypedBinOp::TYPED_EQ>(gate);
LowerTypedEqOrNotEq<TypedBinOp::TYPED_EQ>(gate);
break;
case EcmaOpcode::STRICTEQ_IMM8_V8:
LowerTypedEqOrStrictEq<TypedBinOp::TYPED_STRICTEQ>(gate);
LowerTypedEqOrNotEq<TypedBinOp::TYPED_STRICTEQ>(gate);
break;
case EcmaOpcode::NOTEQ_IMM8_V8:
LowerTypedBinOp<TypedBinOp::TYPED_NOTEQ>(gate, false);
LowerTypedEqOrNotEq<TypedBinOp::TYPED_NOTEQ>(gate);
break;
case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
LowerTypedEqOrNotEq<TypedBinOp::TYPED_STRICTNOTEQ>(gate);
break;
case EcmaOpcode::SHL2_IMM8_V8:
LowerTypedBinOp<TypedBinOp::TYPED_SHL>(gate);
@ -371,7 +374,7 @@ void TypeBytecodeLowering::LowerTypedUnOp(GateRef gate)
}
template<TypedBinOp Op>
void TypeBytecodeLowering::LowerTypedEqOrStrictEq(GateRef gate)
void TypeBytecodeLowering::LowerTypedEqOrNotEq(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
GateRef right = acc_.GetValueIn(gate, 1);
@ -1600,7 +1603,7 @@ void TypeBytecodeLowering::LowerTypedSuperCall(GateRef gate)
}
void TypeBytecodeLowering::SpeculateCallBuiltin(GateRef gate, GateRef func, const std::vector<GateRef> &args,
BuiltinsStubCSigns::ID id, bool isThrow)
BuiltinsStubCSigns::ID id, bool isThrow)
{
if (!Uncheck()) {
builder_.CallTargetCheck(gate, func, builder_.IntPtr(static_cast<int64_t>(id)), args[0]);
@ -1828,7 +1831,7 @@ bool TypeBytecodeLowering::CanOptimizeAsFastCall(GateRef func)
}
void TypeBytecodeLowering::CheckFastCallThisCallTarget(GateRef gate, GateRef func, GlobalTSTypeRef funcGt,
GateType funcType, bool isNoGC)
GateType funcType, bool isNoGC)
{
if (noCheck_) {
return;

View File

@ -101,7 +101,7 @@ private:
template<TypedUnOp Op>
void LowerTypedUnOp(GateRef gate);
template<TypedBinOp Op>
void LowerTypedEqOrStrictEq(GateRef gate);
void LowerTypedEqOrNotEq(GateRef gate);
void LowerTypeToNumeric(GateRef gate);
void LowerPrimitiveTypeToNumber(GateRef gate);
void LowerConditionJump(GateRef gate, bool flag);

View File

@ -177,6 +177,7 @@ group("ark_aot_ts_test") {
"newobjrange",
"newobjspread",
"not",
"not_equal",
"numberspeculativeretype",
"operations_stub_test",
"optimization",

View File

@ -36,6 +36,7 @@ print(intNum >= undf);
print(intNum == undf);
print(intNum === undf);
print(intNum != undf);
print(intNum !== undf);
print(intNum << undf);
print(intNum >> undf);
print(intNum >>> undf);
@ -56,6 +57,7 @@ print(doubleNum >= undf);
print(doubleNum == undf);
print(doubleNum === undf);
print(doubleNum != undf);
print(doubleNum !== undf);
print(doubleNum << undf);
print(doubleNum >> undf);
print(doubleNum >>> undf);
@ -76,6 +78,7 @@ print(falseValue >= undf);
print(falseValue == undf);
print(falseValue === undf);
print(falseValue != undf);
print(falseValue !== undf);
print(falseValue << undf);
print(falseValue >> undf);
print(falseValue >>> undf);
@ -96,6 +99,7 @@ print(trueValue >= undf);
print(trueValue == undf);
print(trueValue === undf);
print(trueValue != undf);
print(trueValue !== undf);
print(trueValue << undf);
print(trueValue >> undf);
print(trueValue >>> undf);
@ -116,6 +120,7 @@ print(nullValue >= undf);
print(nullValue == undf);
print(nullValue === undf);
print(nullValue != undf);
print(nullValue !== undf);
print(nullValue << undf);
print(nullValue >> undf);
print(nullValue >>> undf);
@ -136,6 +141,7 @@ print(intNum >= nullValue);
print(intNum == nullValue);
print(intNum === nullValue);
print(intNum != nullValue);
print(intNum !== nullValue);
print(intNum << nullValue);
print(intNum >> nullValue);
print(intNum >>> nullValue);
@ -156,6 +162,7 @@ print(doubleNum >= nullValue);
print(doubleNum == nullValue);
print(doubleNum === nullValue);
print(doubleNum != nullValue);
print(doubleNum !== nullValue);
print(doubleNum << nullValue);
print(doubleNum >> nullValue);
print(doubleNum >>> nullValue);
@ -176,6 +183,7 @@ print(falseValue >= nullValue);
print(falseValue == nullValue);
print(falseValue === nullValue);
print(falseValue != nullValue);
print(falseValue !== nullValue);
print(falseValue << nullValue);
print(falseValue >> nullValue);
print(falseValue >>> nullValue);
@ -196,6 +204,7 @@ print(trueValue >= nullValue);
print(trueValue == nullValue);
print(trueValue === nullValue);
print(trueValue != nullValue);
print(trueValue !== nullValue);
print(trueValue << nullValue);
print(trueValue >> nullValue);
print(trueValue >>> nullValue);
@ -216,6 +225,7 @@ print(intNum >= falseValue);
print(intNum == falseValue);
print(intNum === falseValue);
print(intNum != falseValue);
print(intNum !== falseValue);
print(intNum << falseValue);
print(intNum >> falseValue);
print(intNum >>> falseValue);
@ -236,6 +246,7 @@ print(doubleNum >= falseValue);
print(doubleNum == falseValue);
print(doubleNum === falseValue);
print(doubleNum != falseValue);
print(doubleNum !== falseValue);
print(doubleNum << falseValue);
print(doubleNum >> falseValue);
print(doubleNum >>> falseValue);
@ -256,6 +267,7 @@ print(trueValue >= falseValue);
print(trueValue == falseValue);
print(trueValue === falseValue);
print(trueValue != falseValue);
print(trueValue !== falseValue);
print(trueValue << falseValue);
print(trueValue >> falseValue);
print(trueValue >>> falseValue);
@ -276,6 +288,7 @@ print(intNum >= trueValue);
print(intNum == trueValue);
print(intNum === trueValue);
print(intNum != trueValue);
print(intNum !== trueValue);
print(intNum << trueValue);
print(intNum >> trueValue);
print(intNum >>> trueValue);
@ -296,6 +309,7 @@ print(doubleNum >= trueValue);
print(doubleNum == trueValue);
print(doubleNum === trueValue);
print(doubleNum != trueValue);
print(doubleNum !== trueValue);
print(doubleNum << trueValue);
print(doubleNum >> trueValue);
print(doubleNum >>> trueValue);
@ -316,6 +330,7 @@ print(trueValue >= falseValue);
print(trueValue == falseValue);
print(trueValue === falseValue);
print(trueValue != falseValue);
print(trueValue !== falseValue);
print(trueValue << falseValue);
print(trueValue >> falseValue);
print(trueValue >>> falseValue);
@ -336,6 +351,7 @@ print(undf >= undf);
print(undf == undf);
print(undf === undf);
print(undf != undf);
print(undf !== undf);
print(undf << undf);
print(undf >> undf);
print(undf >>> undf);
@ -356,6 +372,7 @@ print(nullValue >= nullValue);
print(nullValue == nullValue);
print(nullValue === nullValue);
print(nullValue != nullValue);
print(nullValue !== nullValue);
print(nullValue << nullValue);
print(nullValue >> nullValue);
print(nullValue >>> nullValue);
@ -376,6 +393,7 @@ print(trueValue >= trueValue);
print(trueValue == trueValue);
print(trueValue === trueValue);
print(trueValue != trueValue);
print(trueValue !== trueValue);
print(trueValue << trueValue);
print(trueValue >> trueValue);
print(trueValue >>> trueValue);
@ -396,6 +414,7 @@ print(falseValue >= falseValue);
print(falseValue == falseValue);
print(falseValue === falseValue);
print(falseValue != falseValue);
print(falseValue !== falseValue);
print(falseValue << falseValue);
print(falseValue >> falseValue);
print(falseValue >>> falseValue);

View File

@ -24,6 +24,7 @@ false
false
false
true
true
5
5
5
@ -42,6 +43,7 @@ false
false
false
true
true
1
1
1
@ -60,6 +62,7 @@ false
false
false
true
true
0
0
0
@ -78,6 +81,7 @@ false
false
false
true
true
1
1
1
@ -96,6 +100,7 @@ false
true
false
false
true
0
0
0
@ -114,6 +119,7 @@ true
false
false
true
true
5
5
5
@ -132,6 +138,7 @@ true
false
false
true
true
1
1
1
@ -150,6 +157,7 @@ true
false
false
true
true
0
0
0
@ -168,6 +176,7 @@ true
false
false
true
true
1
1
1
@ -186,6 +195,7 @@ true
false
false
true
true
5
5
5
@ -204,6 +214,7 @@ true
false
false
true
true
1
1
1
@ -222,6 +233,7 @@ true
false
false
true
true
1
1
1
@ -240,6 +252,7 @@ true
false
false
true
true
10
2
2
@ -258,6 +271,7 @@ true
false
false
true
true
2
0
0
@ -276,6 +290,7 @@ true
false
false
true
true
1
1
1
@ -294,6 +309,7 @@ false
true
true
false
false
0
0
0
@ -312,6 +328,7 @@ true
true
true
false
false
0
0
0
@ -330,6 +347,7 @@ true
true
true
false
false
2
0
0
@ -348,6 +366,7 @@ true
true
true
false
false
0
0
0

View File

@ -0,0 +1,18 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//arkcompiler/ets_runtime/test/test_helper.gni")
host_aot_js_test_action("not_equal") {
deps = []
}

View File

@ -0,0 +1,37 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
true
true
true
true
false
false
false
false
false
false
false
false
true
true
true
true
false
false
true
true
true
true
false
false

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var a = 2;
print(a != null);
print(null != a);
print(a != undefined);
print(undefined != a);
var b = null;
print(b != null);
print(null != b);
print(b != undefined);
print(undefined != b);
var c = undefined;
print(c != null);
print(null != c);
print(c != undefined);
print(undefined != c);
var d = 2;
print(d !== null);
print(null !== d);
print(d !== undefined);
print(undefined !== d);
var e = null;
print(e !== null);
print(null !== e);
print(e !== undefined);
print(undefined !== e);
var f = undefined;
print(f !== null);
print(null !== f);
print(f !== undefined);
print(undefined !== f);