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 336 : 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 336 : 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 : var_type_feedback.Bind(
71 336 : 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 336 : }
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 336 : 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 :
164 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kString));
165 : var_result.Bind(
166 336 : CallBuiltin(Builtins::kStringAdd_CheckNone, context, lhs, rhs));
167 :
168 672 : Goto(&end);
169 336 : }
170 : }
171 :
172 336 : BIND(&check_rhsisoddball);
173 : {
174 : // Check if rhs is an oddball. At this point we know lhs is either a
175 : // Smi or number or oddball and rhs is not a number or Smi.
176 336 : Node* rhs_instance_type = LoadInstanceType(rhs);
177 336 : Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
178 336 : GotoIf(rhs_is_oddball, &call_with_oddball_feedback);
179 672 : Branch(IsBigIntInstanceType(rhs_instance_type), &bigint,
180 336 : &call_with_any_feedback);
181 : }
182 :
183 336 : BIND(&bigint);
184 : {
185 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
186 : var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
187 336 : SmiConstant(Operation::kAdd)));
188 336 : Goto(&end);
189 : }
190 :
191 336 : BIND(&call_with_oddball_feedback);
192 : {
193 : var_type_feedback.Bind(
194 336 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
195 336 : Goto(&call_add_stub);
196 : }
197 :
198 336 : BIND(&call_with_any_feedback);
199 : {
200 336 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
201 336 : Goto(&call_add_stub);
202 : }
203 :
204 336 : BIND(&call_add_stub);
205 : {
206 336 : var_result.Bind(CallBuiltin(Builtins::kAdd, context, lhs, rhs));
207 336 : Goto(&end);
208 : }
209 :
210 336 : BIND(&end);
211 336 : UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
212 672 : return var_result.value();
213 : }
214 :
215 1344 : Node* BinaryOpAssembler::Generate_BinaryOperationWithFeedback(
216 : Node* context, Node* lhs, Node* rhs, Node* slot_id, Node* feedback_vector,
217 : const SmiOperation& smiOperation, const FloatOperation& floatOperation,
218 : Operation op, bool rhs_is_smi) {
219 2688 : Label do_float_operation(this), end(this), call_stub(this),
220 2688 : check_rhsisoddball(this, Label::kDeferred), call_with_any_feedback(this),
221 2688 : if_lhsisnotnumber(this, Label::kDeferred),
222 2688 : if_bigint(this, Label::kDeferred);
223 2688 : VARIABLE(var_float_lhs, MachineRepresentation::kFloat64);
224 2688 : VARIABLE(var_float_rhs, MachineRepresentation::kFloat64);
225 2688 : VARIABLE(var_type_feedback, MachineRepresentation::kTaggedSigned);
226 2688 : VARIABLE(var_result, MachineRepresentation::kTagged);
227 :
228 2688 : Label if_lhsissmi(this);
229 : // If rhs is known to be an Smi (in the SubSmi, MulSmi, DivSmi, ModSmi
230 : // bytecode handlers) we want to fast path Smi operation. For the normal
231 : // operation, we want to fast path both Smi and Number operations, so this
232 : // path should not be marked as Deferred.
233 : Label if_lhsisnotsmi(this,
234 2688 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
235 1344 : Branch(TaggedIsNotSmi(lhs), &if_lhsisnotsmi, &if_lhsissmi);
236 :
237 : // Check if the {lhs} is a Smi or a HeapObject.
238 1344 : BIND(&if_lhsissmi);
239 : {
240 1344 : Comment("lhs is Smi");
241 1344 : if (!rhs_is_smi) {
242 : // Check if the {rhs} is also a Smi.
243 1344 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
244 672 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
245 672 : BIND(&if_rhsisnotsmi);
246 : {
247 : // Check if {rhs} is a HeapNumber.
248 672 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
249 :
250 : // Perform a floating point operation.
251 672 : var_float_lhs.Bind(SmiToFloat64(lhs));
252 672 : var_float_rhs.Bind(LoadHeapNumberValue(rhs));
253 672 : Goto(&do_float_operation);
254 : }
255 :
256 1344 : BIND(&if_rhsissmi);
257 : }
258 :
259 : {
260 1344 : Comment("perform smi operation");
261 1344 : var_result.Bind(smiOperation(lhs, rhs, &var_type_feedback));
262 1344 : Goto(&end);
263 : }
264 : }
265 :
266 1344 : BIND(&if_lhsisnotsmi);
267 : {
268 1344 : Comment("lhs is not Smi");
269 : // Check if the {lhs} is a HeapNumber.
270 1344 : GotoIfNot(IsHeapNumber(lhs), &if_lhsisnotnumber);
271 :
272 1344 : if (!rhs_is_smi) {
273 : // Check if the {rhs} is a Smi.
274 1344 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
275 672 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
276 :
277 672 : BIND(&if_rhsisnotsmi);
278 : {
279 : // Check if the {rhs} is a HeapNumber.
280 672 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
281 :
282 : // Perform a floating point operation.
283 672 : var_float_lhs.Bind(LoadHeapNumberValue(lhs));
284 672 : var_float_rhs.Bind(LoadHeapNumberValue(rhs));
285 672 : Goto(&do_float_operation);
286 : }
287 :
288 1344 : BIND(&if_rhsissmi);
289 : }
290 :
291 : {
292 : // Perform floating point operation.
293 1344 : var_float_lhs.Bind(LoadHeapNumberValue(lhs));
294 1344 : var_float_rhs.Bind(SmiToFloat64(rhs));
295 1344 : Goto(&do_float_operation);
296 : }
297 : }
298 :
299 1344 : BIND(&do_float_operation);
300 : {
301 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
302 1344 : Node* lhs_value = var_float_lhs.value();
303 1344 : Node* rhs_value = var_float_rhs.value();
304 1344 : Node* value = floatOperation(lhs_value, rhs_value);
305 1344 : var_result.Bind(AllocateHeapNumberWithValue(value));
306 1344 : Goto(&end);
307 : }
308 :
309 1344 : BIND(&if_lhsisnotnumber);
310 : {
311 : // No checks on rhs are done yet. We just know lhs is not a number or Smi.
312 2688 : Label if_left_bigint(this), if_left_oddball(this);
313 1344 : Node* lhs_instance_type = LoadInstanceType(lhs);
314 1344 : GotoIf(IsBigIntInstanceType(lhs_instance_type), &if_left_bigint);
315 1344 : Node* lhs_is_oddball = InstanceTypeEqual(lhs_instance_type, ODDBALL_TYPE);
316 1344 : Branch(lhs_is_oddball, &if_left_oddball, &call_with_any_feedback);
317 :
318 1344 : BIND(&if_left_oddball);
319 : {
320 2688 : Label if_rhsissmi(this), if_rhsisnotsmi(this);
321 1344 : Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
322 :
323 1344 : BIND(&if_rhsissmi);
324 : {
325 : var_type_feedback.Bind(
326 1344 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
327 1344 : Goto(&call_stub);
328 : }
329 :
330 1344 : BIND(&if_rhsisnotsmi);
331 : {
332 : // Check if {rhs} is a HeapNumber.
333 1344 : GotoIfNot(IsHeapNumber(rhs), &check_rhsisoddball);
334 :
335 : var_type_feedback.Bind(
336 1344 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
337 1344 : Goto(&call_stub);
338 1344 : }
339 : }
340 :
341 1344 : BIND(&if_left_bigint);
342 : {
343 1344 : GotoIf(TaggedIsSmi(rhs), &call_with_any_feedback);
344 1344 : Branch(IsBigInt(rhs), &if_bigint, &call_with_any_feedback);
345 1344 : }
346 : }
347 :
348 1344 : BIND(&check_rhsisoddball);
349 : {
350 : // Check if rhs is an oddball. At this point we know lhs is either a
351 : // Smi or number or oddball and rhs is not a number or Smi.
352 1344 : Node* rhs_instance_type = LoadInstanceType(rhs);
353 1344 : GotoIf(IsBigIntInstanceType(rhs_instance_type), &if_bigint);
354 1344 : Node* rhs_is_oddball = InstanceTypeEqual(rhs_instance_type, ODDBALL_TYPE);
355 1344 : GotoIfNot(rhs_is_oddball, &call_with_any_feedback);
356 :
357 : var_type_feedback.Bind(
358 1344 : SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
359 1344 : Goto(&call_stub);
360 : }
361 :
362 : // This handles the case where at least one input is a BigInt.
363 1344 : BIND(&if_bigint);
364 : {
365 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kBigInt));
366 : var_result.Bind(CallRuntime(Runtime::kBigIntBinaryOp, context, lhs, rhs,
367 1344 : SmiConstant(op)));
368 1344 : Goto(&end);
369 : }
370 :
371 1344 : BIND(&call_with_any_feedback);
372 : {
373 1344 : var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
374 1344 : Goto(&call_stub);
375 : }
376 :
377 1344 : BIND(&call_stub);
378 : {
379 : Node* result;
380 1344 : switch (op) {
381 : case Operation::kSubtract:
382 336 : result = CallBuiltin(Builtins::kSubtract, context, lhs, rhs);
383 336 : break;
384 : case Operation::kMultiply:
385 336 : result = CallBuiltin(Builtins::kMultiply, context, lhs, rhs);
386 336 : break;
387 : case Operation::kDivide:
388 336 : result = CallBuiltin(Builtins::kDivide, context, lhs, rhs);
389 336 : break;
390 : case Operation::kModulus:
391 336 : result = CallBuiltin(Builtins::kModulus, context, lhs, rhs);
392 336 : break;
393 : default:
394 0 : UNREACHABLE();
395 : }
396 1344 : var_result.Bind(result);
397 1344 : Goto(&end);
398 : }
399 :
400 1344 : BIND(&end);
401 1344 : UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_id);
402 2688 : return var_result.value();
403 : }
404 :
405 336 : Node* BinaryOpAssembler::Generate_SubtractWithFeedback(Node* context, Node* lhs,
406 : Node* rhs, Node* slot_id,
407 : Node* feedback_vector,
408 : bool rhs_is_smi) {
409 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
410 336 : Label end(this);
411 672 : TVARIABLE(Number, var_result);
412 : // If rhs is known to be an Smi (for SubSmi) we want to fast path Smi
413 : // operation. For the normal Sub operation, we want to fast path both
414 : // Smi and Number operations, so this path should not be marked as Deferred.
415 : Label if_overflow(this,
416 672 : rhs_is_smi ? Label::kDeferred : Label::kNonDeferred);
417 336 : var_result = TrySmiSub(CAST(lhs), CAST(rhs), &if_overflow);
418 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
419 336 : Goto(&end);
420 :
421 336 : BIND(&if_overflow);
422 : {
423 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
424 336 : Node* value = Float64Sub(SmiToFloat64(lhs), SmiToFloat64(rhs));
425 336 : var_result = AllocateHeapNumberWithValue(value);
426 336 : Goto(&end);
427 : }
428 :
429 336 : BIND(&end);
430 672 : return var_result.value();
431 672 : };
432 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
433 672 : return Float64Sub(lhs, rhs);
434 1008 : };
435 : return Generate_BinaryOperationWithFeedback(
436 : context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
437 336 : Operation::kSubtract, rhs_is_smi);
438 : }
439 :
440 336 : Node* BinaryOpAssembler::Generate_MultiplyWithFeedback(Node* context, Node* lhs,
441 : Node* rhs, Node* slot_id,
442 : Node* feedback_vector,
443 : bool rhs_is_smi) {
444 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
445 336 : TNode<Number> result = SmiMul(CAST(lhs), CAST(rhs));
446 : var_type_feedback->Bind(SelectSmiConstant(
447 672 : TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
448 336 : BinaryOperationFeedback::kNumber));
449 336 : return result;
450 336 : };
451 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
452 672 : return Float64Mul(lhs, rhs);
453 1008 : };
454 : return Generate_BinaryOperationWithFeedback(
455 : context, lhs, rhs, slot_id, feedback_vector, smiFunction, floatFunction,
456 336 : Operation::kMultiply, rhs_is_smi);
457 : }
458 :
459 336 : Node* BinaryOpAssembler::Generate_DivideWithFeedback(
460 : Node* context, Node* dividend, Node* divisor, Node* slot_id,
461 : Node* feedback_vector, bool rhs_is_smi) {
462 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
463 336 : VARIABLE(var_result, MachineRepresentation::kTagged);
464 : // If rhs is known to be an Smi (for DivSmi) we want to fast path Smi
465 : // operation. For the normal Div operation, we want to fast path both
466 : // Smi and Number operations, so this path should not be marked as Deferred.
467 672 : Label bailout(this, rhs_is_smi ? Label::kDeferred : Label::kNonDeferred),
468 672 : end(this);
469 336 : var_result.Bind(TrySmiDiv(CAST(lhs), CAST(rhs), &bailout));
470 336 : var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
471 336 : Goto(&end);
472 :
473 336 : BIND(&bailout);
474 : {
475 : var_type_feedback->Bind(
476 336 : SmiConstant(BinaryOperationFeedback::kSignedSmallInputs));
477 336 : Node* value = Float64Div(SmiToFloat64(lhs), SmiToFloat64(rhs));
478 336 : var_result.Bind(AllocateHeapNumberWithValue(value));
479 336 : Goto(&end);
480 : }
481 :
482 336 : BIND(&end);
483 672 : return var_result.value();
484 672 : };
485 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
486 672 : return Float64Div(lhs, rhs);
487 1008 : };
488 : return Generate_BinaryOperationWithFeedback(
489 : context, dividend, divisor, slot_id, feedback_vector, smiFunction,
490 336 : floatFunction, Operation::kDivide, rhs_is_smi);
491 : }
492 :
493 336 : Node* BinaryOpAssembler::Generate_ModulusWithFeedback(
494 : Node* context, Node* dividend, Node* divisor, Node* slot_id,
495 : Node* feedback_vector, bool rhs_is_smi) {
496 336 : auto smiFunction = [=](Node* lhs, Node* rhs, Variable* var_type_feedback) {
497 336 : TNode<Number> result = SmiMod(CAST(lhs), CAST(rhs));
498 : var_type_feedback->Bind(SelectSmiConstant(
499 672 : TaggedIsSmi(result), BinaryOperationFeedback::kSignedSmall,
500 336 : BinaryOperationFeedback::kNumber));
501 336 : return result;
502 336 : };
503 336 : auto floatFunction = [=](Node* lhs, Node* rhs) {
504 672 : return Float64Mod(lhs, rhs);
505 1008 : };
506 : return Generate_BinaryOperationWithFeedback(
507 : context, dividend, divisor, slot_id, feedback_vector, smiFunction,
508 336 : floatFunction, Operation::kModulus, rhs_is_smi);
509 : }
510 :
511 336 : Node* BinaryOpAssembler::Generate_ExponentiateWithFeedback(
512 : Node* context, Node* base, Node* exponent, Node* slot_id,
513 : Node* feedback_vector, bool rhs_is_smi) {
514 : // We currently don't optimize exponentiation based on feedback.
515 336 : Node* dummy_feedback = SmiConstant(BinaryOperationFeedback::kAny);
516 336 : UpdateFeedback(dummy_feedback, feedback_vector, slot_id);
517 336 : return CallBuiltin(Builtins::kExponentiate, context, base, exponent);
518 : }
519 :
520 : } // namespace internal
521 86739 : } // namespace v8
|