Commit 6fd19f7e authored by Adam Klein's avatar Adam Klein Committed by Commit Bot

[bigint] Move desugaring of unary ops from Parser to BytecodeGenerator

This is in preparation for BigInt, since for BigInt operands the desugared
operations will no longer be equivalent.

Future CLs can move the handling of these operations further down the
pipeline; this is merely a start to get the Parser out of this business.

Bug: v8:6791
Change-Id: I9df89e03d3ca2bf627c75fc5efb10463c3ed8cf9
Reviewed-on: https://chromium-review.googlesource.com/653433
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47902}
parent 9c0471b3
......@@ -213,6 +213,7 @@ void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
} else {
Visit(node->expression());
}
ReserveFeedbackSlots(node);
}
......
......@@ -815,6 +815,24 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) {
DCHECK(IsRegExpLiteral());
}
void UnaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
FeedbackSlotCache* cache) {
switch (op()) {
// Only unary plus, minus, and bitwise-not currently collect feedback.
case Token::ADD:
case Token::SUB:
case Token::BIT_NOT:
// Note that the slot kind remains "BinaryOp", as the operation
// is transformed into a binary operation in the BytecodeGenerator.
feedback_slot_ = spec->AddInterpreterBinaryOpICSlot();
return;
default:
return;
}
}
void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FunctionKind kind,
......
......@@ -1803,6 +1803,11 @@ class UnaryOperation final : public Expression {
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FunctionKind kind, FeedbackSlotCache* cache);
FeedbackSlot UnaryOperationFeedbackSlot() const { return feedback_slot_; }
private:
friend class AstNodeFactory;
......@@ -1812,6 +1817,7 @@ class UnaryOperation final : public Expression {
DCHECK(Token::IsUnaryOp(op));
}
FeedbackSlot feedback_slot_;
Expression* expression_;
class OperatorField
......
......@@ -312,6 +312,7 @@ 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);
// Same as above, but lhs in the accumulator and rhs in |literal|.
BytecodeArrayBuilder& BinaryOperationSmiLiteral(Token::Value binop,
Smi* literal,
int feedback_slot);
......
......@@ -3439,6 +3439,15 @@ void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
}
}
void BytecodeGenerator::BuildBinaryOperationForUnaryOperation(
UnaryOperation* expr, Token::Value binop, int rhs) {
VisitForAccumulatorValue(expr->expression());
builder()->SetExpressionPosition(expr);
builder()->BinaryOperationSmiLiteral(
binop, Smi::FromInt(rhs),
feedback_index(expr->UnaryOperationFeedbackSlot()));
}
void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
switch (expr->op()) {
case Token::Value::NOT:
......@@ -3453,12 +3462,17 @@ void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
case Token::Value::DELETE:
VisitDelete(expr);
break;
case Token::Value::BIT_NOT:
// TODO(adamk): Output specific bytecodes for ADD, SUB, and BIT_NOT
// instead of transforming them to binary operations.
case Token::Value::ADD:
BuildBinaryOperationForUnaryOperation(expr, Token::Value::MUL, 1);
break;
case Token::Value::SUB:
// These operators are converted to an equivalent binary operators in
// the parser. These operators are not expected to be visited here.
UNREACHABLE();
BuildBinaryOperationForUnaryOperation(expr, Token::Value::MUL, -1);
break;
case Token::Value::BIT_NOT:
BuildBinaryOperationForUnaryOperation(expr, Token::Value::BIT_XOR, -1);
break;
default:
UNREACHABLE();
}
......@@ -3713,8 +3727,6 @@ 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.
FeedbackSlot slot = expr->BinaryOperationFeedbackSlot();
Expression* subexpr;
Smi* literal;
......
......@@ -195,6 +195,9 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
void BuildTest(ToBooleanMode mode, BytecodeLabels* then_labels,
BytecodeLabels* else_labels, TestFallthrough fallthrough);
void BuildBinaryOperationForUnaryOperation(UnaryOperation* expr,
Token::Value binop, int rhs);
// Visitors for obtaining expression result in the accumulator, in a
// register, or just getting the effect. Some visitors return a TypeHint which
// specifies the type of the result of the visited expression.
......
......@@ -332,21 +332,6 @@ Expression* Parser::BuildUnaryExpression(Expression* expression,
}
}
}
// Desugar '+foo' => 'foo*1'
if (op == Token::ADD) {
return factory()->NewBinaryOperation(
Token::MUL, expression, factory()->NewNumberLiteral(1, pos), pos);
}
// The same idea for '-foo' => 'foo*(-1)'.
if (op == Token::SUB) {
return factory()->NewBinaryOperation(
Token::MUL, expression, factory()->NewNumberLiteral(-1, pos), pos);
}
// ...and one more time for '~foo' => 'foo^(~0)'.
if (op == Token::BIT_NOT) {
return factory()->NewBinaryOperation(
Token::BIT_XOR, expression, factory()->NewNumberLiteral(~0, pos), pos);
}
return factory()->NewUnaryOperation(op, expression, pos);
}
......
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