@@ -348,6 +348,102 @@ void Compiler::branch_if_both_int32(Assembler::Reg lhs, Assembler::Reg rhs, Code
348
348
not_int32_case.link (m_assembler);
349
349
}
350
350
351
+ void Compiler::jump_if_not_double (Assembler::Reg reg, Assembler::Reg nan, Assembler::Reg temp, Assembler::Label& label)
352
+ {
353
+ Assembler::Label is_double {};
354
+ // if (reg == nan) goto is_double
355
+ m_assembler.jump_if (
356
+ Assembler::Operand::Register (reg),
357
+ Assembler::Condition::EqualTo,
358
+ Assembler::Operand::Register (nan),
359
+ is_double);
360
+ // temp = reg
361
+ m_assembler.mov (Assembler::Operand::Register (temp), Assembler::Operand::Register (reg));
362
+ // if (temp & CANON_NAN_BITS == CANON_NAN_BITS) goto label
363
+ m_assembler.bitwise_and (
364
+ Assembler::Operand::Register (temp),
365
+ Assembler::Operand::Register (nan));
366
+ m_assembler.jump_if (
367
+ Assembler::Operand::Register (temp),
368
+ Assembler::Condition::EqualTo,
369
+ Assembler::Operand::Register (nan),
370
+ label);
371
+ is_double.link (m_assembler);
372
+ }
373
+
374
+ void Compiler::convert_to_double (Assembler::Reg dst, Assembler::Reg src, Assembler::Reg nan, Assembler::Reg temp, Assembler::Label& not_number)
375
+ {
376
+ Assembler::Label is_i32;
377
+ Assembler::Label end;
378
+ jump_if_int32 (src, is_i32);
379
+ jump_if_not_double (src, nan, temp, not_number);
380
+ m_assembler.mov (
381
+ Assembler::Operand::FloatRegister (dst),
382
+ Assembler::Operand::Register (src));
383
+ m_assembler.jump (end);
384
+ is_i32.link (m_assembler);
385
+ m_assembler.convert_i32_to_double (
386
+ Assembler::Operand::FloatRegister (dst),
387
+ Assembler::Operand::Register (src));
388
+ end.link (m_assembler);
389
+ }
390
+
391
+ template <typename CodegenI32, typename CodegenDouble, typename CodegenValue>
392
+ void Compiler::branch_if_both_numbers (Assembler::Reg lhs, Assembler::Reg rhs, CodegenI32 codegen_i32, CodegenDouble codegen_double, CodegenValue codegen_value)
393
+ {
394
+ Assembler::Label end {};
395
+ Assembler::Label slow_case {};
396
+
397
+ // The only case where we can take the int32 fastpath
398
+ branch_if_both_int32 (lhs, rhs, [&] {
399
+ // use GPR0 to preserve lhs for the slow case
400
+ m_assembler.mov32 (
401
+ Assembler::Operand::Register (GPR0),
402
+ Assembler::Operand::Register (lhs));
403
+ store_accumulator (codegen_i32 (GPR0, rhs, slow_case));
404
+
405
+ // accumulator |= SHIFTED_INT32_TAG;
406
+ m_assembler.mov (
407
+ Assembler::Operand::Register (GPR0),
408
+ Assembler::Operand::Imm (SHIFTED_INT32_TAG));
409
+ m_assembler.bitwise_or (
410
+ Assembler::Operand::Register (CACHED_ACCUMULATOR),
411
+ Assembler::Operand::Register (GPR0));
412
+ m_assembler.jump (end);
413
+ });
414
+
415
+ // accumulator = op_double(lhs.to_double(), rhs.to_double()) [if not numeric goto slow_case]
416
+ auto temp_register = GPR0;
417
+ auto nan_register = GPR1;
418
+ m_assembler.mov (Assembler::Operand::Register (nan_register), Assembler::Operand::Imm (CANON_NAN_BITS));
419
+ convert_to_double (FPR0, ARG1, nan_register, temp_register, slow_case);
420
+ convert_to_double (FPR1, ARG2, nan_register, temp_register, slow_case);
421
+ auto result_fp_register = codegen_double (FPR0, FPR1);
422
+ // if result != result then result = nan (canonical)
423
+ Assembler::Label nan_case;
424
+ m_assembler.jump_if (
425
+ Assembler::Operand::FloatRegister (result_fp_register),
426
+ Assembler::Condition::Unordered,
427
+ Assembler::Operand::FloatRegister (result_fp_register),
428
+ nan_case);
429
+ m_assembler.mov (
430
+ Assembler::Operand::Register (CACHED_ACCUMULATOR),
431
+ Assembler::Operand::FloatRegister (result_fp_register));
432
+ m_assembler.jump (end);
433
+ nan_case.link (m_assembler);
434
+ m_assembler.mov (
435
+ Assembler::Operand::Register (CACHED_ACCUMULATOR),
436
+ Assembler::Operand::Register (nan_register));
437
+ m_assembler.jump (end);
438
+
439
+ slow_case.link (m_assembler);
440
+
441
+ // accumulator = TRY(op_value(lhs, rhs))
442
+ store_accumulator (codegen_value (lhs, rhs));
443
+ check_exception ();
444
+ end.link (m_assembler);
445
+ }
446
+
351
447
void Compiler::compile_increment (Bytecode::Op::Increment const &)
352
448
{
353
449
load_accumulator (ARG1);
0 commit comments