Skip to content

Commit 5483d8e

Browse files
LeszekSwirskiV8 LUCI CQ
authored andcommitted
[interpreter] Add shortcut for !!foo
Special case nested logical not in the interpreter, to shortcut repeated logical nots. This in particular adds a faster path for the !!foo convention of converting a value to a boolean (which, it turns out, means we have to add a ToBoolean bytecode). As a related fix, support ToBoolean/ToBooleanLogicalNot in maglev's BuildBranchIfToBooleanTrue, avoiding a repeat ToBoolean operation on them. Change-Id: I68f99d71dc69b385b5a5fa144c885bafea1e2dee Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4466570 Auto-Submit: Leszek Swirski <[email protected]> Reviewed-by: Michael Lippautz <[email protected]> Commit-Queue: Michael Lippautz <[email protected]> Commit-Queue: Leszek Swirski <[email protected]> Cr-Commit-Position: refs/heads/main@{#87241}
1 parent 56dbf8e commit 5483d8e

10 files changed

Lines changed: 89 additions & 4 deletions

src/baseline/baseline-compiler.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,10 @@ void BaselineCompiler::VisitToString() {
17331733
CallBuiltin<Builtin::kToString>(kInterpreterAccumulatorRegister);
17341734
}
17351735

1736+
void BaselineCompiler::VisitToBoolean() {
1737+
CallBuiltin<Builtin::kToBoolean>(kInterpreterAccumulatorRegister);
1738+
}
1739+
17361740
void BaselineCompiler::VisitCreateRegExpLiteral() {
17371741
CallBuiltin<Builtin::kCreateRegExpLiteral>(
17381742
FeedbackVector(), // feedback vector

src/compiler/bytecode-graph-builder.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3421,6 +3421,12 @@ void BytecodeGraphBuilder::VisitToString() {
34213421
environment()->BindAccumulator(value, Environment::kAttachFrameState);
34223422
}
34233423

3424+
void BytecodeGraphBuilder::VisitToBoolean() {
3425+
Node* value =
3426+
NewNode(simplified()->ToBoolean(), environment()->LookupAccumulator());
3427+
environment()->BindAccumulator(value, Environment::kAttachFrameState);
3428+
}
3429+
34243430
void BytecodeGraphBuilder::VisitToNumber() {
34253431
PrepareEagerCheckpoint();
34263432
Node* object = environment()->LookupAccumulator();

src/debug/debug-evaluate.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
524524
case Bytecode::kToNumber:
525525
case Bytecode::kToNumeric:
526526
case Bytecode::kToString:
527+
case Bytecode::kToBoolean:
527528
// Misc.
528529
case Bytecode::kIncBlockCounter: // Coverage counters.
529530
case Bytecode::kForInEnumerate:

src/interpreter/bytecode-array-builder.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,17 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ToString() {
10851085
return *this;
10861086
}
10871087

1088+
BytecodeArrayBuilder& BytecodeArrayBuilder::ToBoolean(ToBooleanMode mode) {
1089+
if (mode == ToBooleanMode::kAlreadyBoolean) {
1090+
// No-op, the accumulator is already a boolean and ToBoolean both reads and
1091+
// writes the accumulator.
1092+
} else {
1093+
DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
1094+
OutputToBoolean();
1095+
}
1096+
return *this;
1097+
}
1098+
10881099
BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumber(int feedback_slot) {
10891100
OutputToNumber(feedback_slot);
10901101
return *this;

src/interpreter/bytecode-array-builder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,9 +407,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
407407
// Converts accumulator and stores result in register |out|.
408408
BytecodeArrayBuilder& ToObject(Register out);
409409
BytecodeArrayBuilder& ToName(Register out);
410-
BytecodeArrayBuilder& ToString();
411410

412411
// Converts accumulator and stores result back in accumulator.
412+
BytecodeArrayBuilder& ToString();
413+
BytecodeArrayBuilder& ToBoolean(ToBooleanMode mode);
413414
BytecodeArrayBuilder& ToNumber(int feedback_slot);
414415
BytecodeArrayBuilder& ToNumeric(int feedback_slot);
415416

src/interpreter/bytecode-generator.cc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "src/common/globals.h"
2020
#include "src/compiler-dispatcher/lazy-compile-dispatcher.h"
2121
#include "src/heap/parked-scope.h"
22+
#include "src/interpreter/bytecode-array-builder.h"
2223
#include "src/interpreter/bytecode-flags.h"
2324
#include "src/interpreter/bytecode-jump-table.h"
2425
#include "src/interpreter/bytecode-label.h"
@@ -6208,8 +6209,16 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
62086209
test_result->InvertControlFlow();
62096210
VisitInSameTestExecutionScope(expr->expression());
62106211
} else {
6211-
TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
6212-
builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
6212+
UnaryOperation* unary_op = expr->expression()->AsUnaryOperation();
6213+
if (unary_op && unary_op->op() == Token::Value::NOT) {
6214+
// Shortcut repeated nots, to capture the `!!foo` pattern for converting
6215+
// expressions to booleans.
6216+
TypeHint type_hint = VisitForAccumulatorValue(unary_op->expression());
6217+
builder()->ToBoolean(ToBooleanModeFromTypeHint(type_hint));
6218+
} else {
6219+
TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
6220+
builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
6221+
}
62136222
// Always returns a boolean value.
62146223
execution_result()->SetResultIsBoolean();
62156224
}

src/interpreter/bytecodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ namespace interpreter {
298298
V(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
299299
V(ToObject, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut) \
300300
V(ToString, ImplicitRegisterUse::kReadWriteAccumulator) \
301+
V(ToBoolean, ImplicitRegisterUse::kReadWriteAccumulator) \
301302
\
302303
/* Literals */ \
303304
V(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator, \

src/interpreter/interpreter-generator.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,29 @@ IGNITION_HANDLER(ToString, InterpreterAssembler) {
12081208
Dispatch();
12091209
}
12101210

1211+
// ToString
1212+
//
1213+
// Convert the accumulator to a String.
1214+
IGNITION_HANDLER(ToBoolean, InterpreterAssembler) {
1215+
TNode<Object> value = GetAccumulator();
1216+
TVARIABLE(Oddball, result);
1217+
Label if_true(this), if_false(this), end(this);
1218+
BranchIfToBooleanIsTrue(value, &if_true, &if_false);
1219+
BIND(&if_true);
1220+
{
1221+
result = TrueConstant();
1222+
Goto(&end);
1223+
}
1224+
BIND(&if_false);
1225+
{
1226+
result = FalseConstant();
1227+
Goto(&end);
1228+
}
1229+
BIND(&end);
1230+
SetAccumulator(result.value());
1231+
Dispatch();
1232+
}
1233+
12111234
// Inc
12121235
//
12131236
// Increments value in the accumulator by one.

src/maglev/maglev-graph-builder.cc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6311,6 +6311,23 @@ void MaglevGraphBuilder::VisitToString() {
63116311
SetAccumulator(BuildToString(value, ToString::kThrowOnSymbol));
63126312
}
63136313

6314+
void MaglevGraphBuilder::VisitToBoolean() {
6315+
ValueNode* value = GetAccumulatorTagged();
6316+
switch (value->opcode()) {
6317+
#define CASE(Name) \
6318+
case Opcode::k##Name: { \
6319+
SetAccumulator( \
6320+
GetBooleanConstant(value->Cast<Name>()->ToBoolean(local_isolate()))); \
6321+
break; \
6322+
}
6323+
CONSTANT_VALUE_NODE_LIST(CASE)
6324+
#undef CASE
6325+
default:
6326+
SetAccumulator(AddNewNode<ToBoolean>({value}));
6327+
break;
6328+
}
6329+
}
6330+
63146331
void MaglevGraphBuilder::VisitCreateRegExpLiteral() {
63156332
// CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
63166333
compiler::StringRef pattern = GetRefOperand<String>(0);
@@ -7304,6 +7321,13 @@ void MaglevGraphBuilder::BuildBranchIfToBooleanTrue(ValueNode* node,
73047321
Operation::kEqual, true_target, false_target);
73057322
break;
73067323
}
7324+
// Known boolean-valued codes, we don't need to call ToBoolean on them.
7325+
case Opcode::kToBoolean:
7326+
case Opcode::kToBooleanLogicalNot: {
7327+
block = FinishBlock<BranchIfRootConstant>({node}, RootIndex::kTrueValue,
7328+
true_target, false_target);
7329+
break;
7330+
}
73077331
default:
73087332
block =
73097333
BuildSpecializedBranchIfCompareNode(node, true_target, false_target);

test/unittests/interpreter/bytecode-array-builder-unittest.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
274274
.CompareNull();
275275

276276
// Emit conversion operator invocations.
277-
builder.ToNumber(1).ToNumeric(1).ToObject(reg).ToName(reg).ToString();
277+
builder.ToNumber(1)
278+
.ToNumeric(1)
279+
.ToObject(reg)
280+
.ToName(reg)
281+
.ToString()
282+
.ToBoolean(ToBooleanMode::kConvertToBoolean);
278283

279284
// Emit GetSuperConstructor.
280285
builder.GetSuperConstructor(reg);

0 commit comments

Comments
 (0)