No longer desugar the exponentiation (**) operator.

Prior to this change, the exponentiation operator was rewritten by the
parser to a call of the Math.pow builtin. However, Math.pow does not
accept BigInt arguments, while the exponentiation operator must accept
them.

This CL
- removes the parser's special treatment of ** and **=, treating them
  like any other binary op instead.
- adds a TFC builtin Exponentiate that does the right thing for
  all inputs.
- adds interpreter bytecodes Exp and ExpSmi whose handlers call the
  Exponentiate builtin. For simplicity, they currently always collect
  kAny feedback.
- adds a Turbofan operator JSExponentiate with a typed-lowering to
  the existing NumberPow and a generic-lowering to the Exponentiate
  builtin. There is currently no speculative lowering.

Note that exponentiation for BigInts is actually not implemented yet,
so we can't yet test it.

Bug: v8:6791
Change-Id: Id90914c9c3fce310ce01e715c09eaa9f294f4f8a
Reviewed-on: https://chromium-review.googlesource.com/785694
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Mythri Alle <mythria@chromium.org>
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49696}
This commit is contained in:
Georg Neis 2017-11-28 11:05:00 +01:00 committed by Commit Bot
parent 9fb39c6b91
commit b97567a976
30 changed files with 169 additions and 112 deletions

View File

