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