[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}
This commit is contained in:
parent
d73b11ecd2
commit
f4f58e31c1
@ -1943,23 +1943,20 @@ void BytecodeGraphBuilder::VisitTestInstanceOf() {
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTestUndetectable() {
|
||||
Node* object =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
Node* object = environment()->LookupAccumulator();
|
||||
Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object);
|
||||
environment()->BindAccumulator(node);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTestNull() {
|
||||
Node* object =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
Node* object = environment()->LookupAccumulator();
|
||||
Node* result = NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->NullConstant());
|
||||
environment()->BindAccumulator(result);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTestUndefined() {
|
||||
Node* object =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
Node* object = environment()->LookupAccumulator();
|
||||
Node* result = NewNode(simplified()->ReferenceEqual(), object,
|
||||
jsgraph()->UndefinedConstant());
|
||||
environment()->BindAccumulator(result);
|
||||
@ -2082,6 +2079,14 @@ void BytecodeGraphBuilder::VisitJumpIfNullConstant() {
|
||||
BuildJumpIfEqual(jsgraph()->NullConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpIfNotNull() {
|
||||
BuildJumpIfNotEqual(jsgraph()->NullConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpIfNotNullConstant() {
|
||||
BuildJumpIfNotEqual(jsgraph()->NullConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpIfUndefined() {
|
||||
BuildJumpIfEqual(jsgraph()->UndefinedConstant());
|
||||
}
|
||||
@ -2090,6 +2095,14 @@ void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() {
|
||||
BuildJumpIfEqual(jsgraph()->UndefinedConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpIfNotUndefined() {
|
||||
BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() {
|
||||
BuildJumpIfNotEqual(jsgraph()->UndefinedConstant());
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitJumpLoop() { BuildJump(); }
|
||||
|
||||
void BytecodeGraphBuilder::VisitStackCheck() {
|
||||
@ -2365,6 +2378,13 @@ void BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) {
|
||||
BuildJumpIf(condition);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) {
|
||||
Node* accumulator = environment()->LookupAccumulator();
|
||||
Node* condition =
|
||||
NewNode(simplified()->ReferenceEqual(), accumulator, comperand);
|
||||
BuildJumpIfNot(condition);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildJumpIfFalse() {
|
||||
NewBranch(environment()->LookupAccumulator());
|
||||
Environment* if_true_environment = environment()->Copy();
|
||||
|
@ -212,6 +212,7 @@ class BytecodeGraphBuilder {
|
||||
void BuildJumpIf(Node* condition);
|
||||
void BuildJumpIfNot(Node* condition);
|
||||
void BuildJumpIfEqual(Node* comperand);
|
||||
void BuildJumpIfNotEqual(Node* comperand);
|
||||
void BuildJumpIfTrue();
|
||||
void BuildJumpIfFalse();
|
||||
void BuildJumpIfToBooleanTrue();
|
||||
|
@ -389,6 +389,36 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
|
||||
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(
|
||||
TestTypeOfFlags::LiteralFlag literal_flag) {
|
||||
DCHECK(literal_flag != TestTypeOfFlags::LiteralFlag::kOther);
|
||||
@ -885,6 +915,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNull(
|
||||
BytecodeLabel* label) {
|
||||
DCHECK(!label->is_bound());
|
||||
OutputJumpIfNotNull(label, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
|
||||
BytecodeLabel* label) {
|
||||
DCHECK(!label->is_bound());
|
||||
@ -892,6 +929,47 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
|
||||
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(
|
||||
BytecodeLabel* label) {
|
||||
DCHECK(!label->is_bound());
|
||||
|
@ -314,6 +314,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
|
||||
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
|
||||
int feedback_slot);
|
||||
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
|
||||
BytecodeArrayBuilder& CompareUndetectable();
|
||||
BytecodeArrayBuilder& CompareUndefined();
|
||||
BytecodeArrayBuilder& CompareNull();
|
||||
BytecodeArrayBuilder& CompareNil(Token::Value op, NilValue nil);
|
||||
BytecodeArrayBuilder& CompareTypeOf(
|
||||
TestTypeOfFlags::LiteralFlag literal_flag);
|
||||
|
||||
@ -332,7 +336,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
|
||||
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
|
||||
BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
|
||||
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
|
||||
BytecodeArrayBuilder& JumpIfNotNull(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& StackCheck(int position);
|
||||
|
@ -162,8 +162,12 @@ Bytecode GetJumpWithConstantOperand(Bytecode jump_bytecode) {
|
||||
return Bytecode::kJumpIfNotHoleConstant;
|
||||
case Bytecode::kJumpIfNull:
|
||||
return Bytecode::kJumpIfNullConstant;
|
||||
case Bytecode::kJumpIfNotNull:
|
||||
return Bytecode::kJumpIfNotNullConstant;
|
||||
case Bytecode::kJumpIfUndefined:
|
||||
return Bytecode::kJumpIfUndefinedConstant;
|
||||
case Bytecode::kJumpIfNotUndefined:
|
||||
return Bytecode::kJumpIfNotUndefinedConstant;
|
||||
case Bytecode::kJumpIfJSReceiver:
|
||||
return Bytecode::kJumpIfJSReceiverConstant;
|
||||
default:
|
||||
|
@ -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) {
|
||||
Expression* sub_expr;
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
|
||||
// Emit a fast literal comparion for expressions of the form:
|
||||
// typeof(x) === 'string'.
|
||||
Expression* typeof_sub_expr;
|
||||
Literal* literal;
|
||||
if (expr->IsLiteralCompareTypeof(&typeof_sub_expr, &literal)) {
|
||||
VisitForTypeOfValue(typeof_sub_expr);
|
||||
VisitForTypeOfValue(sub_expr);
|
||||
builder()->SetExpressionPosition(expr);
|
||||
TestTypeOfFlags::LiteralFlag literal_flag =
|
||||
TestTypeOfFlags::GetFlagForLiteral(ast_string_constants(), literal);
|
||||
@ -3055,6 +3076,14 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
|
||||
} else {
|
||||
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 {
|
||||
Register lhs = VisitForRegisterValue(expr->left());
|
||||
VisitForAccumulatorValue(expr->right());
|
||||
|
@ -109,7 +109,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
|
||||
void BuildVariableAssignment(Variable* variable, Token::Value op,
|
||||
FeedbackSlot slot,
|
||||
HoleCheckMode hole_check_mode);
|
||||
|
||||
void BuildLiteralCompareNil(Token::Value compare_op, NilValue nil);
|
||||
void BuildReturn();
|
||||
void BuildAsyncReturn();
|
||||
void BuildAsyncGeneratorReturn();
|
||||
|
@ -141,20 +141,6 @@ BytecodeNode TransformLdaZeroBinaryOpToBinaryOpWithZero(
|
||||
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
|
||||
|
||||
void BytecodePeepholeOptimizer::DefaultAction(
|
||||
@ -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(
|
||||
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
|
||||
DCHECK(LastIsValid());
|
||||
|
@ -20,8 +20,7 @@ namespace interpreter {
|
||||
V(ElideLastAction) \
|
||||
V(ChangeBytecodeAction) \
|
||||
V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \
|
||||
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction) \
|
||||
V(TransformEqualityWithNullOrUndefinedAction)
|
||||
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction)
|
||||
|
||||
#define PEEPHOLE_JUMP_ACTION_LIST(V) \
|
||||
V(DefaultJumpAction) \
|
||||
|
@ -207,9 +207,9 @@ namespace interpreter {
|
||||
V(TestEqualStrictNoFeedback, AccumulatorUse::kReadWrite, OperandType::kReg) \
|
||||
V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \
|
||||
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
|
||||
V(TestUndetectable, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestNull, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestUndefined, AccumulatorUse::kWrite, OperandType::kReg) \
|
||||
V(TestUndetectable, AccumulatorUse::kReadWrite) \
|
||||
V(TestNull, AccumulatorUse::kReadWrite) \
|
||||
V(TestUndefined, AccumulatorUse::kReadWrite) \
|
||||
V(TestTypeOf, AccumulatorUse::kReadWrite, OperandType::kFlag8) \
|
||||
\
|
||||
/* Cast operators */ \
|
||||
@ -253,7 +253,9 @@ namespace interpreter {
|
||||
/* - [Conditional jumps] */ \
|
||||
/* - [Conditional constant jumps] */ \
|
||||
V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfNotNullConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfNotUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
V(JumpIfJSReceiverConstant, AccumulatorUse::kRead, OperandType::kIdx) \
|
||||
@ -269,7 +271,9 @@ namespace interpreter {
|
||||
V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfNull, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfNotNull, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfNotUndefined, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfJSReceiver, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kUImm) \
|
||||
\
|
||||
@ -363,14 +367,18 @@ namespace interpreter {
|
||||
V(JumpIfTrue) \
|
||||
V(JumpIfFalse) \
|
||||
V(JumpIfNull) \
|
||||
V(JumpIfNotNull) \
|
||||
V(JumpIfUndefined) \
|
||||
V(JumpIfNotUndefined) \
|
||||
V(JumpIfJSReceiver) \
|
||||
V(JumpIfNotHole)
|
||||
|
||||
#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
|
||||
JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
|
||||
V(JumpIfNullConstant) \
|
||||
V(JumpIfNotNullConstant) \
|
||||
V(JumpIfUndefinedConstant) \
|
||||
V(JumpIfNotUndefinedConstant) \
|
||||
V(JumpIfTrueConstant) \
|
||||
V(JumpIfFalseConstant) \
|
||||
V(JumpIfJSReceiverConstant) \
|
||||
@ -534,6 +542,15 @@ class V8_EXPORT_PRIVATE Bytecodes final {
|
||||
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,
|
||||
// e.g. Mov, Star.
|
||||
static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
|
||||
@ -619,7 +636,8 @@ class V8_EXPORT_PRIVATE Bytecodes final {
|
||||
static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
|
||||
return (IsAccumulatorLoadWithoutEffects(bytecode) ||
|
||||
IsRegisterLoadWithoutEffects(bytecode) ||
|
||||
bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode));
|
||||
IsCompareWithoutEffects(bytecode) || bytecode == Bytecode::kNop ||
|
||||
IsJumpWithoutEffects(bytecode));
|
||||
}
|
||||
|
||||
// Returns true if the bytecode is Ldar or Star.
|
||||
|
@ -2429,82 +2429,53 @@ void InterpreterGenerator::DoTestInstanceOf(InterpreterAssembler* assembler) {
|
||||
DoCompareOp(Token::INSTANCEOF, assembler);
|
||||
}
|
||||
|
||||
// TestUndetectable <src>
|
||||
// TestUndetectable
|
||||
//
|
||||
// Test if the value in the <src> register equals to null/undefined. This is
|
||||
// done by checking undetectable bit on the map of the object.
|
||||
// Test if the value in the accumulator is undetectable (null, undefined or
|
||||
// document.all).
|
||||
void InterpreterGenerator::DoTestUndetectable(InterpreterAssembler* assembler) {
|
||||
Node* reg_index = __ BytecodeOperandReg(0);
|
||||
Node* object = __ LoadRegister(reg_index);
|
||||
Label return_false(assembler), end(assembler);
|
||||
Node* object = __ GetAccumulator();
|
||||
|
||||
Label not_equal(assembler), end(assembler);
|
||||
// If the object is an Smi then return false.
|
||||
__ GotoIf(__ TaggedIsSmi(object), ¬_equal);
|
||||
__ SetAccumulator(__ BooleanConstant(false));
|
||||
__ GotoIf(__ TaggedIsSmi(object), &end);
|
||||
|
||||
// If it is a HeapObject, load the map and check for undetectable bit.
|
||||
Node* map = __ LoadMap(object);
|
||||
Node* map_bitfield = __ LoadMapBitField(map);
|
||||
Node* map_undetectable =
|
||||
__ Word32And(map_bitfield, __ Int32Constant(1 << Map::kIsUndetectable));
|
||||
__ GotoIf(__ Word32Equal(map_undetectable, __ Int32Constant(0)), ¬_equal);
|
||||
|
||||
__ SetAccumulator(__ BooleanConstant(true));
|
||||
Node* result = __ SelectBooleanConstant(
|
||||
__ Word32NotEqual(map_undetectable, __ Int32Constant(0)));
|
||||
__ SetAccumulator(result);
|
||||
__ Goto(&end);
|
||||
|
||||
__ Bind(¬_equal);
|
||||
{
|
||||
__ SetAccumulator(__ BooleanConstant(false));
|
||||
__ Goto(&end);
|
||||
}
|
||||
|
||||
__ Bind(&end);
|
||||
__ 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) {
|
||||
Node* reg_index = __ BytecodeOperandReg(0);
|
||||
Node* object = __ LoadRegister(reg_index);
|
||||
Node* object = __ GetAccumulator();
|
||||
Node* null_value = __ HeapConstant(isolate_->factory()->null_value());
|
||||
|
||||
Label equal(assembler), end(assembler);
|
||||
__ GotoIf(__ WordEqual(object, null_value), &equal);
|
||||
__ SetAccumulator(__ BooleanConstant(false));
|
||||
__ Goto(&end);
|
||||
|
||||
__ Bind(&equal);
|
||||
{
|
||||
__ SetAccumulator(__ BooleanConstant(true));
|
||||
__ Goto(&end);
|
||||
}
|
||||
|
||||
__ Bind(&end);
|
||||
Node* result = __ SelectBooleanConstant(__ WordEqual(object, null_value));
|
||||
__ SetAccumulator(result);
|
||||
__ 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) {
|
||||
Node* reg_index = __ BytecodeOperandReg(0);
|
||||
Node* object = __ LoadRegister(reg_index);
|
||||
Node* object = __ GetAccumulator();
|
||||
Node* undefined_value =
|
||||
__ HeapConstant(isolate_->factory()->undefined_value());
|
||||
|
||||
Label equal(assembler), end(assembler);
|
||||
__ GotoIf(__ WordEqual(object, undefined_value), &equal);
|
||||
__ SetAccumulator(__ BooleanConstant(false));
|
||||
__ Goto(&end);
|
||||
|
||||
__ Bind(&equal);
|
||||
{
|
||||
__ SetAccumulator(__ BooleanConstant(true));
|
||||
__ Goto(&end);
|
||||
}
|
||||
|
||||
__ Bind(&end);
|
||||
Node* result =
|
||||
__ SelectBooleanConstant(__ WordEqual(object, undefined_value));
|
||||
__ SetAccumulator(result);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -2797,6 +2768,30 @@ void InterpreterGenerator::DoJumpIfNullConstant(
|
||||
__ 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>
|
||||
//
|
||||
// Jump by number of bytes represented by an immediate operand if the object
|
||||
@ -2823,6 +2818,33 @@ void InterpreterGenerator::DoJumpIfUndefinedConstant(
|
||||
__ 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>
|
||||
//
|
||||
// Jump by number of bytes represented by an immediate operand if the object
|
||||
|
@ -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
|
||||
// bytecode or for jumps emit incoming bytecode immediately.
|
||||
if (last == Bytecode::kIllegal) {
|
||||
|
289
test/cctest/interpreter/bytecode_expectations/CompareNil.golden
Normal file
289
test/cctest/interpreter/bytecode_expectations/CompareNil.golden
Normal file
@ -0,0 +1,289 @@
|
||||
#
|
||||
# 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
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaSmi), I8(1),
|
||||
/* 51 E> */ B(TestTypeOf), U8(0),
|
||||
B(TestTypeOf), U8(0),
|
||||
/* 65 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -33,7 +33,7 @@ bytecode array length: 6
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaConstant), U8(0),
|
||||
/* 50 E> */ B(TestTypeOf), U8(1),
|
||||
B(TestTypeOf), U8(1),
|
||||
/* 69 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -52,7 +52,7 @@ bytecode array length: 5
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaTrue),
|
||||
/* 54 E> */ B(TestTypeOf), U8(3),
|
||||
B(TestTypeOf), U8(3),
|
||||
/* 68 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@ -70,7 +70,7 @@ bytecode array length: 5
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 34 S> */ B(LdaUndefined),
|
||||
/* 50 E> */ B(TestTypeOf), U8(1),
|
||||
B(TestTypeOf), U8(1),
|
||||
/* 73 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
|
@ -16,7 +16,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1030
|
||||
bytecode array length: 1027
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(39),
|
||||
@ -204,8 +204,7 @@ bytecodes: [
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(21),
|
||||
B(StaContextSlot), R(1), U8(13), U8(0),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
@ -468,20 +467,20 @@ constant pool: [
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [560],
|
||||
Smi [557],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [702],
|
||||
Smi [699],
|
||||
Smi [348],
|
||||
Smi [374],
|
||||
Smi [371],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [317],
|
||||
]
|
||||
handlers: [
|
||||
[80, 943, 949],
|
||||
[83, 889, 891],
|
||||
[80, 940, 946],
|
||||
[83, 886, 888],
|
||||
[100, 423, 429],
|
||||
[103, 375, 377],
|
||||
[519, 645, 647],
|
||||
[516, 642, 644],
|
||||
]
|
||||
|
||||
---
|
||||
@ -493,7 +492,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1088
|
||||
bytecode array length: 1085
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(39),
|
||||
@ -688,8 +687,7 @@ bytecodes: [
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(21),
|
||||
B(StaContextSlot), R(1), U8(13), U8(0),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
@ -974,20 +972,20 @@ constant pool: [
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [572],
|
||||
Smi [569],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [714],
|
||||
Smi [711],
|
||||
Smi [348],
|
||||
Smi [374],
|
||||
Smi [371],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [340],
|
||||
]
|
||||
handlers: [
|
||||
[80, 978, 984],
|
||||
[83, 924, 926],
|
||||
[80, 975, 981],
|
||||
[83, 921, 923],
|
||||
[100, 435, 441],
|
||||
[103, 387, 389],
|
||||
[531, 657, 659],
|
||||
[528, 654, 656],
|
||||
]
|
||||
|
||||
---
|
||||
@ -1002,7 +1000,7 @@ snippet: "
|
||||
"
|
||||
frame size: 19
|
||||
parameter count: 1
|
||||
bytecode array length: 1067
|
||||
bytecode array length: 1064
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(39),
|
||||
@ -1206,8 +1204,7 @@ bytecodes: [
|
||||
B(LdaNamedProperty), R(12), U8(10), U8(23),
|
||||
B(StaContextSlot), R(1), U8(13), U8(0),
|
||||
B(LdaContextSlot), R(1), U8(13), U8(0),
|
||||
B(Star), R(12),
|
||||
B(TestUndetectable), R(12),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(JumpConstant), U8(15),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
@ -1470,20 +1467,20 @@ constant pool: [
|
||||
FIXED_ARRAY_TYPE,
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
Smi [597],
|
||||
Smi [594],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [739],
|
||||
Smi [736],
|
||||
Smi [348],
|
||||
Smi [374],
|
||||
Smi [371],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [317],
|
||||
]
|
||||
handlers: [
|
||||
[80, 980, 986],
|
||||
[83, 926, 928],
|
||||
[80, 977, 983],
|
||||
[83, 923, 925],
|
||||
[100, 460, 466],
|
||||
[103, 412, 414],
|
||||
[556, 682, 684],
|
||||
[553, 679, 681],
|
||||
]
|
||||
|
||||
---
|
||||
@ -1496,7 +1493,7 @@ snippet: "
|
||||
"
|
||||
frame size: 14
|
||||
parameter count: 1
|
||||
bytecode array length: 582
|
||||
bytecode array length: 579
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(22),
|
||||
@ -1608,14 +1605,13 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(11), U8(21),
|
||||
B(JumpIfTrue), U8(129),
|
||||
B(JumpIfTrue), U8(126),
|
||||
B(LdaCurrentContextSlot), U8(7),
|
||||
B(Star), R(11),
|
||||
B(LdaNamedProperty), R(11), U8(9), U8(22),
|
||||
B(StaCurrentContextSlot), U8(11),
|
||||
B(LdaCurrentContextSlot), U8(11),
|
||||
B(Star), R(11),
|
||||
B(TestUndetectable), R(11),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(109),
|
||||
B(LdaCurrentContextSlot), U8(9),
|
||||
@ -1778,10 +1774,10 @@ constant pool: [
|
||||
FIXED_ARRAY_TYPE,
|
||||
]
|
||||
handlers: [
|
||||
[63, 499, 505],
|
||||
[66, 445, 447],
|
||||
[63, 496, 502],
|
||||
[66, 442, 444],
|
||||
[81, 241, 247],
|
||||
[84, 193, 195],
|
||||
[325, 337, 339],
|
||||
[322, 334, 336],
|
||||
]
|
||||
|
||||
|
@ -11,7 +11,7 @@ snippet: "
|
||||
"
|
||||
frame size: 15
|
||||
parameter count: 1
|
||||
bytecode array length: 263
|
||||
bytecode array length: 262
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(LdaZero),
|
||||
@ -72,10 +72,10 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(4), U8(16),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(JumpIfTrue), U8(104),
|
||||
B(LdaNamedProperty), R(2), U8(7), U8(17),
|
||||
B(Star), R(6),
|
||||
B(TestUndetectable), R(6),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
@ -140,7 +140,7 @@ constant pool: [
|
||||
handlers: [
|
||||
[7, 124, 130],
|
||||
[10, 88, 90],
|
||||
[191, 201, 203],
|
||||
[190, 200, 202],
|
||||
]
|
||||
|
||||
---
|
||||
@ -150,7 +150,7 @@ snippet: "
|
||||
"
|
||||
frame size: 16
|
||||
parameter count: 1
|
||||
bytecode array length: 276
|
||||
bytecode array length: 275
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(LdaConstant), U8(0),
|
||||
@ -213,10 +213,10 @@ bytecodes: [
|
||||
B(Star), R(12),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(5), U8(15),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(JumpIfTrue), U8(104),
|
||||
B(LdaNamedProperty), R(3), U8(7), U8(16),
|
||||
B(Star), R(7),
|
||||
B(TestUndetectable), R(7),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
@ -286,7 +286,7 @@ constant pool: [
|
||||
handlers: [
|
||||
[11, 127, 133],
|
||||
[14, 91, 93],
|
||||
[195, 205, 207],
|
||||
[194, 204, 206],
|
||||
]
|
||||
|
||||
---
|
||||
@ -298,7 +298,7 @@ snippet: "
|
||||
"
|
||||
frame size: 15
|
||||
parameter count: 1
|
||||
bytecode array length: 281
|
||||
bytecode array length: 280
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
B(LdaZero),
|
||||
@ -367,10 +367,10 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(4), U8(18),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(JumpIfTrue), U8(104),
|
||||
B(LdaNamedProperty), R(2), U8(7), U8(19),
|
||||
B(Star), R(6),
|
||||
B(TestUndetectable), R(6),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
@ -435,7 +435,7 @@ constant pool: [
|
||||
handlers: [
|
||||
[7, 142, 148],
|
||||
[10, 106, 108],
|
||||
[209, 219, 221],
|
||||
[208, 218, 220],
|
||||
]
|
||||
|
||||
---
|
||||
@ -445,7 +445,7 @@ snippet: "
|
||||
"
|
||||
frame size: 14
|
||||
parameter count: 1
|
||||
bytecode array length: 287
|
||||
bytecode array length: 286
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(8),
|
||||
@ -511,10 +511,10 @@ bytecodes: [
|
||||
B(Star), R(10),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(3), U8(21),
|
||||
B(JumpIfTrue), U8(105),
|
||||
B(JumpIfTrue), U8(104),
|
||||
B(LdaNamedProperty), R(1), U8(9), U8(22),
|
||||
B(Star), R(5),
|
||||
B(TestUndetectable), R(5),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(93),
|
||||
B(LdaSmi), I8(1),
|
||||
@ -586,6 +586,6 @@ constant pool: [
|
||||
handlers: [
|
||||
[15, 138, 144],
|
||||
[18, 102, 104],
|
||||
[206, 216, 218],
|
||||
[205, 215, 217],
|
||||
]
|
||||
|
||||
|
@ -14,15 +14,16 @@ snippet: "
|
||||
"
|
||||
frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 24
|
||||
bytecode array length: 25
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndetectable), R(0),
|
||||
B(JumpIfFalse), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(TestUndetectable),
|
||||
/* 77 E> */ B(JumpIfFalse), U8(6),
|
||||
/* 88 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 97 S> */ B(Ldar), R(1),
|
||||
@ -43,15 +44,16 @@ snippet: "
|
||||
"
|
||||
frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 24
|
||||
bytecode array length: 25
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndetectable), R(0),
|
||||
B(JumpIfFalse), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(TestUndetectable),
|
||||
/* 77 E> */ B(JumpIfFalse), U8(6),
|
||||
/* 93 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 102 S> */ B(Ldar), R(1),
|
||||
@ -72,15 +74,16 @@ snippet: "
|
||||
"
|
||||
frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 24
|
||||
bytecode array length: 25
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndetectable), R(0),
|
||||
B(JumpIfTrue), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(TestUndetectable),
|
||||
/* 77 E> */ B(JumpIfTrue), U8(6),
|
||||
/* 88 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 97 S> */ B(Ldar), R(1),
|
||||
@ -101,15 +104,16 @@ snippet: "
|
||||
"
|
||||
frame size: 3
|
||||
parameter count: 1
|
||||
bytecode array length: 24
|
||||
bytecode array length: 25
|
||||
bytecodes: [
|
||||
/* 30 E> */ B(StackCheck),
|
||||
/* 46 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(2),
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndetectable), R(0),
|
||||
B(JumpIfTrue), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(TestUndetectable),
|
||||
/* 77 E> */ B(JumpIfTrue), U8(6),
|
||||
/* 93 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 102 S> */ B(Ldar), R(1),
|
||||
@ -137,8 +141,8 @@ bytecodes: [
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestNull), R(0),
|
||||
B(JumpIfFalse), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(JumpIfNotNull), U8(6),
|
||||
/* 89 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 98 S> */ B(Ldar), R(1),
|
||||
@ -166,8 +170,8 @@ bytecodes: [
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndefined), R(0),
|
||||
B(JumpIfFalse), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(JumpIfNotUndefined), U8(6),
|
||||
/* 94 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 103 S> */ B(Ldar), R(1),
|
||||
@ -195,8 +199,8 @@ bytecodes: [
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestNull), R(0),
|
||||
B(JumpIfTrue), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(JumpIfNull), U8(6),
|
||||
/* 89 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 98 S> */ B(Ldar), R(1),
|
||||
@ -224,8 +228,8 @@ bytecodes: [
|
||||
B(Mov), R(2), R(0),
|
||||
/* 63 S> */ B(LdaSmi), I8(10),
|
||||
B(Star), R(1),
|
||||
/* 67 S> */ B(TestUndefined), R(0),
|
||||
B(JumpIfTrue), U8(6),
|
||||
/* 67 S> */ B(Ldar), R(0),
|
||||
B(JumpIfUndefined), U8(6),
|
||||
/* 94 S> */ B(LdaSmi), I8(20),
|
||||
B(Star), R(1),
|
||||
/* 103 S> */ B(Ldar), R(1),
|
||||
|
@ -280,7 +280,7 @@ snippet: "
|
||||
"
|
||||
frame size: 18
|
||||
parameter count: 1
|
||||
bytecode array length: 754
|
||||
bytecode array length: 751
|
||||
bytecodes: [
|
||||
B(Ldar), R(new_target),
|
||||
B(JumpIfUndefined), U8(33),
|
||||
@ -474,14 +474,13 @@ bytecodes: [
|
||||
B(Star), R(11),
|
||||
B(LdaZero),
|
||||
B(TestEqualStrict), R(11), U8(16),
|
||||
B(JumpIfTrue), U8(153),
|
||||
B(JumpIfTrue), U8(150),
|
||||
B(LdaContextSlot), R(1), U8(7), U8(0),
|
||||
B(Star), R(11),
|
||||
B(LdaNamedProperty), R(11), U8(9), U8(17),
|
||||
B(StaContextSlot), R(1), U8(11), U8(0),
|
||||
B(LdaContextSlot), R(1), U8(11), U8(0),
|
||||
B(Star), R(11),
|
||||
B(TestUndetectable), R(11),
|
||||
B(TestUndetectable),
|
||||
B(JumpIfFalse), U8(4),
|
||||
B(Jump), U8(127),
|
||||
B(LdaContextSlot), R(1), U8(9), U8(0),
|
||||
@ -617,12 +616,12 @@ constant pool: [
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"],
|
||||
ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
|
||||
FIXED_ARRAY_TYPE,
|
||||
Smi [566],
|
||||
Smi [563],
|
||||
]
|
||||
handlers: [
|
||||
[51, 678, 684],
|
||||
[51, 675, 681],
|
||||
[146, 437, 443],
|
||||
[149, 393, 395],
|
||||
[533, 549, 551],
|
||||
[530, 546, 548],
|
||||
]
|
||||
|
||||
|
@ -1027,6 +1027,61 @@ TEST(CompareTypeOf) {
|
||||
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) {
|
||||
InitializedIgnitionHandleScope scope;
|
||||
BytecodeExpectationsPrinter printer(CcTest::isolate());
|
||||
|
@ -215,7 +215,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
.CompareOperation(Token::Value::GTE, reg, 6)
|
||||
.CompareTypeOf(TestTypeOfFlags::LiteralFlag::kNumber)
|
||||
.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.
|
||||
builder.LoadUndefined()
|
||||
@ -238,23 +241,27 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
// Short jumps with Imm8 operands
|
||||
{
|
||||
BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4,
|
||||
after_jump5;
|
||||
after_jump5, after_jump6, after_jump7;
|
||||
builder.Bind(&start)
|
||||
.Jump(&after_jump1)
|
||||
.Bind(&after_jump1)
|
||||
.JumpIfNull(&after_jump2)
|
||||
.Bind(&after_jump2)
|
||||
.JumpIfUndefined(&after_jump3)
|
||||
.JumpIfNotNull(&after_jump3)
|
||||
.Bind(&after_jump3)
|
||||
.JumpIfNotHole(&after_jump4)
|
||||
.JumpIfUndefined(&after_jump4)
|
||||
.Bind(&after_jump4)
|
||||
.JumpIfJSReceiver(&after_jump5)
|
||||
.JumpIfNotUndefined(&after_jump5)
|
||||
.Bind(&after_jump5)
|
||||
.JumpIfNotHole(&after_jump6)
|
||||
.Bind(&after_jump6)
|
||||
.JumpIfJSReceiver(&after_jump7)
|
||||
.Bind(&after_jump7)
|
||||
.JumpLoop(&start, 0);
|
||||
}
|
||||
|
||||
// Longer jumps with constant operands
|
||||
BytecodeLabel end[9];
|
||||
BytecodeLabel end[11];
|
||||
{
|
||||
BytecodeLabel after_jump;
|
||||
builder.Jump(&end[0])
|
||||
@ -268,10 +275,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
.LoadLiteral(Smi::kZero)
|
||||
.JumpIfFalse(&end[4])
|
||||
.JumpIfNull(&end[5])
|
||||
.JumpIfUndefined(&end[6])
|
||||
.JumpIfNotHole(&end[7])
|
||||
.JumpIfNotNull(&end[6])
|
||||
.JumpIfUndefined(&end[7])
|
||||
.JumpIfNotUndefined(&end[8])
|
||||
.JumpIfNotHole(&end[9])
|
||||
.LoadLiteral(ast_factory.prototype_string())
|
||||
.JumpIfJSReceiver(&end[8]);
|
||||
.JumpIfJSReceiver(&end[10]);
|
||||
}
|
||||
|
||||
// Perform an operation that returns boolean value to
|
||||
@ -442,9 +451,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1;
|
||||
scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 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) {
|
||||
|
@ -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 internal
|
||||
} // namespace v8
|
||||
|
Loading…
Reference in New Issue
Block a user