1// Copyright 2017 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_IC_BINARY_OP_ASSEMBLER_H_
6#define V8_IC_BINARY_OP_ASSEMBLER_H_
7
8#include <functional>
9
10#include "src/codegen/code-stub-assembler.h"
11
12namespace v8 {
13namespace internal {
14
15namespace compiler {
16class CodeAssemblerState;
17}  // namespace compiler
18
19class BinaryOpAssembler : public CodeStubAssembler {
20 public:
21  explicit BinaryOpAssembler(compiler::CodeAssemblerState* state)
22      : CodeStubAssembler(state) {}
23
24  TNode<Object> Generate_AddWithFeedback(
25      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
26      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
27      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
28
29  TNode<Object> Generate_SubtractWithFeedback(
30      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
31      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
32      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
33
34  TNode<Object> Generate_MultiplyWithFeedback(
35      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
36      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
37      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
38
39  TNode<Object> Generate_DivideWithFeedback(
40      const LazyNode<Context>& context, TNode<Object> dividend,
41      TNode<Object> divisor, TNode<UintPtrT> slot,
42      const LazyNode<HeapObject>& maybe_feedback_vector,
43      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
44
45  TNode<Object> Generate_ModulusWithFeedback(
46      const LazyNode<Context>& context, TNode<Object> dividend,
47      TNode<Object> divisor, TNode<UintPtrT> slot,
48      const LazyNode<HeapObject>& maybe_feedback_vector,
49      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
50
51  TNode<Object> Generate_ExponentiateWithFeedback(
52      const LazyNode<Context>& context, TNode<Object> base,
53      TNode<Object> exponent, TNode<UintPtrT> slot,
54      const LazyNode<HeapObject>& maybe_feedback_vector,
55      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi);
56
57  TNode<Object> Generate_BitwiseOrWithFeedback(
58      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
59      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
60      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
61    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
62        Operation::kBitwiseOr, left, right, context, slot,
63        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
64    return result;
65  }
66
67  TNode<Object> Generate_BitwiseXorWithFeedback(
68      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
69      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
70      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
71    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
72        Operation::kBitwiseXor, left, right, context, slot,
73        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
74
75    return result;
76  }
77
78  TNode<Object> Generate_BitwiseAndWithFeedback(
79      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
80      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
81      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
82    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
83        Operation::kBitwiseAnd, left, right, context, slot,
84        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
85
86    return result;
87  }
88
89  TNode<Object> Generate_ShiftLeftWithFeedback(
90      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
91      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
92      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
93    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
94        Operation::kShiftLeft, left, right, context, slot,
95        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
96
97    return result;
98  }
99
100  TNode<Object> Generate_ShiftRightWithFeedback(
101      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
102      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
103      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
104    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
105        Operation::kShiftRight, left, right, context, slot,
106        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
107
108    return result;
109  }
110
111  TNode<Object> Generate_ShiftRightLogicalWithFeedback(
112      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
113      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
114      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
115    TNode<Object> result = Generate_BitwiseBinaryOpWithFeedback(
116        Operation::kShiftRightLogical, left, right, context, slot,
117        maybe_feedback_vector, update_feedback_mode, rhs_known_smi);
118
119    return result;
120  }
121
122  TNode<Object> Generate_BitwiseBinaryOpWithFeedback(
123      Operation bitwise_op, TNode<Object> left, TNode<Object> right,
124      const LazyNode<Context>& context, TNode<UintPtrT> slot,
125      const LazyNode<HeapObject>& maybe_feedback_vector,
126      UpdateFeedbackMode update_feedback_mode, bool rhs_known_smi) {
127    return rhs_known_smi
128               ? Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback(
129                     bitwise_op, left, right, context, &slot,
130                     &maybe_feedback_vector, update_feedback_mode)
131               : Generate_BitwiseBinaryOpWithOptionalFeedback(
132                     bitwise_op, left, right, context, &slot,
133                     &maybe_feedback_vector, update_feedback_mode);
134  }
135
136  TNode<Object> Generate_BitwiseBinaryOp(Operation bitwise_op,
137                                         TNode<Object> left,
138                                         TNode<Object> right,
139                                         TNode<Context> context) {
140    return Generate_BitwiseBinaryOpWithOptionalFeedback(
141        bitwise_op, left, right, [&] { return context; }, nullptr, nullptr,
142        UpdateFeedbackMode::kOptionalFeedback);
143  }
144
145 private:
146  using SmiOperation =
147      std::function<TNode<Object>(TNode<Smi>, TNode<Smi>, TVariable<Smi>*)>;
148  using FloatOperation =
149      std::function<TNode<Float64T>(TNode<Float64T>, TNode<Float64T>)>;
150
151  TNode<Object> Generate_BinaryOperationWithFeedback(
152      const LazyNode<Context>& context, TNode<Object> left, TNode<Object> right,
153      TNode<UintPtrT> slot, const LazyNode<HeapObject>& maybe_feedback_vector,
154      const SmiOperation& smiOperation, const FloatOperation& floatOperation,
155      Operation op, UpdateFeedbackMode update_feedback_mode,
156      bool rhs_known_smi);
157
158  TNode<Object> Generate_BitwiseBinaryOpWithOptionalFeedback(
159      Operation bitwise_op, TNode<Object> left, TNode<Object> right,
160      const LazyNode<Context>& context, TNode<UintPtrT>* slot,
161      const LazyNode<HeapObject>* maybe_feedback_vector,
162      UpdateFeedbackMode update_feedback_mode);
163
164  TNode<Object> Generate_BitwiseBinaryOpWithSmiOperandAndOptionalFeedback(
165      Operation bitwise_op, TNode<Object> left, TNode<Object> right,
166      const LazyNode<Context>& context, TNode<UintPtrT>* slot,
167      const LazyNode<HeapObject>* maybe_feedback_vector,
168      UpdateFeedbackMode update_feedback_mode);
169
170  // Check if output is known to be Smi when both operands of bitwise operation
171  // are Smi.
172  bool IsBitwiseOutputKnownSmi(Operation bitwise_op) {
173    switch (bitwise_op) {
174      case Operation::kBitwiseAnd:
175      case Operation::kBitwiseOr:
176      case Operation::kBitwiseXor:
177      case Operation::kShiftRight:
178        return true;
179      default:
180        return false;
181    }
182  }
183};
184
185}  // namespace internal
186}  // namespace v8
187
188#endif  // V8_IC_BINARY_OP_ASSEMBLER_H_
189