OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/compiler/code-stub-assembler.h" | 10 #include "src/compiler/code-stub-assembler.h" |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
466 void StringLengthStub::GenerateAssembly( | 466 void StringLengthStub::GenerateAssembly( |
467 compiler::CodeStubAssembler* assembler) const { | 467 compiler::CodeStubAssembler* assembler) const { |
468 compiler::Node* value = assembler->Parameter(0); | 468 compiler::Node* value = assembler->Parameter(0); |
469 compiler::Node* string = | 469 compiler::Node* string = |
470 assembler->LoadObjectField(value, JSValue::kValueOffset); | 470 assembler->LoadObjectField(value, JSValue::kValueOffset); |
471 compiler::Node* result = | 471 compiler::Node* result = |
472 assembler->LoadObjectField(string, String::kLengthOffset); | 472 assembler->LoadObjectField(string, String::kLengthOffset); |
473 assembler->Return(result); | 473 assembler->Return(result); |
474 } | 474 } |
475 | 475 |
476 void StrictEqualStub::GenerateAssembly( | |
477 compiler::CodeStubAssembler* assembler) const { | |
478 typedef compiler::CodeStubAssembler::Label Label; | |
479 typedef compiler::Node Node; | |
480 | |
481 Node* lhs = assembler->Parameter(0); | |
482 Node* rhs = assembler->Parameter(1); | |
483 Node* context = assembler->Parameter(2); | |
484 | |
Yang
2016/03/02 10:29:16
This is really hard to read... :P
I'd have preferr
Benedikt Meurer
2016/03/02 11:27:04
Added the pseudo-code thanks. The short-cut unfort
| |
485 Label if_true(assembler), if_false(assembler); | |
486 | |
487 // Check if {lhs} and {rhs} refer to the same object. | |
488 Label if_same(assembler), if_notsame(assembler); | |
489 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); | |
490 | |
491 assembler->Bind(&if_same); | |
492 { | |
493 // The {lhs} and {rhs} reference the exact same value, yet we need special | |
494 // treatment for HeapNumber, as NaN is not equal to NaN. | |
495 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it | |
496 // seems to be what is tested in the current SIMD.js testsuite. | |
497 | |
498 // Check if {lhs} (and therefore {rhs}) is a Smi or a HeapObject. | |
499 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
500 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | |
501 | |
502 assembler->Bind(&if_lhsisnotsmi); | |
503 { | |
504 // Load the map of {lhs}. | |
505 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | |
506 | |
507 // Check if {lhs} (and therefore {rhs}) is a HeapNumber. | |
508 Node* number_map = assembler->HeapNumberMapConstant(); | |
509 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | |
510 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | |
511 &if_lhsisnumber, &if_lhsisnotnumber); | |
512 | |
513 assembler->Bind(&if_lhsisnumber); | |
514 { | |
515 // Convert {lhs} (and therefore {rhs}) to floating point value. | |
516 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
517 | |
518 // Check if the HeapNumber value is a NaN. | |
519 assembler->BranchIfFloat64IsNaN(lhs_value, &if_false, &if_true); | |
520 } | |
521 | |
522 assembler->Bind(&if_lhsisnotnumber); | |
523 assembler->Goto(&if_true); | |
524 } | |
525 | |
526 assembler->Bind(&if_lhsissmi); | |
527 assembler->Goto(&if_true); | |
528 } | |
529 | |
530 assembler->Bind(&if_notsame); | |
531 { | |
532 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, | |
533 // String and Simd128Value they can still be considered equal. | |
534 Node* number_map = assembler->HeapNumberMapConstant(); | |
535 | |
536 // Check if {lhs} is a Smi or a HeapObject. | |
537 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); | |
538 assembler->Branch(assembler->WordIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi); | |
539 | |
540 assembler->Bind(&if_lhsisnotsmi); | |
541 { | |
542 // Load the map of {lhs}. | |
543 Node* lhs_map = assembler->LoadObjectField(lhs, HeapObject::kMapOffset); | |
544 | |
545 // Check if {lhs} is a HeapNumber. | |
546 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); | |
547 assembler->Branch(assembler->WordEqual(lhs_map, number_map), | |
548 &if_lhsisnumber, &if_lhsisnotnumber); | |
549 | |
550 assembler->Bind(&if_lhsisnumber); | |
551 { | |
552 // Check if {rhs} is a Smi or a HeapObject. | |
553 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
554 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
555 &if_rhsisnotsmi); | |
556 | |
557 assembler->Bind(&if_rhsissmi); | |
558 { | |
559 // Convert {lhs} and {rhs} to floating point values. | |
560 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
561 Node* rhs_value = assembler->SmiToFloat64(rhs); | |
562 | |
563 // Perform a floating point comparison of {lhs} and {rhs}. | |
564 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
565 &if_false); | |
566 } | |
567 | |
568 assembler->Bind(&if_rhsisnotsmi); | |
569 { | |
570 // Load the map of {rhs}. | |
571 Node* rhs_map = | |
572 assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | |
573 | |
574 // Check if {rhs} is also a HeapNumber. | |
575 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | |
576 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | |
577 &if_rhsisnumber, &if_rhsisnotnumber); | |
578 | |
579 assembler->Bind(&if_rhsisnumber); | |
580 { | |
581 // Convert {lhs} and {rhs} to floating point values. | |
582 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); | |
583 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); | |
584 | |
585 // Perform a floating point comparison of {lhs} and {rhs}. | |
586 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
587 &if_false); | |
588 } | |
589 | |
590 assembler->Bind(&if_rhsisnotnumber); | |
591 assembler->Goto(&if_false); | |
592 } | |
593 } | |
594 | |
595 assembler->Bind(&if_lhsisnotnumber); | |
596 { | |
597 // Check if {rhs} is a Smi or a HeapObject. | |
598 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
599 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
600 &if_rhsisnotsmi); | |
601 | |
602 assembler->Bind(&if_rhsissmi); | |
603 assembler->Goto(&if_false); | |
604 | |
605 assembler->Bind(&if_rhsisnotsmi); | |
606 { | |
607 // Load the instance type of {lhs}. | |
608 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); | |
609 | |
610 // Check if {lhs} is a String. | |
611 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); | |
612 assembler->Branch(assembler->Int32LessThan( | |
613 lhs_instance_type, | |
614 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
615 &if_lhsisstring, &if_lhsisnotstring); | |
616 | |
617 assembler->Bind(&if_lhsisstring); | |
618 { | |
619 // Load the instance type of {rhs}. | |
620 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); | |
621 | |
622 // Check if {rhs} is also a String. | |
623 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); | |
624 assembler->Branch(assembler->Int32LessThan( | |
625 rhs_instance_type, assembler->Int32Constant( | |
626 FIRST_NONSTRING_TYPE)), | |
627 &if_rhsisstring, &if_rhsisnotstring); | |
628 | |
629 assembler->Bind(&if_rhsisstring); | |
630 { | |
631 // TODO(bmeurer): Optimize this further once the StringEqual | |
632 // functionality is available in TurboFan land. | |
633 assembler->TailCallRuntime(Runtime::kStringEqual, context, lhs, | |
634 rhs); | |
635 } | |
636 | |
637 assembler->Bind(&if_rhsisnotstring); | |
638 assembler->Goto(&if_false); | |
639 } | |
640 | |
641 assembler->Bind(&if_lhsisnotstring); | |
642 { | |
643 // Check if {lhs} is a Simd128Value. | |
644 Label if_lhsissimd128value(assembler), | |
645 if_lhsisnotsimd128value(assembler); | |
646 assembler->Branch(assembler->Word32Equal( | |
647 lhs_instance_type, | |
648 assembler->Int32Constant(SIMD128_VALUE_TYPE)), | |
649 &if_lhsissimd128value, &if_lhsisnotsimd128value); | |
650 | |
651 assembler->Bind(&if_lhsissimd128value); | |
652 { | |
653 // TODO(bmeurer): Inline the Simd128Value equality check. | |
654 assembler->TailCallRuntime(Runtime::kStrictEqual, context, lhs, | |
655 rhs); | |
656 } | |
657 | |
658 assembler->Bind(&if_lhsisnotsimd128value); | |
659 assembler->Goto(&if_false); | |
660 } | |
661 } | |
662 } | |
663 } | |
664 | |
665 assembler->Bind(&if_lhsissmi); | |
666 { | |
667 // We already know that {lhs} and {rhs} are not reference equal, and {lhs} | |
668 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a | |
669 // HeapNumber with an equal floating point value. | |
670 | |
671 // Check if {rhs} is a Smi or a HeapObject. | |
672 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); | |
673 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, | |
674 &if_rhsisnotsmi); | |
675 | |
676 assembler->Bind(&if_rhsissmi); | |
677 assembler->Goto(&if_false); | |
678 | |
679 assembler->Bind(&if_rhsisnotsmi); | |
680 { | |
681 // Load the map of the {rhs}. | |
682 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); | |
683 | |
684 // The {rhs} could be a HeapNumber with the same value as {lhs}. | |
685 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); | |
686 assembler->Branch(assembler->WordEqual(rhs_map, number_map), | |
687 &if_rhsisnumber, &if_rhsisnotnumber); | |
688 | |
689 assembler->Bind(&if_rhsisnumber); | |
690 { | |
691 // Convert {lhs} and {rhs} to floating point values. | |
692 Node* lhs_value = assembler->SmiToFloat64(lhs); | |
693 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); | |
694 | |
695 // Perform a floating point comparison of {lhs} and {rhs}. | |
696 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, | |
697 &if_false); | |
698 } | |
699 | |
700 assembler->Bind(&if_rhsisnotnumber); | |
701 assembler->Goto(&if_false); | |
702 } | |
703 } | |
704 } | |
705 | |
706 assembler->Bind(&if_true); | |
707 assembler->Return(assembler->BooleanConstant(true)); | |
708 | |
709 assembler->Bind(&if_false); | |
710 assembler->Return(assembler->BooleanConstant(false)); | |
711 } | |
712 | |
476 void ToBooleanStub::GenerateAssembly( | 713 void ToBooleanStub::GenerateAssembly( |
477 compiler::CodeStubAssembler* assembler) const { | 714 compiler::CodeStubAssembler* assembler) const { |
478 typedef compiler::Node Node; | 715 typedef compiler::Node Node; |
479 typedef compiler::CodeStubAssembler::Label Label; | 716 typedef compiler::CodeStubAssembler::Label Label; |
480 | 717 |
481 Node* value = assembler->Parameter(0); | 718 Node* value = assembler->Parameter(0); |
482 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); | 719 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); |
483 | 720 |
484 // Check if {value} is a Smi or a HeapObject. | 721 // Check if {value} is a Smi or a HeapObject. |
485 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, | 722 assembler->Branch(assembler->WordIsSmi(value), &if_valueissmi, |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1041 if (type->Is(Type::UntaggedPointer())) { | 1278 if (type->Is(Type::UntaggedPointer())) { |
1042 return Representation::External(); | 1279 return Representation::External(); |
1043 } | 1280 } |
1044 | 1281 |
1045 DCHECK(!type->Is(Type::Untagged())); | 1282 DCHECK(!type->Is(Type::Untagged())); |
1046 return Representation::Tagged(); | 1283 return Representation::Tagged(); |
1047 } | 1284 } |
1048 | 1285 |
1049 } // namespace internal | 1286 } // namespace internal |
1050 } // namespace v8 | 1287 } // namespace v8 |
OLD | NEW |