Commit e6682554 authored by Mythri's avatar Mythri Committed by Commit Bot

[Interpreter] Introduce strict equality bytecode that does not collect feedback.

Some of the StrictEquality comparisons do not require feedback (for ex: in
try-finally, generators). This cl introduces StrictEqualityNoFeedback bytecode
to be used in such cases. With this change, we no longer have to check if the 
type feedback slot is valid in compare bytecode handlers.

This is the first step in reworking the compare bytecode handler to avoid
duplicate checks when collecting feedback and when performing the operation.

BUG=v8:4280

Change-Id: Ia650fd43c0466b8625d3ce98c39ed1073ba42a6b
Reviewed-on: https://chromium-review.googlesource.com/455778
Commit-Queue: Mythri Alle <mythria@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44020}
parent 1cedeb39
......@@ -1850,19 +1850,15 @@ void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* right = environment()->LookupAccumulator();
Node* node = nullptr;
int slot_index = bytecode_iterator().GetIndexOperand(1);
if (slot_index != 0) {
FeedbackSlot slot = feedback_vector()->ToSlot(slot_index);
if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
node = simplified;
} else {
node = NewNode(op, left, right);
}
DCHECK(slot_index != 0);
FeedbackSlot slot = feedback_vector()->ToSlot(slot_index);
Node* node = nullptr;
if (Node* simplified = TryBuildSimplifiedBinaryOp(op, left, right, slot)) {
node = simplified;
} else {
node = NewNode(op, left, right);
}
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
......@@ -1890,6 +1886,21 @@ void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestEqualStrictNoFeedback() {
// TODO(5310): Currently this is used with both Smi operands and with
// string operands. We pass string operands for static property check in
// VisitClassLiteralProperties. This should be changed, so we only use this
// for Smi operations and lower it to SpeculativeNumberEqual[kSignedSmall]
PrepareEagerCheckpoint();
Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* right = environment()->LookupAccumulator();
Node* node = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
left, right);
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::BuildTestingOp(const Operator* op) {
PrepareEagerCheckpoint();
Node* left =
......
......@@ -333,6 +333,7 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::GetSuperConstructor(Register out) {
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
Token::Value op, Register reg, int feedback_slot) {
DCHECK(feedback_slot != kNoFeedbackSlot);
switch (op) {
case Token::Value::EQ:
OutputTestEqual(reg, feedback_slot);
......@@ -352,6 +353,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
case Token::Value::GTE:
OutputTestGreaterThanOrEqual(reg, feedback_slot);
break;
default:
UNREACHABLE();
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
Register reg) {
switch (op) {
case Token::Value::EQ_STRICT:
OutputTestEqualStrictNoFeedback(reg);
break;
case Token::Value::INSTANCEOF:
OutputTestInstanceOf(reg);
break;
......
......@@ -311,7 +311,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Tests.
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
int feedback_slot = kNoFeedbackSlot);
int feedback_slot);
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
BytecodeArrayBuilder& CompareTypeOf(
TestTypeOfFlags::LiteralFlag literal_flag);
......
......@@ -817,7 +817,7 @@ void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
BytecodeLabel not_resuming;
builder()
->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
.CompareOperation(Token::Value::EQ, generator_state_)
.CompareOperation(Token::Value::EQ_STRICT, generator_state_)
.JumpIfTrue(&not_resuming);
BuildIndexedJump(generator_state_, first_yield,
stmt->yield_count(), generator_resume_points_);
......@@ -2987,7 +2987,11 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
VisitForAccumulatorValue(expr->right());
builder()->SetExpressionPosition(expr);
FeedbackSlot slot = expr->CompareOperationFeedbackSlot();
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
if (slot.IsInvalid()) {
builder()->CompareOperation(expr->op(), lhs);
} else {
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
}
}
}
......
......@@ -205,6 +205,7 @@ namespace interpreter {
OperandType::kIdx) \
V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestEqualStrictNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestUndetectable, AccumulatorUse::kWrite, OperandType::kReg) \
......@@ -506,6 +507,7 @@ class V8_EXPORT_PRIVATE Bytecodes final {
case Bytecode::kTestGreaterThanOrEqual:
case Bytecode::kTestInstanceOf:
case Bytecode::kTestIn:
case Bytecode::kTestEqualStrictNoFeedback:
case Bytecode::kTestUndetectable:
case Bytecode::kTestTypeOf:
case Bytecode::kForInContinue:
......
This diff is collapsed.
......@@ -118,7 +118,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 117
bytecode array length: 116
bytecodes: [
B(CreateFunctionContext), U8(2),
B(PushContext), R(3),
......@@ -153,7 +153,7 @@ bytecodes: [
B(LdaImmutableCurrentContextSlot), U8(5),
/* 106 E> */ B(ToName), R(7),
B(LdaConstant), U8(4),
B(TestEqualStrict), R(7), U8(0),
B(TestEqualStrictNoFeedback), R(7),
B(Mov), R(4), R(6),
B(JumpIfToBooleanFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
......
......@@ -11,7 +11,7 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 264
bytecode array length: 263
bytecodes: [
/* 30 E> */ B(StackCheck),
B(LdaZero),
......@@ -117,7 +117,7 @@ bytecodes: [
B(Ldar), R(11),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(9), U8(0),
B(TestEqualStrictNoFeedback), R(9),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(10),
......@@ -150,7 +150,7 @@ snippet: "
"
frame size: 16
parameter count: 1
bytecode array length: 278
bytecode array length: 276
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -258,10 +258,10 @@ bytecodes: [
B(Ldar), R(12),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(10), U8(0),
B(JumpIfTrue), U8(11),
B(TestEqualStrictNoFeedback), R(10),
B(JumpIfTrue), U8(10),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(10), U8(0),
B(TestEqualStrictNoFeedback), R(10),
B(JumpIfTrue), U8(7),
B(Jump), U8(8),
B(Ldar), R(11),
......@@ -298,7 +298,7 @@ snippet: "
"
frame size: 15
parameter count: 1
bytecode array length: 282
bytecode array length: 281
bytecodes: [
/* 30 E> */ B(StackCheck),
B(LdaZero),
......@@ -412,7 +412,7 @@ bytecodes: [
B(Ldar), R(11),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(9), U8(0),
B(TestEqualStrictNoFeedback), R(9),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(10),
......@@ -445,7 +445,7 @@ snippet: "
"
frame size: 14
parameter count: 1
bytecode array length: 289
bytecode array length: 287
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8),
......@@ -556,10 +556,10 @@ bytecodes: [
B(Ldar), R(10),
B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(8), U8(0),
B(JumpIfTrue), U8(11),
B(TestEqualStrictNoFeedback), R(8),
B(JumpIfTrue), U8(10),
B(LdaSmi), I8(1),
B(TestEqualStrict), R(8), U8(0),
B(TestEqualStrictNoFeedback), R(8),
B(JumpIfTrue), U8(7),
B(Jump), U8(8),
B(Ldar), R(9),
......
......@@ -12,7 +12,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 47
bytecode array length: 46
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
......@@ -34,7 +34,7 @@ bytecodes: [
B(Ldar), R(3),
/* 72 E> */ B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(1), U8(0),
B(TestEqualStrictNoFeedback), R(1),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(2),
......@@ -55,7 +55,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 74
bytecode array length: 73
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
......@@ -90,7 +90,7 @@ bytecodes: [
B(Ldar), R(4),
/* 92 E> */ B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(2), U8(0),
B(TestEqualStrictNoFeedback), R(2),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(3),
......@@ -115,7 +115,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 97
bytecode array length: 96
bytecodes: [
/* 30 E> */ B(StackCheck),
B(Mov), R(context), R(4),
......@@ -161,7 +161,7 @@ bytecodes: [
B(Ldar), R(4),
/* 116 E> */ B(SetPendingMessage),
B(LdaZero),
B(TestEqualStrict), R(2), U8(0),
B(TestEqualStrictNoFeedback), R(2),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(3),
......
......@@ -2151,7 +2151,7 @@ TEST(InterpreterInstanceOf) {
size_t func_entry = builder.AllocateDeferredConstantPoolEntry();
builder.SetDeferredConstantPoolEntry(func_entry, func);
builder.LoadConstantPoolEntry(func_entry)
.CompareOperation(Token::Value::INSTANCEOF, r0, 0)
.CompareOperation(Token::Value::INSTANCEOF, r0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
......@@ -2187,7 +2187,7 @@ TEST(InterpreterTestIn) {
size_t array_entry = builder.AllocateDeferredConstantPoolEntry();
builder.SetDeferredConstantPoolEntry(array_entry, array);
builder.LoadConstantPoolEntry(array_entry)
.CompareOperation(Token::Value::IN, r0, 0)
.CompareOperation(Token::Value::IN, r0)
.Return();
ast_factory.Internalize(isolate);
......
......@@ -208,13 +208,14 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit test operator invocations.
builder.CompareOperation(Token::Value::EQ, reg, 1)
.CompareOperation(Token::Value::EQ_STRICT, reg, 2)
.CompareOperation(Token::Value::EQ_STRICT, reg)
.CompareOperation(Token::Value::LT, reg, 3)
.CompareOperation(Token::Value::GT, reg, 4)
.CompareOperation(Token::Value::LTE, reg, 5)
.CompareOperation(Token::Value::GTE, reg, 6)
.CompareOperation(Token::Value::INSTANCEOF, reg, 7)
.CompareOperation(Token::Value::IN, reg, 8)
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber);
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber)
.CompareOperation(Token::Value::INSTANCEOF, reg)
.CompareOperation(Token::Value::IN, reg);
// Emit peephole optimizations of equality with Null or Undefined.
builder.LoadUndefined()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment