Commit 7bedd111 authored by Ross McIlroy's avatar Ross McIlroy Committed by Commit Bot

[Interpreter] Move ToBoolean elision in BytecodeGenerator.

Move the ToBoolean elision in the BytecodeGenerator instead of the
peephole optimizer. Adds a TypeHint mechanism to the ExpressionResult
to enable passing of type hints through the ast visitor.

BUG=v8:6194

Change-Id: Ic55506ba11b213f7459250004d3f18cab04ee9b3
Reviewed-on: https://chromium-review.googlesource.com/467208
Commit-Queue: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44415}
parent 5e8eb624
...@@ -338,7 +338,6 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { ...@@ -338,7 +338,6 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
typedef interpreter::Bytecodes Bytecodes; typedef interpreter::Bytecodes Bytecodes;
if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true; if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
if (Bytecodes::IsCallOrConstruct(bytecode)) return true; if (Bytecodes::IsCallOrConstruct(bytecode)) return true;
if (Bytecodes::WritesBooleanToAccumulator(bytecode)) return true;
if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true; if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true;
if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true; if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true;
switch (bytecode) { switch (bytecode) {
...@@ -385,6 +384,20 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { ...@@ -385,6 +384,20 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
case Bytecode::kCreateClosure: case Bytecode::kCreateClosure:
case Bytecode::kCreateUnmappedArguments: case Bytecode::kCreateUnmappedArguments:
case Bytecode::kCreateRestParameter: case Bytecode::kCreateRestParameter:
// Comparisons.
case Bytecode::kTestEqual:
case Bytecode::kTestEqualStrict:
case Bytecode::kTestLessThan:
case Bytecode::kTestLessThanOrEqual:
case Bytecode::kTestGreaterThan:
case Bytecode::kTestGreaterThanOrEqual:
case Bytecode::kTestInstanceOf:
case Bytecode::kTestIn:
case Bytecode::kTestEqualStrictNoFeedback:
case Bytecode::kTestUndetectable:
case Bytecode::kTestTypeOf:
case Bytecode::kTestUndefined:
case Bytecode::kTestNull:
// Conversions. // Conversions.
case Bytecode::kToObject: case Bytecode::kToObject:
case Bytecode::kToNumber: case Bytecode::kToNumber:
......
...@@ -328,8 +328,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op, ...@@ -328,8 +328,13 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() { BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot(ToBooleanMode mode) {
OutputToBooleanLogicalNot(); if (mode == ToBooleanMode::kAlreadyBoolean) {
OutputLogicalNot();
} else {
DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
OutputToBooleanLogicalNot();
}
return *this; return *this;
} }
...@@ -895,17 +900,27 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { ...@@ -895,17 +900,27 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) { BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(ToBooleanMode mode,
// The peephole optimizer attempts to simplify JumpIfToBooleanTrue BytecodeLabel* label) {
// to JumpIfTrue.
DCHECK(!label->is_bound()); DCHECK(!label->is_bound());
OutputJumpIfToBooleanTrue(label, 0); if (mode == ToBooleanMode::kAlreadyBoolean) {
OutputJumpIfTrue(label, 0);
} else {
DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
OutputJumpIfToBooleanTrue(label, 0);
}
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) { BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(ToBooleanMode mode,
BytecodeLabel* label) {
DCHECK(!label->is_bound()); DCHECK(!label->is_bound());
OutputJumpIfToBooleanFalse(label, 0); if (mode == ToBooleanMode::kAlreadyBoolean) {
OutputJumpIfFalse(label, 0);
} else {
DCHECK_EQ(mode, ToBooleanMode::kConvertToBoolean);
OutputJumpIfToBooleanFalse(label, 0);
}
return *this; return *this;
} }
...@@ -941,7 +956,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label, ...@@ -941,7 +956,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNil(BytecodeLabel* label,
NilValue nil) { NilValue nil) {
if (op == Token::EQ) { if (op == Token::EQ) {
// TODO(rmcilroy): Implement JumpIfUndetectable. // TODO(rmcilroy): Implement JumpIfUndetectable.
return CompareUndetectable().JumpIfTrue(label); return CompareUndetectable().JumpIfTrue(ToBooleanMode::kAlreadyBoolean,
label);
} else { } else {
DCHECK_EQ(Token::EQ_STRICT, op); DCHECK_EQ(Token::EQ_STRICT, op);
if (nil == kUndefinedValue) { if (nil == kUndefinedValue) {
...@@ -958,7 +974,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label, ...@@ -958,7 +974,8 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNotNil(BytecodeLabel* label,
NilValue nil) { NilValue nil) {
if (op == Token::EQ) { if (op == Token::EQ) {
// TODO(rmcilroy): Implement JumpIfUndetectable. // TODO(rmcilroy): Implement JumpIfUndetectable.
return CompareUndetectable().JumpIfFalse(label); return CompareUndetectable().JumpIfFalse(ToBooleanMode::kAlreadyBoolean,
label);
} else { } else {
DCHECK_EQ(Token::EQ_STRICT, op); DCHECK_EQ(Token::EQ_STRICT, op);
if (nil == kUndefinedValue) { if (nil == kUndefinedValue) {
...@@ -1328,6 +1345,18 @@ uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand( ...@@ -1328,6 +1345,18 @@ uint32_t BytecodeArrayBuilder::GetOutputRegisterListOperand(
return static_cast<uint32_t>(reg_list.first_register().ToOperand()); return static_cast<uint32_t>(reg_list.first_register().ToOperand());
} }
std::ostream& operator<<(std::ostream& os,
const BytecodeArrayBuilder::ToBooleanMode& mode) {
switch (mode) {
case BytecodeArrayBuilder::ToBooleanMode::kAlreadyBoolean:
return os << "AlreadyBoolean";
case BytecodeArrayBuilder::ToBooleanMode::kConvertToBoolean:
return os << "ConvertToBoolean";
}
UNREACHABLE();
return os;
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -297,8 +297,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -297,8 +297,13 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Type feedback will be recorded in the |feedback_slot| // Type feedback will be recorded in the |feedback_slot|
BytecodeArrayBuilder& CountOperation(Token::Value op, int feedback_slot); BytecodeArrayBuilder& CountOperation(Token::Value op, int feedback_slot);
enum class ToBooleanMode {
kConvertToBoolean, // Perform ToBoolean conversion on accumulator.
kAlreadyBoolean, // Accumulator is already a Boolean.
};
// Unary Operators. // Unary Operators.
BytecodeArrayBuilder& LogicalNot(); BytecodeArrayBuilder& LogicalNot(ToBooleanMode mode);
BytecodeArrayBuilder& TypeOf(); BytecodeArrayBuilder& TypeOf();
// Expects a heap object in the accumulator. Returns its super constructor in // Expects a heap object in the accumulator. Returns its super constructor in
...@@ -331,8 +336,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -331,8 +336,10 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label); BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label);
BytecodeArrayBuilder& Jump(BytecodeLabel* label); BytecodeArrayBuilder& Jump(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfTrue(BytecodeLabel* label); BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
BytecodeArrayBuilder& JumpIfFalse(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfNotHole(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfJSReceiver(BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label); BytecodeArrayBuilder& JumpIfNull(BytecodeLabel* label);
...@@ -343,7 +350,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -343,7 +350,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
NilValue nil); NilValue nil);
BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op, BytecodeArrayBuilder& JumpIfNotNil(BytecodeLabel* label, Token::Value op,
NilValue nil); NilValue nil);
BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth);
BytecodeArrayBuilder& StackCheck(int position); BytecodeArrayBuilder& StackCheck(int position);
...@@ -505,6 +511,9 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final ...@@ -505,6 +511,9 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder); DISALLOW_COPY_AND_ASSIGN(BytecodeArrayBuilder);
}; };
V8_EXPORT_PRIVATE std::ostream& operator<<(
std::ostream& os, const BytecodeArrayBuilder::ToBooleanMode& mode);
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -190,7 +190,7 @@ class BytecodeGenerator::ControlScope::DeferredCommands final { ...@@ -190,7 +190,7 @@ class BytecodeGenerator::ControlScope::DeferredCommands final {
Entry& entry = deferred_[i]; Entry& entry = deferred_[i];
builder()->LoadLiteral(Smi::FromInt(entry.token)); builder()->LoadLiteral(Smi::FromInt(entry.token));
builder()->CompareOperation(Token::EQ_STRICT, token_register_); builder()->CompareOperation(Token::EQ_STRICT, token_register_);
dispatch.Case(static_cast<int>(i)); dispatch.Case(ToBooleanMode::kAlreadyBoolean, static_cast<int>(i));
} }
dispatch.DefaultAt(static_cast<int>(deferred_.size())); dispatch.DefaultAt(static_cast<int>(deferred_.size()));
for (size_t i = 0; i < deferred_.size(); ++i) { for (size_t i = 0; i < deferred_.size(); ++i) {
...@@ -411,9 +411,10 @@ class BytecodeGenerator::ExpressionResultScope { ...@@ -411,9 +411,10 @@ class BytecodeGenerator::ExpressionResultScope {
public: public:
ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
: generator_(generator), : generator_(generator),
kind_(kind),
outer_(generator->execution_result()), outer_(generator->execution_result()),
allocator_(generator) { allocator_(generator),
kind_(kind),
type_hint_(TypeHint::kAny) {
generator_->set_execution_result(this); generator_->set_execution_result(this);
} }
...@@ -430,11 +431,20 @@ class BytecodeGenerator::ExpressionResultScope { ...@@ -430,11 +431,20 @@ class BytecodeGenerator::ExpressionResultScope {
return reinterpret_cast<TestResultScope*>(this); return reinterpret_cast<TestResultScope*>(this);
} }
// Specify expression always returns a Boolean result value.
void SetResultIsBoolean() {
DCHECK(type_hint_ == TypeHint::kAny);
type_hint_ = TypeHint::kBoolean;
}
TypeHint type_hint() const { return type_hint_; }
private: private:
BytecodeGenerator* generator_; BytecodeGenerator* generator_;
Expression::Context kind_;
ExpressionResultScope* outer_; ExpressionResultScope* outer_;
RegisterAllocationScope allocator_; RegisterAllocationScope allocator_;
Expression::Context kind_;
TypeHint type_hint_;
DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
}; };
...@@ -473,8 +483,7 @@ class BytecodeGenerator::TestResultScope final : public ExpressionResultScope { ...@@ -473,8 +483,7 @@ class BytecodeGenerator::TestResultScope final : public ExpressionResultScope {
void SetResultConsumedByTest() { void SetResultConsumedByTest() {
result_consumed_by_test_ = true; result_consumed_by_test_ = true;
} }
bool result_consumed_by_test() { return result_consumed_by_test_; }
bool ResultConsumedByTest() { return result_consumed_by_test_; }
BytecodeLabel* NewThenLabel() { return then_labels_->New(); } BytecodeLabel* NewThenLabel() { return then_labels_->New(); }
BytecodeLabel* NewElseLabel() { return else_labels_->New(); } BytecodeLabel* NewElseLabel() { return else_labels_->New(); }
...@@ -794,7 +803,7 @@ void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index, ...@@ -794,7 +803,7 @@ void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
builder() builder()
->LoadLiteral(Smi::FromInt(static_cast<int>(i))) ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
.CompareOperation(Token::Value::EQ_STRICT, index) .CompareOperation(Token::Value::EQ_STRICT, index)
.JumpIfTrue(&(targets[i])); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &(targets[i]));
} }
BuildAbort(BailoutReason::kInvalidJumpTableIndex); BuildAbort(BailoutReason::kInvalidJumpTableIndex);
} }
...@@ -828,7 +837,7 @@ void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt, ...@@ -828,7 +837,7 @@ void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
builder() builder()
->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)) ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
.CompareOperation(Token::Value::EQ_STRICT, generator_state_) .CompareOperation(Token::Value::EQ_STRICT, generator_state_)
.JumpIfTrue(&not_resuming); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &not_resuming);
BuildIndexedJump(generator_state_, first_yield, stmt->suspend_count(), BuildIndexedJump(generator_state_, first_yield, stmt->suspend_count(),
generator_resume_points_); generator_resume_points_);
builder()->Bind(&not_resuming); builder()->Bind(&not_resuming);
...@@ -1142,7 +1151,7 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { ...@@ -1142,7 +1151,7 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
builder()->CompareOperation( builder()->CompareOperation(
Token::Value::EQ_STRICT, tag, Token::Value::EQ_STRICT, tag,
feedback_index(clause->CompareOperationFeedbackSlot())); feedback_index(clause->CompareOperationFeedbackSlot()));
switch_builder.Case(i); switch_builder.Case(ToBooleanMode::kAlreadyBoolean, i);
} }
if (default_index >= 0) { if (default_index >= 0) {
...@@ -1344,7 +1353,7 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { ...@@ -1344,7 +1353,7 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->each()); builder()->SetExpressionAsStatementPosition(stmt->each());
builder()->ForInContinue(index, cache_length); builder()->ForInContinue(index, cache_length);
loop_builder.BreakIfFalse(); loop_builder.BreakIfFalse(ToBooleanMode::kAlreadyBoolean);
FeedbackSlot slot = stmt->ForInFeedbackSlot(); FeedbackSlot slot = stmt->ForInFeedbackSlot();
builder()->ForInNext(receiver, index, triple.Truncate(2), builder()->ForInNext(receiver, index, triple.Truncate(2),
feedback_index(slot)); feedback_index(slot));
...@@ -1368,8 +1377,8 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { ...@@ -1368,8 +1377,8 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->next_result()); builder()->SetExpressionAsStatementPosition(stmt->next_result());
VisitForEffect(stmt->next_result()); VisitForEffect(stmt->next_result());
VisitForAccumulatorValue(stmt->result_done()); TypeHint type_hint = VisitForAccumulatorValue(stmt->result_done());
loop_builder.BreakIfTrue(); loop_builder.BreakIfTrue(ToBooleanModeFromTypeHint(type_hint));
VisitForEffect(stmt->assign_each()); VisitForEffect(stmt->assign_each());
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
...@@ -1562,7 +1571,7 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr, ...@@ -1562,7 +1571,7 @@ void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
builder() builder()
->LoadLiteral(ast_string_constants()->prototype_string()) ->LoadLiteral(ast_string_constants()->prototype_string())
.CompareOperation(Token::Value::EQ_STRICT, key) .CompareOperation(Token::Value::EQ_STRICT, key)
.JumpIfFalse(&done) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done)
.CallRuntime(Runtime::kThrowStaticPrototypeError) .CallRuntime(Runtime::kThrowStaticPrototypeError)
.Bind(&done); .Bind(&done);
} }
...@@ -1662,6 +1671,9 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) { ...@@ -1662,6 +1671,9 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
if (!execution_result()->IsEffect()) { if (!execution_result()->IsEffect()) {
const AstValue* raw_value = expr->raw_value(); const AstValue* raw_value = expr->raw_value();
builder()->LoadLiteral(raw_value); builder()->LoadLiteral(raw_value);
if (raw_value->IsTrue() || raw_value->IsFalse()) {
execution_result()->SetResultIsBoolean();
}
} }
} }
...@@ -2450,10 +2462,10 @@ void BytecodeGenerator::VisitSuspend(Suspend* expr) { ...@@ -2450,10 +2462,10 @@ void BytecodeGenerator::VisitSuspend(Suspend* expr) {
builder() builder()
->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext)) ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
.CompareOperation(Token::EQ_STRICT, resume_mode) .CompareOperation(Token::EQ_STRICT, resume_mode)
.JumpIfTrue(&resume_with_next) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_with_next)
.LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow)) .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
.CompareOperation(Token::EQ_STRICT, resume_mode) .CompareOperation(Token::EQ_STRICT, resume_mode)
.JumpIfTrue(&resume_with_throw) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &resume_with_throw)
.Jump(&resume_with_return); .Jump(&resume_with_return);
builder()->Bind(&resume_with_return); builder()->Bind(&resume_with_return);
...@@ -2814,9 +2826,11 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) { ...@@ -2814,9 +2826,11 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
test_result->inverted_fallthrough()); test_result->inverted_fallthrough());
test_result->SetResultConsumedByTest(); test_result->SetResultConsumedByTest();
} else { } else {
VisitForAccumulatorValue(expr->expression()); TypeHint type_hint = VisitForAccumulatorValue(expr->expression());
builder()->LogicalNot(); builder()->LogicalNot(ToBooleanModeFromTypeHint(type_hint));
} }
// Always returns a boolean value.
execution_result()->SetResultIsBoolean();
} }
void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
...@@ -3095,6 +3109,8 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { ...@@ -3095,6 +3109,8 @@ void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
builder()->CompareOperation(expr->op(), lhs, feedback_index(slot)); builder()->CompareOperation(expr->op(), lhs, feedback_index(slot));
} }
} }
// Always returns a boolean value.
execution_result()->SetResultIsBoolean();
} }
void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
...@@ -3229,8 +3245,8 @@ void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { ...@@ -3229,8 +3245,8 @@ void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
VisitForAccumulatorValue(right); VisitForAccumulatorValue(right);
} else { } else {
BytecodeLabel end_label; BytecodeLabel end_label;
VisitForAccumulatorValue(left); TypeHint type_hint = VisitForAccumulatorValue(left);
builder()->JumpIfTrue(&end_label); builder()->JumpIfTrue(ToBooleanModeFromTypeHint(type_hint), &end_label);
VisitForAccumulatorValue(right); VisitForAccumulatorValue(right);
builder()->Bind(&end_label); builder()->Bind(&end_label);
} }
...@@ -3264,8 +3280,8 @@ void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { ...@@ -3264,8 +3280,8 @@ void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
VisitForAccumulatorValue(right); VisitForAccumulatorValue(right);
} else { } else {
BytecodeLabel end_label; BytecodeLabel end_label;
VisitForAccumulatorValue(left); TypeHint type_hint = VisitForAccumulatorValue(left);
builder()->JumpIfFalse(&end_label); builder()->JumpIfFalse(ToBooleanModeFromTypeHint(type_hint), &end_label);
VisitForAccumulatorValue(right); VisitForAccumulatorValue(right);
builder()->Bind(&end_label); builder()->Bind(&end_label);
} }
...@@ -3485,9 +3501,11 @@ void BytecodeGenerator::VisitFunctionClosureForContext() { ...@@ -3485,9 +3501,11 @@ void BytecodeGenerator::VisitFunctionClosureForContext() {
} }
// Visits the expression |expr| and places the result in the accumulator. // Visits the expression |expr| and places the result in the accumulator.
void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { BytecodeGenerator::TypeHint BytecodeGenerator::VisitForAccumulatorValue(
Expression* expr) {
ValueResultScope accumulator_scope(this); ValueResultScope accumulator_scope(this);
Visit(expr); Visit(expr);
return accumulator_scope.type_hint();
} }
void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
...@@ -3551,24 +3569,27 @@ void BytecodeGenerator::VisitForTest(Expression* expr, ...@@ -3551,24 +3569,27 @@ void BytecodeGenerator::VisitForTest(Expression* expr,
BytecodeLabels* else_labels, BytecodeLabels* else_labels,
TestFallthrough fallthrough) { TestFallthrough fallthrough) {
bool result_consumed; bool result_consumed;
TypeHint type_hint;
{ {
// To make sure that all temporary registers are returned before generating // To make sure that all temporary registers are returned before generating
// jumps below, we ensure that the result scope is deleted before doing so. // jumps below, we ensure that the result scope is deleted before doing so.
// Dead registers might be materialized otherwise. // Dead registers might be materialized otherwise.
TestResultScope test_result(this, then_labels, else_labels, fallthrough); TestResultScope test_result(this, then_labels, else_labels, fallthrough);
Visit(expr); Visit(expr);
result_consumed = test_result.ResultConsumedByTest(); result_consumed = test_result.result_consumed_by_test();
type_hint = test_result.type_hint();
} }
if (!result_consumed) { if (!result_consumed) {
ToBooleanMode mode(ToBooleanModeFromTypeHint(type_hint));
switch (fallthrough) { switch (fallthrough) {
case TestFallthrough::kThen: case TestFallthrough::kThen:
builder()->JumpIfFalse(else_labels->New()); builder()->JumpIfFalse(mode, else_labels->New());
break; break;
case TestFallthrough::kElse: case TestFallthrough::kElse:
builder()->JumpIfTrue(then_labels->New()); builder()->JumpIfTrue(mode, then_labels->New());
break; break;
case TestFallthrough::kNone: case TestFallthrough::kNone:
builder()->JumpIfTrue(then_labels->New()); builder()->JumpIfTrue(mode, then_labels->New());
builder()->Jump(else_labels->New()); builder()->Jump(else_labels->New());
} }
} }
...@@ -3581,6 +3602,12 @@ void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { ...@@ -3581,6 +3602,12 @@ void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
Visit(stmt); Visit(stmt);
} }
BytecodeArrayBuilder::ToBooleanMode
BytecodeGenerator::ToBooleanModeFromTypeHint(TypeHint type_hint) {
return type_hint == TypeHint::kBoolean ? ToBooleanMode::kAlreadyBoolean
: ToBooleanMode::kConvertToBoolean;
}
LanguageMode BytecodeGenerator::language_mode() const { LanguageMode BytecodeGenerator::language_mode() const {
return current_scope()->language_mode(); return current_scope()->language_mode();
} }
......
...@@ -53,7 +53,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -53,7 +53,10 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
class TestResultScope; class TestResultScope;
class ValueResultScope; class ValueResultScope;
using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
enum class TestFallthrough { kThen, kElse, kNone }; enum class TestFallthrough { kThen, kElse, kNone };
enum class TypeHint { kAny, kBoolean };
void GenerateBytecodeBody(); void GenerateBytecodeBody();
void AllocateDeferredConstants(Isolate* isolate); void AllocateDeferredConstants(Isolate* isolate);
...@@ -161,8 +164,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -161,8 +164,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list); void BuildPushUndefinedIntoRegisterList(RegisterList* reg_list);
// Visitors for obtaining expression result in the accumulator, in a // Visitors for obtaining expression result in the accumulator, in a
// register, or just getting the effect. // register, or just getting the effect. Some visitors return a TypeHint which
void VisitForAccumulatorValue(Expression* expr); // specifies the type of the result of the visited expression.
TypeHint VisitForAccumulatorValue(Expression* expr);
void VisitForAccumulatorValueOrTheHole(Expression* expr); void VisitForAccumulatorValueOrTheHole(Expression* expr);
MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr); MUST_USE_RESULT Register VisitForRegisterValue(Expression* expr);
void VisitForRegisterValue(Expression* expr, Register destination); void VisitForRegisterValue(Expression* expr, Register destination);
...@@ -176,6 +180,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -176,6 +180,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
inline Runtime::FunctionId StoreToSuperRuntimeId(); inline Runtime::FunctionId StoreToSuperRuntimeId();
inline Runtime::FunctionId StoreKeyedToSuperRuntimeId(); inline Runtime::FunctionId StoreKeyedToSuperRuntimeId();
ToBooleanMode ToBooleanModeFromTypeHint(TypeHint type_hint);
inline BytecodeArrayBuilder* builder() const { return builder_; } inline BytecodeArrayBuilder* builder() const { return builder_; }
inline Zone* zone() const { return zone_; } inline Zone* zone() const { return zone_; }
inline DeclarationScope* closure_scope() const { return closure_scope_; } inline DeclarationScope* closure_scope() const { return closure_scope_; }
......
...@@ -269,16 +269,6 @@ void BytecodePeepholeOptimizer::UpdateLastJumpAction( ...@@ -269,16 +269,6 @@ void BytecodePeepholeOptimizer::UpdateLastJumpAction(
DCHECK(Bytecodes::IsJump(node->bytecode())); DCHECK(Bytecodes::IsJump(node->bytecode()));
} }
void BytecodePeepholeOptimizer::ChangeJumpBytecodeAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid());
DCHECK(Bytecodes::IsJump(node->bytecode()));
next_stage()->Write(last());
InvalidateLast();
node->replace_bytecode(action_data->bytecode);
}
void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction(
BytecodeNode* const node, const PeepholeActionAndData* action_data) { BytecodeNode* const node, const PeepholeActionAndData* action_data) {
DCHECK(LastIsValid()); DCHECK(LastIsValid());
......
...@@ -25,7 +25,6 @@ namespace interpreter { ...@@ -25,7 +25,6 @@ namespace interpreter {
#define PEEPHOLE_JUMP_ACTION_LIST(V) \ #define PEEPHOLE_JUMP_ACTION_LIST(V) \
V(DefaultJumpAction) \ V(DefaultJumpAction) \
V(UpdateLastJumpAction) \ V(UpdateLastJumpAction) \
V(ChangeJumpBytecodeAction) \
V(ElideLastBeforeJumpAction) V(ElideLastBeforeJumpAction)
#define PEEPHOLE_ACTION_LIST(V) \ #define PEEPHOLE_ACTION_LIST(V) \
......
...@@ -500,33 +500,6 @@ class V8_EXPORT_PRIVATE Bytecodes final { ...@@ -500,33 +500,6 @@ class V8_EXPORT_PRIVATE Bytecodes final {
return BytecodeOperands::WritesAccumulator(GetAccumulatorUse(bytecode)); return BytecodeOperands::WritesAccumulator(GetAccumulatorUse(bytecode));
} }
// Return true if |bytecode| writes the accumulator with a boolean value.
static bool WritesBooleanToAccumulator(Bytecode bytecode) {
switch (bytecode) {
case Bytecode::kLdaTrue:
case Bytecode::kLdaFalse:
case Bytecode::kToBooleanLogicalNot:
case Bytecode::kLogicalNot:
case Bytecode::kTestEqual:
case Bytecode::kTestEqualStrict:
case Bytecode::kTestLessThan:
case Bytecode::kTestLessThanOrEqual:
case Bytecode::kTestGreaterThan:
case Bytecode::kTestGreaterThanOrEqual:
case Bytecode::kTestInstanceOf:
case Bytecode::kTestIn:
case Bytecode::kTestEqualStrictNoFeedback:
case Bytecode::kTestUndetectable:
case Bytecode::kTestTypeOf:
case Bytecode::kForInContinue:
case Bytecode::kTestUndefined:
case Bytecode::kTestNull:
return true;
default:
return false;
}
}
// Return true if |bytecode| is an accumulator load without effects, // Return true if |bytecode| is an accumulator load without effects,
// e.g. LdaConstant, LdaTrue, Ldar. // e.g. LdaConstant, LdaTrue, Ldar.
static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
......
...@@ -22,12 +22,14 @@ void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) { ...@@ -22,12 +22,14 @@ void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
builder()->Jump(sites->New()); builder()->Jump(sites->New());
} }
void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) { void BreakableControlFlowBuilder::EmitJumpIfTrue(
builder()->JumpIfTrue(sites->New()); BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
builder()->JumpIfTrue(mode, sites->New());
} }
void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) { void BreakableControlFlowBuilder::EmitJumpIfFalse(
builder()->JumpIfFalse(sites->New()); BytecodeArrayBuilder::ToBooleanMode mode, BytecodeLabels* sites) {
builder()->JumpIfFalse(mode, sites->New());
} }
void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) { void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
...@@ -38,7 +40,6 @@ void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) { ...@@ -38,7 +40,6 @@ void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
builder()->JumpIfNull(sites->New()); builder()->JumpIfNull(sites->New());
} }
void BlockBuilder::EndBlock() { void BlockBuilder::EndBlock() {
builder()->Bind(&block_end_); builder()->Bind(&block_end_);
BindBreakTarget(); BindBreakTarget();
......
...@@ -44,8 +44,12 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder ...@@ -44,8 +44,12 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder
// Inserts a jump to an unbound label that is patched when the corresponding // Inserts a jump to an unbound label that is patched when the corresponding
// BindBreakTarget is called. // BindBreakTarget is called.
void Break() { EmitJump(&break_labels_); } void Break() { EmitJump(&break_labels_); }
void BreakIfTrue() { EmitJumpIfTrue(&break_labels_); } void BreakIfTrue(BytecodeArrayBuilder::ToBooleanMode mode) {
void BreakIfFalse() { EmitJumpIfFalse(&break_labels_); } EmitJumpIfTrue(mode, &break_labels_);
}
void BreakIfFalse(BytecodeArrayBuilder::ToBooleanMode mode) {
EmitJumpIfFalse(mode, &break_labels_);
}
void BreakIfUndefined() { EmitJumpIfUndefined(&break_labels_); } void BreakIfUndefined() { EmitJumpIfUndefined(&break_labels_); }
void BreakIfNull() { EmitJumpIfNull(&break_labels_); } void BreakIfNull() { EmitJumpIfNull(&break_labels_); }
...@@ -53,8 +57,10 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder ...@@ -53,8 +57,10 @@ class V8_EXPORT_PRIVATE BreakableControlFlowBuilder
protected: protected:
void EmitJump(BytecodeLabels* labels); void EmitJump(BytecodeLabels* labels);
void EmitJumpIfTrue(BytecodeLabels* labels); void EmitJumpIfTrue(BytecodeArrayBuilder::ToBooleanMode mode,
void EmitJumpIfFalse(BytecodeLabels* labels); BytecodeLabels* labels);
void EmitJumpIfFalse(BytecodeArrayBuilder::ToBooleanMode mode,
BytecodeLabels* labels);
void EmitJumpIfUndefined(BytecodeLabels* labels); void EmitJumpIfUndefined(BytecodeLabels* labels);
void EmitJumpIfNull(BytecodeLabels* labels); void EmitJumpIfNull(BytecodeLabels* labels);
...@@ -96,7 +102,6 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder { ...@@ -96,7 +102,6 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
// Inserts a jump to an unbound label that is patched when BindContinueTarget // Inserts a jump to an unbound label that is patched when BindContinueTarget
// is called. // is called.
void Continue() { EmitJump(&continue_labels_); } void Continue() { EmitJump(&continue_labels_); }
void ContinueIfTrue() { EmitJumpIfTrue(&continue_labels_); }
void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); } void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); }
void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); } void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
...@@ -126,9 +131,11 @@ class V8_EXPORT_PRIVATE SwitchBuilder final ...@@ -126,9 +131,11 @@ class V8_EXPORT_PRIVATE SwitchBuilder final
void SetCaseTarget(int index); void SetCaseTarget(int index);
// This method is called when visiting case comparison operation for |index|. // This method is called when visiting case comparison operation for |index|.
// Inserts a JumpIfTrue to a unbound label that is patched when the // Inserts a JumpIfTrue with ToBooleanMode |mode| to a unbound label that is
// corresponding SetCaseTarget is called. // patched when the corresponding SetCaseTarget is called.
void Case(int index) { builder()->JumpIfTrue(&case_sites_.at(index)); } void Case(BytecodeArrayBuilder::ToBooleanMode mode, int index) {
builder()->JumpIfTrue(mode, &case_sites_.at(index));
}
// This method is called when all cases comparisons have been emitted if there // This method is called when all cases comparisons have been emitted if there
// is a default case statement. Inserts a Jump to a unbound label that is // is a default case statement. Inserts a Jump to a unbound label that is
......
...@@ -79,8 +79,6 @@ const char* PeepholeActionTableWriter::kNamespaceElements[] = {"v8", "internal", ...@@ -79,8 +79,6 @@ const char* PeepholeActionTableWriter::kNamespaceElements[] = {"v8", "internal",
// static // static
PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData( PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData(
Bytecode last, Bytecode current) { Bytecode last, Bytecode current) {
// ToName bytecodes can be replaced by Star with the same output register if
// the value in the accumulator is already a name.
if (current == Bytecode::kToName && Bytecodes::PutsNameInAccumulator(last)) { if (current == Bytecode::kToName && Bytecodes::PutsNameInAccumulator(last)) {
return {PeepholeAction::kChangeBytecodeAction, Bytecode::kStar}; return {PeepholeAction::kChangeBytecodeAction, Bytecode::kStar};
} }
...@@ -122,16 +120,6 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData( ...@@ -122,16 +120,6 @@ PeepholeActionAndData PeepholeActionTableWriter::LookupActionAndData(
// TODO(rmcilroy): Add elide for consecutive mov to and from the same // TODO(rmcilroy): Add elide for consecutive mov to and from the same
// register. // register.
// Remove ToBoolean coercion from conditional jumps where possible.
if (Bytecodes::WritesBooleanToAccumulator(last)) {
if (Bytecodes::IsJumpIfToBoolean(current)) {
return {PeepholeAction::kChangeJumpBytecodeAction,
Bytecodes::GetJumpWithoutToBoolean(current)};
} else if (current == Bytecode::kToBooleanLogicalNot) {
return {PeepholeAction::kChangeBytecodeAction, Bytecode::kLogicalNot};
}
}
// Fuse LdaSmi followed by binary op to produce binary op with a // Fuse LdaSmi followed by binary op to produce binary op with a
// immediate integer argument. This savaes on dispatches and size. // immediate integer argument. This savaes on dispatches and size.
if (last == Bytecode::kLdaSmi) { if (last == Bytecode::kLdaSmi) {
......
...@@ -155,7 +155,7 @@ bytecodes: [ ...@@ -155,7 +155,7 @@ bytecodes: [
B(LdaConstant), U8(4), B(LdaConstant), U8(4),
B(TestEqualStrictNoFeedback), R(7), B(TestEqualStrictNoFeedback), R(7),
B(Mov), R(4), R(6), B(Mov), R(4), R(6),
B(JumpIfToBooleanFalse), U8(7), B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0), B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0),
B(CreateClosure), U8(5), U8(4), U8(2), B(CreateClosure), U8(5), U8(4), U8(2),
B(Star), R(8), B(Star), R(8),
......
...@@ -143,7 +143,7 @@ bytecodes: [ ...@@ -143,7 +143,7 @@ bytecodes: [
/* 42 S> */ B(LdaZero), /* 42 S> */ B(LdaZero),
B(Star), R(0), B(Star), R(0),
/* 45 S> */ B(TestUndetectable), /* 45 S> */ B(TestUndetectable),
/* 57 E> */ B(JumpIfFalse), U8(6), B(JumpIfFalse), U8(6),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Jump), U8(4), B(Jump), U8(4),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
...@@ -244,7 +244,7 @@ bytecodes: [ ...@@ -244,7 +244,7 @@ bytecodes: [
/* 42 S> */ B(LdaZero), /* 42 S> */ B(LdaZero),
B(Star), R(0), B(Star), R(0),
/* 45 S> */ B(TestUndetectable), /* 45 S> */ B(TestUndetectable),
/* 51 E> */ B(JumpIfTrue), U8(5), B(JumpIfTrue), U8(5),
/* 69 S> */ B(LdaSmi), I8(1), /* 69 S> */ B(LdaSmi), I8(1),
/* 81 S> */ B(Return), /* 81 S> */ B(Return),
B(LdaUndefined), B(LdaUndefined),
......
...@@ -23,7 +23,7 @@ bytecodes: [ ...@@ -23,7 +23,7 @@ bytecodes: [
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(Ldar), R(0), /* 67 S> */ B(Ldar), R(0),
B(TestUndetectable), B(TestUndetectable),
/* 77 E> */ B(JumpIfFalse), U8(6), B(JumpIfFalse), U8(6),
/* 88 S> */ B(LdaSmi), I8(20), /* 88 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 97 S> */ B(Ldar), R(1), /* 97 S> */ B(Ldar), R(1),
...@@ -53,7 +53,7 @@ bytecodes: [ ...@@ -53,7 +53,7 @@ bytecodes: [
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(Ldar), R(0), /* 67 S> */ B(Ldar), R(0),
B(TestUndetectable), B(TestUndetectable),
/* 77 E> */ B(JumpIfFalse), U8(6), B(JumpIfFalse), U8(6),
/* 93 S> */ B(LdaSmi), I8(20), /* 93 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 102 S> */ B(Ldar), R(1), /* 102 S> */ B(Ldar), R(1),
...@@ -83,7 +83,7 @@ bytecodes: [ ...@@ -83,7 +83,7 @@ bytecodes: [
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(Ldar), R(0), /* 67 S> */ B(Ldar), R(0),
B(TestUndetectable), B(TestUndetectable),
/* 77 E> */ B(JumpIfTrue), U8(6), B(JumpIfTrue), U8(6),
/* 88 S> */ B(LdaSmi), I8(20), /* 88 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 97 S> */ B(Ldar), R(1), /* 97 S> */ B(Ldar), R(1),
...@@ -113,7 +113,7 @@ bytecodes: [ ...@@ -113,7 +113,7 @@ bytecodes: [
B(Star), R(1), B(Star), R(1),
/* 67 S> */ B(Ldar), R(0), /* 67 S> */ B(Ldar), R(0),
B(TestUndetectable), B(TestUndetectable),
/* 77 E> */ B(JumpIfTrue), U8(6), B(JumpIfTrue), U8(6),
/* 93 S> */ B(LdaSmi), I8(20), /* 93 S> */ B(LdaSmi), I8(20),
B(Star), R(1), B(Star), R(1),
/* 102 S> */ B(Ldar), R(1), /* 102 S> */ B(Ldar), R(1),
......
...@@ -24,7 +24,7 @@ bytecodes: [ ...@@ -24,7 +24,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(1), /* 45 S> */ B(LdaSmi), I8(1),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrue), U8(7), B(JumpIfTrue), U8(7),
...@@ -60,7 +60,7 @@ bytecodes: [ ...@@ -60,7 +60,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(1), /* 45 S> */ B(LdaSmi), I8(1),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrue), U8(10), B(JumpIfTrue), U8(10),
...@@ -98,7 +98,7 @@ bytecodes: [ ...@@ -98,7 +98,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(1), /* 45 S> */ B(LdaSmi), I8(1),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrue), U8(8), B(JumpIfTrue), U8(8),
...@@ -136,7 +136,7 @@ bytecodes: [ ...@@ -136,7 +136,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(2), /* 45 S> */ B(LdaSmi), I8(2),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(3), B(LdaSmi), I8(3),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrue), U8(6), B(JumpIfTrue), U8(6),
...@@ -175,7 +175,7 @@ bytecodes: [ ...@@ -175,7 +175,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(2), /* 45 S> */ B(LdaSmi), I8(2),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(1), R(2), B(Mov), R(1), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(3), B(LdaSmi), I8(3),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrue), U8(10), B(JumpIfTrue), U8(10),
...@@ -216,7 +216,7 @@ bytecodes: [ ...@@ -216,7 +216,7 @@ bytecodes: [
/* 45 S> */ B(TypeOf), /* 45 S> */ B(TypeOf),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(4), B(JumpIfTrue), U8(4),
B(Jump), U8(8), B(Jump), U8(8),
/* 74 S> */ B(LdaSmi), I8(1), /* 74 S> */ B(LdaSmi), I8(1),
B(Star), R(0), B(Star), R(0),
...@@ -318,7 +318,7 @@ bytecodes: [ ...@@ -318,7 +318,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(1), /* 45 S> */ B(LdaSmi), I8(1),
B(TestEqualStrict), R(1), U8(2), B(TestEqualStrict), R(1), U8(2),
B(Mov), R(0), R(2), B(Mov), R(0), R(2),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(TestEqualStrict), R(2), U8(3), B(TestEqualStrict), R(2), U8(3),
B(JumpIfTrueConstant), U8(0), B(JumpIfTrueConstant), U8(0),
...@@ -488,7 +488,7 @@ bytecodes: [ ...@@ -488,7 +488,7 @@ bytecodes: [
/* 45 S> */ B(LdaSmi), I8(1), /* 45 S> */ B(LdaSmi), I8(1),
B(TestEqualStrict), R(2), U8(5), B(TestEqualStrict), R(2), U8(5),
B(Mov), R(0), R(3), B(Mov), R(0), R(3),
B(JumpIfToBooleanTrue), U8(11), B(JumpIfTrue), U8(11),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(TestEqualStrict), R(3), U8(6), B(TestEqualStrict), R(3), U8(6),
B(JumpIfTrue), U8(34), B(JumpIfTrue), U8(34),
...@@ -498,7 +498,7 @@ bytecodes: [ ...@@ -498,7 +498,7 @@ bytecodes: [
/* 70 S> */ B(LdaSmi), I8(2), /* 70 S> */ B(LdaSmi), I8(2),
B(TestEqualStrict), R(1), U8(3), B(TestEqualStrict), R(1), U8(3),
B(Mov), R(1), R(4), B(Mov), R(1), R(4),
B(JumpIfToBooleanTrue), U8(4), B(JumpIfTrue), U8(4),
B(Jump), U8(8), B(Jump), U8(8),
/* 101 S> */ B(LdaSmi), I8(1), /* 101 S> */ B(LdaSmi), I8(1),
B(Star), R(0), B(Star), R(0),
......
...@@ -27,6 +27,8 @@ static int GetIndex(FeedbackSlot slot) { ...@@ -27,6 +27,8 @@ static int GetIndex(FeedbackSlot slot) {
return FeedbackVector::GetIndex(slot); return FeedbackVector::GetIndex(slot);
} }
using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
TEST(InterpreterReturn) { TEST(InterpreterReturn) {
HandleAndZoneScope handles; HandleAndZoneScope handles;
Isolate* isolate = handles.main_isolate(); Isolate* isolate = handles.main_isolate();
...@@ -1510,19 +1512,19 @@ TEST(InterpreterConditionalJumps) { ...@@ -1510,19 +1512,19 @@ TEST(InterpreterConditionalJumps) {
builder.LoadLiteral(Smi::kZero) builder.LoadLiteral(Smi::kZero)
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
.LoadFalse() .LoadFalse()
.JumpIfFalse(&label[0]); .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &label[0]);
IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot)) IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot))
.Bind(&label[0]) .Bind(&label[0])
.LoadTrue() .LoadTrue()
.JumpIfFalse(&done); .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done);
IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1)) IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1))
.LoadTrue() .LoadTrue()
.JumpIfTrue(&label[1]); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &label[1]);
IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2)) IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2))
.Bind(&label[1]); .Bind(&label[1]);
IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3)) IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3))
.LoadFalse() .LoadFalse()
.JumpIfTrue(&done1); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &done1);
IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4)) IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4))
.LoadAccumulatorWithRegister(reg) .LoadAccumulatorWithRegister(reg)
.Bind(&done) .Bind(&done)
...@@ -1560,19 +1562,19 @@ TEST(InterpreterConditionalJumps2) { ...@@ -1560,19 +1562,19 @@ TEST(InterpreterConditionalJumps2) {
builder.LoadLiteral(Smi::kZero) builder.LoadLiteral(Smi::kZero)
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
.LoadFalse() .LoadFalse()
.JumpIfFalse(&label[0]); .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &label[0]);
IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot)) IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot))
.Bind(&label[0]) .Bind(&label[0])
.LoadTrue() .LoadTrue()
.JumpIfFalse(&done); .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done);
IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1)) IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1))
.LoadTrue() .LoadTrue()
.JumpIfTrue(&label[1]); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &label[1]);
IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2)) IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2))
.Bind(&label[1]); .Bind(&label[1]);
IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3)) IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3))
.LoadFalse() .LoadFalse()
.JumpIfTrue(&done1); .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &done1);
IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4)) IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4))
.LoadAccumulatorWithRegister(reg) .LoadAccumulatorWithRegister(reg)
.Bind(&done) .Bind(&done)
...@@ -2203,7 +2205,7 @@ TEST(InterpreterUnaryNot) { ...@@ -2203,7 +2205,7 @@ TEST(InterpreterUnaryNot) {
Register r0(0); Register r0(0);
builder.LoadFalse(); builder.LoadFalse();
for (size_t j = 0; j < i; j++) { for (size_t j = 0; j < i; j++) {
builder.LogicalNot(); builder.LogicalNot(ToBooleanMode::kAlreadyBoolean);
} }
builder.Return(); builder.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
...@@ -2241,7 +2243,7 @@ TEST(InterpreterUnaryNotNonBoolean) { ...@@ -2241,7 +2243,7 @@ TEST(InterpreterUnaryNotNonBoolean) {
Register r0(0); Register r0(0);
builder.LoadLiteral(object_type_tuples[i].first); builder.LoadLiteral(object_type_tuples[i].first);
builder.LogicalNot(); builder.LogicalNot(ToBooleanMode::kConvertToBoolean);
builder.Return(); builder.Return();
ast_factory.Internalize(isolate); ast_factory.Internalize(isolate);
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
......
...@@ -17,6 +17,8 @@ namespace v8 { ...@@ -17,6 +17,8 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
using ToBooleanMode = interpreter::BytecodeArrayBuilder::ToBooleanMode;
class BytecodeAnalysisTest : public TestWithIsolateAndZone { class BytecodeAnalysisTest : public TestWithIsolateAndZone {
public: public:
BytecodeAnalysisTest() {} BytecodeAnalysisTest() {}
...@@ -155,7 +157,7 @@ TEST_F(BytecodeAnalysisTest, DiamondLoad) { ...@@ -155,7 +157,7 @@ TEST_F(BytecodeAnalysisTest, DiamondLoad) {
interpreter::BytecodeLabel ld1_label; interpreter::BytecodeLabel ld1_label;
interpreter::BytecodeLabel end_label; interpreter::BytecodeLabel end_label;
builder.JumpIfTrue(&ld1_label); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &ld1_label);
expected_liveness.emplace_back("LLLL", "LLL."); expected_liveness.emplace_back("LLLL", "LLL.");
builder.LoadAccumulatorWithRegister(reg_0); builder.LoadAccumulatorWithRegister(reg_0);
...@@ -195,7 +197,7 @@ TEST_F(BytecodeAnalysisTest, DiamondLookupsAndBinds) { ...@@ -195,7 +197,7 @@ TEST_F(BytecodeAnalysisTest, DiamondLookupsAndBinds) {
builder.StoreAccumulatorInRegister(reg_0); builder.StoreAccumulatorInRegister(reg_0);
expected_liveness.emplace_back(".LLL", "LLLL"); expected_liveness.emplace_back(".LLL", "LLLL");
builder.JumpIfTrue(&ld1_label); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &ld1_label);
expected_liveness.emplace_back("LLLL", "LLL."); expected_liveness.emplace_back("LLLL", "LLL.");
{ {
...@@ -242,7 +244,8 @@ TEST_F(BytecodeAnalysisTest, SimpleLoop) { ...@@ -242,7 +244,8 @@ TEST_F(BytecodeAnalysisTest, SimpleLoop) {
interpreter::LoopBuilder loop_builder(&builder); interpreter::LoopBuilder loop_builder(&builder);
loop_builder.LoopHeader(); loop_builder.LoopHeader();
{ {
builder.JumpIfTrue(loop_builder.break_labels()->New()); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
loop_builder.break_labels()->New());
expected_liveness.emplace_back("L.LL", "L.L."); expected_liveness.emplace_back("L.LL", "L.L.");
builder.LoadAccumulatorWithRegister(reg_0); builder.LoadAccumulatorWithRegister(reg_0);
...@@ -327,12 +330,13 @@ TEST_F(BytecodeAnalysisTest, DiamondInLoop) { ...@@ -327,12 +330,13 @@ TEST_F(BytecodeAnalysisTest, DiamondInLoop) {
interpreter::LoopBuilder loop_builder(&builder); interpreter::LoopBuilder loop_builder(&builder);
loop_builder.LoopHeader(); loop_builder.LoopHeader();
{ {
builder.JumpIfTrue(loop_builder.break_labels()->New()); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
loop_builder.break_labels()->New());
expected_liveness.emplace_back("L..L", "L..L"); expected_liveness.emplace_back("L..L", "L..L");
interpreter::BytecodeLabel ld1_label; interpreter::BytecodeLabel ld1_label;
interpreter::BytecodeLabel end_label; interpreter::BytecodeLabel end_label;
builder.JumpIfTrue(&ld1_label); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &ld1_label);
expected_liveness.emplace_back("L..L", "L..L"); expected_liveness.emplace_back("L..L", "L..L");
{ {
...@@ -381,7 +385,8 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) { ...@@ -381,7 +385,8 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) {
builder.LoadAccumulatorWithRegister(reg_1); builder.LoadAccumulatorWithRegister(reg_1);
expected_liveness.emplace_back(".L..", ".L.L"); expected_liveness.emplace_back(".L..", ".L.L");
builder.JumpIfTrue(loop_builder.break_labels()->New()); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
loop_builder.break_labels()->New());
expected_liveness.emplace_back(".L.L", ".L.L"); expected_liveness.emplace_back(".L.L", ".L.L");
interpreter::LoopBuilder inner_loop_builder(&builder); interpreter::LoopBuilder inner_loop_builder(&builder);
...@@ -390,7 +395,8 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) { ...@@ -390,7 +395,8 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) {
builder.StoreAccumulatorInRegister(reg_0); builder.StoreAccumulatorInRegister(reg_0);
expected_liveness.emplace_back(".L.L", "LL.L"); expected_liveness.emplace_back(".L.L", "LL.L");
builder.JumpIfTrue(inner_loop_builder.break_labels()->New()); builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean,
inner_loop_builder.break_labels()->New());
expected_liveness.emplace_back("LL.L", "LL.L"); expected_liveness.emplace_back("LL.L", "LL.L");
inner_loop_builder.BindContinueTarget(); inner_loop_builder.BindContinueTarget();
......
...@@ -22,6 +22,8 @@ class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { ...@@ -22,6 +22,8 @@ class BytecodeArrayBuilderTest : public TestWithIsolateAndZone {
~BytecodeArrayBuilderTest() override {} ~BytecodeArrayBuilderTest() override {}
}; };
using ToBooleanMode = BytecodeArrayBuilder::ToBooleanMode;
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
CanonicalHandleScope canonical(isolate()); CanonicalHandleScope canonical(isolate());
BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131);
...@@ -194,9 +196,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -194,9 +196,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CountOperation(Token::Value::SUB, 1); .CountOperation(Token::Value::SUB, 1);
// Emit unary operator invocations. // Emit unary operator invocations.
builder builder.LogicalNot(ToBooleanMode::kConvertToBoolean)
.LogicalNot() // ToBooleanLogicalNot .LogicalNot(ToBooleanMode::kAlreadyBoolean)
.LogicalNot() // non-ToBoolean LogicalNot
.TypeOf(); .TypeOf();
// Emit delete // Emit delete
...@@ -241,7 +242,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -241,7 +242,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Short jumps with Imm8 operands // Short jumps with Imm8 operands
{ {
BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4,
after_jump5, after_jump6, after_jump7; after_jump5, after_jump6, after_jump7, after_jump8, after_jump9,
after_jump10, after_jump11;
builder.Bind(&start) builder.Bind(&start)
.Jump(&after_jump1) .Jump(&after_jump1)
.Bind(&after_jump1) .Bind(&after_jump1)
...@@ -257,6 +259,14 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -257,6 +259,14 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.Bind(&after_jump6) .Bind(&after_jump6)
.JumpIfJSReceiver(&after_jump7) .JumpIfJSReceiver(&after_jump7)
.Bind(&after_jump7) .Bind(&after_jump7)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &after_jump8)
.Bind(&after_jump8)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &after_jump9)
.Bind(&after_jump9)
.JumpIfFalse(ToBooleanMode::kConvertToBoolean, &after_jump10)
.Bind(&after_jump10)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump11)
.Bind(&after_jump11)
.JumpLoop(&start, 0); .JumpLoop(&start, 0);
} }
...@@ -266,14 +276,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -266,14 +276,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
BytecodeLabel after_jump; BytecodeLabel after_jump;
builder.Jump(&end[0]) builder.Jump(&end[0])
.Bind(&after_jump) .Bind(&after_jump)
.LoadTrue() .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &end[1])
.JumpIfTrue(&end[1]) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &end[2])
.LoadTrue() .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &end[3])
.JumpIfFalse(&end[2]) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &end[4])
.LoadLiteral(Smi::kZero)
.JumpIfTrue(&end[3])
.LoadLiteral(Smi::kZero)
.JumpIfFalse(&end[4])
.JumpIfNull(&end[5]) .JumpIfNull(&end[5])
.JumpIfNotNull(&end[6]) .JumpIfNotNull(&end[6])
.JumpIfUndefined(&end[7]) .JumpIfUndefined(&end[7])
...@@ -283,30 +289,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -283,30 +289,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.JumpIfJSReceiver(&end[10]); .JumpIfJSReceiver(&end[10]);
} }
// Perform an operation that returns boolean value to
// generate JumpIfTrue/False
{
BytecodeLabel after_jump1, after_jump2;
builder.CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&after_jump1)
.Bind(&after_jump1)
.CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&after_jump2)
.Bind(&after_jump2);
}
// Perform an operation that returns a non-boolean operation to
// generate JumpIfToBooleanTrue/False.
{
BytecodeLabel after_jump1, after_jump2;
builder.BinaryOperation(Token::Value::ADD, reg, 1)
.JumpIfTrue(&after_jump1)
.Bind(&after_jump1)
.BinaryOperation(Token::Value::ADD, reg, 2)
.JumpIfFalse(&after_jump2)
.Bind(&after_jump2);
}
// Emit set pending message bytecode. // Emit set pending message bytecode.
builder.SetPendingMessage(); builder.SetPendingMessage();
...@@ -439,12 +421,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -439,12 +421,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
if (!FLAG_ignition_peephole) { if (!FLAG_ignition_peephole) {
// Insert entries for bytecodes only emitted by peephole optimizer. // Insert entries for bytecodes only emitted by peephole optimizer.
scorecard[Bytecodes::ToByte(Bytecode::kLogicalNot)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kJump)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrue)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalse)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrueConstant)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalseConstant)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kAddSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kAddSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kSubSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kSubSmi)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kBitwiseAndSmi)] = 1; scorecard[Bytecodes::ToByte(Bytecode::kBitwiseAndSmi)] = 1;
...@@ -573,13 +549,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -573,13 +549,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
builder.Jump(&near0) builder.Jump(&near0)
.Bind(&after_jump0) .Bind(&after_jump0)
.CompareOperation(Token::Value::EQ, reg, 1) .CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(&near1) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &near1)
.CompareOperation(Token::Value::EQ, reg, 2) .CompareOperation(Token::Value::EQ, reg, 2)
.JumpIfFalse(&near2) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &near2)
.BinaryOperation(Token::Value::ADD, reg, 1) .BinaryOperation(Token::Value::ADD, reg, 1)
.JumpIfTrue(&near3) .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &near3)
.BinaryOperation(Token::Value::ADD, reg, 2) .BinaryOperation(Token::Value::ADD, reg, 2)
.JumpIfFalse(&near4) .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &near4)
.Bind(&near0) .Bind(&near0)
.Bind(&near1) .Bind(&near1)
.Bind(&near2) .Bind(&near2)
...@@ -588,13 +564,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -588,13 +564,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
.Jump(&far0) .Jump(&far0)
.Bind(&after_jump1) .Bind(&after_jump1)
.CompareOperation(Token::Value::EQ, reg, 3) .CompareOperation(Token::Value::EQ, reg, 3)
.JumpIfTrue(&far1) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &far1)
.CompareOperation(Token::Value::EQ, reg, 4) .CompareOperation(Token::Value::EQ, reg, 4)
.JumpIfFalse(&far2) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &far2)
.BinaryOperation(Token::Value::ADD, reg, 3) .BinaryOperation(Token::Value::ADD, reg, 3)
.JumpIfTrue(&far3) .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &far3)
.BinaryOperation(Token::Value::ADD, reg, 4) .BinaryOperation(Token::Value::ADD, reg, 4)
.JumpIfFalse(&far4); .JumpIfFalse(ToBooleanMode::kConvertToBoolean, &far4);
for (int i = 0; i < kFarJumpDistance - 22; i++) { for (int i = 0; i < kFarJumpDistance - 22; i++) {
builder.Debugger(); builder.Debugger();
} }
......
...@@ -128,56 +128,6 @@ TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { ...@@ -128,56 +128,6 @@ TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) {
CHECK_EQ(add, last_written()); CHECK_EQ(add, last_written());
} }
// Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
BytecodeNode first(Bytecode::kLdaNull);
BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
BytecodeLabel label;
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->WriteJump(&second, &label);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written(), second);
}
TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
BytecodeNode first(Bytecode::kLdaTrue);
BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3);
BytecodeLabel label;
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->WriteJump(&second, &label);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written(), second);
}
TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) {
BytecodeNode first(Bytecode::kLdaNull);
BytecodeNode second(Bytecode::kToBooleanLogicalNot);
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written(), first);
Flush();
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written(), second);
}
TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) {
BytecodeNode first(Bytecode::kLdaTrue);
BytecodeNode second(Bytecode::kToBooleanLogicalNot);
optimizer()->Write(&first);
CHECK_EQ(write_count(), 0);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written(), first);
Flush();
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot);
}
// Tests covering BytecodePeepholeOptimizer::CanElideCurrent(). // Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) { TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) {
......
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