Commit f4f58e31 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Optimize code of the form 'if (x === undefined)'.

Translates code of the form 'if (x === undefined)' into the JumpIfUndefined
bytecode, and similarly for comparisons with null. Also adds bytecodes for
JumpIfNotUndefined / Null.

Moves the peephole optimization for CompareUndefined out of the peephole
optimizer and into the BytecodeGenerator, having the side-effect of enabling
it for comparisons with undefined on both side of the compare operation.

BUG=v8:6107

Review-Url: https://codereview.chromium.org/2793923002
Cr-Commit-Position: refs/heads/master@{#44341}
parent d73b11ec
...@@ -1943,23 +1943,20 @@ void BytecodeGraphBuilder::VisitTestInstanceOf() { ...@@ -1943,23 +1943,20 @@ void BytecodeGraphBuilder::VisitTestInstanceOf() {
} }
void BytecodeGraphBuilder::VisitTestUndetectable() { void BytecodeGraphBuilder::VisitTestUndetectable() {
Node* object = Node* object = environment()->LookupAccumulator();
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object); Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
environment()->BindAccumulator(node); environment()->BindAccumulator(node);
} }
void BytecodeGraphBuilder::VisitTestNull() { void BytecodeGraphBuilder::VisitTestNull() {
Node* object = Node* object = environment()->LookupAccumulator();
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* result = NewNode(simplified()->ReferenceEqual(), object, Node* result = NewNode(simplified()->ReferenceEqual(), object,
jsgraph()->NullConstant()); jsgraph()->NullConstant());
environment()->BindAccumulator(result); environment()->BindAccumulator(result);
} }
void BytecodeGraphBuilder::VisitTestUndefined() { void BytecodeGraphBuilder::VisitTestUndefined() {
Node* object = Node* object = environment()->LookupAccumulator();
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* result = NewNode(simplified()->ReferenceEqual(), object, Node* result = NewNode(simplified()->ReferenceEqual(), object,
jsgraph()->UndefinedConstant()); jsgraph()->UndefinedConstant());
environment()->BindAccumulator(result); environment()->BindAccumulator(result);
...@@ -2082,6 +2079,14 @@ void BytecodeGraphBuilder::VisitJumpIfNullConstant() { ...@@ -2082,6 +2079,14 @@ void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
BuildJumpIfEqual(jsgraph()->NullConstant()); BuildJumpIfEqual(jsgraph()->NullConstant());
} }
void BytecodeGraphBuilder::VisitJumpIfNotNull() {
BuildJumpIfNotEqual(jsgraph()->NullConstant());
}
void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
BuildJumpIfNotEqual(jsgraph()->NullConstant());
}
void BytecodeGraphBuilder::VisitJumpIfUndefined() { void BytecodeGraphBuilder::VisitJumpIfUndefined() {
BuildJumpIfEqual(jsgraph()->UndefinedConstant()); BuildJumpIfEqual(jsgraph()->UndefinedConstant());
} }
...@@ -2090,6 +2095,14 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { ...@@ -2090,6 +2095,14 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
BuildJumpIfEqual(jsgraph()->UndefinedConstant()); BuildJumpIfEqual(jsgraph()->UndefinedConstant());
} }
void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
}
void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
}
void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); } void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
void BytecodeGraphBuilder::VisitStackCheck() { void BytecodeGraphBuilder::VisitStackCheck() {
...@@ -2365,6 +2378,13 @@ void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { ...@@ -2365,6 +2378,13 @@ void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
BuildJumpIf(condition); BuildJumpIf(condition);
} }
void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
Node* accumulator = environment()->LookupAccumulator();
Node* condition =
NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
BuildJumpIfNot(condition);
}
void BytecodeGraphBuilder::BuildJumpIfFalse() { void BytecodeGraphBuilder::BuildJumpIfFalse() {
NewBranch(environment()->LookupAccumulator()); NewBranch(environment()->LookupAccumulator());
Environment* if_true_environment = environment()->Copy(); Environment* if_true_environment = environment()->Copy();
......
...@@ -212,6 +212,7 @@ class BytecodeGraphBuilder { ...@@ -212,6 +212,7 @@ class BytecodeGraphBuilder {
void BuildJumpIf(Node* condition); void BuildJumpIf(Node* condition);
void BuildJumpIfNot(Node* condition); void BuildJumpIfNot(Node* condition);
void BuildJumpIfEqual(Node* comperand); void BuildJumpIfEqual(Node* comperand);
void BuildJumpIfNotEqual(Node* comperand);
void BuildJumpIfTrue(); void BuildJumpIfTrue();
void BuildJumpIfFalse(); void BuildJumpIfFalse();
void BuildJumpIfToBooleanTrue(); void BuildJumpIfToBooleanTrue();
......
...@@ -389,6 +389,36 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op, ...@@ -389,6 +389,36 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndetectable() {
OutputTestUndetectable();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareUndefined() {
OutputTestUndefined();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNull() {
OutputTestNull();
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareNil(Token::Value op,
NilValue nil) {
if (op == Token::EQ) {
return CompareUndetectable();
} else {
DCHECK_EQ(Token::EQ_STRICT, op);
if (nil == kUndefinedValue) {
return CompareUndefined();
} else {
DCHECK_EQ(kNullValue, nil);
return CompareNull();
}
}
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf( BytecodeArrayBuilder& BytecodeArrayBuilder::CompareTypeOf(
TestTypeOfFlags::LiteralFlag literal_flag) { TestTypeOfFlags::LiteralFlag literal_flag) {
DCHECK(literal_flag != TestTypeOfFlags::LiteralFlag::kOther); DCHECK(literal_flag != TestTypeOfFlags::LiteralFlag::kOther);
...@@ -885,6 +915,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) { ...@@ -885,6 +915,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
BytecodeLabel* label) {
DCHECK(!label->is_bound());
OutputJumpIfNotNull(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
BytecodeLabel* label) { BytecodeLabel* label) {
DCHECK(!label->is_bound()); DCHECK(!label->is_bound());
...@@ -892,6 +929,47 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined( ...@@ -892,6 +929,47 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotUndefined(
BytecodeLabel* label) {
DCHECK(!label->is_bound());
OutputJumpIfNotUndefined(label, 0);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
Token::Value op,
NilValue nil) {
if (op == Token::EQ) {
// TODO(rmcilroy): Implement JumpIfUndetectable.
return CompareUndetectable().JumpIfTrue(label);
} else {
DCHECK_EQ(Token::EQ_STRICT, op);
if (nil == kUndefinedValue) {
return JumpIfUndefined(label);
} else {
DCHECK_EQ(kNullValue, nil);
return JumpIfNull(label);
}
}
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
Token::Value op,
NilValue nil) {
if (op == Token::EQ) {
// TODO(rmcilroy): Implement JumpIfUndetectable.
return CompareUndetectable().JumpIfFalse(label);
} else {
DCHECK_EQ(Token::EQ_STRICT, op);
if (nil == kUndefinedValue) {
return JumpIfNotUndefined(label);
} else {
DCHECK_EQ(kNullValue, nil);
return JumpIfNotNull(label);
}
}
}
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole( BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotHole(
BytecodeLabel* label) { BytecodeLabel* label) {
DCHECK(!label->is_bound()); DCHECK(!label->is_bound());
......
...@@ -314,6 +314,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -314,6 +314,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg, BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
int feedback_slot); int feedback_slot);
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg); BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
BytecodeArrayBuilder& CompareUndetectable();
BytecodeArrayBuilder& CompareUndefined();
BytecodeArrayBuilder& CompareNull();
BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
BytecodeArrayBuilder& CompareTypeOf( BytecodeArrayBuilder& CompareTypeOf(
TestTypeOfFlags::LiteralFlag literal_flag); TestTypeOfFlags::LiteralFlag literal_flag);
...@@ -332,7 +336,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -332,7 +336,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNotNull(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfUndefined(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNotUndefined(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNil(BytecodeLabel* label, Token::Value op,
NilValue nil);
BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
NilValue nil);
BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth); BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
BytecodeArrayBuilder& StackCheck(int position); BytecodeArrayBuilder& StackCheck(int position);
......
...@@ -162,8 +162,12 @@ Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) { ...@@ -162,8 +162,12 @@ Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
return Bytecode::kJumpIfNotHoleConstant; return Bytecode::kJumpIfNotHoleConstant;
case Bytecode::kJumpIfNull: case Bytecode::kJumpIfNull:
return Bytecode::kJumpIfNullConstant; return Bytecode::kJumpIfNullConstant;
case Bytecode::kJumpIfNotNull:
return Bytecode::kJumpIfNotNullConstant;
case Bytecode::kJumpIfUndefined: case Bytecode::kJumpIfUndefined:
return Bytecode::kJumpIfUndefinedConstant; return Bytecode::kJumpIfUndefinedConstant;
case Bytecode::kJumpIfNotUndefined:
return Bytecode::kJumpIfNotUndefinedConstant;
case Bytecode::kJumpIfJSReceiver: case Bytecode::kJumpIfJSReceiver:
return Bytecode::kJumpIfJSReceiverConstant; return Bytecode::kJumpIfJSReceiverConstant;
default: default:
......
...@@ -3040,13 +3040,34 @@ void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { ...@@ -3040,13 +3040,34 @@ void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
} }
} }
void BytecodeGenerator::BuildLiteralCompareNil(Token::Value op, NilValue nil) {
if (execution_result()->IsTest()) {
TestResultScope* test_result = execution_result()->AsTest();
switch (test_result->fallthrough()) {
case TestFallthrough::kThen:
builder()->JumpIfNotNil(test_result->NewElseLabel(), op, nil);
break;
case TestFallthrough::kElse:
builder()->JumpIfNil(test_result->NewThenLabel(), op, nil);
break;
case TestFallthrough::kNone:
builder()
->JumpIfNil(test_result->NewThenLabel(), op, nil)
.Jump(test_result->NewElseLabel());
}
test_result->SetResultConsumedByTest();
} else {
builder()->CompareNil(op, nil);
}
}
void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Emit a fast literal comparion for expressions of the form: Expression* sub_expr;
// typeof(x) === 'string'.
Expression* typeof_sub_expr;
Literal* literal; Literal* literal;
if (expr->IsLiteralCompareTypeof(&typeof_sub_expr, &literal)) { if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
VisitForTypeOfValue(typeof_sub_expr); // Emit a fast literal comparion for expressions of the form:
// typeof(x) === 'string'.
VisitForTypeOfValue(sub_expr);
builder()->SetExpressionPosition(expr); builder()->SetExpressionPosition(expr);
TestTypeOfFlags::LiteralFlag literal_flag = TestTypeOfFlags::LiteralFlag literal_flag =
TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal); TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
...@@ -3055,6 +3076,14 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -3055,6 +3076,14 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
} else { } else {
builder()->CompareTypeOf(literal_flag); builder()->CompareTypeOf(literal_flag);
} }
} else if (expr->IsLiteralCompareUndefined(&sub_expr)) {
VisitForAccumulatorValue(sub_expr);
builder()->SetExpressionPosition(expr);
BuildLiteralCompareNil(expr->op(), kUndefinedValue);
} else if (expr->IsLiteralCompareNull(&sub_expr)) {
VisitForAccumulatorValue(sub_expr);
builder()->SetExpressionPosition(expr);
BuildLiteralCompareNil(expr->op(), kNullValue);
} else { } else {
Register lhs = VisitForRegisterValue(expr->left()); Register lhs = VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right()); VisitForAccumulatorValue(expr->right());
......
...@@ -109,7 +109,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -109,7 +109,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildVariableAssignment(Variable* variable, Token::Value op, void BuildVariableAssignment(Variable* variable, Token::Value op,
FeedbackSlot slot, FeedbackSlot slot,
HoleCheckMode hole_check_mode); HoleCheckMode hole_check_mode);
void BuildLiteralCompareNil(Token::Value compare_op, NilValue nil);
void BuildReturn(); void BuildReturn();
void BuildAsyncReturn(); void BuildAsyncReturn();
void BuildAsyncGeneratorReturn(); void BuildAsyncGeneratorReturn();
......
...@@ -141,20 +141,6 @@ BytecodeNode TransformLdaZeroBinaryOpToBinaryOpWithZero( ...@@ -141,20 +141,6 @@ BytecodeNode TransformLdaZeroBinaryOpToBinaryOpWithZero(
return node; return node;
} }
BytecodeNode TransformEqualityWithNullOrUndefined(Bytecode new_bytecode,
BytecodeNode* const last,
BytecodeNode* const current) {
DCHECK((last->bytecode() == Bytecode::kLdaNull) ||
(last->bytecode() == Bytecode::kLdaUndefined));
DCHECK((current->bytecode() == Bytecode::kTestEqual) ||
(current->bytecode() == Bytecode::kTestEqualStrict));
BytecodeNode node(new_bytecode, current->operand(0), current->source_info());
if (last->source_info().is_valid()) {
node.set_source_info(last->source_info());
}
return node;
}
} // namespace } // namespace
void BytecodePeepholeOptimizer::DefaultAction( void BytecodePeepholeOptimizer::DefaultAction(
...@@ -268,16 +254,6 @@ void BytecodePeepholeOptimizer:: ...@@ -268,16 +254,6 @@ void BytecodePeepholeOptimizer::
} }
} }
void BytecodePeepholeOptimizer::TransformEqualityWithNullOrUndefinedAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
DCHECK(!Bytecodes::IsJump(node->bytecode()));
// Fused last and current into current.
BytecodeNode new_node(TransformEqualityWithNullOrUndefined(
action_data->bytecode, last(), node));
SetLast(&new_node);
}
void BytecodePeepholeOptimizer::DefaultJumpAction( void BytecodePeepholeOptimizer::DefaultJumpAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) { BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid()); DCHECK(LastIsValid());
......
...@@ -11,17 +11,16 @@ namespace v8 { ...@@ -11,17 +11,16 @@ namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
#define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \ #define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \
V(DefaultAction) \ V(DefaultAction) \
V(UpdateLastAction) \ V(UpdateLastAction) \
V(UpdateLastIfSourceInfoPresentAction) \ V(UpdateLastIfSourceInfoPresentAction) \
V(ElideCurrentAction) \ V(ElideCurrentAction) \
V(ElideCurrentIfOperand0MatchesAction) \ V(ElideCurrentIfOperand0MatchesAction) \
V(ElideLastAction) \ V(ElideLastAction) \
V(ChangeBytecodeAction) \ V(ChangeBytecodeAction) \
V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \ V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction) \ V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction)
V(TransformEqualityWithNullOrUndefinedAction)
#define PEEPHOLE_JUMP_ACTION_LIST(V) \ #define PEEPHOLE_JUMP_ACTION_LIST(V) \
V(DefaultJumpAction) \ V(DefaultJumpAction) \
......
...@@ -207,9 +207,9 @@ namespace interpreter { ...@@ -207,9 +207,9 @@ namespace interpreter {
V(TestEqualStrictNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(TestEqualStrictNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \ V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestUndetectable, AccumulatorUse::kWrite, OperandType::kReg) \ V(TestUndetectable, AccumulatorUse::kReadWrite) \
V(TestNull, AccumulatorUse::kWrite, OperandType::kReg) \ V(TestNull, AccumulatorUse::kReadWrite) \
V(TestUndefined, AccumulatorUse::kWrite, OperandType::kReg) \ V(TestUndefined, AccumulatorUse::kReadWrite) \
V(TestTypeOf, AccumulatorUse::kReadWrite, OperandType::kFlag8) \ V(TestTypeOf, AccumulatorUse::kReadWrite, OperandType::kFlag8) \
\ \
/* Cast operators */ \ /* Cast operators */ \
...@@ -253,7 +253,9 @@ namespace interpreter { ...@@ -253,7 +253,9 @@ namespace interpreter {
/* - [Conditional jumps] */ \ /* - [Conditional jumps] */ \
/* - [Conditional constant jumps] */ \ /* - [Conditional constant jumps] */ \
V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx) \ V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfNotNullConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx) \ V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfNotUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx) \ V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx) \ V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx) \
V(JumpIfJSReceiverConstant, AccumulatorUse::kRead, OperandType::kIdx) \ V(JumpIfJSReceiverConstant, AccumulatorUse::kRead, OperandType::kIdx) \
...@@ -269,7 +271,9 @@ namespace interpreter { ...@@ -269,7 +271,9 @@ namespace interpreter {
V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfNull, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfNull, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfNotNull, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfNotUndefined, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfJSReceiver, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfJSReceiver, AccumulatorUse::kRead, OperandType::kUImm) \
V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kUImm) \ V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kUImm) \
\ \
...@@ -363,14 +367,18 @@ namespace interpreter { ...@@ -363,14 +367,18 @@ namespace interpreter {
V(JumpIfTrue) \ V(JumpIfTrue) \
V(JumpIfFalse) \ V(JumpIfFalse) \
V(JumpIfNull) \ V(JumpIfNull) \
V(JumpIfNotNull) \
V(JumpIfUndefined) \ V(JumpIfUndefined) \
V(JumpIfNotUndefined) \
V(JumpIfJSReceiver) \ V(JumpIfJSReceiver) \
V(JumpIfNotHole) V(JumpIfNotHole)
#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \ #define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \ JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
V(JumpIfNullConstant) \ V(JumpIfNullConstant) \
V(JumpIfNotNullConstant) \
V(JumpIfUndefinedConstant) \ V(JumpIfUndefinedConstant) \
V(JumpIfNotUndefinedConstant) \
V(JumpIfTrueConstant) \ V(JumpIfTrueConstant) \
V(JumpIfFalseConstant) \ V(JumpIfFalseConstant) \
V(JumpIfJSReceiverConstant) \ V(JumpIfJSReceiverConstant) \
...@@ -534,6 +542,15 @@ class V8_EXPORT_PRIVATE Bytecodes final { ...@@ -534,6 +542,15 @@ class V8_EXPORT_PRIVATE Bytecodes final {
bytecode == Bytecode::kLdaImmutableCurrentContextSlot; bytecode == Bytecode::kLdaImmutableCurrentContextSlot;
} }
// Returns true if |bytecode| is a compare operation without external effects
// (e.g., Type cooersion).
static constexpr bool IsCompareWithoutEffects(Bytecode bytecode) {
return bytecode == Bytecode::kTestUndetectable ||
bytecode == Bytecode::kTestNull ||
bytecode == Bytecode::kTestUndefined ||
bytecode == Bytecode::kTestTypeOf;
}
// Return true if |bytecode| is a register load without effects, // Return true if |bytecode| is a register load without effects,
// e.g. Mov, Star. // e.g. Mov, Star.
static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) { static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
...@@ -619,7 +636,8 @@ class V8_EXPORT_PRIVATE Bytecodes final { ...@@ -619,7 +636,8 @@ class V8_EXPORT_PRIVATE Bytecodes final {
static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) { static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
return (IsAccumulatorLoadWithoutEffects(bytecode) || return (IsAccumulatorLoadWithoutEffects(bytecode) ||
IsRegisterLoadWithoutEffects(bytecode) || IsRegisterLoadWithoutEffects(bytecode) ||
bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode)); IsCompareWithoutEffects(bytecode) || bytecode == Bytecode::kNop ||
IsJumpWithoutEffects(bytecode));
} }
// Returns true if the bytecode is Ldar or Star. // Returns true if the bytecode is Ldar or Star.
......
...@@ -2429,82 +2429,53 @@ void InterpreterGenerator::DoTestInstanceOf(InterpreterAssembler* assembler) { ...@@ -2429,82 +2429,53 @@ void InterpreterGenerator::DoTestInstanceOf(InterpreterAssembler* assembler) {
DoCompareOp(Token::INSTANCEOF, assembler); DoCompareOp(Token::INSTANCEOF, assembler);
} }
// TestUndetectable <src> // TestUndetectable
// //
// Test if the value in the <src> register equals to null/undefined. This is // Test if the value in the accumulator is undetectable (null, undefined or
// done by checking undetectable bit on the map of the object. // document.all).
void InterpreterGenerator::DoTestUndetectable(InterpreterAssembler* assembler) { void InterpreterGenerator::DoTestUndetectable(InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0); Label return_false(assembler), end(assembler);
Node* object = __ LoadRegister(reg_index); Node* object = __ GetAccumulator();
Label not_equal(assembler), end(assembler);
// If the object is an Smi then return false. // If the object is an Smi then return false.
__ GotoIf(__ TaggedIsSmi(object), &not_equal); __ SetAccumulator(__ BooleanConstant(false));
__ GotoIf(__ TaggedIsSmi(object), &end);
// If it is a HeapObject, load the map and check for undetectable bit. // If it is a HeapObject, load the map and check for undetectable bit.
Node* map = __ LoadMap(object); Node* map = __ LoadMap(object);
Node* map_bitfield = __ LoadMapBitField(map); Node* map_bitfield = __ LoadMapBitField(map);
Node* map_undetectable = Node* map_undetectable =
__ Word32And(map_bitfield, __ Int32Constant(1 << Map::kIsUndetectable)); __ Word32And(map_bitfield, __ Int32Constant(1 << Map::kIsUndetectable));
__ GotoIf(__ Word32Equal(map_undetectable, __ Int32Constant(0)), &not_equal); Node* result = __ SelectBooleanConstant(
__ Word32NotEqual(map_undetectable, __ Int32Constant(0)));
__ SetAccumulator(__ BooleanConstant(true)); __ SetAccumulator(result);
__ Goto(&end); __ Goto(&end);
__ Bind(&not_equal);
{
__ SetAccumulator(__ BooleanConstant(false));
__ Goto(&end);
}
__ Bind(&end); __ Bind(&end);
__ Dispatch(); __ Dispatch();
} }
// TestNull <src> // TestNull
// //
// Test if the value in the <src> register is strictly equal to null. // Test if the value in accumulator is strictly equal to null.
void InterpreterGenerator::DoTestNull(InterpreterAssembler* assembler) { void InterpreterGenerator::DoTestNull(InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0); Node* object = __ GetAccumulator();
Node* object = __ LoadRegister(reg_index);
Node* null_value = __ HeapConstant(isolate_->factory()->null_value()); Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
Node* result = __ SelectBooleanConstant(__ WordEqual(object, null_value));
Label equal(assembler), end(assembler); __ SetAccumulator(result);
__ GotoIf(__ WordEqual(object, null_value), &equal);
__ SetAccumulator(__ BooleanConstant(false));
__ Goto(&end);
__ Bind(&equal);
{
__ SetAccumulator(__ BooleanConstant(true));
__ Goto(&end);
}
__ Bind(&end);
__ Dispatch(); __ Dispatch();
} }
// TestUndefined <src> // TestUndefined
// //
// Test if the value in the <src> register is strictly equal to undefined. // Test if the value in the accumulator is strictly equal to undefined.
void InterpreterGenerator::DoTestUndefined(InterpreterAssembler* assembler) { void InterpreterGenerator::DoTestUndefined(InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0); Node* object = __ GetAccumulator();
Node* object = __ LoadRegister(reg_index);
Node* undefined_value = Node* undefined_value =
__ HeapConstant(isolate_->factory()->undefined_value()); __ HeapConstant(isolate_->factory()->undefined_value());
Node* result =
Label equal(assembler), end(assembler); __ SelectBooleanConstant(__ WordEqual(object, undefined_value));
__ GotoIf(__ WordEqual(object, undefined_value), &equal); __ SetAccumulator(result);
__ SetAccumulator(__ BooleanConstant(false));
__ Goto(&end);
__ Bind(&equal);
{
__ SetAccumulator(__ BooleanConstant(true));
__ Goto(&end);
}
__ Bind(&end);
__ Dispatch(); __ Dispatch();
} }
...@@ -2797,6 +2768,30 @@ void InterpreterGenerator::DoJumpIfNullConstant( ...@@ -2797,6 +2768,30 @@ void InterpreterGenerator::DoJumpIfNullConstant(
__ JumpIfWordEqual(accumulator, null_value, relative_jump); __ JumpIfWordEqual(accumulator, null_value, relative_jump);
} }
// JumpIfNotNull <imm>
//
// Jump by number of bytes represented by an immediate operand if the object
// referenced by the accumulator is not the null constant.
void InterpreterGenerator::DoJumpIfNotNull(InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
Node* relative_jump = __ BytecodeOperandUImmWord(0);
__ JumpIfWordNotEqual(accumulator, null_value, relative_jump);
}
// JumpIfNotNullConstant <idx>
//
// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
// if the object referenced by the accumulator is not the null constant.
void InterpreterGenerator::DoJumpIfNotNullConstant(
InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
Node* index = __ BytecodeOperandIdx(0);
Node* relative_jump = __ LoadAndUntagConstantPoolEntry(index);
__ JumpIfWordNotEqual(accumulator, null_value, relative_jump);
}
// JumpIfUndefined <imm> // JumpIfUndefined <imm>
// //
// Jump by number of bytes represented by an immediate operand if the object // Jump by number of bytes represented by an immediate operand if the object
...@@ -2823,6 +2818,33 @@ void InterpreterGenerator::DoJumpIfUndefinedConstant( ...@@ -2823,6 +2818,33 @@ void InterpreterGenerator::DoJumpIfUndefinedConstant(
__ JumpIfWordEqual(accumulator, undefined_value, relative_jump); __ JumpIfWordEqual(accumulator, undefined_value, relative_jump);
} }
// JumpIfNotUndefined <imm>
//
// Jump by number of bytes represented by an immediate operand if the object
// referenced by the accumulator is not the undefined constant.
void InterpreterGenerator::DoJumpIfNotUndefined(
InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* undefined_value =
__ HeapConstant(isolate_->factory()->undefined_value());
Node* relative_jump = __ BytecodeOperandUImmWord(0);
__ JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
}
// JumpIfNotUndefinedConstant <idx>
//
// Jump by number of bytes in the Smi in the |idx| entry in the constant pool
// if the object referenced by the accumulator is not the undefined constant.
void InterpreterGenerator::DoJumpIfNotUndefinedConstant(
InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* undefined_value =
__ HeapConstant(isolate_->factory()->undefined_value());
Node* index = __ BytecodeOperandIdx(0);
Node* relative_jump = __ LoadAndUntagConstantPoolEntry(index);
__ JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
}
// JumpIfJSReceiver <imm> // JumpIfJSReceiver <imm>
// //
// Jump by number of bytes represented by an immediate operand if the object // Jump by number of bytes represented by an immediate operand if the object
......
...@@ -192,28 +192,6 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData( ...@@ -192,28 +192,6 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData(
} }
} }
// Fuse LdaNull/LdaUndefined followed by a equality comparison with test
// undetectable. Testing undetectable is a simple check on the map which is
// more efficient than the full comparison operation.
if (last == Bytecode::kLdaNull || last == Bytecode::kLdaUndefined) {
if (current == Bytecode::kTestEqual) {
return {PeepholeAction::kTransformEqualityWithNullOrUndefinedAction,
Bytecode::kTestUndetectable};
}
}
// Fuse LdaNull/LdaUndefined followed by a strict equals with
// TestNull/TestUndefined.
if (current == Bytecode::kTestEqualStrict) {
if (last == Bytecode::kLdaNull) {
return {PeepholeAction::kTransformEqualityWithNullOrUndefinedAction,
Bytecode::kTestNull};
} else if (last == Bytecode::kLdaUndefined) {
return {PeepholeAction::kTransformEqualityWithNullOrUndefinedAction,
Bytecode::kTestUndefined};
}
}
// If there is no last bytecode to optimize against, store the incoming // If there is no last bytecode to optimize against, store the incoming
// bytecode or for jumps emit incoming bytecode immediately. // bytecode or for jumps emit incoming bytecode immediately.
if (last == Bytecode::kIllegal) { if (last == Bytecode::kIllegal) {
......
#
# Autogenerated by generate-bytecode-expectations.
#
---
wrap: yes
---
snippet: "
var a = 1;
return a === null;
"
frame size: 1
parameter count: 1
bytecode array length: 7
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(TestNull),
/* 64 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = undefined;
return undefined === a;
"
frame size: 1
parameter count: 1
bytecode array length: 6
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 53 S> */ B(TestUndefined),
/* 77 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = undefined;
return undefined !== a;
"
frame size: 1
parameter count: 1
bytecode array length: 7
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 53 S> */ B(TestUndefined),
/* 70 E> */ B(LogicalNot),
/* 77 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 2;
return a != null;
"
frame size: 1
parameter count: 1
bytecode array length: 8
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(2),
B(Star), R(0),
/* 45 S> */ B(TestUndetectable),
/* 54 E> */ B(LogicalNot),
/* 63 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = undefined;
return undefined == a;
"
frame size: 1
parameter count: 1
bytecode array length: 6
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 53 S> */ B(TestUndetectable),
/* 76 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = undefined;
return undefined === a ? 1 : 2;
"
frame size: 1
parameter count: 1
bytecode array length: 13
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 53 S> */ B(JumpIfNotUndefined), U8(6),
B(LdaSmi), I8(1),
B(Jump), U8(4),
B(LdaSmi), I8(2),
/* 85 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 0;
return null == a ? 1 : 2;
"
frame size: 1
parameter count: 1
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(TestUndetectable),
/* 57 E> */ B(JumpIfFalse), U8(6),
B(LdaSmi), I8(1),
B(Jump), U8(4),
B(LdaSmi), I8(2),
/* 71 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 0;
return undefined !== a ? 1 : 2;
"
frame size: 1
parameter count: 1
bytecode array length: 13
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(JumpIfUndefined), U8(6),
B(LdaSmi), I8(1),
B(Jump), U8(4),
B(LdaSmi), I8(2),
/* 77 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 0;
return a === null ? 1 : 2;
"
frame size: 1
parameter count: 1
bytecode array length: 13
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(JumpIfNotNull), U8(6),
B(LdaSmi), I8(1),
B(Jump), U8(4),
B(LdaSmi), I8(2),
/* 72 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 0;
if (a === null) {
return 1;
} else {
return 2;
}
"
frame size: 1
parameter count: 1
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(JumpIfNotNull), U8(5),
/* 65 S> */ B(LdaSmi), I8(1),
/* 98 S> */ B(Return),
/* 86 S> */ B(LdaSmi), I8(2),
/* 98 S> */ B(Return),
B(LdaUndefined),
/* 98 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = 0;
if (a != undefined) {
return 1;
}
"
frame size: 1
parameter count: 1
bytecode array length: 12
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(TestUndetectable),
/* 51 E> */ B(JumpIfTrue), U8(5),
/* 69 S> */ B(LdaSmi), I8(1),
/* 81 S> */ B(Return),
B(LdaUndefined),
/* 81 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var a = undefined;
var b = 0;
while (a !== undefined) {
b++;
}
"
frame size: 2
parameter count: 1
bytecode array length: 23
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 61 S> */ B(LdaZero),
B(Star), R(1),
/* 73 S> */ B(Ldar), R(0),
B(JumpIfUndefined), U8(12),
/* 64 E> */ B(StackCheck),
/* 92 S> */ B(Ldar), R(1),
B(Inc), U8(5),
B(Star), R(1),
B(JumpLoop), U8(11), I8(0),
B(LdaUndefined),
/* 99 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
...@@ -15,7 +15,7 @@ bytecode array length: 6 ...@@ -15,7 +15,7 @@ bytecode array length: 6
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaSmi), I8(1), /* 34 S> */ B(LdaSmi), I8(1),
/* 51 E> */ B(TestTypeOf), U8(0), B(TestTypeOf), U8(0),
/* 65 S> */ B(Return), /* 65 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -33,7 +33,7 @@ bytecode array length: 6 ...@@ -33,7 +33,7 @@ bytecode array length: 6
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaConstant), U8(0), /* 34 S> */ B(LdaConstant), U8(0),
/* 50 E> */ B(TestTypeOf), U8(1), B(TestTypeOf), U8(1),
/* 69 S> */ B(Return), /* 69 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -52,7 +52,7 @@ bytecode array length: 5 ...@@ -52,7 +52,7 @@ bytecode array length: 5
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaTrue), /* 34 S> */ B(LdaTrue),
/* 54 E> */ B(TestTypeOf), U8(3), B(TestTypeOf), U8(3),
/* 68 S> */ B(Return), /* 68 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -70,7 +70,7 @@ bytecode array length: 5 ...@@ -70,7 +70,7 @@ bytecode array length: 5
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaUndefined), /* 34 S> */ B(LdaUndefined),
/* 50 E> */ B(TestTypeOf), U8(1), B(TestTypeOf), U8(1),
/* 73 S> */ B(Return), /* 73 S> */ B(Return),
] ]
constant pool: [ constant pool: [
......
...@@ -16,7 +16,7 @@ snippet: " ...@@ -16,7 +16,7 @@ snippet: "
" "
frame size: 19 frame size: 19
parameter count: 1 parameter count: 1
bytecode array length: 1030 bytecode array length: 1027
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(39), B(JumpIfUndefined), U8(39),
...@@ -204,8 +204,7 @@ bytecodes: [ ...@@ -204,8 +204,7 @@ bytecodes: [
B(LdaNamedProperty), R(12), U8(10), U8(21), B(LdaNamedProperty), R(12), U8(10), U8(21),
B(StaContextSlot), R(1), U8(13), U8(0), B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0), B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12), B(TestUndetectable),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(JumpConstant), U8(15), B(JumpConstant), U8(15),
B(LdaContextSlot), R(1), U8(9), U8(0), B(LdaContextSlot), R(1), U8(9), U8(0),
...@@ -468,20 +467,20 @@ constant pool: [ ...@@ -468,20 +467,20 @@ constant pool: [
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""], ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [560], Smi [557],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [702], Smi [699],
Smi [348], Smi [348],
Smi [374], Smi [371],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [317], Smi [317],
] ]
handlers: [ handlers: [
[80, 943, 949], [80, 940, 946],
[83, 889, 891], [83, 886, 888],
[100, 423, 429], [100, 423, 429],
[103, 375, 377], [103, 375, 377],
[519, 645, 647], [516, 642, 644],
] ]
--- ---
...@@ -493,7 +492,7 @@ snippet: " ...@@ -493,7 +492,7 @@ snippet: "
" "
frame size: 19 frame size: 19
parameter count: 1 parameter count: 1
bytecode array length: 1088 bytecode array length: 1085
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(39), B(JumpIfUndefined), U8(39),
...@@ -688,8 +687,7 @@ bytecodes: [ ...@@ -688,8 +687,7 @@ bytecodes: [
B(LdaNamedProperty), R(12), U8(10), U8(21), B(LdaNamedProperty), R(12), U8(10), U8(21),
B(StaContextSlot), R(1), U8(13), U8(0), B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0), B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12), B(TestUndetectable),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(JumpConstant), U8(15), B(JumpConstant), U8(15),
B(LdaContextSlot), R(1), U8(9), U8(0), B(LdaContextSlot), R(1), U8(9), U8(0),
...@@ -974,20 +972,20 @@ constant pool: [ ...@@ -974,20 +972,20 @@ constant pool: [
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""], ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [572], Smi [569],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [714], Smi [711],
Smi [348], Smi [348],
Smi [374], Smi [371],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [340], Smi [340],
] ]
handlers: [ handlers: [
[80, 978, 984], [80, 975, 981],
[83, 924, 926], [83, 921, 923],
[100, 435, 441], [100, 435, 441],
[103, 387, 389], [103, 387, 389],
[531, 657, 659], [528, 654, 656],
] ]
--- ---
...@@ -1002,7 +1000,7 @@ snippet: " ...@@ -1002,7 +1000,7 @@ snippet: "
" "
frame size: 19 frame size: 19
parameter count: 1 parameter count: 1
bytecode array length: 1067 bytecode array length: 1064
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(39), B(JumpIfUndefined), U8(39),
...@@ -1206,8 +1204,7 @@ bytecodes: [ ...@@ -1206,8 +1204,7 @@ bytecodes: [
B(LdaNamedProperty), R(12), U8(10), U8(23), B(LdaNamedProperty), R(12), U8(10), U8(23),
B(StaContextSlot), R(1), U8(13), U8(0), B(StaContextSlot), R(1), U8(13), U8(0),
B(LdaContextSlot), R(1), U8(13), U8(0), B(LdaContextSlot), R(1), U8(13), U8(0),
B(Star), R(12), B(TestUndetectable),
B(TestUndetectable), R(12),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(JumpConstant), U8(15), B(JumpConstant), U8(15),
B(LdaContextSlot), R(1), U8(9), U8(0), B(LdaContextSlot), R(1), U8(9), U8(0),
...@@ -1470,20 +1467,20 @@ constant pool: [ ...@@ -1470,20 +1467,20 @@ constant pool: [
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""], ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
Smi [597], Smi [594],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [739], Smi [736],
Smi [348], Smi [348],
Smi [374], Smi [371],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [317], Smi [317],
] ]
handlers: [ handlers: [
[80, 980, 986], [80, 977, 983],
[83, 926, 928], [83, 923, 925],
[100, 460, 466], [100, 460, 466],
[103, 412, 414], [103, 412, 414],
[556, 682, 684], [553, 679, 681],
] ]
--- ---
...@@ -1496,7 +1493,7 @@ snippet: " ...@@ -1496,7 +1493,7 @@ snippet: "
" "
frame size: 14 frame size: 14
parameter count: 1 parameter count: 1
bytecode array length: 582 bytecode array length: 579
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(22), B(JumpIfUndefined), U8(22),
...@@ -1608,14 +1605,13 @@ bytecodes: [ ...@@ -1608,14 +1605,13 @@ bytecodes: [
B(Star), R(11), B(Star), R(11),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(11), U8(21), B(TestEqualStrict), R(11), U8(21),
B(JumpIfTrue), U8(129), B(JumpIfTrue), U8(126),
B(LdaCurrentContextSlot), U8(7), B(LdaCurrentContextSlot), U8(7),
B(Star), R(11), B(Star), R(11),
B(LdaNamedProperty), R(11), U8(9), U8(22), B(LdaNamedProperty), R(11), U8(9), U8(22),
B(StaCurrentContextSlot), U8(11), B(StaCurrentContextSlot), U8(11),
B(LdaCurrentContextSlot), U8(11), B(LdaCurrentContextSlot), U8(11),
B(Star), R(11), B(TestUndetectable),
B(TestUndetectable), R(11),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(109), B(Jump), U8(109),
B(LdaCurrentContextSlot), U8(9), B(LdaCurrentContextSlot), U8(9),
...@@ -1778,10 +1774,10 @@ constant pool: [ ...@@ -1778,10 +1774,10 @@ constant pool: [
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
] ]
handlers: [ handlers: [
[63, 499, 505], [63, 496, 502],
[66, 445, 447], [66, 442, 444],
[81, 241, 247], [81, 241, 247],
[84, 193, 195], [84, 193, 195],
[325, 337, 339], [322, 334, 336],
] ]
...@@ -11,7 +11,7 @@ snippet: " ...@@ -11,7 +11,7 @@ snippet: "
" "
frame size: 15 frame size: 15
parameter count: 1 parameter count: 1
bytecode array length: 263 bytecode array length: 262
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(LdaZero), B(LdaZero),
...@@ -72,10 +72,10 @@ bytecodes: [ ...@@ -72,10 +72,10 @@ bytecodes: [
B(Star), R(11), B(Star), R(11),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(4), U8(16), B(TestEqualStrict), R(4), U8(16),
B(JumpIfTrue), U8(105), B(JumpIfTrue), U8(104),
B(LdaNamedProperty), R(2), U8(7), U8(17), B(LdaNamedProperty), R(2), U8(7), U8(17),
B(Star), R(6), B(Star), R(6),
B(TestUndetectable), R(6), B(TestUndetectable),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(93), B(Jump), U8(93),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
...@@ -140,7 +140,7 @@ constant pool: [ ...@@ -140,7 +140,7 @@ constant pool: [
handlers: [ handlers: [
[7, 124, 130], [7, 124, 130],
[10, 88, 90], [10, 88, 90],
[191, 201, 203], [190, 200, 202],
] ]
--- ---
...@@ -150,7 +150,7 @@ snippet: " ...@@ -150,7 +150,7 @@ snippet: "
" "
frame size: 16 frame size: 16
parameter count: 1 parameter count: 1
bytecode array length: 276 bytecode array length: 275
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0), /* 42 S> */ B(LdaConstant), U8(0),
...@@ -213,10 +213,10 @@ bytecodes: [ ...@@ -213,10 +213,10 @@ bytecodes: [
B(Star), R(12), B(Star), R(12),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(5), U8(15), B(TestEqualStrict), R(5), U8(15),
B(JumpIfTrue), U8(105), B(JumpIfTrue), U8(104),
B(LdaNamedProperty), R(3), U8(7), U8(16), B(LdaNamedProperty), R(3), U8(7), U8(16),
B(Star), R(7), B(Star), R(7),
B(TestUndetectable), R(7), B(TestUndetectable),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(93), B(Jump), U8(93),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
...@@ -286,7 +286,7 @@ constant pool: [ ...@@ -286,7 +286,7 @@ constant pool: [
handlers: [ handlers: [
[11, 127, 133], [11, 127, 133],
[14, 91, 93], [14, 91, 93],
[195, 205, 207], [194, 204, 206],
] ]
--- ---
...@@ -298,7 +298,7 @@ snippet: " ...@@ -298,7 +298,7 @@ snippet: "
" "
frame size: 15 frame size: 15
parameter count: 1 parameter count: 1
bytecode array length: 281 bytecode array length: 280
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(LdaZero), B(LdaZero),
...@@ -367,10 +367,10 @@ bytecodes: [ ...@@ -367,10 +367,10 @@ bytecodes: [
B(Star), R(11), B(Star), R(11),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(4), U8(18), B(TestEqualStrict), R(4), U8(18),
B(JumpIfTrue), U8(105), B(JumpIfTrue), U8(104),
B(LdaNamedProperty), R(2), U8(7), U8(19), B(LdaNamedProperty), R(2), U8(7), U8(19),
B(Star), R(6), B(Star), R(6),
B(TestUndetectable), R(6), B(TestUndetectable),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(93), B(Jump), U8(93),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
...@@ -435,7 +435,7 @@ constant pool: [ ...@@ -435,7 +435,7 @@ constant pool: [
handlers: [ handlers: [
[7, 142, 148], [7, 142, 148],
[10, 106, 108], [10, 106, 108],
[209, 219, 221], [208, 218, 220],
] ]
--- ---
...@@ -445,7 +445,7 @@ snippet: " ...@@ -445,7 +445,7 @@ snippet: "
" "
frame size: 14 frame size: 14
parameter count: 1 parameter count: 1
bytecode array length: 287 bytecode array length: 286
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8), /* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8),
...@@ -511,10 +511,10 @@ bytecodes: [ ...@@ -511,10 +511,10 @@ bytecodes: [
B(Star), R(10), B(Star), R(10),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(3), U8(21), B(TestEqualStrict), R(3), U8(21),
B(JumpIfTrue), U8(105), B(JumpIfTrue), U8(104),
B(LdaNamedProperty), R(1), U8(9), U8(22), B(LdaNamedProperty), R(1), U8(9), U8(22),
B(Star), R(5), B(Star), R(5),
B(TestUndetectable), R(5), B(TestUndetectable),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(93), B(Jump), U8(93),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
...@@ -586,6 +586,6 @@ constant pool: [ ...@@ -586,6 +586,6 @@ constant pool: [
handlers: [ handlers: [
[15, 138, 144], [15, 138, 144],
[18, 102, 104], [18, 102, 104],
[206, 216, 218], [205, 215, 217],
] ]
...@@ -14,15 +14,16 @@ snippet: " ...@@ -14,15 +14,16 @@ snippet: "
" "
frame size: 3 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 25
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2), /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndetectable), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfFalse), U8(6), B(TestUndetectable),
/* 77 E> */ B(JumpIfFalse), U8(6),
/* 88 S> */ B(LdaSmi), I8(20), /* 88 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 97 S> */ B(Ldar), R(1), /* 97 S> */ B(Ldar), R(1),
...@@ -43,15 +44,16 @@ snippet: " ...@@ -43,15 +44,16 @@ snippet: "
" "
frame size: 3 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 25
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2), /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndetectable), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfFalse), U8(6), B(TestUndetectable),
/* 77 E> */ B(JumpIfFalse), U8(6),
/* 93 S> */ B(LdaSmi), I8(20), /* 93 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 102 S> */ B(Ldar), R(1), /* 102 S> */ B(Ldar), R(1),
...@@ -72,15 +74,16 @@ snippet: " ...@@ -72,15 +74,16 @@ snippet: "
" "
frame size: 3 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 25
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2), /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndetectable), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfTrue), U8(6), B(TestUndetectable),
/* 77 E> */ B(JumpIfTrue), U8(6),
/* 88 S> */ B(LdaSmi), I8(20), /* 88 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 97 S> */ B(Ldar), R(1), /* 97 S> */ B(Ldar), R(1),
...@@ -101,15 +104,16 @@ snippet: " ...@@ -101,15 +104,16 @@ snippet: "
" "
frame size: 3 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 25
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2), /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndetectable), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfTrue), U8(6), B(TestUndetectable),
/* 77 E> */ B(JumpIfTrue), U8(6),
/* 93 S> */ B(LdaSmi), I8(20), /* 93 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 102 S> */ B(Ldar), R(1), /* 102 S> */ B(Ldar), R(1),
...@@ -137,8 +141,8 @@ bytecodes: [ ...@@ -137,8 +141,8 @@ bytecodes: [
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestNull), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfFalse), U8(6), B(JumpIfNotNull), U8(6),
/* 89 S> */ B(LdaSmi), I8(20), /* 89 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 98 S> */ B(Ldar), R(1), /* 98 S> */ B(Ldar), R(1),
...@@ -166,8 +170,8 @@ bytecodes: [ ...@@ -166,8 +170,8 @@ bytecodes: [
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndefined), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfFalse), U8(6), B(JumpIfNotUndefined), U8(6),
/* 94 S> */ B(LdaSmi), I8(20), /* 94 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 103 S> */ B(Ldar), R(1), /* 103 S> */ B(Ldar), R(1),
...@@ -195,8 +199,8 @@ bytecodes: [ ...@@ -195,8 +199,8 @@ bytecodes: [
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestNull), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfTrue), U8(6), B(JumpIfNull), U8(6),
/* 89 S> */ B(LdaSmi), I8(20), /* 89 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 98 S> */ B(Ldar), R(1), /* 98 S> */ B(Ldar), R(1),
...@@ -224,8 +228,8 @@ bytecodes: [ ...@@ -224,8 +228,8 @@ bytecodes: [
B(Mov), R(2), R(0), B(Mov), R(2), R(0),
/* 63 S> */ B(LdaSmi), I8(10), /* 63 S> */ B(LdaSmi), I8(10),
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(TestUndefined), R(0), /* 67 S> */ B(Ldar), R(0),
B(JumpIfTrue), U8(6), B(JumpIfUndefined), U8(6),
/* 94 S> */ B(LdaSmi), I8(20), /* 94 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 103 S> */ B(Ldar), R(1), /* 103 S> */ B(Ldar), R(1),
......
...@@ -280,7 +280,7 @@ snippet: " ...@@ -280,7 +280,7 @@ snippet: "
" "
frame size: 18 frame size: 18
parameter count: 1 parameter count: 1
bytecode array length: 754 bytecode array length: 751
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(33), B(JumpIfUndefined), U8(33),
...@@ -474,14 +474,13 @@ bytecodes: [ ...@@ -474,14 +474,13 @@ bytecodes: [
B(Star), R(11), B(Star), R(11),
B(LdaZero), B(LdaZero),
B(TestEqualStrict), R(11), U8(16), B(TestEqualStrict), R(11), U8(16),
B(JumpIfTrue), U8(153), B(JumpIfTrue), U8(150),
B(LdaContextSlot), R(1), U8(7), U8(0), B(LdaContextSlot), R(1), U8(7), U8(0),
B(Star), R(11), B(Star), R(11),
B(LdaNamedProperty), R(11), U8(9), U8(17), B(LdaNamedProperty), R(11), U8(9), U8(17),
B(StaContextSlot), R(1), U8(11), U8(0), B(StaContextSlot), R(1), U8(11), U8(0),
B(LdaContextSlot), R(1), U8(11), U8(0), B(LdaContextSlot), R(1), U8(11), U8(0),
B(Star), R(11), B(TestUndetectable),
B(TestUndetectable), R(11),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(127), B(Jump), U8(127),
B(LdaContextSlot), R(1), U8(9), U8(0), B(LdaContextSlot), R(1), U8(9), U8(0),
...@@ -617,12 +616,12 @@ constant pool: [ ...@@ -617,12 +616,12 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
ONE_BYTE_INTERNALIZED_STRING_TYPE [""], ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
FIXED_ARRAY_TYPE, FIXED_ARRAY_TYPE,
Smi [566], Smi [563],
] ]
handlers: [ handlers: [
[51, 678, 684], [51, 675, 681],
[146, 437, 443], [146, 437, 443],
[149, 393, 395], [149, 393, 395],
[533, 549, 551], [530, 546, 548],
] ]
...@@ -1027,6 +1027,61 @@ TEST(CompareTypeOf) { ...@@ -1027,6 +1027,61 @@ TEST(CompareTypeOf) {
LoadGolden("CompareTypeOf.golden"))); LoadGolden("CompareTypeOf.golden")));
} }
TEST(CompareNil) {
InitializedIgnitionHandleScope scope;
BytecodeExpectationsPrinter printer(CcTest::isolate());
const char* snippets[] = {
"var a = 1;\n"
"return a === null;\n",
"var a = undefined;\n"
"return undefined === a;\n",
"var a = undefined;\n"
"return undefined !== a;\n",
"var a = 2;\n"
"return a != null;\n",
"var a = undefined;\n"
"return undefined == a;\n",
"var a = undefined;\n"
"return undefined === a ? 1 : 2;\n",
"var a = 0;\n"
"return null == a ? 1 : 2;\n",
"var a = 0;\n"
"return undefined !== a ? 1 : 2;\n",
"var a = 0;\n"
"return a === null ? 1 : 2;\n",
"var a = 0;\n"
"if (a === null) {\n"
" return 1;\n"
"} else {\n"
" return 2;\n"
"}\n",
"var a = 0;\n"
"if (a != undefined) {\n"
" return 1;\n"
"}\n",
"var a = undefined;\n"
"var b = 0;\n"
"while (a !== undefined) {\n"
" b++;\n"
"}\n",
};
CHECK(CompareTexts(BuildActual(printer, snippets),
LoadGolden("CompareNil.golden")));
}
TEST(Delete) { TEST(Delete) {
InitializedIgnitionHandleScope scope; InitializedIgnitionHandleScope scope;
BytecodeExpectationsPrinter printer(CcTest::isolate()); BytecodeExpectationsPrinter printer(CcTest::isolate());
......
...@@ -215,7 +215,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -215,7 +215,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CompareOperation(Token::Value::GTE, reg, 6) .CompareOperation(Token::Value::GTE, reg, 6)
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber) .CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber)
.CompareOperation(Token::Value::INSTANCEOF, reg) .CompareOperation(Token::Value::INSTANCEOF, reg)
.CompareOperation(Token::Value::IN, reg); .CompareOperation(Token::Value::IN, reg)
.CompareUndetectable()
.CompareUndefined()
.CompareNull();
// Emit peephole optimizations of equality with Null or Undefined. // Emit peephole optimizations of equality with Null or Undefined.
builder.LoadUndefined() builder.LoadUndefined()
...@@ -238,23 +241,27 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -238,23 +241,27 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Short jumps with Imm8 operands // Short jumps with Imm8 operands
{ {
BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4,
after_jump5; after_jump5, after_jump6, after_jump7;
builder.Bind(&start) builder.Bind(&start)
.Jump(&after_jump1) .Jump(&after_jump1)
.Bind(&after_jump1) .Bind(&after_jump1)
.JumpIfNull(&after_jump2) .JumpIfNull(&after_jump2)
.Bind(&after_jump2) .Bind(&after_jump2)
.JumpIfUndefined(&after_jump3) .JumpIfNotNull(&after_jump3)
.Bind(&after_jump3) .Bind(&after_jump3)
.JumpIfNotHole(&after_jump4) .JumpIfUndefined(&after_jump4)
.Bind(&after_jump4) .Bind(&after_jump4)
.JumpIfJSReceiver(&after_jump5) .JumpIfNotUndefined(&after_jump5)
.Bind(&after_jump5) .Bind(&after_jump5)
.JumpIfNotHole(&after_jump6)
.Bind(&after_jump6)
.JumpIfJSReceiver(&after_jump7)
.Bind(&after_jump7)
.JumpLoop(&start, 0); .JumpLoop(&start, 0);
} }
// Longer jumps with constant operands // Longer jumps with constant operands
BytecodeLabel end[9]; BytecodeLabel end[11];
{ {
BytecodeLabel after_jump; BytecodeLabel after_jump;
builder.Jump(&end[0]) builder.Jump(&end[0])
...@@ -268,10 +275,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -268,10 +275,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.LoadLiteral(Smi::kZero) .LoadLiteral(Smi::kZero)
.JumpIfFalse(&end[4]) .JumpIfFalse(&end[4])
.JumpIfNull(&end[5]) .JumpIfNull(&end[5])
.JumpIfUndefined(&end[6]) .JumpIfNotNull(&end[6])
.JumpIfNotHole(&end[7]) .JumpIfUndefined(&end[7])
.JumpIfNotUndefined(&end[8])
.JumpIfNotHole(&end[9])
.LoadLiteral(ast_factory.prototype_string()) .LoadLiteral(ast_factory.prototype_string())
.JumpIfJSReceiver(&end[8]); .JumpIfJSReceiver(&end[10]);
} }
// Perform an operation that returns boolean value to // Perform an operation that returns boolean value to
...@@ -442,9 +451,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -442,9 +451,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kShiftRightSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kShiftRightSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kTestUndetectable)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kTestUndefined)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kTestNull)] = 1;
} }
if (!FLAG_type_profile) { if (!FLAG_type_profile) {
......
...@@ -404,25 +404,6 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) { ...@@ -404,25 +404,6 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) {
} }
} }
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaNullOrUndefinedWithCompareOp) {
Bytecode first_bytecodes[] = {Bytecode::kLdaUndefined, Bytecode::kLdaNull};
for (auto first_bytecode : first_bytecodes) {
uint32_t reg_operand = Register(0).ToOperand();
uint32_t idx_operand = 1;
BytecodeNode first(first_bytecode);
BytecodeNode second(Bytecode::kTestEqual, reg_operand, idx_operand);
optimizer()->Write(&first);
optimizer()->Write(&second);
Flush();
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kTestUndetectable);
CHECK_EQ(last_written().operand_count(), 1);
CHECK_EQ(last_written().operand(0), reg_operand);
Reset();
}
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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