@ -1022,6 +1022,7 @@ v8_source_set("v8_initializers") {
"src/builtins/builtins-iterator-gen.cc",
"src/builtins/builtins-iterator-gen.h",
"src/builtins/builtins-math-gen.cc",
"src/builtins/builtins-math-gen.h",
"src/builtins/builtins-number-gen.cc",
"src/builtins/builtins-object-gen.cc",
"src/builtins/builtins-promise-gen.cc",

View File

@ -688,6 +688,7 @@ namespace internal {
TFC(Multiply, BinaryOp, 1) \
TFC(Divide, BinaryOp, 1) \
TFC(Modulus, BinaryOp, 1) \
TFC(Exponentiate, BinaryOp, 1) \
TFC(BitwiseAnd, BinaryOp, 1) \
TFC(BitwiseOr, BinaryOp, 1) \
TFC(BitwiseXor, BinaryOp, 1) \

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-math-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/code-factory.h"
@ -14,24 +16,6 @@ namespace internal {
// -----------------------------------------------------------------------------
// ES6 section 20.2.2 Function Properties of the Math Object
class MathBuiltinsAssembler : public CodeStubAssembler {
public:
explicit MathBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
protected:
void MathRoundingOperation(
Node* context, Node* x,
TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>));
void MathUnaryOperation(
Node* context, Node* x,
TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>));
void MathMaxMin(Node* context, Node* argc,
TNode<Float64T> (CodeStubAssembler::*float64op)(
SloppyTNode<Float64T>, SloppyTNode<Float64T>),
double default_val);
};
// ES6 #sec-math.abs
TF_BUILTIN(MathAbs, CodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
@ -405,16 +389,19 @@ TF_BUILTIN(MathLog2, MathBuiltinsAssembler) {
MathUnaryOperation(context, x, &CodeStubAssembler::Float64Log2);
}
CodeStubAssembler::Node* MathBuiltinsAssembler::MathPow(Node* context,
Node* base,
Node* exponent) {
Node* base_value = TruncateTaggedToFloat64(context, base);
Node* exponent_value = TruncateTaggedToFloat64(context, exponent);
Node* value = Float64Pow(base_value, exponent_value);
return ChangeFloat64ToTagged(value);
}
// ES6 #sec-math.pow
TF_BUILTIN(MathPow, CodeStubAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* x = Parameter(Descriptor::kBase);
Node* y = Parameter(Descriptor::kExponent);
Node* x_value = TruncateTaggedToFloat64(context, x);
Node* y_value = TruncateTaggedToFloat64(context, y);
Node* value = Float64Pow(x_value, y_value);
Node* result = ChangeFloat64ToTagged(value);
Return(result);
TF_BUILTIN(MathPow, MathBuiltinsAssembler) {
Return(MathPow(Parameter(Descriptor::kContext), Parameter(Descriptor::kBase),
Parameter(Descriptor::kExponent)));
}
// ES6 #sec-math.random

View File

@ -0,0 +1,36 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_BUILTINS_BUILTINS_MATH_GEN_H_
#define V8_BUILTINS_BUILTINS_MATH_GEN_H_
#include "src/code-stub-assembler.h"
namespace v8 {
namespace internal {
class MathBuiltinsAssembler : public CodeStubAssembler {
public:
explicit MathBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
Node* MathPow(Node* context, Node* base, Node* exponent);
protected:
void MathRoundingOperation(
Node* context, Node* x,
TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>));
void MathUnaryOperation(
Node* context, Node* x,
TNode<Float64T> (CodeStubAssembler::*float64op)(SloppyTNode<Float64T>));
void MathMaxMin(Node* context, Node* argc,
TNode<Float64T> (CodeStubAssembler::*float64op)(
SloppyTNode<Float64T>, SloppyTNode<Float64T>),
double default_val);
};
} // namespace internal
} // namespace v8
#endif // V8_BUILTINS_BUILTINS_MATH_GEN_H_

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/builtins/builtins-math-gen.h"
#include "src/builtins/builtins-utils-gen.h"
#include "src/builtins/builtins.h"
#include "src/code-stub-assembler.h"
@ -636,8 +637,11 @@ void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
Label* bigints) {
DCHECK_EQ(var_left->rep(), MachineRepresentation::kTagged);
DCHECK_EQ(var_right->rep(), MachineRepresentation::kTagged);
DCHECK_EQ(var_left_double->rep(), MachineRepresentation::kFloat64);
DCHECK_EQ(var_right_double->rep(), MachineRepresentation::kFloat64);
DCHECK_IMPLIES(var_left_double != nullptr,
var_left_double->rep() == MachineRepresentation::kFloat64);
DCHECK_IMPLIES(var_right_double != nullptr,
var_right_double->rep() == MachineRepresentation::kFloat64);
DCHECK_EQ(var_left_double == nullptr, var_right_double == nullptr);
Node* context = Parameter(Descriptor::kContext);
var_left->Bind(Parameter(Descriptor::kLeft));
@ -655,8 +659,10 @@ void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
// At this point, var_left is a Smi but var_right is not.
GotoIfNot(IsHeapNumber(var_right->value()), &right_not_number);
var_left_double->Bind(SmiToFloat64(var_left->value()));
var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
if (var_left_double != nullptr) {
var_left_double->Bind(SmiToFloat64(var_left->value()));
var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
}
Goto(doubles);
BIND(&left_not_smi);
@ -665,16 +671,20 @@ void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
GotoIfNot(TaggedIsSmi(var_right->value()), &right_not_smi);
// At this point, var_left is a HeapNumber and var_right is a Smi.
var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
var_right_double->Bind(SmiToFloat64(var_right->value()));
if (var_left_double != nullptr) {
var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
var_right_double->Bind(SmiToFloat64(var_right->value()));
}
Goto(doubles);
}
BIND(&right_not_smi);
{
GotoIfNot(IsHeapNumber(var_right->value()), &right_not_number);
var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
if (var_left_double != nullptr) {
var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
}
Goto(doubles);
}
@ -970,6 +980,26 @@ TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
}
}
TF_BUILTIN(Exponentiate, NumberBuiltinsAssembler) {
VARIABLE(var_left, MachineRepresentation::kTagged);
VARIABLE(var_right, MachineRepresentation::kTagged);
Label do_number_exp(this), do_bigint_exp(this);
Node* context = Parameter(Descriptor::kContext);
BinaryOp<Descriptor>(&do_number_exp, &var_left, &var_right, &do_number_exp,
nullptr, nullptr, &do_bigint_exp);
BIND(&do_number_exp);
{
MathBuiltinsAssembler math_asm(state());
Return(math_asm.MathPow(context, var_left.value(), var_right.value()));
}
BIND(&do_bigint_exp);
Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
var_right.value(), SmiConstant(Operation::kExponentiate)));
}
TF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
EmitBitwiseOp<Descriptor>(Operation::kShiftLeft);
}

View File

@ -2139,6 +2139,10 @@ void BytecodeGraphBuilder::VisitMod() {
BuildBinaryOp(javascript()->Modulus());
}
void BytecodeGraphBuilder::VisitExp() {
BuildBinaryOp(javascript()->Exponentiate());
}
void BytecodeGraphBuilder::VisitBitwiseOr() {
BuildBinaryOp(javascript()->BitwiseOr());
}
@ -2205,6 +2209,10 @@ void BytecodeGraphBuilder::VisitModSmi() {
BuildBinaryOpWithImmediate(javascript()->Modulus());
}
void BytecodeGraphBuilder::VisitExpSmi() {
BuildBinaryOpWithImmediate(javascript()->Exponentiate());
}
void BytecodeGraphBuilder::VisitBitwiseOrSmi() {
BuildBinaryOpWithImmediate(javascript()->BitwiseOr());
}

