Commit d3e9aade authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Interpreter] Move BinaryOp Smi transformation into BytecodeGenerator.

Perform the transformation to <BinaryOp>Smi for Binary ops which take Smi
literals in the BytecodeGenerator. This enables us to perform the
transformation for literals on either side for commutative operations, and
Avoids having to do the check on every bytecode in the peephole optimizer.

In the process, adds Smi bytecode variants for all binary operations, adding
 - MulSmi
 - DivSmi
 - ModSmi
 - BitwiseXorSmi
 - ShiftRightLogical

BUG=v8:6194

Change-Id: If1484252f5385c16957004b9cac8bfbb1f209219
Reviewed-on: https://chromium-review.googlesource.com/466246
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44477}
parent 4a87608d
......@@ -884,6 +884,30 @@ void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
}
}
static bool IsCommutativeOperationWithSmiLiteral(Token::Value op) {
// Add is not commutative due to potential for string addition.
return op == Token::MUL || op == Token::BIT_AND || op == Token::BIT_OR ||
op == Token::BIT_XOR;
}
// Check for the pattern: x + 1.
static bool MatchSmiLiteralOperation(Expression* left, Expression* right,
Expression** expr, Smi** literal) {
if (right->IsSmiLiteral()) {
*expr = left;
*literal = right->AsLiteral()->AsSmiLiteral();
return true;
}
return false;
}
bool BinaryOperation::IsSmiLiteralOperation(Expression** subexpr,
Smi** literal) {
return MatchSmiLiteralOperation(left_, right_, subexpr, literal) ||
(IsCommutativeOperationWithSmiLiteral(op()) &&
MatchSmiLiteralOperation(right_, left_, subexpr, literal));
}
static bool IsTypeof(Expression* expr) {
UnaryOperation* maybe_unary = expr->AsUnaryOperation();
return maybe_unary != NULL && maybe_unary->op() == Token::TYPEOF;
......
......@@ -1201,6 +1201,11 @@ class Literal final : public Expression {
return value_->AsString();
}
Smi* AsSmiLiteral() {
DCHECK(IsSmiLiteral());
return raw_value()->AsSmi();
}
bool ToBooleanIsTrue() const { return raw_value()->BooleanValue(); }
bool ToBooleanIsFalse() const { return !raw_value()->BooleanValue(); }
......@@ -2134,6 +2139,11 @@ class BinaryOperation final : public Expression {
TypeFeedbackId BinaryOperationFeedbackId() const {
return TypeFeedbackId(local_id(1));
}
// Returns true if one side is a Smi literal, returning the other side's
// sub-expression in |subexpr| and the literal Smi in |literal|.
bool IsSmiLiteralOperation(Expression** subexpr, Smi** literal);
Maybe<int> fixed_right_arg() const {
return has_fixed_right_arg_ ? Just(fixed_right_arg_value_) : Nothing<int>();
}
......
......@@ -618,6 +618,9 @@ namespace internal {
TFS(StrictEqual, Compare, 1) \
TFS(AddWithFeedback, BinaryOpWithVector, 1) \
TFS(SubtractWithFeedback, BinaryOpWithVector, 1) \
TFS(MultiplyWithFeedback, BinaryOpWithVector, 1) \
TFS(DivideWithFeedback, BinaryOpWithVector, 1) \
TFS(ModulusWithFeedback, BinaryOpWithVector, 1) \
\
/* Object */ \
CPP(ObjectAssign) \
......
......@@ -1415,5 +1415,38 @@ TF_BUILTIN(SubtractWithFeedback, BinaryOpAssembler) {
ChangeUint32ToWord(slot), vector));
}
TF_BUILTIN(MultiplyWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Return(Generate_MultiplyWithFeedback(context, left, right,
ChangeUint32ToWord(slot), vector));
}
TF_BUILTIN(DivideWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Return(Generate_DivideWithFeedback(context, left, right,
ChangeUint32ToWord(slot), vector));
}
TF_BUILTIN(ModulusWithFeedback, BinaryOpAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* left = Parameter(Descriptor::kLeft);
Node* right = Parameter(Descriptor::kRight);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Return(Generate_ModulusWithFeedback(context, left, right,
ChangeUint32ToWord(slot), vector));
}
} // namespace internal
} // namespace v8
......@@ -581,6 +581,53 @@ Node* CodeStubAssembler::SmiMul(Node* a, Node* b) {
return var_result.value();
}
Node* CodeStubAssembler::TrySmiDiv(Node* dividend, Node* divisor,
Label* bailout) {
// Both {a} and {b} are Smis. Bailout to floating point division if {divisor}
// is zero.
GotoIf(WordEqual(divisor, SmiConstant(0)), bailout);
// Do floating point division if {dividend} is zero and {divisor} is
// negative.
Label dividend_is_zero(this), dividend_is_not_zero(this);
Branch(WordEqual(dividend, SmiConstant(0)), &dividend_is_zero,
&dividend_is_not_zero);
Bind(&dividend_is_zero);
{
GotoIf(SmiLessThan(divisor, SmiConstant(0)), bailout);
Goto(&dividend_is_not_zero);
}
Bind(&dividend_is_not_zero);
Node* untagged_divisor = SmiToWord32(divisor);
Node* untagged_dividend = SmiToWord32(dividend);
// Do floating point division if {dividend} is kMinInt (or kMinInt - 1
// if the Smi size is 31) and {divisor} is -1.
Label divisor_is_minus_one(this), divisor_is_not_minus_one(this);
Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
&divisor_is_minus_one, &divisor_is_not_minus_one);
Bind(&divisor_is_minus_one);
{
GotoIf(Word32Equal(
untagged_dividend,
Int32Constant(kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
bailout);
Goto(&divisor_is_not_minus_one);
}
Bind(&divisor_is_not_minus_one);
Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor);
Node* truncated = Int32Mul(untagged_result, untagged_divisor);
// Do floating point division if the remainder is not 0.
GotoIf(Word32NotEqual(untagged_dividend, truncated), bailout);
return SmiFromWord32(untagged_result);
}
Node* CodeStubAssembler::TruncateWordToWord32(Node* value) {
if (Is64()) {
return TruncateInt64ToInt32(value);
......
......@@ -237,6 +237,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Node* SmiMod(Node* a, Node* b);
// Computes a * b for Smi inputs a and b; result is not necessarily a Smi.
Node* SmiMul(Node* a, Node* b);
// Tries to computes dividend / divisor for Smi inputs; branching to bailout
// if the division needs to be performed as a floating point operation.
Node* TrySmiDiv(Node* dividend, Node* divisor, Label* bailout);
// Smi | HeapNumber operations.
Node* NumberInc(Node* value);
......
......@@ -1745,8 +1745,7 @@ void BytecodeGraphBuilder::VisitShiftRightLogical() {
void BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) {
PrepareEagerCheckpoint();
Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1));
Node* left = environment()->LookupAccumulator();
Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0));
Node* node = nullptr;
......@@ -1770,10 +1769,26 @@ void BytecodeGraphBuilder::VisitSubSmi() {
BuildBinaryOpWithImmediate(javascript()->Subtract());
}
void BytecodeGraphBuilder::VisitMulSmi() {
BuildBinaryOpWithImmediate(javascript()->Multiply());
}
void BytecodeGraphBuilder::VisitDivSmi() {
BuildBinaryOpWithImmediate(javascript()->Divide());
}
void BytecodeGraphBuilder::VisitModSmi() {
BuildBinaryOpWithImmediate(javascript()->Modulus());
}
void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
BuildBinaryOpWithImmediate(javascript()->BitwiseOr());
}
void BytecodeGraphBuilder::VisitBitwiseXorSmi() {
BuildBinaryOpWithImmediate(javascript()->BitwiseXor());
}
void BytecodeGraphBuilder::VisitBitwiseAndSmi() {
BuildBinaryOpWithImmediate(javascript()->BitwiseAnd());
}
......@@ -1786,6 +1801,10 @@ void BytecodeGraphBuilder::VisitShiftRightSmi() {
BuildBinaryOpWithImmediate(javascript()->ShiftRight());
}
void BytecodeGraphBuilder::VisitShiftRightLogicalSmi() {
BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical());
}
void BytecodeGraphBuilder::VisitInc() {
PrepareEagerCheckpoint();
// Note: Use subtract -1 here instead of add 1 to ensure we always convert to
......
......@@ -361,7 +361,7 @@ class BytecodeGraphBuilder {
static int const kBinaryOperationHintIndex = 1;
static int const kCountOperationHintIndex = 0;
static int const kBinaryOperationSmiHintIndex = 2;
static int const kBinaryOperationSmiHintIndex = 1;
DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
};
......
......@@ -353,18 +353,23 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
case Bytecode::kSub:
case Bytecode::kSubSmi:
case Bytecode::kMul:
case Bytecode::kMulSmi:
case Bytecode::kDiv:
case Bytecode::kDivSmi:
case Bytecode::kMod:
case Bytecode::kModSmi:
case Bytecode::kBitwiseAnd:
case Bytecode::kBitwiseAndSmi:
case Bytecode::kBitwiseOr:
case Bytecode::kBitwiseOrSmi:
case Bytecode::kBitwiseXor:
case Bytecode::kBitwiseXorSmi:
case Bytecode::kShiftLeft:
case Bytecode::kShiftLeftSmi:
case Bytecode::kShiftRight:
case Bytecode::kShiftRightSmi:
case Bytecode::kShiftRightLogical:
case Bytecode::kShiftRightLogicalSmi:
case Bytecode::kInc:
case Bytecode::kDec:
case Bytecode::kLogicalNot:
......
......@@ -546,48 +546,10 @@ Node* BinaryOpAssembler::Generate_DivideWithFeedback(Node* context,
{
Label bailout(this);
// Do floating point division if {divisor} is zero.
GotoIf(WordEqual(divisor, SmiConstant(0)), &bailout);
// Do floating point division {dividend} is zero and {divisor} is
// negative.
Label dividend_is_zero(this), dividend_is_not_zero(this);
Branch(WordEqual(dividend, SmiConstant(0)), &dividend_is_zero,
&dividend_is_not_zero);
BIND(&dividend_is_zero);
{
GotoIf(SmiLessThan(divisor, SmiConstant(0)), &bailout);
Goto(&dividend_is_not_zero);
}
BIND(&dividend_is_not_zero);
Node* untagged_divisor = SmiToWord32(divisor);
Node* untagged_dividend = SmiToWord32(dividend);
// Do floating point division if {dividend} is kMinInt (or kMinInt - 1
// if the Smi size is 31) and {divisor} is -1.
Label divisor_is_minus_one(this), divisor_is_not_minus_one(this);
Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
&divisor_is_minus_one, &divisor_is_not_minus_one);
BIND(&divisor_is_minus_one);
{
GotoIf(Word32Equal(untagged_dividend,
Int32Constant(kSmiValueSize == 32 ? kMinInt
: (kMinInt >> 1))),
&bailout);
Goto(&divisor_is_not_minus_one);
}
BIND(&divisor_is_not_minus_one);
Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor);
Node* truncated = Int32Mul(untagged_result, untagged_divisor);
// Do floating point division if the remainder is not 0.
GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout);
// Try to perform Smi division if possible.
var_result.Bind(TrySmiDiv(dividend, divisor, &bailout));
var_type_feedback.Bind(
SmiConstant(BinaryOperationFeedback::kSignedSmall));
var_result.Bind(SmiFromWord32(untagged_result));
Goto(&end);
// Bailout: convert {dividend} and {divisor} to double and do double
......
......@@ -317,6 +317,48 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
Token::Value op, Smi* literal, int feedback_slot) {
switch (op) {
case Token::Value::ADD:
OutputAddSmi(literal->value(), feedback_slot);
break;
case Token::Value::SUB:
OutputSubSmi(literal->value(), feedback_slot);
break;
case Token::Value::MUL:
OutputMulSmi(literal->value(), feedback_slot);
break;
case Token::Value::DIV:
OutputDivSmi(literal->value(), feedback_slot);
break;
case Token::Value::MOD:
OutputModSmi(literal->value(), feedback_slot);
break;
case Token::Value::BIT_OR:
OutputBitwiseOrSmi(literal->value(), feedback_slot);
break;
case Token::Value::BIT_XOR:
OutputBitwiseXorSmi(literal->value(), feedback_slot);
break;
case Token::Value::BIT_AND:
OutputBitwiseAndSmi(literal->value(), feedback_slot);
break;
case Token::Value::SHL:
OutputShiftLeftSmi(literal->value(), feedback_slot);
break;
case Token::Value::SAR:
OutputShiftRightSmi(literal->value(), feedback_slot);
break;
case Token::Value::SHR:
OutputShiftRightLogicalSmi(literal->value(), feedback_slot);
break;
default:
UNREACHABLE();
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
int feedback_slot) {
if (op == Token::Value::ADD) {
......
......@@ -292,6 +292,9 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Type feedback will be recorded in the |feedback_slot|
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
int feedback_slot);
BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
Smi* literal,
int feedback_slot);
// Count Operators (value stored in accumulator).
// Type feedback will be recorded in the |feedback_slot|
......
......@@ -2299,50 +2299,48 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
// Evaluate the value and potentially handle compound assignments by loading
// the left-hand side value and performing a binary operation.
if (expr->is_compound()) {
Register old_value = register_allocator()->NewRegister();
switch (assign_type) {
case VARIABLE: {
VariableProxy* proxy = expr->target()->AsVariableProxy();
BuildVariableLoad(proxy->var(), proxy->VariableFeedbackSlot(),
proxy->hole_check_mode());
builder()->StoreAccumulatorInRegister(old_value);
break;
}
case NAMED_PROPERTY: {
FeedbackSlot slot = property->PropertyFeedbackSlot();
builder()
->LoadNamedProperty(object, name, feedback_index(slot))
.StoreAccumulatorInRegister(old_value);
builder()->LoadNamedProperty(object, name, feedback_index(slot));
break;
}
case KEYED_PROPERTY: {
// Key is already in accumulator at this point due to evaluating the
// LHS above.
FeedbackSlot slot = property->PropertyFeedbackSlot();
builder()
->LoadKeyedProperty(object, feedback_index(slot))
.StoreAccumulatorInRegister(old_value);
builder()->LoadKeyedProperty(object, feedback_index(slot));
break;
}
case NAMED_SUPER_PROPERTY: {
builder()
->CallRuntime(Runtime::kLoadFromSuper,
super_property_args.Truncate(3))
.StoreAccumulatorInRegister(old_value);
builder()->CallRuntime(Runtime::kLoadFromSuper,
super_property_args.Truncate(3));
break;
}
case KEYED_SUPER_PROPERTY: {
builder()
->CallRuntime(Runtime::kLoadKeyedFromSuper,
super_property_args.Truncate(3))
.StoreAccumulatorInRegister(old_value);
builder()->CallRuntime(Runtime::kLoadKeyedFromSuper,
super_property_args.Truncate(3));
break;
}
}
VisitForAccumulatorValue(expr->value());
FeedbackSlot slot = expr->binary_operation()->BinaryOperationFeedbackSlot();
builder()->BinaryOperation(expr->binary_op(), old_value,
feedback_index(slot));
if (expr->value()->IsSmiLiteral()) {
builder()->BinaryOperationSmiLiteral(
expr->binary_op(), expr->value()->AsLiteral()->AsSmiLiteral(),
feedback_index(slot));
} else {
Register old_value = register_allocator()->NewRegister();
builder()->StoreAccumulatorInRegister(old_value);
VisitForAccumulatorValue(expr->value());
builder()->BinaryOperation(expr->binary_op(), old_value,
feedback_index(slot));
}
} else {
VisitForAccumulatorValue(expr->value());
}
......@@ -3109,11 +3107,20 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
// TODO(rmcilroy): Special case "x * 1.0" and "x * -1" which are generated for
// +x and -x by the parser.
Register lhs = VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right());
FeedbackSlot slot = expr->BinaryOperationFeedbackSlot();
builder()->SetExpressionPosition(expr);
builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
Expression* subexpr;
Smi* literal;
if (expr->IsSmiLiteralOperation(&subexpr, &literal)) {
VisitForAccumulatorValue(subexpr);
builder()->SetExpressionPosition(expr);
builder()->BinaryOperationSmiLiteral(expr->op(), literal,
feedback_index(slot));
} else {
Register lhs = VisitForRegisterValue(expr->left());
VisitForAccumulatorValue(expr->right());
builder()->SetExpressionPosition(expr);
builder()->BinaryOperation(expr->op(), lhs, feedback_index(slot));
}
}
void BytecodeGenerator::VisitSpread(Spread* expr) { Visit(expr->expression()); }
......
......@@ -117,30 +117,6 @@ bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition(
namespace {
BytecodeNode TransformLdaSmiBinaryOpToBinaryOpWithSmi(
Bytecode new_bytecode, BytecodeNode* const last,
BytecodeNode* const current) {
DCHECK_EQ(last->bytecode(), Bytecode::kLdaSmi);
BytecodeNode node(new_bytecode, last->operand(0), current->operand(0),
current->operand(1), current->source_info());
if (last->source_info().is_valid()) {
node.set_source_info(last->source_info());
}
return node;
}
BytecodeNode TransformLdaZeroBinaryOpToBinaryOpWithZero(
Bytecode new_bytecode, BytecodeNode* const last,
BytecodeNode* const current) {
DCHECK_EQ(last->bytecode(), Bytecode::kLdaZero);
BytecodeNode node(new_bytecode, 0, current->operand(0), current->operand(1),
current->source_info());
if (last->source_info().is_valid()) {
node.set_source_info(last->source_info());
}
return node;
}
} // namespace
void BytecodePeepholeOptimizer::DefaultAction(
......@@ -224,36 +200,6 @@ void BytecodePeepholeOptimizer::ChangeBytecodeAction(
DefaultAction(node);
}
void BytecodePeepholeOptimizer::TransformLdaSmiBinaryOpToBinaryOpWithSmiAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
DCHECK(!Bytecodes::IsJump(node->bytecode()));
if (!node->source_info().is_valid() || !last()->source_info().is_valid()) {
// Fused last and current into current.
BytecodeNode new_node(TransformLdaSmiBinaryOpToBinaryOpWithSmi(
action_data->bytecode, last(), node));
SetLast(&new_node);
} else {
DefaultAction(node);
}
}
void BytecodePeepholeOptimizer::
TransformLdaZeroBinaryOpToBinaryOpWithZeroAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
DCHECK(!Bytecodes::IsJump(node->bytecode()));
if (!node->source_info().is_valid() || !last()->source_info().is_valid()) {
// Fused last and current into current.
BytecodeNode new_node(TransformLdaZeroBinaryOpToBinaryOpWithZero(
action_data->bytecode, last(), node));
SetLast(&new_node);
} else {
DefaultAction(node);
}
}
void BytecodePeepholeOptimizer::DefaultJumpAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
......
......@@ -11,16 +11,14 @@ namespace v8 {
namespace internal {
namespace interpreter {
#define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \
V(DefaultAction) \
V(UpdateLastAction) \
V(UpdateLastIfSourceInfoPresentAction) \
V(ElideCurrentAction) \
V(ElideCurrentIfOperand0MatchesAction) \
V(ElideLastAction) \
V(ChangeBytecodeAction) \
V(TransformLdaSmiBinaryOpToBinaryOpWithSmiAction) \
V(TransformLdaZeroBinaryOpToBinaryOpWithZeroAction)
#define PEEPHOLE_NON_JUMP_ACTION_LIST(V) \
V(DefaultAction) \
V(UpdateLastAction) \
V(UpdateLastIfSourceInfoPresentAction) \
V(ElideCurrentAction) \
V(ElideCurrentIfOperand0MatchesAction) \
V(ElideLastAction) \
V(ChangeBytecodeAction)
#define PEEPHOLE_JUMP_ACTION_LIST(V) \
V(DefaultJumpAction) \
......
......@@ -127,18 +127,23 @@ namespace interpreter {
OperandType::kIdx) \
\
/* Binary operators with immediate operands */ \
V(AddSmi, AccumulatorUse::kWrite, OperandType::kImm, OperandType::kReg, \
V(AddSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(SubSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(MulSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(DivSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(ModSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(BitwiseOrSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(SubSmi, AccumulatorUse::kWrite, OperandType::kImm, OperandType::kReg, \
V(BitwiseXorSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(BitwiseAndSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(ShiftLeftSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(ShiftRightSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(ShiftRightLogicalSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(BitwiseOrSmi, AccumulatorUse::kWrite, OperandType::kImm, \
OperandType::kReg, OperandType::kIdx) \
V(BitwiseAndSmi, AccumulatorUse::kWrite, OperandType::kImm, \
OperandType::kReg, OperandType::kIdx) \
V(ShiftLeftSmi, AccumulatorUse::kWrite, OperandType::kImm, \
OperandType::kReg, OperandType::kIdx) \
V(ShiftRightSmi, AccumulatorUse::kWrite, OperandType::kImm, \
OperandType::kReg, OperandType::kIdx) \
\
/* Unary Operators */ \
V(Inc, AccumulatorUse::kReadWrite, OperandType::kIdx) \
......
This diff is collapsed.
......@@ -116,66 +116,6 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData(
// TODO(rmcilroy): Add elide for consecutive mov to and from the same
// register.
// Fuse LdaSmi followed by binary op to produce binary op with a
// immediate integer argument. This savaes on dispatches and size.
if (last == Bytecode::kLdaSmi) {
switch (current) {
case Bytecode::kAdd:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kAddSmi};
case Bytecode::kSub:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kSubSmi};
case Bytecode::kBitwiseAnd:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kBitwiseAndSmi};
case Bytecode::kBitwiseOr:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kBitwiseOrSmi};
case Bytecode::kShiftLeft:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kShiftLeftSmi};
case Bytecode::kShiftRight:
return {PeepholeAction::kTransformLdaSmiBinaryOpToBinaryOpWithSmiAction,
Bytecode::kShiftRightSmi};
default:
break;
}
}
// Fuse LdaZero followed by binary op to produce binary op with a
// zero immediate argument. This saves dispatches, but not size.
if (last == Bytecode::kLdaZero) {
switch (current) {
case Bytecode::kAdd:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kAddSmi};
case Bytecode::kSub:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kSubSmi};
case Bytecode::kBitwiseAnd:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kBitwiseAndSmi};
case Bytecode::kBitwiseOr:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kBitwiseOrSmi};
case Bytecode::kShiftLeft:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kShiftLeftSmi};
case Bytecode::kShiftRight:
return {
PeepholeAction::kTransformLdaZeroBinaryOpToBinaryOpWithZeroAction,
Bytecode::kShiftRightSmi};
default:
break;
}
}
// If there is no last bytecode to optimize against, store the incoming
// bytecode or for jumps emit incoming bytecode immediately.
if (last == Bytecode::kIllegal) {
......
......@@ -29,7 +29,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 35
bytecode array length: 36
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
......@@ -42,7 +42,8 @@ bytecodes: [
/* 54 E> */ B(StaKeyedPropertySloppy), R(2), R(1), U8(4),
B(LdaSmi), I8(1),
B(Star), R(1),
/* 59 E> */ B(AddSmi), I8(1), R(0), U8(2),
B(Ldar), R(0),
/* 59 E> */ B(AddSmi), I8(1), U8(2),
B(StaKeyedPropertySloppy), R(2), R(1), U8(4),
B(Ldar), R(2),
/* 66 S> */ B(Return),
......@@ -77,7 +78,7 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 65
bytecode array length: 66
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
......@@ -100,7 +101,8 @@ bytecodes: [
B(Star), R(4),
B(LdaZero),
B(Star), R(3),
/* 68 E> */ B(AddSmi), I8(2), R(0), U8(5),
B(Ldar), R(0),
/* 68 E> */ B(AddSmi), I8(2), U8(5),
B(StaKeyedPropertySloppy), R(4), R(3), U8(7),
B(Ldar), R(4),
B(StaKeyedPropertySloppy), R(2), R(1), U8(10),
......
......@@ -195,7 +195,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 72
bytecode array length: 73
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
......@@ -207,7 +207,8 @@ bytecodes: [
B(Star), R(0),
/* 63 E> */ B(Add), R(2), U8(2),
B(Star), R(2),
/* 78 E> */ B(AddSmi), I8(1), R(0), U8(3),
B(Ldar), R(0),
/* 78 E> */ B(AddSmi), I8(1), U8(3),
B(Star), R(3),
B(LdaSmi), I8(2),
B(Star), R(1),
......
......@@ -74,11 +74,11 @@ bytecodes: [
/* 65 E> */ B(TestLessThan), R(0), U8(2),
B(JumpIfFalse), U8(38),
/* 56 E> */ B(StackCheck),
/* 75 S> */ B(LdaSmi), I8(12),
/* 81 E> */ B(Mul), R(1), U8(3),
/* 75 S> */ B(Ldar), R(1),
/* 81 E> */ B(MulSmi), I8(12), U8(3),
B(Star), R(1),
/* 89 S> */ B(LdaSmi), I8(1),
/* 95 E> */ B(Add), R(0), U8(4),
/* 89 S> */ B(Ldar), R(0),
/* 95 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
/* 102 S> */ B(LdaSmi), I8(3),
/* 108 E> */ B(TestEqual), R(0), U8(5),
......@@ -138,8 +138,8 @@ bytecodes: [
/* 158 E> */ B(TestEqual), R(0), U8(6),
B(JumpIfFalse), U8(4),
/* 164 S> */ B(Jump), U8(12),
/* 173 S> */ B(LdaSmi), I8(1),
/* 179 E> */ B(Add), R(0), U8(7),
/* 173 S> */ B(Ldar), R(0),
/* 179 E> */ B(AddSmi), I8(1), U8(7),
B(Star), R(0),
B(JumpLoop), U8(52), I8(0),
/* 186 S> */ B(Ldar), R(0),
......@@ -179,12 +179,12 @@ bytecodes: [
/* 88 E> */ B(TestEqual), R(0), U8(3),
B(JumpIfFalse), U8(4),
/* 94 S> */ B(Jump), U8(12),
/* 105 S> */ B(LdaSmi), I8(1),
/* 111 E> */ B(Add), R(0), U8(4),
/* 105 S> */ B(Ldar), R(0),
/* 111 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
B(JumpLoop), U8(24), I8(1),
/* 122 S> */ B(LdaSmi), I8(1),
/* 128 E> */ B(Add), R(0), U8(5),
/* 122 S> */ B(Ldar), R(0),
/* 128 E> */ B(AddSmi), I8(1), U8(5),
B(Star), R(0),
/* 135 S> */ B(Jump), U8(2),
/* 144 S> */ B(Ldar), R(0),
......@@ -217,11 +217,11 @@ bytecodes: [
/* 64 S> */ B(Ldar), R(0),
B(JumpIfToBooleanFalse), U8(20),
/* 57 E> */ B(StackCheck),
/* 71 S> */ B(LdaSmi), I8(12),
/* 77 E> */ B(Mul), R(1), U8(2),
/* 71 S> */ B(Ldar), R(1),
/* 77 E> */ B(MulSmi), I8(12), U8(2),
B(Star), R(1),
/* 85 S> */ B(LdaSmi), I8(1),
/* 91 E> */ B(Sub), R(0), U8(3),
/* 85 S> */ B(Ldar), R(0),
/* 91 E> */ B(SubSmi), I8(1), U8(3),
B(Star), R(0),
B(JumpLoop), U8(19), I8(0),
/* 98 S> */ B(Ldar), R(1),
......@@ -253,8 +253,8 @@ bytecodes: [
/* 53 S> */ B(LdaSmi), I8(1),
B(Star), R(1),
/* 56 E> */ B(StackCheck),
/* 63 S> */ B(LdaSmi), I8(10),
/* 69 E> */ B(Mul), R(1), U8(2),
/* 63 S> */ B(Ldar), R(1),
/* 69 E> */ B(MulSmi), I8(10), U8(2),
B(Star), R(1),
/* 77 S> */ B(LdaSmi), I8(5),
/* 83 E> */ B(TestEqual), R(0), U8(3),
......@@ -264,8 +264,8 @@ bytecodes: [
/* 104 E> */ B(TestEqual), R(0), U8(4),
B(JumpIfFalse), U8(4),
/* 110 S> */ B(Jump), U8(9),
/* 122 S> */ B(LdaSmi), I8(1),
/* 128 E> */ B(Add), R(0), U8(5),
/* 122 S> */ B(Ldar), R(0),
/* 128 E> */ B(AddSmi), I8(1), U8(5),
B(Star), R(0),
/* 144 S> */ B(LdaSmi), I8(10),
/* 144 E> */ B(TestLessThan), R(0), U8(6),
......@@ -299,11 +299,11 @@ bytecodes: [
/* 54 S> */ B(LdaSmi), I8(1),
B(Star), R(1),
/* 57 E> */ B(StackCheck),
/* 64 S> */ B(LdaSmi), I8(12),
/* 70 E> */ B(Mul), R(1), U8(2),
/* 64 S> */ B(Ldar), R(1),
/* 70 E> */ B(MulSmi), I8(12), U8(2),
B(Star), R(1),
/* 78 S> */ B(LdaSmi), I8(1),
/* 84 E> */ B(Sub), R(0), U8(3),
/* 78 S> */ B(Ldar), R(0),
/* 84 E> */ B(SubSmi), I8(1), U8(3),
B(Star), R(0),
/* 98 S> */ B(JumpIfToBooleanFalse), U8(5),
B(JumpLoop), U8(17), I8(0),
......@@ -328,7 +328,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 44
bytecode array length: 43
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
......@@ -336,15 +336,15 @@ bytecodes: [
/* 53 S> */ B(LdaSmi), I8(1),
B(Star), R(1),
/* 56 E> */ B(StackCheck),
/* 63 S> */ B(LdaSmi), I8(10),
/* 69 E> */ B(Mul), R(1), U8(2),
/* 63 S> */ B(Nop),
/* 69 E> */ B(MulSmi), I8(10), U8(2),
B(Star), R(1),
/* 77 S> */ B(LdaSmi), I8(5),
/* 83 E> */ B(TestEqual), R(0), U8(3),
B(JumpIfFalse), U8(4),
/* 89 S> */ B(Jump), U8(18),
/* 98 S> */ B(LdaSmi), I8(1),
/* 104 E> */ B(Add), R(0), U8(4),
/* 98 S> */ B(Ldar), R(0),
/* 104 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
/* 111 S> */ B(LdaSmi), I8(6),
/* 117 E> */ B(TestEqual), R(0), U8(5),
......@@ -379,15 +379,15 @@ bytecodes: [
/* 53 S> */ B(LdaSmi), I8(1),
B(Star), R(1),
/* 56 E> */ B(StackCheck),
/* 63 S> */ B(LdaSmi), I8(10),
/* 69 E> */ B(Mul), R(1), U8(2),
/* 63 S> */ B(Ldar), R(1),
/* 69 E> */ B(MulSmi), I8(10), U8(2),
B(Star), R(1),
/* 77 S> */ B(LdaSmi), I8(5),
/* 83 E> */ B(TestEqual), R(0), U8(3),
B(JumpIfFalse), U8(4),
/* 89 S> */ B(Jump), U8(21),
/* 98 S> */ B(LdaSmi), I8(1),
/* 104 E> */ B(Add), R(0), U8(4),
/* 98 S> */ B(Ldar), R(0),
/* 104 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
/* 111 S> */ B(LdaSmi), I8(6),
/* 117 E> */ B(TestEqual), R(0), U8(5),
......@@ -427,8 +427,8 @@ bytecodes: [
/* 85 E> */ B(TestEqual), R(0), U8(3),
B(JumpIfFalse), U8(4),
/* 91 S> */ B(Jump), U8(9),
/* 103 S> */ B(LdaSmi), I8(1),
/* 109 E> */ B(Add), R(0), U8(4),
/* 103 S> */ B(Ldar), R(0),
/* 109 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
B(JumpLoop), U8(26), I8(0),
B(LdaUndefined),
......@@ -463,8 +463,8 @@ bytecodes: [
/* 83 E> */ B(TestEqual), R(0), U8(3),
B(JumpIfFalse), U8(4),
/* 89 S> */ B(Jump), U8(9),
/* 101 S> */ B(LdaSmi), I8(1),
/* 107 E> */ B(Add), R(0), U8(4),
/* 101 S> */ B(Ldar), R(0),
/* 107 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
B(JumpLoop), U8(26), I8(0),
B(LdaUndefined),
......@@ -499,8 +499,8 @@ bytecodes: [
/* 95 E> */ B(TestEqual), R(0), U8(4),
B(JumpIfFalse), U8(4),
/* 101 S> */ B(Jump), U8(2),
/* 55 S> */ B(LdaSmi), I8(1),
/* 59 E> */ B(Add), R(0), U8(2),
/* 55 S> */ B(Ldar), R(0),
/* 59 E> */ B(AddSmi), I8(1), U8(2),
B(Star), R(0),
B(JumpLoop), U8(26), I8(0),
B(LdaUndefined),
......@@ -534,8 +534,8 @@ bytecodes: [
/* 93 E> */ B(TestEqual), R(0), U8(4),
B(JumpIfFalse), U8(4),
/* 99 S> */ B(Jump), U8(2),
/* 53 S> */ B(LdaSmi), I8(1),
/* 57 E> */ B(Add), R(0), U8(2),
/* 53 S> */ B(Ldar), R(0),
/* 57 E> */ B(AddSmi), I8(1), U8(2),
B(Star), R(0),
B(JumpLoop), U8(26), I8(0),
B(LdaUndefined),
......@@ -567,12 +567,12 @@ bytecodes: [
/* 63 E> */ B(TestLessThan), R(1), U8(2),
B(JumpIfFalse), U8(22),
/* 45 E> */ B(StackCheck),
/* 85 S> */ B(LdaSmi), I8(1),
/* 91 E> */ B(Add), R(0), U8(4),
/* 85 S> */ B(Ldar), R(0),
/* 91 E> */ B(AddSmi), I8(1), U8(4),
B(Star), R(0),
/* 98 S> */ B(Jump), U8(2),
/* 72 S> */ B(LdaSmi), I8(1),
/* 76 E> */ B(Add), R(1), U8(3),
/* 72 S> */ B(Ldar), R(1),
/* 76 E> */ B(AddSmi), I8(1), U8(3),
B(Star), R(1),
B(JumpLoop), U8(24), I8(0),
B(LdaUndefined),
......@@ -603,8 +603,8 @@ bytecodes: [
/* 62 S> */ B(Ldar), R(1),
B(JumpIfToBooleanFalse), U8(19),
/* 45 E> */ B(StackCheck),
/* 74 S> */ B(LdaSmi), I8(12),
/* 80 E> */ B(Mul), R(0), U8(3),
/* 74 S> */ B(Ldar), R(0),
/* 80 E> */ B(MulSmi), I8(12), U8(3),
B(Star), R(0),
/* 67 S> */ B(Ldar), R(1),
B(Dec), U8(2),
......@@ -662,8 +662,8 @@ bytecodes: [
/* 58 S> */ B(LdaZero),
B(Star), R(1),
/* 45 E> */ B(StackCheck),
/* 76 S> */ B(LdaSmi), I8(1),
/* 82 E> */ B(Add), R(0), U8(3),
/* 76 S> */ B(Ldar), R(0),
/* 82 E> */ B(AddSmi), I8(1), U8(3),
B(Star), R(0),
/* 89 S> */ B(LdaSmi), I8(20),
/* 95 E> */ B(TestEqual), R(0), U8(4),
......
......@@ -17,13 +17,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 16
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 56 S> */ B(LdaSmi), I8(1),
/* 62 E> */ B(Add), R(0), U8(2),
/* 56 S> */ B(Nop),
/* 62 E> */ B(AddSmi), I8(1), U8(2),
B(Star), R(0),
/* 69 S> */ B(Jump), U8(2),
/* 97 S> */ B(Ldar), R(0),
......
......@@ -22,7 +22,7 @@ snippet: "
"
frame size: 6
parameter count: 1
bytecode array length: 36
bytecode array length: 33
bytecodes: [
B(Mov), R(closure), R(0),
/* 99 E> */ B(StackCheck),
......@@ -35,8 +35,7 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
B(Star), R(1),
/* 117 E> */ B(Call0), R(1), R(this), U8(2),
B(Star), R(1),
/* 126 E> */ B(AddSmi), I8(1), R(1), U8(8),
/* 126 E> */ B(AddSmi), I8(1), U8(8),
/* 131 S> */ B(Return),
]
constant pool: [
......
......@@ -9,15 +9,14 @@ wrap: yes
snippet: "
var a = 1; a += 2;
"
frame size: 2
frame size: 1
parameter count: 1
bytecode array length: 16
bytecode array length: 12
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(AddSmi), I8(2), R(0), U8(2),
B(Mov), R(0), R(1),
/* 45 S> */ B(AddSmi), I8(2), U8(2),
B(Star), R(0),
B(LdaUndefined),
/* 53 S> */ B(Return),
......@@ -31,16 +30,14 @@ handlers: [
snippet: "
var a = 1; a /= 2;
"
frame size: 2
frame size: 1
parameter count: 1
bytecode array length: 17
bytecode array length: 12
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(2),
B(Div), R(0), U8(2),
B(Mov), R(0), R(1),
/* 45 S> */ B(DivSmi), I8(2), U8(2),
B(Star), R(0),
B(LdaUndefined),
/* 53 S> */ B(Return),
......@@ -54,17 +51,15 @@ handlers: [
snippet: "
var a = { val: 2 }; a.name *= 2;
"
frame size: 3
frame size: 2
parameter count: 1
bytecode array length: 26
bytecode array length: 22
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(1),
B(Mov), R(1), R(0),
/* 54 S> */ B(LdaNamedProperty), R(0), U8(1), U8(3),
B(Star), R(2),
B(LdaSmi), I8(2),
B(Mul), R(2), U8(5),
B(MulSmi), I8(2), U8(5),
/* 61 E> */ B(StaNamedPropertySloppy), R(0), U8(1), U8(6),
B(LdaUndefined),
/* 67 S> */ B(Return),
......@@ -80,9 +75,9 @@ handlers: [
snippet: "
var a = { 1: 2 }; a[1] ^= 2;
"
frame size: 4
frame size: 3
parameter count: 1
bytecode array length: 29
bytecode array length: 25
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(2), U8(1), R(1),
......@@ -90,9 +85,7 @@ bytecodes: [
/* 52 S> */ B(LdaSmi), I8(1),
B(Star), R(2),
B(LdaKeyedProperty), R(0), U8(3),
B(Star), R(3),
B(LdaSmi), I8(2),
B(BitwiseXor), R(3), U8(5),
B(BitwiseXorSmi), I8(2), U8(5),
/* 57 E> */ B(StaKeyedPropertySloppy), R(0), R(2), U8(6),
B(LdaUndefined),
/* 63 S> */ B(Return),
......@@ -107,9 +100,9 @@ handlers: [
snippet: "
var a = 1; (function f() { return a; }); a |= 24;
"
frame size: 2
frame size: 1
parameter count: 1
bytecode array length: 25
bytecode array length: 22
bytecodes: [
B(CreateFunctionContext), U8(1),
B(PushContext), R(0),
......@@ -118,8 +111,7 @@ bytecodes: [
/* 42 E> */ B(StaCurrentContextSlot), U8(4),
/* 45 S> */ B(CreateClosure), U8(0), U8(2), U8(2),
/* 75 S> */ B(LdaCurrentContextSlot), U8(4),
B(Star), R(1),
B(BitwiseOrSmi), I8(24), R(1), U8(3),
B(BitwiseOrSmi), I8(24), U8(3),
/* 77 E> */ B(StaCurrentContextSlot), U8(4),
B(LdaUndefined),
/* 84 S> */ B(Return),
......
......@@ -12,14 +12,13 @@ snippet: "
function f() { return global &= 1; }
f();
"
frame size: 1
frame size: 0
parameter count: 1
bytecode array length: 14
bytecode array length: 11
bytecodes: [
/* 26 E> */ B(StackCheck),
/* 31 S> */ B(LdaGlobal), U8(0), U8(2),
B(Star), R(0),
B(BitwiseAndSmi), I8(1), R(0), U8(4),
B(BitwiseAndSmi), I8(1), U8(4),
/* 45 E> */ B(StaGlobalSloppy), U8(0), U8(5),
/* 51 S> */ B(Return),
]
......@@ -35,14 +34,13 @@ snippet: "
function f() { return unallocated += 1; }
f();
"
frame size: 1
frame size: 0
parameter count: 1
bytecode array length: 14
bytecode array length: 11
bytecodes: [
/* 27 E> */ B(StackCheck),
/* 32 S> */ B(LdaGlobal), U8(0), U8(2),
B(Star), R(0),
B(AddSmi), I8(1), R(0), U8(4),
B(AddSmi), I8(1), U8(4),
/* 51 E> */ B(StaGlobalSloppy), U8(0), U8(5),
/* 57 S> */ B(Return),
]
......
......@@ -112,16 +112,16 @@ snippet: "
};
f();
"
frame size: 2
frame size: 1
parameter count: 1
bytecode array length: 23
bytecode array length: 21
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 25 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 30 S> */ B(JumpIfToBooleanFalse), U8(13),
/* 43 S> */ B(AddSmi), I8(1), R(0), U8(2),
B(Mov), R(0), R(1),
/* 30 S> */ B(JumpIfToBooleanFalse), U8(11),
/* 43 S> */ B(Ldar), R(0),
B(AddSmi), I8(1), U8(2),
B(Star), R(0),
B(Jump), U8(5),
/* 66 S> */ B(LdaSmi), I8(2),
......
......@@ -72,13 +72,13 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 21
bytecode array length: 20
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(CreateObjectLiteral), U8(0), U8(3), U8(1), R(1),
/* 69 E> */ B(AddSmi), I8(1), R(0), U8(2),
/* 69 E> */ B(AddSmi), I8(1), U8(2),
B(StaNamedOwnProperty), R(1), U8(1), U8(4),
B(Ldar), R(1),
/* 76 S> */ B(Return),
......
......@@ -30,13 +30,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(AddSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 0; return 3 + x;
"
frame size: 2
parameter count: 1
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(3),
/* 54 E> */ B(Add), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 54 E> */ B(Add), R(1), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -50,13 +72,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecode array length: 9
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(SubSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 0; return 3 - x;
"
frame size: 2
parameter count: 1
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(3),
/* 54 E> */ B(Sub), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 54 E> */ B(Sub), R(1), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -70,13 +114,33 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(3),
/* 54 E> */ B(Mul), R(0), U8(2),
/* 45 S> */ B(Nop),
/* 54 E> */ B(MulSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 4; return 3 * x;
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(MulSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -90,13 +154,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(DivSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 4; return 3 / x;
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(3),
/* 54 E> */ B(Div), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 54 E> */ B(Div), R(1), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -110,13 +196,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(ModSmi), I8(3), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 4; return 3 % x;
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(4),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(3),
/* 54 E> */ B(Mod), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 54 E> */ B(Mod), R(1), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -130,13 +238,33 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(2),
/* 54 E> */ B(BitwiseOr), R(0), U8(2),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseOrSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 1; return 2 | x;
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseOrSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -150,13 +278,33 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(2),
/* 54 E> */ B(BitwiseXor), R(0), U8(2),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseXorSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 1; return 2 ^ x;
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseXorSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -170,13 +318,33 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseAndSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 1; return 2 & x;
"
frame size: 1
parameter count: 1
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
B(Star), R(0),
/* 45 S> */ B(LdaSmi), I8(2),
/* 54 E> */ B(BitwiseAnd), R(0), U8(2),
/* 45 S> */ B(Nop),
/* 54 E> */ B(BitwiseAndSmi), I8(2), U8(2),
/* 59 S> */ B(Return),
]
constant pool: [
......@@ -190,13 +358,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(Nop),
/* 55 E> */ B(ShiftLeftSmi), I8(3), U8(2),
/* 61 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 10; return 3 << x;
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(3),
/* 55 E> */ B(ShiftLeft), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 55 E> */ B(ShiftLeft), R(1), U8(2),
/* 61 S> */ B(Return),
]
constant pool: [
......@@ -210,13 +400,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(Nop),
/* 55 E> */ B(ShiftRightSmi), I8(3), U8(2),
/* 61 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 10; return 3 >> x;
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(3),
/* 55 E> */ B(ShiftRight), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 55 E> */ B(ShiftRight), R(1), U8(2),
/* 61 S> */ B(Return),
]
constant pool: [
......@@ -230,13 +442,35 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(Nop),
/* 55 E> */ B(ShiftRightLogicalSmi), I8(3), U8(2),
/* 62 S> */ B(Return),
]
constant pool: [
]
handlers: [
]
---
snippet: "
var x = 10; return 3 >>> x;
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(10),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(3),
/* 55 E> */ B(ShiftRightLogical), R(0), U8(2),
B(Star), R(1),
B(Ldar), R(0),
/* 55 E> */ B(ShiftRightLogical), R(1), U8(2),
/* 62 S> */ B(Return),
]
constant pool: [
......
......@@ -479,7 +479,7 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 62
bytecode array length: 63
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(1),
......@@ -491,9 +491,10 @@ bytecodes: [
B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2),
B(TestEqualStrict), R(3), U8(6),
B(JumpIfTrue), U8(34),
B(Jump), U8(36),
/* 79 E> */ B(AddSmi), I8(1), R(0), U8(2),
B(JumpIfTrue), U8(35),
B(Jump), U8(37),
B(Ldar), R(0),
/* 79 E> */ B(AddSmi), I8(1), U8(2),
B(Star), R(1),
/* 70 S> */ B(LdaSmi), I8(2),
B(TestEqualStrict), R(1), U8(3),
......
......@@ -24,8 +24,8 @@ bytecodes: [
/* 54 E> */ B(TestEqual), R(0), U8(2),
B(JumpIfTrue), U8(13),
/* 45 E> */ B(StackCheck),
/* 65 S> */ B(LdaSmi), I8(10),
/* 71 E> */ B(Add), R(0), U8(3),
/* 65 S> */ B(Ldar), R(0),
/* 71 E> */ B(AddSmi), I8(10), U8(3),
B(Star), R(0),
B(JumpLoop), U8(15), I8(0),
/* 79 S> */ B(Ldar), R(0),
......@@ -74,13 +74,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 12
bytecode array length: 11
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(101),
B(Star), R(0),
/* 47 S> */ B(LdaSmi), I8(3),
/* 61 E> */ B(Mul), R(0), U8(2),
/* 47 S> */ B(Nop),
/* 61 E> */ B(MulSmi), I8(3), U8(2),
B(LdaUndefined),
/* 67 S> */ B(Return),
]
......@@ -95,17 +95,16 @@ snippet: "
var y = void (x * x - 1);
return y;
"
frame size: 3
frame size: 2
parameter count: 1
bytecode array length: 22
bytecode array length: 19
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(Wide), B(LdaSmi), I16(1234),
B(Star), R(0),
/* 56 S> */ B(Nop),
/* 64 E> */ B(Mul), R(0), U8(2),
B(Star), R(2),
/* 68 E> */ B(SubSmi), I8(1), R(2), U8(3),
/* 68 E> */ B(SubSmi), I8(1), U8(3),
B(LdaUndefined),
B(Star), R(1),
/* 74 S> */ B(Nop),
......@@ -123,13 +122,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(13),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(-1),
/* 53 E> */ B(BitwiseXor), R(0), U8(2),
/* 46 S> */ B(Nop),
/* 53 E> */ B(BitwiseXorSmi), I8(-1), U8(2),
/* 57 S> */ B(Return),
]
constant pool: [
......@@ -144,13 +143,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(13),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(1),
/* 53 E> */ B(Mul), R(0), U8(2),
/* 46 S> */ B(Nop),
/* 53 E> */ B(MulSmi), I8(1), U8(2),
/* 57 S> */ B(Return),
]
constant pool: [
......@@ -165,13 +164,13 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(13),
B(Star), R(0),
/* 46 S> */ B(LdaSmi), I8(-1),
/* 53 E> */ B(Mul), R(0), U8(2),
/* 46 S> */ B(Nop),
/* 53 E> */ B(MulSmi), I8(-1), U8(2),
/* 57 S> */ B(Return),
]
constant pool: [
......
......@@ -190,26 +190,48 @@ TEST(PrimitiveExpressions) {
"var x = 0; return x + 3;\n",
"var x = 0; return 3 + x;\n",
"var x = 0; return x - 3;\n",
"var x = 0; return 3 - x;\n",
"var x = 4; return x * 3;\n",
"var x = 4; return 3 * x;\n",
"var x = 4; return x / 3;\n",
"var x = 4; return 3 / x;\n",
"var x = 4; return x % 3;\n",
"var x = 4; return 3 % x;\n",
"var x = 1; return x | 2;\n",
"var x = 1; return 2 | x;\n",
"var x = 1; return x ^ 2;\n",
"var x = 1; return 2 ^ x;\n",
"var x = 1; return x & 2;\n",
"var x = 1; return 2 & x;\n",
"var x = 10; return x << 3;\n",
"var x = 10; return 3 << x;\n",
"var x = 10; return x >> 3;\n",
"var x = 10; return 3 >> x;\n",
"var x = 10; return x >>> 3;\n",
"var x = 10; return 3 >>> x;\n",
"var x = 0; return (x, 3);\n",
};
......
......@@ -177,19 +177,18 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.BinaryOperation(Token::Value::SAR, reg, 10)
.BinaryOperation(Token::Value::SHR, reg, 11);
// Emit peephole optimizations of LdaSmi followed by binary operation.
builder.LoadLiteral(Smi::FromInt(1))
.BinaryOperation(Token::Value::ADD, reg, 1)
.LoadLiteral(Smi::FromInt(2))
.BinaryOperation(Token::Value::SUB, reg, 2)
.LoadLiteral(Smi::FromInt(3))
.BinaryOperation(Token::Value::BIT_AND, reg, 3)
.LoadLiteral(Smi::FromInt(4))
.BinaryOperation(Token::Value::BIT_OR, reg, 4)
.LoadLiteral(Smi::FromInt(5))
.BinaryOperation(Token::Value::SHL, reg, 5)
.LoadLiteral(Smi::FromInt(6))
.BinaryOperation(Token::Value::SAR, reg, 6);
// Emit Smi binary operations.
builder.BinaryOperationSmiLiteral(Token::Value::ADD, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SUB, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::MUL, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::DIV, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::MOD, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::BIT_OR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::BIT_XOR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::BIT_AND, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SHL, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SAR, Smi::FromInt(42), 2)
.BinaryOperationSmiLiteral(Token::Value::SHR, Smi::FromInt(42), 2);
// Emit count operatior invocations
builder.CountOperation(Token::Value::ADD, 1)
......@@ -421,12 +420,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
if (!FLAG_ignition_peephole) {
// Insert entries for bytecodes only emitted by peephole optimizer.
scorecard[Bytecodes::ToByte(Bytecode::kAddSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kSubSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kBitwiseAndSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kBitwiseOrSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kShiftLeftSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kShiftRightSmi)] = 1;
}
if (!FLAG_type_profile) {
......
......@@ -245,88 +245,6 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
// Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaSmiWithBinaryOp) {
Bytecode operator_replacement_pairs[][2] = {
{Bytecode::kAdd, Bytecode::kAddSmi},
{Bytecode::kSub, Bytecode::kSubSmi},
{Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi},
{Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi},
{Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi},
{Bytecode::kShiftRight, Bytecode::kShiftRightSmi}};
for (auto operator_replacement : operator_replacement_pairs) {
uint32_t imm_operand = 17;
BytecodeSourceInfo source_info(3, true);
BytecodeNode first(Bytecode::kLdaSmi, imm_operand, source_info);
uint32_t reg_operand = Register(0).ToOperand();
uint32_t idx_operand = 1;
BytecodeNode second(operator_replacement[0], reg_operand, idx_operand);
optimizer()->Write(&first);
optimizer()->Write(&second);
Flush();
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), operator_replacement[1]);
CHECK_EQ(last_written().operand_count(), 3);
CHECK_EQ(last_written().operand(0), imm_operand);
CHECK_EQ(last_written().operand(1), reg_operand);
CHECK_EQ(last_written().operand(2), idx_operand);
CHECK_EQ(last_written().source_info(), source_info);
Reset();
}
}
TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) {
Bytecode operator_replacement_pairs[][2] = {
{Bytecode::kAdd, Bytecode::kAddSmi},
{Bytecode::kSub, Bytecode::kSubSmi},
{Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi},
{Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi},
{Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi},
{Bytecode::kShiftRight, Bytecode::kShiftRightSmi}};
for (auto operator_replacement : operator_replacement_pairs) {
uint32_t imm_operand = 17;
BytecodeSourceInfo source_info(3, true);
BytecodeNode first(Bytecode::kLdaSmi, imm_operand, source_info);
uint32_t reg_operand = Register(0).ToOperand();
source_info.MakeStatementPosition(4);
BytecodeNode second(operator_replacement[0], reg_operand, 1, source_info);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(last_written(), first);
Flush();
CHECK_EQ(last_written(), second);
Reset();
}
}
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaZeroWithBinaryOp) {
Bytecode operator_replacement_pairs[][2] = {
{Bytecode::kAdd, Bytecode::kAddSmi},
{Bytecode::kSub, Bytecode::kSubSmi},
{Bytecode::kBitwiseAnd, Bytecode::kBitwiseAndSmi},
{Bytecode::kBitwiseOr, Bytecode::kBitwiseOrSmi},
{Bytecode::kShiftLeft, Bytecode::kShiftLeftSmi},
{Bytecode::kShiftRight, Bytecode::kShiftRightSmi}};
for (auto operator_replacement : operator_replacement_pairs) {
BytecodeNode first(Bytecode::kLdaZero);
uint32_t reg_operand = Register(0).ToOperand();
uint32_t idx_operand = 1;
BytecodeNode second(operator_replacement[0], reg_operand, idx_operand);
optimizer()->Write(&first);
optimizer()->Write(&second);
Flush();
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), operator_replacement[1]);
CHECK_EQ(last_written().operand_count(), 3);
CHECK_EQ(last_written().operand(0), 0u);
CHECK_EQ(last_written().operand(1), reg_operand);
CHECK_EQ(last_written().operand(2), idx_operand);
Reset();
}
}
} // namespace interpreter
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment