From 62632c080515537c4f0f74f1bfb209435d05c151 Mon Sep 17 00:00:00 2001 From: jameslahm Date: Wed, 6 Apr 2022 09:43:43 +0800 Subject: [PATCH] [interpreter] Optimize strict equal boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For strict equal boolean literal like "a===true" or "a===false", we could generate TestReferenceEqual rather than TestStrictEqual. And in `execution_result()->IsTest()` case, we could directly emit JumpIfTrue/JumpIfFalse. E.g. ``` a === true ``` Generated Bytecode From: ``` LdaGlobal Star1 LdaTrue TestEqualStrict ``` To: ``` LdaGlobal Star1 LdaTrue TestReferenceEqual ``` E.g. ``` if (a === true) ``` Generated Bytecode From: ``` LdaGlobal Star1 LdaTrue TestEqualStrict JumpIfFalse ``` To ``` LdaGlobal JumpIfTrue Jump ``` Bug: v8:6403 Change-Id: Ieaca147acd2d523ac0d2466e7861afb2d29a1310 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3568923 Reviewed-by: Leszek Swirski Reviewed-by: Tobias Tebbi Commit-Queue: 王澳 Cr-Commit-Position: refs/heads/main@{#79935} --- src/ast/ast.cc | 22 ++ src/ast/ast.h | 8 + src/compiler/bytecode-graph-builder.cc | 16 +- src/interpreter/bytecode-generator.cc | 28 ++ src/interpreter/bytecode-generator.h | 1 + src/interpreter/interpreter-generator.cc | 4 - .../CompareBoolean.golden | 368 ++++++++++++++++++ .../interpreter/test-bytecode-generator.cc | 56 +++ test/js-perf-test/BytecodeHandlers/compare.js | 114 ++++++ test/js-perf-test/JSTests3.json | 1 + 10 files changed, 608 insertions(+), 10 deletions(-) create mode 100644 test/cctest/interpreter/bytecode_expectations/CompareBoolean.golden diff --git a/src/ast/ast.cc b/src/ast/ast.cc index 804a6840c1..97db02225f 100644 --- a/src/ast/ast.cc +++ b/src/ast/ast.cc @@ -103,6 +103,10 @@ bool Expression::IsNullLiteral() const { return IsLiteral() && AsLiteral()->type() == Literal::kNull; } +bool Expression::IsBooleanLiteral() const { + return IsLiteral() && AsLiteral()->type() == Literal::kBoolean; +} + bool Expression::IsTheHoleLiteral() const { return IsLiteral() && AsLiteral()->type() == Literal::kTheHole; } @@ -892,6 +896,24 @@ static bool IsVoidOfLiteral(Expression* expr) { maybe_unary->expression()->IsLiteral(); } +static bool MatchLiteralStrictCompareBoolean(Expression* left, Token::Value op, + Expression* right, + Expression** expr, + Literal** literal) { + if (left->IsBooleanLiteral() && op == Token::EQ_STRICT) { + *expr = right; + *literal = left->AsLiteral(); + return true; + } + return false; +} + +bool CompareOperation::IsLiteralStrictCompareBoolean(Expression** expr, + Literal** literal) { + return MatchLiteralStrictCompareBoolean(left_, op(), right_, expr, literal) || + MatchLiteralStrictCompareBoolean(right_, op(), left_, expr, literal); +} + // Check for the pattern: void equals or // undefined equals static bool MatchLiteralCompareUndefined(Expression* left, Token::Value op, diff --git a/src/ast/ast.h b/src/ast/ast.h index 971a2b0ec1..a348ccf82a 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -236,6 +236,8 @@ class Expression : public AstNode { // True iff the expression is the null literal. bool IsNullLiteral() const; + bool IsBooleanLiteral() const; + // True iff the expression is the hole literal. bool IsTheHoleLiteral() const; @@ -955,6 +957,11 @@ class Literal final : public Expression { return Smi::FromInt(smi_); } + bool AsBooleanLiteral() const { + DCHECK_EQ(kBoolean, type()); + return boolean_; + } + // Returns true if literal represents a Number. bool IsNumber() const { return type() == kHeapNumber || type() == kSmi; } double AsNumber() const { @@ -1963,6 +1970,7 @@ class CompareOperation final : public Expression { // Match special cases. bool IsLiteralCompareTypeof(Expression** expr, Literal** literal); + bool IsLiteralStrictCompareBoolean(Expression** expr, Literal** literal); bool IsLiteralCompareUndefined(Expression** expr); bool IsLiteralCompareNull(Expression** expr); diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc index 7fe1b626b1..a86f16886a 100644 --- a/src/compiler/bytecode-graph-builder.cc +++ b/src/compiler/bytecode-graph-builder.cc @@ -3977,19 +3977,24 @@ void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) { } void BytecodeGraphBuilder::BuildJumpIfFalse() { - NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); + Node* accumulator = environment()->LookupAccumulator(); + Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator, + jsgraph()->FalseConstant()); + NewBranch(condition, BranchHint::kNone); { SubEnvironment sub_environment(this); - NewIfFalse(); + NewIfTrue(); environment()->BindAccumulator(jsgraph()->FalseConstant()); MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); } - NewIfTrue(); - environment()->BindAccumulator(jsgraph()->TrueConstant()); + NewIfFalse(); } void BytecodeGraphBuilder::BuildJumpIfTrue() { - NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); + Node* accumulator = environment()->LookupAccumulator(); + Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator, + jsgraph()->TrueConstant()); + NewBranch(condition, BranchHint::kNone); { SubEnvironment sub_environment(this); NewIfTrue(); @@ -3997,7 +4002,6 @@ void BytecodeGraphBuilder::BuildJumpIfTrue() { MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); } NewIfFalse(); - environment()->BindAccumulator(jsgraph()->FalseConstant()); } void BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() { diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index 4a0299df55..6d3fe7e76e 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -6157,6 +6157,29 @@ void BytecodeGenerator::BuildLiteralCompareNil( } } +void BytecodeGenerator::BuildLiteralStrictCompareBoolean(Literal* literal) { + DCHECK(literal->IsBooleanLiteral()); + if (execution_result()->IsTest()) { + TestResultScope* test_result = execution_result()->AsTest(); + if (literal->AsBooleanLiteral()) { + builder()->JumpIfTrue(ToBooleanMode::kAlreadyBoolean, + test_result->NewThenLabel()); + } else { + builder()->JumpIfFalse(ToBooleanMode::kAlreadyBoolean, + test_result->NewThenLabel()); + } + if (test_result->fallthrough() != TestFallthrough::kElse) { + builder()->Jump(test_result->NewElseLabel()); + } + test_result->SetResultConsumedByTest(); + } else { + Register result = register_allocator()->NewRegister(); + builder()->StoreAccumulatorInRegister(result); + builder()->LoadBoolean(literal->AsBooleanLiteral()); + builder()->CompareReference(result); + } +} + void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { Expression* sub_expr; Literal* literal; @@ -6172,6 +6195,11 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { } else { builder()->CompareTypeOf(literal_flag); } + } else if (expr->IsLiteralStrictCompareBoolean(&sub_expr, &literal)) { + DCHECK(expr->op() == Token::EQ_STRICT); + VisitForAccumulatorValue(sub_expr); + builder()->SetExpressionPosition(expr); + BuildLiteralStrictCompareBoolean(literal); } else if (expr->IsLiteralCompareUndefined(&sub_expr)) { VisitForAccumulatorValue(sub_expr); builder()->SetExpressionPosition(expr); diff --git a/src/interpreter/bytecode-generator.h b/src/interpreter/bytecode-generator.h index 28ede9457b..075578433c 100644 --- a/src/interpreter/bytecode-generator.h +++ b/src/interpreter/bytecode-generator.h @@ -263,6 +263,7 @@ class BytecodeGenerator final : public AstVisitor { LookupHoistingMode lookup_hoisting_mode = LookupHoistingMode::kNormal); void BuildLiteralCompareNil(Token::Value compare_op, BytecodeArrayBuilder::NilValue nil); + void BuildLiteralStrictCompareBoolean(Literal* literal); void BuildReturn(int source_position); void BuildAsyncReturn(int source_position); void BuildAsyncGeneratorReturn(); diff --git a/src/interpreter/interpreter-generator.cc b/src/interpreter/interpreter-generator.cc index e0c35ac2c9..50e9fff51e 100644 --- a/src/interpreter/interpreter-generator.cc +++ b/src/interpreter/interpreter-generator.cc @@ -1915,7 +1915,6 @@ IGNITION_HANDLER(JumpConstant, InterpreterAssembler) { // will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) { TNode accumulator = GetAccumulator(); - CSA_DCHECK(this, IsBoolean(CAST(accumulator))); JumpIfTaggedEqual(accumulator, TrueConstant(), 0); } @@ -1926,7 +1925,6 @@ IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) { // and will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) { TNode accumulator = GetAccumulator(); - CSA_DCHECK(this, IsBoolean(CAST(accumulator))); JumpIfTaggedEqualConstant(accumulator, TrueConstant(), 0); } @@ -1937,7 +1935,6 @@ IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) { // will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) { TNode accumulator = GetAccumulator(); - CSA_DCHECK(this, IsBoolean(CAST(accumulator))); JumpIfTaggedEqual(accumulator, FalseConstant(), 0); } @@ -1948,7 +1945,6 @@ IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) { // and will misbehave if passed arbitrary input values. IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) { TNode accumulator = GetAccumulator(); - CSA_DCHECK(this, IsBoolean(CAST(accumulator))); JumpIfTaggedEqualConstant(accumulator, FalseConstant(), 0); } diff --git a/test/cctest/interpreter/bytecode_expectations/CompareBoolean.golden b/test/cctest/interpreter/bytecode_expectations/CompareBoolean.golden new file mode 100644 index 0000000000..76646494bd --- /dev/null +++ b/test/cctest/interpreter/bytecode_expectations/CompareBoolean.golden @@ -0,0 +1,368 @@ +# +# Autogenerated by generate-bytecode-expectations. +# + +--- +wrap: yes + +--- +snippet: " + var a = 1; + return a === true; +" +frame size: 1 +parameter count: 1 +bytecode array length: 7 +bytecodes: [ + /* 42 S> */ B(LdaSmi), I8(1), + B(Star0), + /* 45 S> */ B(LdaTrue), + B(TestReferenceEqual), R(0), + /* 63 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = true; + return true === a; +" +frame size: 1 +parameter count: 1 +bytecode array length: 6 +bytecodes: [ + /* 42 S> */ B(LdaTrue), + B(Star0), + /* 48 S> */ B(LdaTrue), + B(TestReferenceEqual), R(0), + /* 66 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = false; + return true !== a; +" +frame size: 1 +parameter count: 1 +bytecode array length: 7 +bytecodes: [ + /* 42 S> */ B(LdaFalse), + B(Star0), + /* 49 S> */ B(LdaTrue), + B(TestReferenceEqual), R(0), + /* 61 E> */ B(LogicalNot), + /* 67 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = 1; + return true === a ? 1 : 2; +" +frame size: 1 +parameter count: 1 +bytecode array length: 14 +bytecodes: [ + /* 42 S> */ B(LdaSmi), I8(1), + B(Star0), + /* 45 S> */ B(JumpIfTrue), U8(4), + B(Jump), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + /* 71 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = true; + return false === a ? 1 : 2; +" +frame size: 1 +parameter count: 1 +bytecode array length: 13 +bytecodes: [ + /* 42 S> */ B(LdaTrue), + B(Star0), + /* 48 S> */ B(JumpIfFalse), U8(4), + B(Jump), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + /* 75 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = 1; + return true !== a ? 1 : 2; +" +frame size: 1 +parameter count: 1 +bytecode array length: 12 +bytecodes: [ + /* 42 S> */ B(LdaSmi), I8(1), + B(Star0), + /* 45 S> */ B(JumpIfTrue), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + /* 71 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = false; + return false !== null ? 1 : 2; +" +frame size: 1 +parameter count: 1 +bytecode array length: 12 +bytecodes: [ + /* 42 S> */ B(LdaFalse), + B(Star0), + /* 49 S> */ B(LdaNull), + B(JumpIfFalse), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + /* 79 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = 0; + if (a !== true) { + return 1; + } +" +frame size: 1 +parameter count: 1 +bytecode array length: 9 +bytecodes: [ + /* 42 S> */ B(LdaZero), + B(Star0), + /* 45 S> */ B(JumpIfTrue), U8(5), + /* 65 S> */ B(LdaSmi), I8(1), + /* 74 S> */ B(Return), + B(LdaUndefined), + /* 77 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var a = true; + var b = 0; + while (a !== true) { + b++; + } +" +frame size: 2 +parameter count: 1 +bytecode array length: 18 +bytecodes: [ + /* 42 S> */ B(LdaTrue), + B(Star0), + /* 56 S> */ B(LdaZero), + B(Star1), + /* 68 S> */ B(Ldar), R(0), + B(JumpIfTrue), U8(10), + /* 82 S> */ B(Ldar), R(1), + B(Inc), U8(0), + B(Star1), + /* 59 E> */ B(JumpLoop), U8(9), I8(0), + B(LdaUndefined), + /* 89 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + (0 === true) ? 1 : 2; +" +frame size: 0 +parameter count: 1 +bytecode array length: 13 +bytecodes: [ + /* 34 S> */ B(LdaZero), + B(JumpIfTrue), U8(4), + B(Jump), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + B(LdaUndefined), + /* 56 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + (0 !== true) ? 1 : 2; +" +frame size: 0 +parameter count: 1 +bytecode array length: 11 +bytecodes: [ + /* 34 S> */ B(LdaZero), + B(JumpIfTrue), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + B(LdaUndefined), + /* 56 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + (false === 0) ? 1 : 2; +" +frame size: 0 +parameter count: 1 +bytecode array length: 13 +bytecodes: [ + /* 34 S> */ B(LdaZero), + B(JumpIfFalse), U8(4), + B(Jump), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + B(LdaUndefined), + /* 57 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + (0 === true || 0 === false) ? 1 : 2; +" +frame size: 0 +parameter count: 1 +bytecode array length: 16 +bytecodes: [ + /* 34 S> */ B(LdaZero), + B(JumpIfTrue), U8(7), + B(LdaZero), + B(JumpIfFalse), U8(4), + B(Jump), U8(6), + B(LdaSmi), I8(1), + B(Jump), U8(4), + B(LdaSmi), I8(2), + B(LdaUndefined), + /* 71 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + if (0 === true || 0 === false) return 1; +" +frame size: 0 +parameter count: 1 +bytecode array length: 13 +bytecodes: [ + /* 34 S> */ B(LdaZero), + B(JumpIfTrue), U8(7), + B(LdaZero), + B(JumpIfFalse), U8(4), + B(Jump), U8(5), + /* 65 S> */ B(LdaSmi), I8(1), + /* 74 S> */ B(Return), + B(LdaUndefined), + /* 75 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + if (!('false' === false)) return 1; +" +frame size: 0 +parameter count: 1 +bytecode array length: 9 +bytecodes: [ + /* 34 S> */ B(LdaConstant), U8(0), + B(JumpIfFalse), U8(5), + /* 60 S> */ B(LdaSmi), I8(1), + /* 69 S> */ B(Return), + B(LdaUndefined), + /* 70 S> */ B(Return), +] +constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["false"], +] +handlers: [ +] + +--- +snippet: " + if (!('false' !== false)) return 1; +" +frame size: 0 +parameter count: 1 +bytecode array length: 11 +bytecodes: [ + /* 34 S> */ B(LdaConstant), U8(0), + B(JumpIfFalse), U8(4), + B(Jump), U8(5), + /* 60 S> */ B(LdaSmi), I8(1), + /* 69 S> */ B(Return), + B(LdaUndefined), + /* 70 S> */ B(Return), +] +constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["false"], +] +handlers: [ +] + diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc index 09e2926059..2a31638d33 100644 --- a/test/cctest/interpreter/test-bytecode-generator.cc +++ b/test/cctest/interpreter/test-bytecode-generator.cc @@ -1161,6 +1161,62 @@ TEST(CompareTypeOf) { LoadGolden("CompareTypeOf.golden"))); } +TEST(CompareBoolean) { + InitializedIgnitionHandleScope scope; + BytecodeExpectationsPrinter printer(CcTest::isolate()); + + std::string snippets[] = { + "var a = 1;\n" + "return a === true;\n", + + "var a = true;\n" + "return true === a;\n", + + "var a = false;\n" + "return true !== a;\n", + + "var a = 1;\n" + "return true === a ? 1 : 2;\n", + + "var a = true;\n" + "return false === a ? 1 : 2;\n", + + "var a = 1;\n" + "return true !== a ? 1 : 2;\n", + + "var a = false;\n" + "return false !== null ? 1 : 2;\n", + + "var a = 0;\n" + "if (a !== true) {\n" + " return 1;\n" + "}\n", + + "var a = true;\n" + "var b = 0;\n" + "while (a !== true) {\n" + " b++;\n" + "}\n", + + "(0 === true) ? 1 : 2;\n", + + "(0 !== true) ? 1 : 2;\n", + + "(false === 0) ? 1 : 2;\n", + + "(0 === true || 0 === false) ? 1 : 2;\n", + + "if (0 === true || 0 === false) return 1;\n", + + "if (!('false' === false)) return 1;\n", + + "if (!('false' !== false)) return 1;\n", + }; + + CHECK(CompareTexts(BuildActual(printer, snippets), + LoadGolden("CompareBoolean.golden"))); +} + TEST(CompareNil) { InitializedIgnitionHandleScope scope; BytecodeExpectationsPrinter printer(CcTest::isolate()); diff --git a/test/js-perf-test/BytecodeHandlers/compare.js b/test/js-perf-test/BytecodeHandlers/compare.js index ea12ff4b21..668ec4b7eb 100644 --- a/test/js-perf-test/BytecodeHandlers/compare.js +++ b/test/js-perf-test/BytecodeHandlers/compare.js @@ -16,6 +16,7 @@ addBenchmark('Number-StrictEquals-False', NumberStrictEqualsFalse); addBenchmark('String-StrictEquals-True', StringStrictEqualsTrue); addBenchmark('String-StrictEquals-False', StringStrictEqualsFalse); addBenchmark('SmiString-StrictEquals', MixedStrictEquals); +addBenchmark('Boolean-StrictEquals', BooleanStrictEquals); addBenchmark('Smi-Equals-True', SmiEqualsTrue); addBenchmark('Smi-Equals-False', SmiEqualsFalse); addBenchmark('Number-Equals-True', NumberEqualsTrue); @@ -46,6 +47,113 @@ function strictEquals(a, b) { } } +function strictEqualsBoolean(a) { + var ret; + for (var i = 0; i < 1000; ++i) { + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === true) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + if (a === false) ret = true; + } + return ret; +} + function equals(a, b) { for (var i = 0; i < 1000; ++i) { a == b; a == b; a == b; a == b; a == b; a == b; a == b; a == b; a == b; a == b; @@ -104,6 +212,12 @@ function StringStrictEqualsTrue() { strictEquals("abc", "abc"); } +function BooleanStrictEquals() { + strictEqualsBoolean("a"); + strictEqualsBoolean(true); + strictEqualsBoolean(false); +} + function MixedStrictEquals() { strictEquals(10, "10"); } diff --git a/test/js-perf-test/JSTests3.json b/test/js-perf-test/JSTests3.json index 244a7e728d..ec57b96abb 100644 --- a/test/js-perf-test/JSTests3.json +++ b/test/js-perf-test/JSTests3.json @@ -318,6 +318,7 @@ {"name": "String-StrictEquals-True"}, {"name": "String-StrictEquals-False"}, {"name": "SmiString-StrictEquals"}, + {"name": "Boolean-StrictEquals"}, {"name": "Smi-Equals-True"}, {"name": "Smi-Equals-False"}, {"name": "Number-Equals-True"},