View File

@ -60,6 +60,7 @@ REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(Multiply)
REPLACE_STUB_CALL(Divide)
REPLACE_STUB_CALL(Modulus)
REPLACE_STUB_CALL(Exponentiate)
REPLACE_STUB_CALL(BitwiseAnd)
REPLACE_STUB_CALL(BitwiseOr)
REPLACE_STUB_CALL(BitwiseXor)

View File

@ -577,6 +577,7 @@ CompareOperationHint CompareOperationHintOf(const Operator* op) {
V(Multiply, Operator::kNoProperties, 2, 1) \
V(Divide, Operator::kNoProperties, 2, 1) \
V(Modulus, Operator::kNoProperties, 2, 1) \
V(Exponentiate, Operator::kNoProperties, 2, 1) \
V(BitwiseNot, Operator::kNoProperties, 1, 1) \
V(Decrement, Operator::kNoProperties, 1, 1) \
V(Increment, Operator::kNoProperties, 1, 1) \

View File

@ -651,6 +651,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* Multiply();
const Operator* Divide();
const Operator* Modulus();
const Operator* Exponentiate();
const Operator* BitwiseNot();
const Operator* Decrement();

View File

@ -344,6 +344,10 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
}
break;
}
case IrOpcode::kJSExponentiate: {
// TODO(neis): Introduce a SpeculativeNumberPow operator?
break;
}
default:
UNREACHABLE();
break;

View File

@ -279,6 +279,8 @@ class JSBinopReduction final {
return simplified()->NumberDivide();
case IrOpcode::kJSModulus:
return simplified()->NumberModulus();
case IrOpcode::kJSExponentiate:
return simplified()->NumberPow();
case IrOpcode::kJSBitwiseAnd:
return simplified()->NumberBitwiseAnd();
case IrOpcode::kJSBitwiseOr:
@ -2123,6 +2125,7 @@ Reduction JSTypedLowering::Reduce(Node* node) {
case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus:
case IrOpcode::kJSExponentiate:
return ReduceNumberBinop(node);
case IrOpcode::kJSBitwiseNot:
return ReduceJSBitwiseNot(node);

View File

@ -105,7 +105,8 @@
V(JSSubtract) \
V(JSMultiply) \
V(JSDivide) \
V(JSModulus)
V(JSModulus) \
V(JSExponentiate)
#define JS_SIMPLE_BINOP_LIST(V) \
JS_COMPARE_BINOP_LIST(V) \

View File

@ -44,6 +44,7 @@ bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus:
case IrOpcode::kJSExponentiate:
// Bitwise operations
case IrOpcode::kJSBitwiseOr:

View File

@ -1103,6 +1103,12 @@ Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
return NumberModulus(ToNumber(lhs, t), ToNumber(rhs, t), t);
}
// TODO(neis): Adapt all these for bigints. Why does this even work in the
// bigint tests?
Type* Typer::Visitor::JSExponentiateTyper(Type* lhs, Type* rhs, Typer* t) {
return Type::Number();
}
// JS unary operators.

View File

@ -608,7 +608,9 @@ void Verifier::Visitor::Check(Node* node, const AllNodes& all) {
case IrOpcode::kJSMultiply:
case IrOpcode::kJSDivide:
case IrOpcode::kJSModulus:
case IrOpcode::kJSExponentiate:
// Type is Number.
// TODO(neis): Adapt for bigints.
CheckTypeIs(node, Type::Number());
break;

View File

@ -382,6 +382,8 @@ bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
case Bytecode::kDivSmi:
case Bytecode::kMod:
case Bytecode::kModSmi:
case Bytecode::kExp:
case Bytecode::kExpSmi:
case Bytecode::kNegate:
case Bytecode::kBitwiseAnd:
case Bytecode::kBitwiseAndSmi:

View File

@ -1305,6 +1305,7 @@ enum class Operation {
kMultiply,
kDivide,
kModulus,
kExponentiate,
kBitwiseAnd,
kBitwiseOr,
kBitwiseXor,

View File

@ -529,5 +529,14 @@ Node* BinaryOpAssembler::Generate_ModulusWithFeedback(
floatFunction, Operation::kModulus, rhs_is_smi);
}
Node* BinaryOpAssembler::Generate_ExponentiateWithFeedback(
Node* context, Node* base, Node* exponent, Node* slot_id,
Node* feedback_vector, bool rhs_is_smi) {
// We currently don't optimize exponentiation based on feedback.
Node* dummy_feedback = SmiConstant(BinaryOperationFeedback::kAny);
UpdateFeedback(dummy_feedback, feedback_vector, slot_id);
return CallBuiltin(Builtins::kExponentiate, context, base, exponent);
}
} // namespace internal
} // namespace v8

