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:
parent
9fb39c6b91
commit
b97567a976
1
BUILD.gn
1
BUILD.gn
@ -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",
|
||||
|
@ -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) \
|
||||
|
@ -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
|
||||
|
36
src/builtins/builtins-math-gen.h
Normal file
36
src/builtins/builtins-math-gen.h
Normal 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_
|
@ -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);
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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) \
|
||||
|
@ -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();
|
||||
|
@ -344,6 +344,10 @@ JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceBinaryOperation(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kJSExponentiate: {
|
||||
// TODO(neis): Introduce a SpeculativeNumberPow operator?
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -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);
|
||||
|
@ -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) \
|
||||
|
@ -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:
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
@ -1305,6 +1305,7 @@ enum class Operation {
|
||||
kMultiply,
|
||||
kDivide,
|
||||
kModulus,
|
||||
kExponentiate,
|
||||
kBitwiseAnd,
|
||||
kBitwiseOr,
|
||||
kBitwiseXor,
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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, \
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user