Commit 708f80d2 authored by epertoso's avatar epertoso Committed by Commit bot

[interpreter] Make the comparison bytecode handlers collect type feedback.

BUG=v8:5273

Review-Url: https://codereview.chromium.org/2286273002
Cr-Commit-Position: refs/heads/master@{#39006}
parent 9bdce030
......@@ -362,6 +362,7 @@ void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
Visit(node->left());
Visit(node->right());
ReserveFeedbackSlots(node);
}
......@@ -436,6 +437,7 @@ void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
if (!node->is_default()) Visit(node->label());
VisitStatements(node->statements());
ReserveFeedbackSlots(node);
}
......
......@@ -737,6 +737,20 @@ static bool IsTypeof(Expression* expr) {
return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
}
void CompareOperation::AssignFeedbackVectorSlots(
Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache_) {
// Feedback vector slot is only used by interpreter for binary operations.
// Full-codegen uses AstId to record type feedback.
switch (op()) {
// instanceof and in do not collect type feedback.
case Token::INSTANCEOF:
case Token::IN:
return;
default:
type_feedback_slot_ = spec->AddGeneralSlot();
}
}
// Check for the pattern: typeof <expression> equals <string literal>.
static bool MatchLiteralCompareTypeof(Expression* left,
......@@ -938,6 +952,12 @@ CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
statements_(statements),
compare_type_(Type::None()) {}
void CaseClause::AssignFeedbackVectorSlots(Isolate* isolate,
FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache) {
type_feedback_slot_ = spec->AddGeneralSlot();
}
uint32_t Literal::Hash() {
return raw_value()->IsString()
? raw_value()->AsString()->hash()
......
......@@ -942,6 +942,16 @@ class CaseClause final : public Expression {
Type* compare_type() { return compare_type_; }
void set_compare_type(Type* type) { compare_type_ = type; }
// CaseClause will have both a slot in the feedback vector and the
// TypeFeedbackId to record the type information. TypeFeedbackId is used by
// full codegen and the feedback vector slot is used by interpreter.
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache);
FeedbackVectorSlot CompareOperationFeedbackSlot() {
return type_feedback_slot_;
}
private:
friend class AstNodeFactory;
......@@ -953,6 +963,7 @@ class CaseClause final : public Expression {
Label body_target_;
ZoneList<Statement*>* statements_;
Type* compare_type_;
FeedbackVectorSlot type_feedback_slot_;
};
......@@ -2199,6 +2210,16 @@ class CompareOperation final : public Expression {
Type* combined_type() const { return combined_type_; }
void set_combined_type(Type* type) { combined_type_ = type; }
// CompareOperation will have both a slot in the feedback vector and the
// TypeFeedbackId to record the type information. TypeFeedbackId is used
// by full codegen and the feedback vector slot is used by interpreter.
void AssignFeedbackVectorSlots(Isolate* isolate, FeedbackVectorSpec* spec,
FeedbackVectorSlotCache* cache);
FeedbackVectorSlot CompareOperationFeedbackSlot() const {
return type_feedback_slot_;
}
// Match special cases.
bool IsLiteralCompareTypeof(Expression** expr, Handle<String>* check);
bool IsLiteralCompareUndefined(Expression** expr);
......@@ -2225,6 +2246,7 @@ class CompareOperation final : public Expression {
Expression* right_;
Type* combined_type_;
FeedbackVectorSlot type_feedback_slot_;
};
......
......@@ -1217,6 +1217,24 @@ BinaryOperationHint BytecodeGraphBuilder::GetBinaryOperationHint(
return hint;
}
// Helper function to create compare operation hint from the recorded type
// feedback.
CompareOperationHint BytecodeGraphBuilder::GetCompareOperationHint() {
int slot_index = bytecode_iterator().GetIndexOperand(1);
if (slot_index == 0) {
return CompareOperationHint::kAny;
}
FeedbackVectorSlot slot =
feedback_vector()->ToSlot(bytecode_iterator().GetIndexOperand(1));
DCHECK_EQ(FeedbackVectorSlotKind::GENERAL, feedback_vector()->GetKind(slot));
Object* feedback = feedback_vector()->Get(slot);
CompareOperationHint hint = CompareOperationHint::kAny;
if (feedback->IsSmi()) {
hint = CompareOperationHintFromFeedback((Smi::cast(feedback))->value());
}
return hint;
}
void BytecodeGraphBuilder::VisitAdd() {
BuildBinaryOp(
javascript()->Add(GetBinaryOperationHint(kBinaryOperationHintIndex)));
......@@ -1380,38 +1398,31 @@ void BytecodeGraphBuilder::BuildCompareOp(const Operator* js_op) {
}
void BytecodeGraphBuilder::VisitTestEqual() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->Equal(hint));
BuildCompareOp(javascript()->Equal(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestNotEqual() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->NotEqual(hint));
BuildCompareOp(javascript()->NotEqual(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestEqualStrict() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->StrictEqual(hint));
BuildCompareOp(javascript()->StrictEqual(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestLessThan() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->LessThan(hint));
BuildCompareOp(javascript()->LessThan(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestGreaterThan() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->GreaterThan(hint));
BuildCompareOp(javascript()->GreaterThan(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestLessThanOrEqual() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->LessThanOrEqual(hint));
BuildCompareOp(javascript()->LessThanOrEqual(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() {
CompareOperationHint hint = CompareOperationHint::kAny;
BuildCompareOp(javascript()->GreaterThanOrEqual(hint));
BuildCompareOp(javascript()->GreaterThanOrEqual(GetCompareOperationHint()));
}
void BytecodeGraphBuilder::VisitTestIn() {
......
......@@ -139,6 +139,10 @@ class BytecodeGraphBuilder {
// type feedback.
BinaryOperationHint GetBinaryOperationHint(int operand_index);
// Helper function to create compare operation hint from the recorded
// type feedback.
CompareOperationHint GetCompareOperationHint();
// Control flow plumbing.
void BuildJump();
void BuildConditionalJump(Node* condition);
......
......@@ -147,6 +147,18 @@ BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
return BinaryOperationHint::kNone;
}
// Helper function to transform the feedback to CompareOperationHint.
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
switch (type_feedback) {
case CompareOperationFeedback::kSignedSmall:
return CompareOperationHint::kSignedSmall;
case CompareOperationFeedback::kNumber:
return CompareOperationHint::kNumber;
default:
return CompareOperationHint::kAny;
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -51,6 +51,7 @@ class TypeHintAnalyzer final {
};
BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);
} // namespace compiler
} // namespace internal
......
......@@ -1161,6 +1161,12 @@ class BinaryOperationFeedback {
enum { kNone = 0x00, kSignedSmall = 0x01, kNumber = 0x3, kAny = 0x7 };
};
// TODO(epertoso): consider unifying this with BinaryOperationFeedback.
class CompareOperationFeedback {
public:
enum { kNone = 0x00, kSignedSmall = 0x01, kNumber = 0x3, kAny = 0x7 };
};
} // namespace internal
} // namespace v8
......
......@@ -175,9 +175,14 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(Token::Value op,
Register reg) {
Output(BytecodeForCompareOperation(op), RegisterOperand(reg));
BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
Token::Value op, Register reg, int feedback_slot) {
if (op == Token::INSTANCEOF || op == Token::IN) {
Output(BytecodeForCompareOperation(op), RegisterOperand(reg));
} else {
Output(BytecodeForCompareOperation(op), RegisterOperand(reg),
UnsignedOperand(feedback_slot));
}
return *this;
}
......
......@@ -230,7 +230,8 @@ class BytecodeArrayBuilder final : public ZoneObject {
BytecodeArrayBuilder& Delete(Register object, LanguageMode language_mode);
// Tests.
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg);
BytecodeArrayBuilder& CompareOperation(Token::Value op, Register reg,
int feedback_slot = kNoFeedbackSlot);
// Casts accumulator and stores result in accumulator.
BytecodeArrayBuilder& CastAccumulatorToBoolean();
......@@ -400,6 +401,8 @@ class BytecodeArrayBuilder final : public ZoneObject {
BytecodePipelineStage* pipeline_;
BytecodeSourceInfo latest_source_info_;
static int const kNoFeedbackSlot = 0;
DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
};
......
......@@ -1123,7 +1123,9 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Perform label comparison as if via '===' with tag.
VisitForAccumulatorValue(clause->label());
builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
builder()->CompareOperation(
Token::Value::EQ_STRICT, tag,
feedback_index(clause->CompareOperationFeedbackSlot()));
switch_builder.Case(i);
}
......@@ -3031,7 +3033,8 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
Register lhs = VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right());
builder()->SetExpressionPosition(expr);
builder()->CompareOperation(expr->op(), lhs);
FeedbackVectorSlot slot = expr->CompareOperationFeedbackSlot();
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
execution_result()->SetResultInAccumulator();
}
......
......@@ -208,13 +208,20 @@ namespace interpreter {
OperandType::kMaybeReg, OperandType::kRegCount) \
\
/* Test Operators */ \
V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestNotEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestEqualStrict, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestLessThan, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestGreaterThan, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestLessThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestNotEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestEqualStrict, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestLessThan, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestGreaterThan, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestLessThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg) \
V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg) \
\
......
......@@ -816,6 +816,80 @@ void Interpreter::DoBinaryOpWithFeedback(InterpreterAssembler* assembler) {
__ Dispatch();
}
template <class Generator>
void Interpreter::DoCompareOpWithFeedback(InterpreterAssembler* assembler) {
Node* reg_index = __ BytecodeOperandReg(0);
Node* lhs = __ LoadRegister(reg_index);
Node* rhs = __ GetAccumulator();
Node* context = __ GetContext();
Node* slot_index = __ BytecodeOperandIdx(1);
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
// TODO(interpreter): the only reason this check is here is because we
// sometimes emit comparisons that shouldn't collect feedback (e.g.
// try-finally blocks and generators), and we could get rid of this by
// introducing Smi equality tests.
Label skip_feedback_update(assembler);
__ GotoIf(__ WordEqual(slot_index, __ IntPtrConstant(0)),
&skip_feedback_update);
Variable var_type_feedback(assembler, MachineRepresentation::kWord32);
Label lhs_is_smi(assembler), lhs_is_not_smi(assembler),
gather_rhs_type(assembler), do_compare(assembler);
__ Branch(__ WordIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
__ Bind(&lhs_is_smi);
var_type_feedback.Bind(
__ Int32Constant(CompareOperationFeedback::kSignedSmall));
__ Goto(&gather_rhs_type);
__ Bind(&lhs_is_not_smi);
{
Label lhs_is_number(assembler), lhs_is_not_number(assembler);
Node* lhs_map = __ LoadMap(lhs);
__ Branch(__ WordEqual(lhs_map, __ HeapNumberMapConstant()), &lhs_is_number,
&lhs_is_not_number);
__ Bind(&lhs_is_number);
var_type_feedback.Bind(__ Int32Constant(CompareOperationFeedback::kNumber));
__ Goto(&gather_rhs_type);
__ Bind(&lhs_is_not_number);
var_type_feedback.Bind(__ Int32Constant(CompareOperationFeedback::kAny));
__ Goto(&do_compare);
}
__ Bind(&gather_rhs_type);
{
Label rhs_is_smi(assembler);
__ GotoIf(__ WordIsSmi(rhs), &rhs_is_smi);
Node* rhs_map = __ LoadMap(rhs);
Node* rhs_type =
__ Select(__ WordEqual(rhs_map, __ HeapNumberMapConstant()),
__ Int32Constant(CompareOperationFeedback::kNumber),
__ Int32Constant(CompareOperationFeedback::kAny));
var_type_feedback.Bind(__ Word32Or(var_type_feedback.value(), rhs_type));
__ Goto(&do_compare);
__ Bind(&rhs_is_smi);
var_type_feedback.Bind(
__ Word32Or(var_type_feedback.value(),
__ Int32Constant(CompareOperationFeedback::kSignedSmall)));
__ Goto(&do_compare);
}
__ Bind(&do_compare);
__ UpdateFeedback(var_type_feedback.value(), type_feedback_vector,
slot_index);
__ Goto(&skip_feedback_update);
__ Bind(&skip_feedback_update);
Node* result = Generator::Generate(assembler, lhs, rhs, context);
__ SetAccumulator(result);
__ Dispatch();
}
// Add <src>
//
// Add register <src> to accumulator.
......@@ -1520,35 +1594,35 @@ void Interpreter::DoNew(InterpreterAssembler* assembler) {
//
// Test if the value in the <src> register equals the accumulator.
void Interpreter::DoTestEqual(InterpreterAssembler* assembler) {
DoBinaryOp<EqualStub>(assembler);
DoCompareOpWithFeedback<EqualStub>(assembler);
}
// TestNotEqual <src>
//
// Test if the value in the <src> register is not equal to the accumulator.
void Interpreter::DoTestNotEqual(InterpreterAssembler* assembler) {
DoBinaryOp<NotEqualStub>(assembler);
DoCompareOpWithFeedback<NotEqualStub>(assembler);
}
// TestEqualStrict <src>
//
// Test if the value in the <src> register is strictly equal to the accumulator.
void Interpreter::DoTestEqualStrict(InterpreterAssembler* assembler) {
DoBinaryOp<StrictEqualStub>(assembler);
DoCompareOpWithFeedback<StrictEqualStub>(assembler);
}
// TestLessThan <src>
//
// Test if the value in the <src> register is less than the accumulator.
void Interpreter::DoTestLessThan(InterpreterAssembler* assembler) {
DoBinaryOp<LessThanStub>(assembler);
DoCompareOpWithFeedback<LessThanStub>(assembler);
}
// TestGreaterThan <src>
//
// Test if the value in the <src> register is greater than the accumulator.
void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
DoBinaryOp<GreaterThanStub>(assembler);
DoCompareOpWithFeedback<GreaterThanStub>(assembler);
}
// TestLessThanOrEqual <src>
......@@ -1556,7 +1630,7 @@ void Interpreter::DoTestGreaterThan(InterpreterAssembler* assembler) {
// Test if the value in the <src> register is less than or equal to the
// accumulator.
void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
DoBinaryOp<LessThanOrEqualStub>(assembler);
DoCompareOpWithFeedback<LessThanOrEqualStub>(assembler);
}
// TestGreaterThanOrEqual <src>
......@@ -1564,7 +1638,7 @@ void Interpreter::DoTestLessThanOrEqual(InterpreterAssembler* assembler) {
// Test if the value in the <src> register is greater than or equal to the
// accumulator.
void Interpreter::DoTestGreaterThanOrEqual(InterpreterAssembler* assembler) {
DoBinaryOp<GreaterThanOrEqualStub>(assembler);
DoCompareOpWithFeedback<GreaterThanOrEqualStub>(assembler);
}
// TestIn <src>
......
......@@ -84,6 +84,11 @@ class Interpreter {
template <class Generator>
void DoBinaryOpWithFeedback(InterpreterAssembler* assembler);
// Generates code to perform the comparison via |Generator| while gathering
// type feedback.
template <class Generator>
void DoCompareOpWithFeedback(InterpreterAssembler* assembler);
// Generates code to perform the bitwise binary operation corresponding to
// |bitwise_op| while gathering type feedback.
void DoBitwiseBinaryOp(Token::Value bitwise_op,
......
......@@ -13,14 +13,14 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 17
bytecode array length: 18
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(7),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(8),
B(LdaZero),
/* 56 E> */ B(TestLessThan), R(0),
/* 56 E> */ B(TestLessThan), R(0), U8(1),
B(JumpIfFalse), U8(5),
/* 63 S> */ B(LdaSmi), U8(1),
/* 75 S> */ B(Return),
......@@ -38,14 +38,14 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 17
bytecode array length: 18
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanFalse), U8(10),
/* 45 S> */ B(JumpIfToBooleanFalse), U8(11),
B(LdaZero),
/* 56 E> */ B(TestLessThan), R(0),
/* 56 E> */ B(TestLessThan), R(0), U8(1),
B(JumpIfFalse), U8(5),
/* 63 S> */ B(LdaSmi), U8(1),
/* 75 S> */ B(Return),
......@@ -63,14 +63,14 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 22
bytecode array length: 23
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(7),
/* 45 S> */ B(JumpIfToBooleanTrue), U8(8),
B(LdaZero),
/* 57 E> */ B(TestLessThan), R(0),
/* 57 E> */ B(TestLessThan), R(0), U8(1),
B(JumpIfFalse), U8(6),
B(LdaSmi), U8(2),
B(Jump), U8(4),
......
......@@ -50,7 +50,7 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 64
bytecode array length: 67
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 44 S> */ B(LdaZero),
......@@ -58,33 +58,33 @@ bytecodes: [
/* 71 S> */ B(LdaZero),
B(Star), R(1),
/* 76 S> */ B(LdaSmi), U8(10),
/* 76 E> */ B(TestLessThan), R(1),
B(JumpIfFalse), U8(50),
/* 76 E> */ B(TestLessThan), R(1), U8(1),
B(JumpIfFalse), U8(52),
/* 58 E> */ B(StackCheck),
/* 106 S> */ B(LdaZero),
B(Star), R(2),
/* 111 S> */ B(LdaSmi), U8(3),
/* 111 E> */ B(TestLessThan), R(2),
B(JumpIfFalse), U8(32),
/* 111 E> */ B(TestLessThan), R(2), U8(3),
B(JumpIfFalse), U8(33),
/* 93 E> */ B(StackCheck),
/* 129 S> */ B(Ldar), R(0),
B(Inc), U8(3),
B(Inc), U8(5),
B(Star), R(0),
/* 142 S> */ B(Ldar), R(2),
/* 150 E> */ B(Add), R(1), U8(4),
/* 150 E> */ B(Add), R(1), U8(6),
B(Star), R(4),
B(LdaSmi), U8(12),
/* 152 E> */ B(TestEqual), R(4),
/* 152 E> */ B(TestEqual), R(4), U8(7),
B(JumpIfFalse), U8(4),
/* 161 S> */ B(Jump), U8(18),
/* 118 S> */ B(Ldar), R(2),
B(Inc), U8(2),
B(Inc), U8(4),
B(Star), R(2),
B(Jump), U8(-34),
B(Jump), U8(-36),
/* 84 S> */ B(Ldar), R(1),
B(Inc), U8(1),
B(Inc), U8(2),
B(Star), R(1),
B(Jump), U8(-52),
B(Jump), U8(-55),
/* 188 S> */ B(Ldar), R(0),
/* 200 S> */ B(Return),
]
......
......@@ -124,7 +124,7 @@ snippet: "
"
frame size: 11
parameter count: 1
bytecode array length: 123
bytecode array length: 124
bytecodes: [
B(CreateFunctionContext), U8(2),
B(PushContext), R(3),
......@@ -161,7 +161,7 @@ bytecodes: [
/* 106 E> */ B(LdaContextSlot), R(context), U8(5),
B(ToName), R(7),
B(LdaConstant), U8(3),
B(TestEqualStrict), R(7),
B(TestEqualStrict), R(7), U8(0),
B(Mov), R(4), R(6),
B(JumpIfToBooleanFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
......
......@@ -47,13 +47,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 17
bytecode array length: 18
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaZero),
B(Star), R(0),
B(LdaSmi), U8(1),
/* 43 E> */ B(TestLessThan), R(0),
/* 43 E> */ B(TestLessThan), R(0), U8(1),
B(JumpIfFalse), U8(6),
B(LdaSmi), U8(2),
B(Jump), U8(4),
......
......@@ -149,40 +149,40 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 80
bytecode array length: 82
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(1),
B(Mov), R(1), R(0),
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(3),
B(JumpIfUndefined), U8(65),
B(JumpIfNull), U8(63),
B(JumpIfUndefined), U8(67),
B(JumpIfNull), U8(65),
B(ToObject), R(1),
B(ForInPrepare), R(1), R(2),
B(LdaZero),
B(Star), R(5),
/* 68 S> */ B(ForInContinue), R(5), R(4),
B(JumpIfFalse), U8(50),
B(ForInNext), R(1), R(5), R(2), U8(9),
B(JumpIfUndefined), U8(37),
B(JumpIfFalse), U8(52),
B(ForInNext), R(1), R(5), R(2), U8(11),
B(JumpIfUndefined), U8(39),
B(Star), R(6),
/* 67 E> */ B(StaNamedPropertySloppy), R(0), U8(2), U8(7),
/* 67 E> */ B(StaNamedPropertySloppy), R(0), U8(2), U8(9),
/* 62 E> */ B(StackCheck),
/* 95 S> */ B(Nop),
/* 100 E> */ B(LdrNamedProperty), R(0), U8(2), U8(3), R(7),
B(LdaSmi), U8(10),
/* 106 E> */ B(TestEqual), R(7),
/* 106 E> */ B(TestEqual), R(7), U8(5),
B(JumpIfFalse), U8(4),
/* 113 S> */ B(Jump), U8(16),
/* 113 S> */ B(Jump), U8(17),
/* 125 S> */ B(Nop),
/* 130 E> */ B(LdrNamedProperty), R(0), U8(2), U8(5), R(7),
/* 130 E> */ B(LdrNamedProperty), R(0), U8(2), U8(6), R(7),
B(LdaSmi), U8(20),
/* 136 E> */ B(TestEqual), R(7),
/* 136 E> */ B(TestEqual), R(7), U8(8),
B(JumpIfFalse), U8(4),
/* 143 S> */ B(Jump), U8(8),
B(ForInStep), R(5),
B(Star), R(5),
B(Jump), U8(-51),
B(Jump), U8(-53),
B(LdaUndefined),
/* 152 S> */ B(Return),
]
......
......@@ -149,11 +149,11 @@ snippet: "
"
frame size: 0
parameter count: 2
bytecode array length: 18
bytecode array length: 19
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 18 S> */ B(LdaZero),
/* 24 E> */ B(TestLessThanOrEqual), R(arg0),
/* 24 E> */ B(TestLessThanOrEqual), R(arg0), U8(1),
B(JumpIfFalse), U8(7),
/* 36 S> */ B(Wide), B(LdaSmi), U16(200),
/* 80 S> */ B(Return),
......@@ -260,7 +260,7 @@ snippet: "
"
frame size: 2
parameter count: 2
bytecode array length: 409
bytecode array length: 410
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 24 S> */ B(LdaZero),
......@@ -268,7 +268,7 @@ bytecodes: [
/* 35 S> */ B(LdaZero),
B(Star), R(1),
/* 38 S> */ B(LdaConstant), U8(0),
/* 44 E> */ B(TestEqualStrict), R(0),
/* 44 E> */ B(TestEqualStrict), R(0), U8(1),
B(JumpIfFalseConstant), U8(1),
/* 58 S> */ B(Mov), R(0), R(1),
/* 65 S> */ B(Mov), R(1), R(0),
......@@ -654,36 +654,36 @@ snippet: "
"
frame size: 0
parameter count: 3
bytecode array length: 75
bytecode array length: 81
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 21 S> */ B(Ldar), R(arg1),
/* 27 E> */ B(TestEqual), R(arg0),
/* 27 E> */ B(TestEqual), R(arg0), U8(1),
B(JumpIfFalse), U8(5),
/* 35 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
/* 49 S> */ B(Ldar), R(arg1),
/* 55 E> */ B(TestEqualStrict), R(arg0),
/* 55 E> */ B(TestEqualStrict), R(arg0), U8(2),
B(JumpIfFalse), U8(5),
/* 64 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
/* 78 S> */ B(Ldar), R(arg1),
/* 84 E> */ B(TestLessThan), R(arg0),
/* 84 E> */ B(TestLessThan), R(arg0), U8(3),
B(JumpIfFalse), U8(5),
/* 91 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
/* 105 S> */ B(Ldar), R(arg1),
/* 111 E> */ B(TestGreaterThan), R(arg0),
/* 111 E> */ B(TestGreaterThan), R(arg0), U8(4),
B(JumpIfFalse), U8(5),
/* 118 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
/* 132 S> */ B(Ldar), R(arg1),
/* 138 E> */ B(TestLessThanOrEqual), R(arg0),
/* 138 E> */ B(TestLessThanOrEqual), R(arg0), U8(5),
B(JumpIfFalse), U8(5),
/* 146 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
/* 160 S> */ B(Ldar), R(arg1),
/* 166 E> */ B(TestGreaterThanOrEqual), R(arg0),
/* 166 E> */ B(TestGreaterThanOrEqual), R(arg0), U8(6),
B(JumpIfFalse), U8(5),
/* 174 S> */ B(LdaSmi), U8(1),
/* 262 S> */ B(Return),
......@@ -752,22 +752,22 @@ snippet: "
"
frame size: 0
parameter count: 3
bytecode array length: 32
bytecode array length: 36
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 21 S> */ B(Ldar), R(arg1),
/* 27 E> */ B(TestEqual), R(arg0),
B(JumpIfTrue), U8(7),
/* 27 E> */ B(TestEqual), R(arg0), U8(1),
B(JumpIfTrue), U8(8),
B(LdaZero),
/* 37 E> */ B(TestLessThan), R(arg0),
/* 37 E> */ B(TestLessThan), R(arg0), U8(2),
B(JumpIfFalse), U8(5),
/* 48 S> */ B(LdaSmi), U8(1),
/* 133 S> */ B(Return),
/* 67 S> */ B(LdaZero),
/* 73 E> */ B(TestGreaterThan), R(arg0),
B(JumpIfFalse), U8(9),
/* 73 E> */ B(TestGreaterThan), R(arg0), U8(3),
B(JumpIfFalse), U8(10),
B(LdaZero),
/* 82 E> */ B(TestGreaterThan), R(arg1),
/* 82 E> */ B(TestGreaterThan), R(arg1), U8(4),
B(JumpIfFalse), U8(4),
/* 93 S> */ B(LdaZero),
/* 133 S> */ B(Return),
......
......@@ -329,7 +329,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 1408
bytecode array length: 1411
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -959,21 +959,21 @@ bytecodes: [
/* 4103 S> */ B(LdaZero),
B(Star), R(1),
/* 4108 S> */ B(LdaSmi), U8(3),
/* 4108 E> */ B(TestLessThan), R(1),
B(Wide), B(JumpIfFalse), U16(36),
/* 4108 E> */ B(TestLessThan), R(1), U8(1),
B(Wide), B(JumpIfFalse), U16(38),
/* 4090 E> */ B(StackCheck),
/* 4122 S> */ B(LdaSmi), U8(1),
/* 4128 E> */ B(TestEqual), R(1),
/* 4128 E> */ B(TestEqual), R(1), U8(3),
B(Wide), B(JumpIfFalse), U16(7),
/* 4134 S> */ B(Wide), B(Jump), U16(15),
/* 4134 S> */ B(Wide), B(Jump), U16(16),
/* 4146 S> */ B(LdaSmi), U8(2),
/* 4152 E> */ B(TestEqual), R(1),
/* 4152 E> */ B(TestEqual), R(1), U8(4),
B(Wide), B(JumpIfFalse), U16(7),
/* 4158 S> */ B(Wide), B(Jump), U16(11),
/* 4114 S> */ B(Ldar), R(1),
B(Inc), U8(1),
B(Inc), U8(2),
B(Star), R(1),
B(Jump), U8(-39),
B(Jump), U8(-42),
/* 4167 S> */ B(LdaSmi), U8(3),
/* 4177 S> */ B(Return),
]
......
......@@ -33,13 +33,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 13
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), U8(1),
/* 55 E> */ B(TestEqual), R(0),
/* 55 E> */ B(TestEqual), R(0), U8(1),
B(JumpIfTrue), U8(4),
B(LdaSmi), U8(3),
/* 67 S> */ B(Return),
......@@ -75,13 +75,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 12
bytecode array length: 13
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(LdaZero),
/* 55 E> */ B(TestEqual), R(0),
/* 55 E> */ B(TestEqual), R(0), U8(1),
B(JumpIfFalse), U8(4),
B(LdaSmi), U8(3),
/* 67 S> */ B(Return),
......@@ -548,7 +548,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 278
bytecode array length: 279
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
......@@ -558,7 +558,7 @@ bytecodes: [
/* 60 S> */ B(LdaSmi), U8(3),
B(Star), R(2),
/* 63 S> */ B(LdaSmi), U8(3),
/* 73 E> */ B(TestGreaterThan), R(0),
/* 73 E> */ B(TestGreaterThan), R(0), U8(1),
B(JumpIfTrueConstant), U8(0),
B(LdaSmi), U8(1),
B(Star), R(1),
......@@ -735,7 +735,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 277
bytecode array length: 278
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
......@@ -745,7 +745,7 @@ bytecodes: [
/* 60 S> */ B(LdaSmi), U8(3),
B(Star), R(2),
/* 63 S> */ B(LdaSmi), U8(5),
/* 73 E> */ B(TestLessThan), R(0),
/* 73 E> */ B(TestLessThan), R(0), U8(1),
B(JumpIfFalseConstant), U8(0),
B(LdaSmi), U8(1),
B(Star), R(1),
......
......@@ -18,7 +18,7 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 26
bytecode array length: 27
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaSmi), U8(1),
......@@ -28,10 +28,10 @@ bytecodes: [
/* 78 E> */ B(Add), R(0), U8(1),
B(Star), R(0),
/* 86 S> */ B(LdaSmi), U8(10),
/* 95 E> */ B(TestGreaterThan), R(0),
/* 95 E> */ B(TestGreaterThan), R(0), U8(2),
B(JumpIfFalse), U8(4),
/* 101 S> */ B(Jump), U8(4),
B(Jump), U8(-16),
B(Jump), U8(-17),
/* 110 S> */ B(Ldar), R(0),
/* 123 S> */ B(Return),
]
......@@ -51,7 +51,7 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 23
bytecode array length: 24
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaSmi), U8(1),
......@@ -61,7 +61,7 @@ bytecodes: [
/* 69 E> */ B(Add), R(0), U8(1),
B(Star), R(0),
/* 77 S> */ B(LdaSmi), U8(10),
/* 86 E> */ B(TestGreaterThan), R(0),
/* 86 E> */ B(TestGreaterThan), R(0), U8(2),
B(JumpIfFalse), U8(4),
/* 92 S> */ B(Jump), U8(2),
/* 118 S> */ B(Ldar), R(0),
......
......@@ -17,18 +17,18 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 32
bytecode array length: 34
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(2),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrue), U8(7),
B(Jump), U8(8),
/* 66 S> */ B(LdaSmi), U8(2),
......@@ -53,18 +53,18 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 38
bytecode array length: 40
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(2),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrue), U8(10),
B(Jump), U8(14),
/* 66 S> */ B(LdaSmi), U8(2),
......@@ -91,18 +91,18 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 36
bytecode array length: 38
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(2),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrue), U8(8),
B(Jump), U8(12),
/* 66 S> */ B(LdaSmi), U8(2),
......@@ -129,18 +129,18 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 36
bytecode array length: 38
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(2),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(3),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrue), U8(6),
B(Jump), U8(6),
/* 66 S> */ B(Jump), U8(10),
......@@ -167,7 +167,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 45
bytecode array length: 47
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
......@@ -175,11 +175,11 @@ bytecodes: [
/* 42 E> */ B(TypeOf),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(2),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(1), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(3),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrue), U8(10),
B(Jump), U8(14),
/* 74 S> */ B(LdaSmi), U8(1),
......@@ -209,14 +209,14 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 31
bytecode array length: 32
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(TypeOf),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(4),
B(Jump), U8(8),
......@@ -311,18 +311,18 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 290
bytecode array length: 292
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(1),
B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(2),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(JumpIfTrueConstant), U8(0),
B(JumpConstant), U8(1),
/* 68 S> */ B(LdaSmi), U8(2),
......@@ -481,24 +481,24 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 59
bytecode array length: 62
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
B(Star), R(0),
B(Star), R(1),
/* 45 S> */ B(LdaSmi), U8(1),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(4),
B(Mov), R(0), R(3),
B(JumpIfToBooleanTrue), U8(10),
B(JumpIfToBooleanTrue), U8(11),
B(LdaSmi), U8(2),
B(TestEqualStrict), R(3),
B(JumpIfTrue), U8(33),
B(Jump), U8(35),
B(TestEqualStrict), R(3), U8(5),
B(JumpIfTrue), U8(34),
B(Jump), U8(36),
/* 77 E> */ B(AddSmi), U8(1), R(0), U8(1),
B(Star), R(2),
/* 70 S> */ B(LdaSmi), U8(2),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(2),
B(Mov), R(2), R(4),
B(JumpIfToBooleanTrue), U8(4),
B(Jump), U8(8),
......
......@@ -14,7 +14,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 51
bytecode array length: 52
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
......@@ -34,7 +34,7 @@ bytecodes: [
B(Star), R(0),
/* 72 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(3), U8(1),
B(LdaZero),
B(TestEqualStrict), R(1),
B(TestEqualStrict), R(1), U8(0),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(2),
......@@ -55,7 +55,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 80
bytecode array length: 81
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(1),
......@@ -87,7 +87,7 @@ bytecodes: [
B(Star), R(0),
/* 92 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
B(LdaZero),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(0),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(3),
......@@ -111,7 +111,7 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 105
bytecode array length: 106
bytecodes: [
/* 30 E> */ B(StackCheck),
B(Mov), R(context), R(4),
......@@ -153,7 +153,7 @@ bytecodes: [
B(Star), R(0),
/* 116 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1),
B(LdaZero),
B(TestEqualStrict), R(2),
B(TestEqualStrict), R(2), U8(0),
B(JumpIfTrue), U8(4),
B(Jump), U8(5),
B(Ldar), R(3),
......
......@@ -17,18 +17,18 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 22
bytecode array length: 23
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 54 S> */ B(LdaSmi), U8(10),
/* 54 E> */ B(TestEqual), R(0),
/* 54 E> */ B(TestEqual), R(0), U8(1),
B(JumpIfTrue), U8(11),
/* 45 E> */ B(StackCheck),
/* 65 S> */ B(AddSmi), U8(10), R(0), U8(1),
/* 65 S> */ B(AddSmi), U8(10), R(0), U8(2),
B(Star), R(0),
B(Jump), U8(-13),
B(Jump), U8(-14),
/* 79 S> */ B(Ldar), R(0),
/* 89 S> */ B(Return),
]
......@@ -47,7 +47,7 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 18
bytecode array length: 19
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaFalse),
......@@ -57,8 +57,8 @@ bytecodes: [
B(ToBooleanLogicalNot),
B(Star), R(0),
/* 74 S> */ B(LdaFalse),
/* 74 E> */ B(TestEqual), R(0),
B(JumpIfTrue), U8(-9),
/* 74 E> */ B(TestEqual), R(0), U8(1),
B(JumpIfTrue), U8(-10),
/* 85 S> */ B(Ldar), R(0),
/* 95 S> */ B(Return),
]
......
......@@ -523,11 +523,11 @@ snippet: "
"
frame size: 157
parameter count: 1
bytecode array length: 17
bytecode array length: 18
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1494 S> */ B(LdaSmi), U8(3),
/* 1501 E> */ B(TestGreaterThan), R(2),
/* 1501 E> */ B(TestGreaterThan), R(2), U8(1),
B(JumpIfFalse), U8(7),
/* 1508 S> */ B(Wide), B(Ldar), R16(129),
/* 1536 S> */ B(Return),
......@@ -705,18 +705,18 @@ snippet: "
"
frame size: 157
parameter count: 1
bytecode array length: 34
bytecode array length: 37
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1503 S> */ B(LdaZero),
B(Star), R(0),
/* 1506 S> */ B(LdaSmi), U8(3),
/* 1515 E> */ B(Wide), B(TestEqual), R16(129),
/* 1515 E> */ B(Wide), B(TestEqual), R16(129), U16(1),
B(JumpIfFalse), U8(10),
/* 1534 S> */ B(Wide), B(Mov), R16(0), R16(129),
B(Ldar), R(0),
/* 1540 S> */ B(LdaSmi), U8(3),
/* 1547 E> */ B(TestGreaterThan), R(2),
/* 1547 E> */ B(TestGreaterThan), R(2), U8(2),
B(JumpIfFalse), U8(5),
/* 1554 S> */ B(Ldar), R(0),
/* 1580 S> */ B(Return),
......@@ -893,7 +893,7 @@ snippet: "
"
frame size: 158
parameter count: 1
bytecode array length: 53
bytecode array length: 55
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 1503 S> */ B(LdaZero),
......@@ -903,17 +903,17 @@ bytecodes: [
/* 1523 S> */ B(LdaZero),
B(Wide), B(Star), R16(128),
/* 1538 S> */ B(LdaSmi), U8(64),
/* 1538 E> */ B(Wide), B(TestLessThan), R16(128),
/* 1538 E> */ B(Wide), B(TestLessThan), R16(128), U16(1),
B(JumpIfFalse), U8(30),
/* 1518 E> */ B(StackCheck),
/* 1555 S> */ B(Wide), B(Ldar), R16(128),
/* 1561 E> */ B(Add), R(1), U8(2),
/* 1561 E> */ B(Add), R(1), U8(3),
B(Wide), B(Mov), R16(1), R16(157),
B(Star), R(1),
/* 1548 S> */ B(Wide), B(Ldar), R16(128),
B(Inc), U8(1),
B(Inc), U8(2),
B(Wide), B(Star), R16(128),
B(Jump), U8(-34),
B(Jump), U8(-36),
/* 1567 S> */ B(Wide), B(Ldar), R16(128),
/* 1580 S> */ B(Return),
]
......
......@@ -1671,22 +1671,32 @@ TEST(InterpreterSmiComparisons) {
for (size_t j = 0; j < arraysize(inputs); j++) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
Zone zone(isolate->allocator());
BytecodeArrayBuilder builder(isolate, handles.main_zone(), 0, 0, 1);
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot = feedback_spec.AddGeneralSlot();
Handle<i::TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate, &feedback_spec);
Register r0(0);
builder.LoadLiteral(Smi::FromInt(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Smi::FromInt(inputs[j]))
.CompareOperation(comparison, r0)
.CompareOperation(comparison, r0, vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
InterpreterTester tester(isolate, bytecode_array, vector);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->IsBoolean());
CHECK_EQ(return_value->BooleanValue(),
CompareC(comparison, inputs[i], inputs[j]));
Object* feedback = vector->Get(slot);
CHECK(feedback->IsSmi());
CHECK_EQ(BinaryOperationFeedback::kSignedSmall,
static_cast<Smi*>(feedback)->value());
}
}
}
......@@ -1708,22 +1718,32 @@ TEST(InterpreterHeapNumberComparisons) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
Factory* factory = isolate->factory();
Zone zone(isolate->allocator());
BytecodeArrayBuilder builder(isolate, handles.main_zone(), 0, 0, 1);
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot = feedback_spec.AddGeneralSlot();
Handle<i::TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate, &feedback_spec);
Register r0(0);
builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewHeapNumber(inputs[j]))
.CompareOperation(comparison, r0)
.CompareOperation(comparison, r0, vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
InterpreterTester tester(isolate, bytecode_array, vector);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->IsBoolean());
CHECK_EQ(return_value->BooleanValue(),
CompareC(comparison, inputs[i], inputs[j]));
Object* feedback = vector->Get(slot);
CHECK(feedback->IsSmi());
CHECK_EQ(BinaryOperationFeedback::kNumber,
static_cast<Smi*>(feedback)->value());
}
}
}
......@@ -1734,6 +1754,7 @@ TEST(InterpreterStringComparisons) {
HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate();
Factory* factory = isolate->factory();
Zone zone(isolate->allocator());
std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"};
......@@ -1744,21 +1765,31 @@ TEST(InterpreterStringComparisons) {
CanonicalHandleScope canonical(isolate);
const char* lhs = inputs[i].c_str();
const char* rhs = inputs[j].c_str();
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot = feedback_spec.AddGeneralSlot();
Handle<i::TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate, &feedback_spec);
BytecodeArrayBuilder builder(isolate, handles.main_zone(), 0, 0, 1);
Register r0(0);
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
.CompareOperation(comparison, r0)
.CompareOperation(comparison, r0, vector->GetIndex(slot))
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
InterpreterTester tester(isolate, bytecode_array, vector);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->IsBoolean());
CHECK_EQ(return_value->BooleanValue(),
CompareC(comparison, inputs[i], inputs[j]));
Object* feedback = vector->Get(slot);
CHECK(feedback->IsSmi());
CHECK_EQ(BinaryOperationFeedback::kAny,
static_cast<Smi*>(feedback)->value());
}
}
}
......@@ -1789,6 +1820,12 @@ TEST(InterpreterMixedComparisons) {
Isolate* isolate = handles.main_isolate();
Factory* factory = isolate->factory();
BytecodeArrayBuilder builder(isolate, handles.main_zone(), 0, 0, 1);
Zone zone(isolate->allocator());
FeedbackVectorSpec feedback_spec(&zone);
FeedbackVectorSlot slot = feedback_spec.AddGeneralSlot();
Handle<i::TypeFeedbackVector> vector =
NewTypeFeedbackVector(isolate, &feedback_spec);
Register r0(0);
if (pass == 0) {
......@@ -1796,25 +1833,29 @@ TEST(InterpreterMixedComparisons) {
builder.LoadLiteral(factory->NewNumber(lhs))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
.CompareOperation(comparison, r0)
.CompareOperation(comparison, r0, vector->GetIndex(slot))
.Return();
} else {
// Comparison with HeapNumber on the rhs and String on the lhs
builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(factory->NewNumber(rhs))
.CompareOperation(comparison, r0)
.CompareOperation(comparison, r0, vector->GetIndex(slot))
.Return();
}
Handle<BytecodeArray> bytecode_array =
builder.ToBytecodeArray(isolate);
InterpreterTester tester(isolate, bytecode_array);
InterpreterTester tester(isolate, bytecode_array, vector);
auto callable = tester.GetCallable<>();
Handle<Object> return_value = callable().ToHandleChecked();
CHECK(return_value->IsBoolean());
CHECK_EQ(return_value->BooleanValue(),
CompareC(comparison, lhs, rhs, true));
Object* feedback = vector->Get(slot);
CHECK(feedback->IsSmi());
CHECK_EQ(BinaryOperationFeedback::kAny,
static_cast<Smi*>(feedback)->value());
}
}
}
......@@ -1910,7 +1951,7 @@ TEST(InterpreterInstanceOf) {
builder.LoadLiteral(cases[i]);
builder.StoreAccumulatorInRegister(r0)
.LoadLiteral(func)
.CompareOperation(Token::Value::INSTANCEOF, r0)
.CompareOperation(Token::Value::INSTANCEOF, r0, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
......@@ -1940,7 +1981,7 @@ TEST(InterpreterTestIn) {
builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
.StoreAccumulatorInRegister(r0)
.LoadLiteral(Handle<Object>::cast(array))
.CompareOperation(Token::Value::IN, r0)
.CompareOperation(Token::Value::IN, r0, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
......
......@@ -43,8 +43,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.LoadLiteral(Smi::FromInt(0))
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(8))
.CompareOperation(Token::Value::NE, reg) // Prevent peephole optimization
// LdaSmi, Star -> LdrSmi.
.CompareOperation(Token::Value::NE, reg,
1) // Prevent peephole optimization
// LdaSmi, Star -> LdrSmi.
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(10000000))
.StoreAccumulatorInRegister(reg)
......@@ -174,15 +175,15 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.New(wide, wide, 0);
// Emit test operator invocations.
builder.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::NE, reg)
.CompareOperation(Token::Value::EQ_STRICT, reg)
.CompareOperation(Token::Value::LT, reg)
.CompareOperation(Token::Value::GT, reg)
.CompareOperation(Token::Value::LTE, reg)
.CompareOperation(Token::Value::GTE, reg)
.CompareOperation(Token::Value::INSTANCEOF, reg)
.CompareOperation(Token::Value::IN, reg);
builder.CompareOperation(Token::Value::EQ, reg, 1)
.CompareOperation(Token::Value::NE, reg, 2)
.CompareOperation(Token::Value::EQ_STRICT, reg, 3)
.CompareOperation(Token::Value::LT, reg, 4)
.CompareOperation(Token::Value::GT, reg, 5)
.CompareOperation(Token::Value::LTE, reg, 6)
.CompareOperation(Token::Value::GTE, reg, 7)
.CompareOperation(Token::Value::INSTANCEOF, reg, 8)
.CompareOperation(Token::Value::IN, reg, 9);
// Emit cast operator invocations.
builder.CastAccumulatorToNumber(reg)
......@@ -223,9 +224,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
builder.CompareOperation(Token::Value::EQ, reg)
builder.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&start)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
......@@ -247,9 +248,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.JumpIfNotHole(&start);
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
builder.CompareOperation(Token::Value::EQ, reg)
builder.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&start)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
......@@ -350,9 +351,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
builder.CompareOperation(Token::Value::EQ, reg)
builder.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&start)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&start);
// Perform an operation that returns a non-boolean operation to
......@@ -563,9 +564,9 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
builder.Jump(&near0)
.Bind(&after_jump0)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&near1)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&near2)
.BinaryOperation(Token::Value::ADD, reg, 1)
.JumpIfTrue(&near3)
......@@ -578,26 +579,26 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
.Bind(&near4)
.Jump(&far0)
.Bind(&after_jump1)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 3)
.JumpIfTrue(&far1)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 4)
.JumpIfFalse(&far2)
.BinaryOperation(Token::Value::ADD, reg, 3)
.JumpIfTrue(&far3)
.BinaryOperation(Token::Value::ADD, reg, 4)
.JumpIfFalse(&far4);
for (int i = 0; i < kFarJumpDistance - 20; i++) {
for (int i = 0; i < kFarJumpDistance - 22; i++) {
builder.Debugger();
}
builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4);
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
DCHECK_EQ(array->length(), 40 + kFarJumpDistance - 20 + 1);
DCHECK_EQ(array->length(), 44 + kFarJumpDistance - 22 + 1);
BytecodeArrayIterator iterator(array);
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.GetImmediateOperand(0), 20);
CHECK_EQ(iterator.GetImmediateOperand(0), 22);
iterator.Advance();
// Ignore compare operation.
......@@ -605,7 +606,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
CHECK_EQ(iterator.GetImmediateOperand(0), 16);
CHECK_EQ(iterator.GetImmediateOperand(0), 17);
iterator.Advance();
// Ignore compare operation.
......@@ -641,7 +642,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrueConstant));
CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance - 4));
Smi::FromInt(kFarJumpDistance - 5));
iterator.Advance();
// Ignore compare operation.
......@@ -650,7 +651,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalseConstant));
CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance - 8));
Smi::FromInt(kFarJumpDistance - 10));
iterator.Advance();
// Ignore add operation.
......@@ -658,7 +659,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant);
CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance - 13));
Smi::FromInt(kFarJumpDistance - 15));
iterator.Advance();
// Ignore add operation.
......@@ -667,7 +668,7 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
Bytecode::kJumpIfToBooleanFalseConstant);
CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance - 18));
Smi::FromInt(kFarJumpDistance - 20));
iterator.Advance();
}
......@@ -682,10 +683,10 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
builder.Bind(&label0)
.Jump(&label0)
.Bind(&label1)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&label1)
.Bind(&label2)
.CompareOperation(Token::Value::EQ, reg)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&label2)
.Bind(&label3)
.BinaryOperation(Token::Value::ADD, reg, 1)
......@@ -705,8 +706,8 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
builder.BinaryOperation(Token::Value::ADD, reg, 1).JumpIfFalse(&label4);
builder.BinaryOperation(Token::Value::ADD, reg, 2).JumpIfTrue(&label3);
builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
builder.CompareOperation(Token::Value::EQ, reg).JumpIfTrue(&label1);
builder.CompareOperation(Token::Value::EQ, reg, 1).JumpIfFalse(&label2);
builder.CompareOperation(Token::Value::EQ, reg, 2).JumpIfTrue(&label1);
builder.Jump(&label0);
BytecodeLabel end;
builder.Bind(&end);
......@@ -722,14 +723,14 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetImmediateOperand(0), -2);
CHECK_EQ(iterator.GetImmediateOperand(0), -3);
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetImmediateOperand(0), -2);
CHECK_EQ(iterator.GetImmediateOperand(0), -3);
iterator.Advance();
// Ignore binary operation.
iterator.Advance();
......@@ -772,18 +773,18 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse));
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
CHECK_EQ(iterator.GetImmediateOperand(0), -411);
CHECK_EQ(iterator.GetImmediateOperand(0), -413);
iterator.Advance();
// Ignore compare operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(),
PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue));
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
CHECK_EQ(iterator.GetImmediateOperand(0), -421);
CHECK_EQ(iterator.GetImmediateOperand(0), -425);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
CHECK_EQ(iterator.GetImmediateOperand(0), -427);
CHECK_EQ(iterator.GetImmediateOperand(0), -431);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
......
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