View File

@ -42,6 +42,11 @@ class BinaryOpAssembler : public CodeStubAssembler {
Node* divisor, Node* slot_id,
Node* feedback_vector, bool rhs_is_smi);
Node* Generate_ExponentiateWithFeedback(Node* context, Node* dividend,
Node* divisor, Node* slot_id,
Node* feedback_vector,
bool rhs_is_smi);
private:
typedef std::function<Node*(Node*, Node*, Variable*)> SmiOperation;
typedef std::function<Node*(Node*, Node*)> FloatOperation;

View File

@ -362,6 +362,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
case Token::Value::MOD:
OutputMod(reg, feedback_slot);
break;
case Token::Value::EXP:
OutputExp(reg, feedback_slot);
break;
case Token::Value::BIT_OR:
OutputBitwiseOr(reg, feedback_slot);
break;
@ -404,6 +407,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperationSmiLiteral(
case Token::Value::MOD:
OutputModSmi(literal->value(), feedback_slot);
break;
case Token::Value::EXP:
OutputExpSmi(literal->value(), feedback_slot);
break;
case Token::Value::BIT_OR:
OutputBitwiseOrSmi(literal->value(), feedback_slot);
break;

View File

@ -110,6 +110,7 @@ namespace interpreter {
V(Mul, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
V(Div, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
V(Mod, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
V(Exp, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx) \
V(BitwiseOr, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(BitwiseXor, AccumulatorUse::kReadWrite, OperandType::kReg, \
@ -129,6 +130,7 @@ namespace interpreter {
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(ExpSmi, AccumulatorUse::kReadWrite, OperandType::kImm, OperandType::kIdx) \
V(BitwiseOrSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \
OperandType::kIdx) \
V(BitwiseXorSmi, AccumulatorUse::kReadWrite, OperandType::kImm, \

View File

@ -910,6 +910,13 @@ IGNITION_HANDLER(Mod, InterpreterBinaryOpAssembler) {
BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
}
// Exp <src>
//
// Exponentiate register <src> (base) with accumulator (exponent).
IGNITION_HANDLER(Exp, InterpreterBinaryOpAssembler) {
BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ExponentiateWithFeedback);
}
// AddSmi <imm>
//
// Adds an immediate value <imm> to the value in the accumulator.
@ -945,6 +952,14 @@ IGNITION_HANDLER(ModSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
}
// ExpSmi <imm>
//
// Exponentiate accumulator (base) with immediate value <imm> (exponent).
IGNITION_HANDLER(ExpSmi, InterpreterBinaryOpAssembler) {
BinaryOpSmiWithFeedback(
&BinaryOpAssembler::Generate_ExponentiateWithFeedback);
}
class InterpreterBitwiseBinaryOpAssembler : public InterpreterAssembler {
public:
InterpreterBitwiseBinaryOpAssembler(CodeAssemblerState* state,

View File

@ -2973,15 +2973,11 @@ ParserBase<Impl>::ParseAssignmentExpression(bool accept_IN, bool* ok) {
impl()->SetFunctionNameFromIdentifierRef(right, expression);
}
if (op == Token::ASSIGN_EXP) {
DCHECK(!is_destructuring_assignment);
return impl()->RewriteAssignExponentiation(expression, right, pos);
}
DCHECK_NE(op, Token::INIT);
ExpressionT result = factory()->NewAssignment(op, expression, right, pos);
if (is_destructuring_assignment) {
DCHECK_NE(op, Token::ASSIGN_EXP);
auto rewritable = factory()->NewRewritableExpression(result, scope());
impl()->QueueDestructuringAssignmentForRewriting(rewritable);
result = rewritable;
@ -3131,8 +3127,6 @@ typename ParserBase<Impl>::ExpressionT ParserBase<Impl>::ParseBinaryExpression(
// The comparison was negated - add a NOT.
x = factory()->NewUnaryOperation(Token::NOT, x, pos);
}
} else if (op == Token::EXP) {
x = impl()->RewriteExponentiation(x, y, pos);
} else if (impl()->CollapseNaryExpression(&x, y, op, pos, right_range)) {
continue;
} else {

View File

@ -3845,58 +3845,6 @@ void Parser::RewriteDestructuringAssignments() {
}
}
Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
int pos) {
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
args->Add(left, zone());
args->Add(right, zone());
return factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
}
Expression* Parser::RewriteAssignExponentiation(Expression* left,
Expression* right, int pos) {
ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
if (left->IsVariableProxy()) {
VariableProxy* lhs = left->AsVariableProxy();
Expression* result;
DCHECK_NOT_NULL(lhs->raw_name());
result = ExpressionFromIdentifier(lhs->raw_name(), lhs->position());
args->Add(left, zone());
args->Add(right, zone());
Expression* call =
factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
} else if (left->IsProperty()) {
Property* prop = left->AsProperty();
auto temp_obj = NewTemporary(ast_value_factory()->empty_string());
auto temp_key = NewTemporary(ast_value_factory()->empty_string());
Expression* assign_obj = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
kNoSourcePosition);
Expression* assign_key = factory()->NewAssignment(
Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
kNoSourcePosition);
args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
factory()->NewVariableProxy(temp_key),
left->position()),
zone());
args->Add(right, zone());
Expression* call =
factory()->NewCallRuntime(Context::MATH_POW_INDEX, args, pos);
Expression* target = factory()->NewProperty(
factory()->NewVariableProxy(temp_obj),
factory()->NewVariableProxy(temp_key), kNoSourcePosition);
Expression* assign =
factory()->NewAssignment(Token::ASSIGN, target, call, pos);
return factory()->NewBinaryOperation(
Token::COMMA, assign_obj,
factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
pos);
}
UNREACHABLE();
}
Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
// Array literals containing spreads are rewritten using do expressions, e.g.
// [1, 2, 3, ...x, 4, ...y, 5]

View File

@ -551,11 +551,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
// Rewrite all DestructuringAssignments in the current FunctionState.
V8_INLINE void RewriteDestructuringAssignments();
V8_INLINE Expression* RewriteExponentiation(Expression* left,
Expression* right, int pos);
V8_INLINE Expression* RewriteAssignExponentiation(Expression* left,
Expression* right, int pos);
Expression* RewriteSpreads(ArrayLiteral* lit);
// Rewrite expressions that are not used as patterns

View File

@ -995,17 +995,6 @@ class PreParser : public ParserBase<PreParser> {
V8_INLINE void RewriteDestructuringAssignments() {}
V8_INLINE PreParserExpression
RewriteExponentiation(const PreParserExpression& left,
const PreParserExpression& right, int pos) {
return left;
}
V8_INLINE PreParserExpression
RewriteAssignExponentiation(const PreParserExpression& left,
const PreParserExpression& right, int pos) {
return left;
}
V8_INLINE void PrepareGeneratorVariables() {}
V8_INLINE void RewriteAsyncFunctionBody(
PreParserStatementList body, PreParserStatement block,

View File

@ -284,6 +284,8 @@ class Token {
return Token::DIV;
case Token::ASSIGN_MOD:
return Token::MOD;
case Token::ASSIGN_EXP:
return Token::EXP;
default:
UNREACHABLE();
}

View File

@ -107,6 +107,9 @@ RUNTIME_FUNCTION(Runtime_BigIntBinaryOp) {
case Operation::kModulus:
result = BigInt::Remainder(left, right);
break;
case Operation::kExponentiate:
UNIMPLEMENTED();
break;
case Operation::kBitwiseAnd:
result = BigInt::BitwiseAnd(left, right);
break;

View File

@ -200,6 +200,7 @@
'builtins/builtins-iterator-gen.h',
'builtins/builtins-iterator-gen.cc',
'builtins/builtins-math-gen.cc',
'builtins/builtins-math-gen.h',
'builtins/builtins-number-gen.cc',
'builtins/builtins-object-gen.cc',
'builtins/builtins-promise-gen.cc',

View File

@ -199,7 +199,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.BinaryOperation(Token::Value::SUB, reg, 2)
.BinaryOperation(Token::Value::MUL, reg, 3)
.BinaryOperation(Token::Value::DIV, reg, 4)
.BinaryOperation(Token::Value::MOD, reg, 5);
.BinaryOperation(Token::Value::MOD, reg, 5)
.BinaryOperation(Token::Value::EXP, reg, 6);
// Emit bitwise operator invocations
builder.BinaryOperation(Token::Value::BIT_OR, reg, 6)
@ -217,6 +218,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.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::EXP, 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)