Line data Source code
1 : // Copyright 2016 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 : #include "src/ic/binary-op-assembler.h"
6 :
7 : #include "src/globals.h"
8 :
9 : namespace v8 {
10 : namespace internal {
11 :
12 : using compiler::Node;
13 :
14 336 : Node* BinaryOpAssembler::Generate_AddWithFeedback(Node* context, Node* lhs,
15 : Node* rhs, Node* slot_id,
16 : Node* feedback_vector,
17 : bool rhs_is_smi) {
18 : // Shared entry for floating point addition.
19 672 : Label do_fadd(this), if_lhsisnotnumber(this, Label::kDeferred),
20 672 : check_rhsisoddball(this, Label::kDeferred),
21 672 : call_with_oddball_feedback(this), call_with_any_feedback(this),
22 672 : call_add_stub(this), end(this), bigint(this, Label::kDeferred);
23 672 : VARIABLE(var_fadd_lhs, MachineRepresentation::kFloat64);
24 672 : VARIABLE(var_fadd_rhs, MachineRepresentation::kFloat64);
25 672 : VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
26 672 : VARIABLE(var_result, MachineRepresentation::kTagged);
27 :
28 : // Check if the {lhs} is a Smi or a HeapObject.
29 672 : Label if_lhsissmi(this);
30 : // If rhs is known to be an Smi we want to fast path Smi operation. This is
31 : // for AddSmi operation. For the normal Add operation, we want to fast path
32 : // both Smi and Number operations, so this path should not be marked as
33 : // Deferred.
34 : Label if_lhsisnotsmi(this,
35 672 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
36 336 : Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
37 :
38 336 : BIND(&if_lhsissmi);
39 : {
40 336 : Comment("lhs is Smi");
41 336 : if (!rhs_is_smi) {
42 : // Check if the {rhs} is also a Smi.
43 336 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
44 168 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
45 :
46 168 : BIND(&if_rhsisnotsmi);
47 : {
48 : // Check if the {rhs} is a HeapNumber.
49 168 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
50 :
51 168 : var_fadd_lhs.Bind(SmiToFloat64(lhs));
52 168 : var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
53 168 : Goto(&do_fadd);
54 : }
55 :
56 168 : BIND(&if_rhsissmi);
57 : }
58 :
59 : {
60 336 : Comment("perform smi operation");
61 : // If rhs is known to be an Smi we want to fast path Smi operation. This
62 : // is for AddSmi operation. For the normal Add operation, we want to fast
63 : // path both Smi and Number operations, so this path should not be marked
64 : // as Deferred.
65 : Label if_overflow(this,
66 672 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
67 336 : TNode<Smi> smi_result = TrySmiAdd(CAST(lhs), CAST(rhs), &if_overflow);
68 : // Not overflowed.
69 : {
70 336 : var_type_feedback.Bind(
71 672 : SmiConstant(BinaryOperationFeedback::kSignedSmall));
72 336 : var_result.Bind(smi_result);
73 336 : Goto(&end);
74 : }
75 :
76 336 : BIND(&if_overflow);
77 : {
78 336 : var_fadd_lhs.Bind(SmiToFloat64(lhs));
79 336 : var_fadd_rhs.Bind(SmiToFloat64(rhs));
80 336 : Goto(&do_fadd);
81 : }
82 : }
83 : }
84 :
85 336 : BIND(&if_lhsisnotsmi);
86 : {
87 : // Check if {lhs} is a HeapNumber.
88 336 : GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
89 :
90 336 : if (!rhs_is_smi) {
91 : // Check if the {rhs} is Smi.
92 336 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
93 168 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
94 :
95 168 : BIND(&if_rhsisnotsmi);
96 : {
97 : // Check if the {rhs} is a HeapNumber.
98 168 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
99 :
100 168 : var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
101 168 : var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
102 168 : Goto(&do_fadd);
103 : }
104 :
105 168 : BIND(&if_rhsissmi);
106 : }
107 : {
108 336 : var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
109 336 : var_fadd_rhs.Bind(SmiToFloat64(rhs));
110 336 : Goto(&do_fadd);
111 : }
112 : }
113 :
114 336 : BIND(&do_fadd);
115 : {
116 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
117 336 : Node* value = Float64Add(var_fadd_lhs.value(), var_fadd_rhs.value());
118 336 : Node* result = AllocateHeapNumberWithValue(value);
119 336 : var_result.Bind(result);
120 336 : Goto(&end);
121 : }
122 :
123 336 : BIND(&if_lhsisnotnumber);
124 : {
125 : // No checks on rhs are done yet. We just know lhs is not a number or Smi.
126 672 : Label if_lhsisoddball(this), if_lhsisnotoddball(this);
127 336 : Node* lhs_instance_type = LoadInstanceType(lhs);
128 336 : Node* lhs_is_oddball = InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
129 336 : Branch(lhs_is_oddball, &if_lhsisoddball, &if_lhsisnotoddball);
130 :
131 336 : BIND(&if_lhsisoddball);
132 : {
133 336 : GotoIf(TaggedIsSmi(rhs), &call_with_oddball_feedback);
134 :
135 : // Check if {rhs} is a HeapNumber.
136 672 : Branch(IsHeapNumber(rhs), &call_with_oddball_feedback,
137 336 : &check_rhsisoddball);
138 : }
139 :
140 336 : BIND(&if_lhsisnotoddball);
141 : {
142 672 : Label lhs_is_string(this), lhs_is_bigint(this);
143 336 : GotoIf(IsStringInstanceType(lhs_instance_type), &lhs_is_string);
144 336 : GotoIf(IsBigIntInstanceType(lhs_instance_type), &lhs_is_bigint);
145 336 : Goto(&call_with_any_feedback);
146 :
147 336 : BIND(&lhs_is_bigint);
148 : {
149 336 : GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
150 336 : Branch(IsBigInt(rhs), &bigint, &call_with_any_feedback);
151 : }
152 :
153 336 : BIND(&lhs_is_string);
154 : // Check if the {rhs} is a smi, and exit the string check early if it is.
155 336 : GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
156 :
157 336 : Node* rhs_instance_type = LoadInstanceType(rhs);
158 :
159 : // Exit unless {rhs} is a string. Since {lhs} is a string we no longer
160 : // need an Oddball check.
161 672 : GotoIfNot(IsStringInstanceType(rhs_instance_type),
162 336 : &call_with_any_feedback);
163 336 : var_result.Bind(
164 672 : StringAdd(context, CAST(lhs), CAST(rhs), &var_type_feedback));
165 336 : Goto(&end);
166 : }
167 : }
168 :
169 336 : BIND(&check_rhsisoddball);
170 : {
171 : // Check if rhs is an oddball. At this point we know lhs is either a
172 : // Smi or number or oddball and rhs is not a number or Smi.
173 336 : Node* rhs_instance_type = LoadInstanceType(rhs);
174 336 : Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
175 336 : GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
176 672 : Branch(IsBigIntInstanceType(rhs_instance_type), &bigint,
177 336 : &call_with_any_feedback);
178 : }
179 :
180 336 : BIND(&bigint);
181 : {
182 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
183 672 : var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
184 1008 : SmiConstant(Operation::kAdd)));
185 336 : Goto(&end);
186 : }
187 :
188 336 : BIND(&call_with_oddball_feedback);
189 : {
190 336 : var_type_feedback.Bind(
191 672 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
192 336 : Goto(&call_add_stub);
193 : }
194 :
195 336 : BIND(&call_with_any_feedback);
196 : {
197 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
198 336 : Goto(&call_add_stub);
199 : }
200 :
201 336 : BIND(&call_add_stub);
202 : {
203 336 : var_result.Bind(CallBuiltin(Builtins::kAdd, context, lhs, rhs));
204 336 : Goto(&end);
205 : }
206 :
207 336 : BIND(&end);
208 336 : UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
209 672 : return var_result.value();
210 : }
211 :
212 1344 : Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
213 : Node* context, Node* lhs, Node* rhs, Node* slot_id, Node* feedback_vector,
214 : const SmiOperation& smiOperation, const FloatOperation& floatOperation,
215 : Operation op, bool rhs_is_smi) {
216 2688 : Label do_float_operation(this), end(this), call_stub(this),
217 2688 : check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
218 2688 : if_lhsisnotnumber(this, Label::kDeferred),
219 2688 : if_bigint(this, Label::kDeferred);
220 2688 : VARIABLE(var_float_lhs, MachineRepresentation::kFloat64);
221 2688 : VARIABLE(var_float_rhs, MachineRepresentation::kFloat64);
222 2688 : VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
223 2688 : VARIABLE(var_result, MachineRepresentation::kTagged);
224 :
225 2688 : Label if_lhsissmi(this);
226 : // If rhs is known to be an Smi (in the SubSmi, MulSmi, DivSmi, ModSmi
227 : // bytecode handlers) we want to fast path Smi operation. For the normal
228 : // operation, we want to fast path both Smi and Number operations, so this
229 : // path should not be marked as Deferred.
230 : Label if_lhsisnotsmi(this,
231 2688 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
232 1344 : Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
233 :
234 : // Check if the {lhs} is a Smi or a HeapObject.
235 1344 : BIND(&if_lhsissmi);
236 : {
237 1344 : Comment("lhs is Smi");
238 1344 : if (!rhs_is_smi) {
239 : // Check if the {rhs} is also a Smi.
240 1344 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
241 672 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
242 672 : BIND(&if_rhsisnotsmi);
243 : {
244 : // Check if {rhs} is a HeapNumber.
245 672 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
246 :
247 : // Perform a floating point operation.
248 672 : var_float_lhs.Bind(SmiToFloat64(lhs));
249 672 : var_float_rhs.Bind(LoadHeapNumberValue(rhs));
250 672 : Goto(&do_float_operation);
251 : }
252 :
253 672 : BIND(&if_rhsissmi);
254 : }
255 :
256 : {
257 1344 : Comment("perform smi operation");
258 1344 : var_result.Bind(smiOperation(lhs, rhs, &var_type_feedback));
259 1344 : Goto(&end);
260 : }
261 : }
262 :
263 1344 : BIND(&if_lhsisnotsmi);
264 : {
265 1344 : Comment("lhs is not Smi");
266 : // Check if the {lhs} is a HeapNumber.
267 1344 : GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
268 :
269 1344 : if (!rhs_is_smi) {
270 : // Check if the {rhs} is a Smi.
271 1344 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
272 672 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
273 :
274 672 : BIND(&if_rhsisnotsmi);
275 : {
276 : // Check if the {rhs} is a HeapNumber.
277 672 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
278 :
279 : // Perform a floating point operation.
280 672 : var_float_lhs.Bind(LoadHeapNumberValue(lhs));
281 672 : var_float_rhs.Bind(LoadHeapNumberValue(rhs));
282 672 : Goto(&do_float_operation);
283 : }
284 :
285 672 : BIND(&if_rhsissmi);
286 : }
287 :
288 : {
289 : // Perform floating point operation.
290 1344 : var_float_lhs.Bind(LoadHeapNumberValue(lhs));
291 1344 : var_float_rhs.Bind(SmiToFloat64(rhs));
292 1344 : Goto(&do_float_operation);
293 : }
294 : }
295 :
296 1344 : BIND(&do_float_operation);
297 : {
298 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
299 1344 : Node* lhs_value = var_float_lhs.value();
300 1344 : Node* rhs_value = var_float_rhs.value();
301 1344 : Node* value = floatOperation(lhs_value, rhs_value);
302 1344 : var_result.Bind(AllocateHeapNumberWithValue(value));
303 1344 : Goto(&end);
304 : }
305 :
306 1344 : BIND(&if_lhsisnotnumber);
307 : {
308 : // No checks on rhs are done yet. We just know lhs is not a number or Smi.
309 2688 : Label if_left_bigint(this), if_left_oddball(this);
310 1344 : Node* lhs_instance_type = LoadInstanceType(lhs);
311 1344 : GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_left_bigint);
312 1344 : Node* lhs_is_oddball = InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
313 1344 : Branch(lhs_is_oddball, &if_left_oddball, &call_with_any_feedback);
314 :
315 1344 : BIND(&if_left_oddball);
316 : {
317 2688 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
318 1344 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
319 :
320 1344 : BIND(&if_rhsissmi);
321 : {
322 1344 : var_type_feedback.Bind(
323 2688 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
324 1344 : Goto(&call_stub);
325 : }
326 :
327 1344 : BIND(&if_rhsisnotsmi);
328 : {
329 : // Check if {rhs} is a HeapNumber.
330 1344 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
331 :
332 1344 : var_type_feedback.Bind(
333 2688 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
334 1344 : Goto(&call_stub);
335 : }
336 : }
337 :
338 1344 : BIND(&if_left_bigint);
339 : {
340 1344 : GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
341 1344 : Branch(IsBigInt(rhs), &if_bigint, &call_with_any_feedback);
342 : }
343 : }
344 :
345 1344 : BIND(&check_rhsisoddball);
346 : {
347 : // Check if rhs is an oddball. At this point we know lhs is either a
348 : // Smi or number or oddball and rhs is not a number or Smi.
349 1344 : Node* rhs_instance_type = LoadInstanceType(rhs);
350 1344 : GotoIf(IsBigIntInstanceType(rhs_instance_type), &if_bigint);
351 1344 : Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
352 1344 : GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
353 :
354 1344 : var_type_feedback.Bind(
355 2688 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
356 1344 : Goto(&call_stub);
357 : }
358 :
359 : // This handles the case where at least one input is a BigInt.
360 1344 : BIND(&if_bigint);
361 : {
362 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
363 2688 : var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
364 4032 : SmiConstant(op)));
365 1344 : Goto(&end);
366 : }
367 :
368 1344 : BIND(&call_with_any_feedback);
369 : {
370 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
371 1344 : Goto(&call_stub);
372 : }
373 :
374 1344 : BIND(&call_stub);
375 : {
376 : Node* result;
377 1344 : switch (op) {
378 : case Operation::kSubtract:
379 336 : result = CallBuiltin(Builtins::kSubtract, context, lhs, rhs);
380 336 : break;
381 : case Operation::kMultiply:
382 336 : result = CallBuiltin(Builtins::kMultiply, context, lhs, rhs);
383 336 : break;
384 : case Operation::kDivide:
385 336 : result = CallBuiltin(Builtins::kDivide, context, lhs, rhs);
386 336 : break;
387 : case Operation::kModulus:
388 336 : result = CallBuiltin(Builtins::kModulus, context, lhs, rhs);
389 336 : break;
390 : default:
391 0 : UNREACHABLE();
392 : }
393 1344 : var_result.Bind(result);
394 1344 : Goto(&end);
395 : }
396 :
397 1344 : BIND(&end);
398 1344 : UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
399 2688 : return var_result.value();
400 : }
401 :
402 336 : Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
403 : Node* rhs, Node* slot_id,
404 : Node* feedback_vector,
405 : bool rhs_is_smi) {
406 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
407 5376 : Label end(this);
408 672 : TVARIABLE(Number, var_result);
409 : // If rhs is known to be an Smi (for SubSmi) we want to fast path Smi
410 : // operation. For the normal Sub operation, we want to fast path both
411 : // Smi and Number operations, so this path should not be marked as Deferred.
412 : Label if_overflow(this,
413 1008 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
414 1008 : var_result = TrySmiSub(CAST(lhs), CAST(rhs), &if_overflow);
415 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
416 336 : Goto(&end);
417 :
418 336 : BIND(&if_overflow);
419 : {
420 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
421 1344 : Node* value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs));
422 672 : var_result = AllocateHeapNumberWithValue(value);
423 336 : Goto(&end);
424 : }
425 :
426 336 : BIND(&end);
427 672 : return var_result.value();
428 336 : };
429 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
430 672 : return Float64Sub(lhs, rhs);
431 1008 : };
432 672 : return Generate_BinaryOperationWithFeedback(
433 : context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
434 672 : Operation::kSubtract, rhs_is_smi);
435 : }
436 :
437 336 : Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
438 : Node* rhs, Node* slot_id,
439 : Node* feedback_vector,
440 : bool rhs_is_smi) {
441 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
442 1008 : TNode<Number> result = SmiMul(CAST(lhs), CAST(rhs));
443 672 : var_type_feedback->Bind(SelectSmiConstant(
444 1008 : TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
445 1344 : BinaryOperationFeedback::kNumber));
446 336 : return result;
447 336 : };
448 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
449 672 : return Float64Mul(lhs, rhs);
450 1008 : };
451 672 : return Generate_BinaryOperationWithFeedback(
452 : context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
453 672 : Operation::kMultiply, rhs_is_smi);
454 : }
455 :
456 336 : Node* BinaryOpAssembler::Generate_DivideWithFeedback(
457 : Node* context, Node* dividend, Node* divisor, Node* slot_id,
458 : Node* feedback_vector, bool rhs_is_smi) {
459 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
460 5712 : VARIABLE(var_result, MachineRepresentation::kTagged);
461 : // If rhs is known to be an Smi (for DivSmi) we want to fast path Smi
462 : // operation. For the normal Div operation, we want to fast path both
463 : // Smi and Number operations, so this path should not be marked as Deferred.
464 1008 : Label bailout(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
465 672 : end(this);
466 1008 : var_result.Bind(TrySmiDiv(CAST(lhs), CAST(rhs), &bailout));
467 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
468 336 : Goto(&end);
469 :
470 336 : BIND(&bailout);
471 : {
472 336 : var_type_feedback->Bind(
473 672 : SmiConstant(BinaryOperationFeedback::kSignedSmallInputs));
474 1344 : Node* value = Float64Div(SmiToFloat64(lhs), SmiToFloat64(rhs));
475 672 : var_result.Bind(AllocateHeapNumberWithValue(value));
476 336 : Goto(&end);
477 : }
478 :
479 336 : BIND(&end);
480 672 : return var_result.value();
481 336 : };
482 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
483 672 : return Float64Div(lhs, rhs);
484 1008 : };
485 672 : return Generate_BinaryOperationWithFeedback(
486 : context, dividend, divisor, slot_id, feedback_vector, smiFunction,
487 672 : floatFunction, Operation::kDivide, rhs_is_smi);
488 : }
489 :
490 336 : Node* BinaryOpAssembler::Generate_ModulusWithFeedback(
491 : Node* context, Node* dividend, Node* divisor, Node* slot_id,
492 : Node* feedback_vector, bool rhs_is_smi) {
493 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
494 1008 : TNode<Number> result = SmiMod(CAST(lhs), CAST(rhs));
495 672 : var_type_feedback->Bind(SelectSmiConstant(
496 1008 : TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
497 1344 : BinaryOperationFeedback::kNumber));
498 336 : return result;
499 336 : };
500 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
501 672 : return Float64Mod(lhs, rhs);
502 1008 : };
503 672 : return Generate_BinaryOperationWithFeedback(
504 : context, dividend, divisor, slot_id, feedback_vector, smiFunction,
505 672 : floatFunction, Operation::kModulus, rhs_is_smi);
506 : }
507 :
508 336 : Node* BinaryOpAssembler::Generate_ExponentiateWithFeedback(
509 : Node* context, Node* base, Node* exponent, Node* slot_id,
510 : Node* feedback_vector, bool rhs_is_smi) {
511 : // We currently don't optimize exponentiation based on feedback.
512 336 : Node* dummy_feedback = SmiConstant(BinaryOperationFeedback::kAny);
513 336 : UpdateFeedback(dummy_feedback, feedback_vector, slot_id);
514 336 : return CallBuiltin(Builtins::kExponentiate, context, base, exponent);
515 : }
516 :
517 : } // namespace internal
518 87414 : } // namespace v8
|