Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: src/crankshaft/ia32/lithium-codegen-ia32.cc

Issue 2161543002: [turbofan] Add support for eager/soft deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Do the ports properly Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/crankshaft/ia32/lithium-codegen-ia32.h ('k') | src/crankshaft/lithium-codegen.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #if V8_TARGET_ARCH_IA32 5 #if V8_TARGET_ARCH_IA32
6 6
7 #include "src/crankshaft/ia32/lithium-codegen-ia32.h" 7 #include "src/crankshaft/ia32/lithium-codegen-ia32.h"
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 WriteTranslation(environment, &translation); 675 WriteTranslation(environment, &translation);
676 int deoptimization_index = deoptimizations_.length(); 676 int deoptimization_index = deoptimizations_.length();
677 int pc_offset = masm()->pc_offset(); 677 int pc_offset = masm()->pc_offset();
678 environment->Register(deoptimization_index, 678 environment->Register(deoptimization_index,
679 translation.index(), 679 translation.index(),
680 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 680 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
681 deoptimizations_.Add(environment, zone()); 681 deoptimizations_.Add(environment, zone());
682 } 682 }
683 } 683 }
684 684
685
686 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 685 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
687 Deoptimizer::DeoptReason deopt_reason, 686 DeoptimizeReason deopt_reason,
688 Deoptimizer::BailoutType bailout_type) { 687 Deoptimizer::BailoutType bailout_type) {
689 LEnvironment* environment = instr->environment(); 688 LEnvironment* environment = instr->environment();
690 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 689 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
691 DCHECK(environment->HasBeenRegistered()); 690 DCHECK(environment->HasBeenRegistered());
692 int id = environment->deoptimization_index(); 691 int id = environment->deoptimization_index();
693 Address entry = 692 Address entry =
694 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 693 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
695 if (entry == NULL) { 694 if (entry == NULL) {
696 Abort(kBailoutWasNotPrepared); 695 Abort(kBailoutWasNotPrepared);
697 return; 696 return;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 jump_table_.Add(table_entry, zone()); 741 jump_table_.Add(table_entry, zone());
743 } 742 }
744 if (cc == no_condition) { 743 if (cc == no_condition) {
745 __ jmp(&jump_table_.last().label); 744 __ jmp(&jump_table_.last().label);
746 } else { 745 } else {
747 __ j(cc, &jump_table_.last().label); 746 __ j(cc, &jump_table_.last().label);
748 } 747 }
749 } 748 }
750 } 749 }
751 750
752
753 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 751 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
754 Deoptimizer::DeoptReason deopt_reason) { 752 DeoptimizeReason deopt_reason) {
755 Deoptimizer::BailoutType bailout_type = info()->IsStub() 753 Deoptimizer::BailoutType bailout_type = info()->IsStub()
756 ? Deoptimizer::LAZY 754 ? Deoptimizer::LAZY
757 : Deoptimizer::EAGER; 755 : Deoptimizer::EAGER;
758 DeoptimizeIf(cc, instr, deopt_reason, bailout_type); 756 DeoptimizeIf(cc, instr, deopt_reason, bailout_type);
759 } 757 }
760 758
761 759
762 void LCodeGen::RecordSafepointWithLazyDeopt( 760 void LCodeGen::RecordSafepointWithLazyDeopt(
763 LInstruction* instr, SafepointMode safepoint_mode) { 761 LInstruction* instr, SafepointMode safepoint_mode) {
764 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) { 762 if (safepoint_mode == RECORD_SIMPLE_SAFEPOINT) {
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
875 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 873 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
876 Label dividend_is_not_negative, done; 874 Label dividend_is_not_negative, done;
877 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 875 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
878 __ test(dividend, dividend); 876 __ test(dividend, dividend);
879 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 877 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
880 // Note that this is correct even for kMinInt operands. 878 // Note that this is correct even for kMinInt operands.
881 __ neg(dividend); 879 __ neg(dividend);
882 __ and_(dividend, mask); 880 __ and_(dividend, mask);
883 __ neg(dividend); 881 __ neg(dividend);
884 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 882 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
885 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 883 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
886 } 884 }
887 __ jmp(&done, Label::kNear); 885 __ jmp(&done, Label::kNear);
888 } 886 }
889 887
890 __ bind(&dividend_is_not_negative); 888 __ bind(&dividend_is_not_negative);
891 __ and_(dividend, mask); 889 __ and_(dividend, mask);
892 __ bind(&done); 890 __ bind(&done);
893 } 891 }
894 892
895 893
896 void LCodeGen::DoModByConstI(LModByConstI* instr) { 894 void LCodeGen::DoModByConstI(LModByConstI* instr) {
897 Register dividend = ToRegister(instr->dividend()); 895 Register dividend = ToRegister(instr->dividend());
898 int32_t divisor = instr->divisor(); 896 int32_t divisor = instr->divisor();
899 DCHECK(ToRegister(instr->result()).is(eax)); 897 DCHECK(ToRegister(instr->result()).is(eax));
900 898
901 if (divisor == 0) { 899 if (divisor == 0) {
902 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 900 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
903 return; 901 return;
904 } 902 }
905 903
906 __ TruncatingDiv(dividend, Abs(divisor)); 904 __ TruncatingDiv(dividend, Abs(divisor));
907 __ imul(edx, edx, Abs(divisor)); 905 __ imul(edx, edx, Abs(divisor));
908 __ mov(eax, dividend); 906 __ mov(eax, dividend);
909 __ sub(eax, edx); 907 __ sub(eax, edx);
910 908
911 // Check for negative zero. 909 // Check for negative zero.
912 HMod* hmod = instr->hydrogen(); 910 HMod* hmod = instr->hydrogen();
913 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 911 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
914 Label remainder_not_zero; 912 Label remainder_not_zero;
915 __ j(not_zero, &remainder_not_zero, Label::kNear); 913 __ j(not_zero, &remainder_not_zero, Label::kNear);
916 __ cmp(dividend, Immediate(0)); 914 __ cmp(dividend, Immediate(0));
917 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero); 915 DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
918 __ bind(&remainder_not_zero); 916 __ bind(&remainder_not_zero);
919 } 917 }
920 } 918 }
921 919
922 920
923 void LCodeGen::DoModI(LModI* instr) { 921 void LCodeGen::DoModI(LModI* instr) {
924 HMod* hmod = instr->hydrogen(); 922 HMod* hmod = instr->hydrogen();
925 923
926 Register left_reg = ToRegister(instr->left()); 924 Register left_reg = ToRegister(instr->left());
927 DCHECK(left_reg.is(eax)); 925 DCHECK(left_reg.is(eax));
928 Register right_reg = ToRegister(instr->right()); 926 Register right_reg = ToRegister(instr->right());
929 DCHECK(!right_reg.is(eax)); 927 DCHECK(!right_reg.is(eax));
930 DCHECK(!right_reg.is(edx)); 928 DCHECK(!right_reg.is(edx));
931 Register result_reg = ToRegister(instr->result()); 929 Register result_reg = ToRegister(instr->result());
932 DCHECK(result_reg.is(edx)); 930 DCHECK(result_reg.is(edx));
933 931
934 Label done; 932 Label done;
935 // Check for x % 0, idiv would signal a divide error. We have to 933 // Check for x % 0, idiv would signal a divide error. We have to
936 // deopt in this case because we can't return a NaN. 934 // deopt in this case because we can't return a NaN.
937 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 935 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
938 __ test(right_reg, Operand(right_reg)); 936 __ test(right_reg, Operand(right_reg));
939 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 937 DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
940 } 938 }
941 939
942 // Check for kMinInt % -1, idiv would signal a divide error. We 940 // Check for kMinInt % -1, idiv would signal a divide error. We
943 // have to deopt if we care about -0, because we can't return that. 941 // have to deopt if we care about -0, because we can't return that.
944 if (hmod->CheckFlag(HValue::kCanOverflow)) { 942 if (hmod->CheckFlag(HValue::kCanOverflow)) {
945 Label no_overflow_possible; 943 Label no_overflow_possible;
946 __ cmp(left_reg, kMinInt); 944 __ cmp(left_reg, kMinInt);
947 __ j(not_equal, &no_overflow_possible, Label::kNear); 945 __ j(not_equal, &no_overflow_possible, Label::kNear);
948 __ cmp(right_reg, -1); 946 __ cmp(right_reg, -1);
949 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 947 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
950 DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero); 948 DeoptimizeIf(equal, instr, DeoptimizeReason::kMinusZero);
951 } else { 949 } else {
952 __ j(not_equal, &no_overflow_possible, Label::kNear); 950 __ j(not_equal, &no_overflow_possible, Label::kNear);
953 __ Move(result_reg, Immediate(0)); 951 __ Move(result_reg, Immediate(0));
954 __ jmp(&done, Label::kNear); 952 __ jmp(&done, Label::kNear);
955 } 953 }
956 __ bind(&no_overflow_possible); 954 __ bind(&no_overflow_possible);
957 } 955 }
958 956
959 // Sign extend dividend in eax into edx:eax. 957 // Sign extend dividend in eax into edx:eax.
960 __ cdq(); 958 __ cdq();
961 959
962 // If we care about -0, test if the dividend is <0 and the result is 0. 960 // If we care about -0, test if the dividend is <0 and the result is 0.
963 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 961 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
964 Label positive_left; 962 Label positive_left;
965 __ test(left_reg, Operand(left_reg)); 963 __ test(left_reg, Operand(left_reg));
966 __ j(not_sign, &positive_left, Label::kNear); 964 __ j(not_sign, &positive_left, Label::kNear);
967 __ idiv(right_reg); 965 __ idiv(right_reg);
968 __ test(result_reg, Operand(result_reg)); 966 __ test(result_reg, Operand(result_reg));
969 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 967 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
970 __ jmp(&done, Label::kNear); 968 __ jmp(&done, Label::kNear);
971 __ bind(&positive_left); 969 __ bind(&positive_left);
972 } 970 }
973 __ idiv(right_reg); 971 __ idiv(right_reg);
974 __ bind(&done); 972 __ bind(&done);
975 } 973 }
976 974
977 975
978 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 976 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
979 Register dividend = ToRegister(instr->dividend()); 977 Register dividend = ToRegister(instr->dividend());
980 int32_t divisor = instr->divisor(); 978 int32_t divisor = instr->divisor();
981 Register result = ToRegister(instr->result()); 979 Register result = ToRegister(instr->result());
982 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 980 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
983 DCHECK(!result.is(dividend)); 981 DCHECK(!result.is(dividend));
984 982
985 // Check for (0 / -x) that will produce negative zero. 983 // Check for (0 / -x) that will produce negative zero.
986 HDiv* hdiv = instr->hydrogen(); 984 HDiv* hdiv = instr->hydrogen();
987 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 985 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
988 __ test(dividend, dividend); 986 __ test(dividend, dividend);
989 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 987 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
990 } 988 }
991 // Check for (kMinInt / -1). 989 // Check for (kMinInt / -1).
992 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 990 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
993 __ cmp(dividend, kMinInt); 991 __ cmp(dividend, kMinInt);
994 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 992 DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
995 } 993 }
996 // Deoptimize if remainder will not be 0. 994 // Deoptimize if remainder will not be 0.
997 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 995 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
998 divisor != 1 && divisor != -1) { 996 divisor != 1 && divisor != -1) {
999 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 997 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1000 __ test(dividend, Immediate(mask)); 998 __ test(dividend, Immediate(mask));
1001 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision); 999 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
1002 } 1000 }
1003 __ Move(result, dividend); 1001 __ Move(result, dividend);
1004 int32_t shift = WhichPowerOf2Abs(divisor); 1002 int32_t shift = WhichPowerOf2Abs(divisor);
1005 if (shift > 0) { 1003 if (shift > 0) {
1006 // The arithmetic shift is always OK, the 'if' is an optimization only. 1004 // The arithmetic shift is always OK, the 'if' is an optimization only.
1007 if (shift > 1) __ sar(result, 31); 1005 if (shift > 1) __ sar(result, 31);
1008 __ shr(result, 32 - shift); 1006 __ shr(result, 32 - shift);
1009 __ add(result, dividend); 1007 __ add(result, dividend);
1010 __ sar(result, shift); 1008 __ sar(result, shift);
1011 } 1009 }
1012 if (divisor < 0) __ neg(result); 1010 if (divisor < 0) __ neg(result);
1013 } 1011 }
1014 1012
1015 1013
1016 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1014 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1017 Register dividend = ToRegister(instr->dividend()); 1015 Register dividend = ToRegister(instr->dividend());
1018 int32_t divisor = instr->divisor(); 1016 int32_t divisor = instr->divisor();
1019 DCHECK(ToRegister(instr->result()).is(edx)); 1017 DCHECK(ToRegister(instr->result()).is(edx));
1020 1018
1021 if (divisor == 0) { 1019 if (divisor == 0) {
1022 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 1020 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
1023 return; 1021 return;
1024 } 1022 }
1025 1023
1026 // Check for (0 / -x) that will produce negative zero. 1024 // Check for (0 / -x) that will produce negative zero.
1027 HDiv* hdiv = instr->hydrogen(); 1025 HDiv* hdiv = instr->hydrogen();
1028 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1026 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1029 __ test(dividend, dividend); 1027 __ test(dividend, dividend);
1030 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1028 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1031 } 1029 }
1032 1030
1033 __ TruncatingDiv(dividend, Abs(divisor)); 1031 __ TruncatingDiv(dividend, Abs(divisor));
1034 if (divisor < 0) __ neg(edx); 1032 if (divisor < 0) __ neg(edx);
1035 1033
1036 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1034 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1037 __ mov(eax, edx); 1035 __ mov(eax, edx);
1038 __ imul(eax, eax, divisor); 1036 __ imul(eax, eax, divisor);
1039 __ sub(eax, dividend); 1037 __ sub(eax, dividend);
1040 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); 1038 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
1041 } 1039 }
1042 } 1040 }
1043 1041
1044 1042
1045 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1043 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1046 void LCodeGen::DoDivI(LDivI* instr) { 1044 void LCodeGen::DoDivI(LDivI* instr) {
1047 HBinaryOperation* hdiv = instr->hydrogen(); 1045 HBinaryOperation* hdiv = instr->hydrogen();
1048 Register dividend = ToRegister(instr->dividend()); 1046 Register dividend = ToRegister(instr->dividend());
1049 Register divisor = ToRegister(instr->divisor()); 1047 Register divisor = ToRegister(instr->divisor());
1050 Register remainder = ToRegister(instr->temp()); 1048 Register remainder = ToRegister(instr->temp());
1051 DCHECK(dividend.is(eax)); 1049 DCHECK(dividend.is(eax));
1052 DCHECK(remainder.is(edx)); 1050 DCHECK(remainder.is(edx));
1053 DCHECK(ToRegister(instr->result()).is(eax)); 1051 DCHECK(ToRegister(instr->result()).is(eax));
1054 DCHECK(!divisor.is(eax)); 1052 DCHECK(!divisor.is(eax));
1055 DCHECK(!divisor.is(edx)); 1053 DCHECK(!divisor.is(edx));
1056 1054
1057 // Check for x / 0. 1055 // Check for x / 0.
1058 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1056 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1059 __ test(divisor, divisor); 1057 __ test(divisor, divisor);
1060 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 1058 DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
1061 } 1059 }
1062 1060
1063 // Check for (0 / -x) that will produce negative zero. 1061 // Check for (0 / -x) that will produce negative zero.
1064 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1062 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1065 Label dividend_not_zero; 1063 Label dividend_not_zero;
1066 __ test(dividend, dividend); 1064 __ test(dividend, dividend);
1067 __ j(not_zero, &dividend_not_zero, Label::kNear); 1065 __ j(not_zero, &dividend_not_zero, Label::kNear);
1068 __ test(divisor, divisor); 1066 __ test(divisor, divisor);
1069 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1067 DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1070 __ bind(&dividend_not_zero); 1068 __ bind(&dividend_not_zero);
1071 } 1069 }
1072 1070
1073 // Check for (kMinInt / -1). 1071 // Check for (kMinInt / -1).
1074 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1072 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1075 Label dividend_not_min_int; 1073 Label dividend_not_min_int;
1076 __ cmp(dividend, kMinInt); 1074 __ cmp(dividend, kMinInt);
1077 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1075 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1078 __ cmp(divisor, -1); 1076 __ cmp(divisor, -1);
1079 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 1077 DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
1080 __ bind(&dividend_not_min_int); 1078 __ bind(&dividend_not_min_int);
1081 } 1079 }
1082 1080
1083 // Sign extend to edx (= remainder). 1081 // Sign extend to edx (= remainder).
1084 __ cdq(); 1082 __ cdq();
1085 __ idiv(divisor); 1083 __ idiv(divisor);
1086 1084
1087 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1085 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1088 // Deoptimize if remainder is not 0. 1086 // Deoptimize if remainder is not 0.
1089 __ test(remainder, remainder); 1087 __ test(remainder, remainder);
1090 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision); 1088 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kLostPrecision);
1091 } 1089 }
1092 } 1090 }
1093 1091
1094 1092
1095 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1093 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1096 Register dividend = ToRegister(instr->dividend()); 1094 Register dividend = ToRegister(instr->dividend());
1097 int32_t divisor = instr->divisor(); 1095 int32_t divisor = instr->divisor();
1098 DCHECK(dividend.is(ToRegister(instr->result()))); 1096 DCHECK(dividend.is(ToRegister(instr->result())));
1099 1097
1100 // If the divisor is positive, things are easy: There can be no deopts and we 1098 // If the divisor is positive, things are easy: There can be no deopts and we
1101 // can simply do an arithmetic right shift. 1099 // can simply do an arithmetic right shift.
1102 if (divisor == 1) return; 1100 if (divisor == 1) return;
1103 int32_t shift = WhichPowerOf2Abs(divisor); 1101 int32_t shift = WhichPowerOf2Abs(divisor);
1104 if (divisor > 1) { 1102 if (divisor > 1) {
1105 __ sar(dividend, shift); 1103 __ sar(dividend, shift);
1106 return; 1104 return;
1107 } 1105 }
1108 1106
1109 // If the divisor is negative, we have to negate and handle edge cases. 1107 // If the divisor is negative, we have to negate and handle edge cases.
1110 __ neg(dividend); 1108 __ neg(dividend);
1111 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1109 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1112 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1110 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1113 } 1111 }
1114 1112
1115 // Dividing by -1 is basically negation, unless we overflow. 1113 // Dividing by -1 is basically negation, unless we overflow.
1116 if (divisor == -1) { 1114 if (divisor == -1) {
1117 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1115 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1118 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1116 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1119 } 1117 }
1120 return; 1118 return;
1121 } 1119 }
1122 1120
1123 // If the negation could not overflow, simply shifting is OK. 1121 // If the negation could not overflow, simply shifting is OK.
1124 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1122 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1125 __ sar(dividend, shift); 1123 __ sar(dividend, shift);
1126 return; 1124 return;
1127 } 1125 }
1128 1126
1129 Label not_kmin_int, done; 1127 Label not_kmin_int, done;
1130 __ j(no_overflow, &not_kmin_int, Label::kNear); 1128 __ j(no_overflow, &not_kmin_int, Label::kNear);
1131 __ mov(dividend, Immediate(kMinInt / divisor)); 1129 __ mov(dividend, Immediate(kMinInt / divisor));
1132 __ jmp(&done, Label::kNear); 1130 __ jmp(&done, Label::kNear);
1133 __ bind(&not_kmin_int); 1131 __ bind(&not_kmin_int);
1134 __ sar(dividend, shift); 1132 __ sar(dividend, shift);
1135 __ bind(&done); 1133 __ bind(&done);
1136 } 1134 }
1137 1135
1138 1136
1139 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1137 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1140 Register dividend = ToRegister(instr->dividend()); 1138 Register dividend = ToRegister(instr->dividend());
1141 int32_t divisor = instr->divisor(); 1139 int32_t divisor = instr->divisor();
1142 DCHECK(ToRegister(instr->result()).is(edx)); 1140 DCHECK(ToRegister(instr->result()).is(edx));
1143 1141
1144 if (divisor == 0) { 1142 if (divisor == 0) {
1145 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 1143 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kDivisionByZero);
1146 return; 1144 return;
1147 } 1145 }
1148 1146
1149 // Check for (0 / -x) that will produce negative zero. 1147 // Check for (0 / -x) that will produce negative zero.
1150 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1148 HMathFloorOfDiv* hdiv = instr->hydrogen();
1151 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1149 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1152 __ test(dividend, dividend); 1150 __ test(dividend, dividend);
1153 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1151 DeoptimizeIf(zero, instr, DeoptimizeReason::kMinusZero);
1154 } 1152 }
1155 1153
1156 // Easy case: We need no dynamic check for the dividend and the flooring 1154 // Easy case: We need no dynamic check for the dividend and the flooring
1157 // division is the same as the truncating division. 1155 // division is the same as the truncating division.
1158 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1156 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1159 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1157 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1160 __ TruncatingDiv(dividend, Abs(divisor)); 1158 __ TruncatingDiv(dividend, Abs(divisor));
1161 if (divisor < 0) __ neg(edx); 1159 if (divisor < 0) __ neg(edx);
1162 return; 1160 return;
1163 } 1161 }
(...skipping 26 matching lines...) Expand all
1190 Register result = ToRegister(instr->result()); 1188 Register result = ToRegister(instr->result());
1191 DCHECK(dividend.is(eax)); 1189 DCHECK(dividend.is(eax));
1192 DCHECK(remainder.is(edx)); 1190 DCHECK(remainder.is(edx));
1193 DCHECK(result.is(eax)); 1191 DCHECK(result.is(eax));
1194 DCHECK(!divisor.is(eax)); 1192 DCHECK(!divisor.is(eax));
1195 DCHECK(!divisor.is(edx)); 1193 DCHECK(!divisor.is(edx));
1196 1194
1197 // Check for x / 0. 1195 // Check for x / 0.
1198 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1196 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1199 __ test(divisor, divisor); 1197 __ test(divisor, divisor);
1200 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 1198 DeoptimizeIf(zero, instr, DeoptimizeReason::kDivisionByZero);
1201 } 1199 }
1202 1200
1203 // Check for (0 / -x) that will produce negative zero. 1201 // Check for (0 / -x) that will produce negative zero.
1204 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1202 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1205 Label dividend_not_zero; 1203 Label dividend_not_zero;
1206 __ test(dividend, dividend); 1204 __ test(dividend, dividend);
1207 __ j(not_zero, &dividend_not_zero, Label::kNear); 1205 __ j(not_zero, &dividend_not_zero, Label::kNear);
1208 __ test(divisor, divisor); 1206 __ test(divisor, divisor);
1209 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1207 DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1210 __ bind(&dividend_not_zero); 1208 __ bind(&dividend_not_zero);
1211 } 1209 }
1212 1210
1213 // Check for (kMinInt / -1). 1211 // Check for (kMinInt / -1).
1214 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1212 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1215 Label dividend_not_min_int; 1213 Label dividend_not_min_int;
1216 __ cmp(dividend, kMinInt); 1214 __ cmp(dividend, kMinInt);
1217 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1215 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1218 __ cmp(divisor, -1); 1216 __ cmp(divisor, -1);
1219 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 1217 DeoptimizeIf(zero, instr, DeoptimizeReason::kOverflow);
1220 __ bind(&dividend_not_min_int); 1218 __ bind(&dividend_not_min_int);
1221 } 1219 }
1222 1220
1223 // Sign extend to edx (= remainder). 1221 // Sign extend to edx (= remainder).
1224 __ cdq(); 1222 __ cdq();
1225 __ idiv(divisor); 1223 __ idiv(divisor);
1226 1224
1227 Label done; 1225 Label done;
1228 __ test(remainder, remainder); 1226 __ test(remainder, remainder);
1229 __ j(zero, &done, Label::kNear); 1227 __ j(zero, &done, Label::kNear);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1287 __ imul(left, left, constant); 1285 __ imul(left, left, constant);
1288 } 1286 }
1289 } else { 1287 } else {
1290 if (instr->hydrogen()->representation().IsSmi()) { 1288 if (instr->hydrogen()->representation().IsSmi()) {
1291 __ SmiUntag(left); 1289 __ SmiUntag(left);
1292 } 1290 }
1293 __ imul(left, ToOperand(right)); 1291 __ imul(left, ToOperand(right));
1294 } 1292 }
1295 1293
1296 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1294 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1297 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1295 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1298 } 1296 }
1299 1297
1300 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1298 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1301 // Bail out if the result is supposed to be negative zero. 1299 // Bail out if the result is supposed to be negative zero.
1302 Label done; 1300 Label done;
1303 __ test(left, Operand(left)); 1301 __ test(left, Operand(left));
1304 __ j(not_zero, &done, Label::kNear); 1302 __ j(not_zero, &done, Label::kNear);
1305 if (right->IsConstantOperand()) { 1303 if (right->IsConstantOperand()) {
1306 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1304 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1307 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 1305 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
1308 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1306 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1309 __ cmp(ToRegister(instr->temp()), Immediate(0)); 1307 __ cmp(ToRegister(instr->temp()), Immediate(0));
1310 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero); 1308 DeoptimizeIf(less, instr, DeoptimizeReason::kMinusZero);
1311 } 1309 }
1312 } else { 1310 } else {
1313 // Test the non-zero operand for negative sign. 1311 // Test the non-zero operand for negative sign.
1314 __ or_(ToRegister(instr->temp()), ToOperand(right)); 1312 __ or_(ToRegister(instr->temp()), ToOperand(right));
1315 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1313 DeoptimizeIf(sign, instr, DeoptimizeReason::kMinusZero);
1316 } 1314 }
1317 __ bind(&done); 1315 __ bind(&done);
1318 } 1316 }
1319 } 1317 }
1320 1318
1321 1319
1322 void LCodeGen::DoBitI(LBitI* instr) { 1320 void LCodeGen::DoBitI(LBitI* instr) {
1323 LOperand* left = instr->left(); 1321 LOperand* left = instr->left();
1324 LOperand* right = instr->right(); 1322 LOperand* right = instr->right();
1325 DCHECK(left->Equals(instr->result())); 1323 DCHECK(left->Equals(instr->result()));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 case Token::ROR: 1376 case Token::ROR:
1379 __ ror_cl(ToRegister(left)); 1377 __ ror_cl(ToRegister(left));
1380 break; 1378 break;
1381 case Token::SAR: 1379 case Token::SAR:
1382 __ sar_cl(ToRegister(left)); 1380 __ sar_cl(ToRegister(left));
1383 break; 1381 break;
1384 case Token::SHR: 1382 case Token::SHR:
1385 __ shr_cl(ToRegister(left)); 1383 __ shr_cl(ToRegister(left));
1386 if (instr->can_deopt()) { 1384 if (instr->can_deopt()) {
1387 __ test(ToRegister(left), ToRegister(left)); 1385 __ test(ToRegister(left), ToRegister(left));
1388 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue); 1386 DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1389 } 1387 }
1390 break; 1388 break;
1391 case Token::SHL: 1389 case Token::SHL:
1392 __ shl_cl(ToRegister(left)); 1390 __ shl_cl(ToRegister(left));
1393 break; 1391 break;
1394 default: 1392 default:
1395 UNREACHABLE(); 1393 UNREACHABLE();
1396 break; 1394 break;
1397 } 1395 }
1398 } else { 1396 } else {
1399 int value = ToInteger32(LConstantOperand::cast(right)); 1397 int value = ToInteger32(LConstantOperand::cast(right));
1400 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1398 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1401 switch (instr->op()) { 1399 switch (instr->op()) {
1402 case Token::ROR: 1400 case Token::ROR:
1403 if (shift_count == 0 && instr->can_deopt()) { 1401 if (shift_count == 0 && instr->can_deopt()) {
1404 __ test(ToRegister(left), ToRegister(left)); 1402 __ test(ToRegister(left), ToRegister(left));
1405 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue); 1403 DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1406 } else { 1404 } else {
1407 __ ror(ToRegister(left), shift_count); 1405 __ ror(ToRegister(left), shift_count);
1408 } 1406 }
1409 break; 1407 break;
1410 case Token::SAR: 1408 case Token::SAR:
1411 if (shift_count != 0) { 1409 if (shift_count != 0) {
1412 __ sar(ToRegister(left), shift_count); 1410 __ sar(ToRegister(left), shift_count);
1413 } 1411 }
1414 break; 1412 break;
1415 case Token::SHR: 1413 case Token::SHR:
1416 if (shift_count != 0) { 1414 if (shift_count != 0) {
1417 __ shr(ToRegister(left), shift_count); 1415 __ shr(ToRegister(left), shift_count);
1418 } else if (instr->can_deopt()) { 1416 } else if (instr->can_deopt()) {
1419 __ test(ToRegister(left), ToRegister(left)); 1417 __ test(ToRegister(left), ToRegister(left));
1420 DeoptimizeIf(sign, instr, Deoptimizer::kNegativeValue); 1418 DeoptimizeIf(sign, instr, DeoptimizeReason::kNegativeValue);
1421 } 1419 }
1422 break; 1420 break;
1423 case Token::SHL: 1421 case Token::SHL:
1424 if (shift_count != 0) { 1422 if (shift_count != 0) {
1425 if (instr->hydrogen_value()->representation().IsSmi() && 1423 if (instr->hydrogen_value()->representation().IsSmi() &&
1426 instr->can_deopt()) { 1424 instr->can_deopt()) {
1427 if (shift_count != 1) { 1425 if (shift_count != 1) {
1428 __ shl(ToRegister(left), shift_count - 1); 1426 __ shl(ToRegister(left), shift_count - 1);
1429 } 1427 }
1430 __ SmiTag(ToRegister(left)); 1428 __ SmiTag(ToRegister(left));
1431 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1429 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1432 } else { 1430 } else {
1433 __ shl(ToRegister(left), shift_count); 1431 __ shl(ToRegister(left), shift_count);
1434 } 1432 }
1435 } 1433 }
1436 break; 1434 break;
1437 default: 1435 default:
1438 UNREACHABLE(); 1436 UNREACHABLE();
1439 break; 1437 break;
1440 } 1438 }
1441 } 1439 }
1442 } 1440 }
1443 1441
1444 1442
1445 void LCodeGen::DoSubI(LSubI* instr) { 1443 void LCodeGen::DoSubI(LSubI* instr) {
1446 LOperand* left = instr->left(); 1444 LOperand* left = instr->left();
1447 LOperand* right = instr->right(); 1445 LOperand* right = instr->right();
1448 DCHECK(left->Equals(instr->result())); 1446 DCHECK(left->Equals(instr->result()));
1449 1447
1450 if (right->IsConstantOperand()) { 1448 if (right->IsConstantOperand()) {
1451 __ sub(ToOperand(left), 1449 __ sub(ToOperand(left),
1452 ToImmediate(right, instr->hydrogen()->representation())); 1450 ToImmediate(right, instr->hydrogen()->representation()));
1453 } else { 1451 } else {
1454 __ sub(ToRegister(left), ToOperand(right)); 1452 __ sub(ToRegister(left), ToOperand(right));
1455 } 1453 }
1456 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1454 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1457 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1455 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1458 } 1456 }
1459 } 1457 }
1460 1458
1461 1459
1462 void LCodeGen::DoConstantI(LConstantI* instr) { 1460 void LCodeGen::DoConstantI(LConstantI* instr) {
1463 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1461 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1464 } 1462 }
1465 1463
1466 1464
1467 void LCodeGen::DoConstantS(LConstantS* instr) { 1465 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1619 __ lea(ToRegister(instr->result()), address); 1617 __ lea(ToRegister(instr->result()), address);
1620 } 1618 }
1621 } else { 1619 } else {
1622 if (right->IsConstantOperand()) { 1620 if (right->IsConstantOperand()) {
1623 __ add(ToOperand(left), 1621 __ add(ToOperand(left),
1624 ToImmediate(right, instr->hydrogen()->representation())); 1622 ToImmediate(right, instr->hydrogen()->representation()));
1625 } else { 1623 } else {
1626 __ add(ToRegister(left), ToOperand(right)); 1624 __ add(ToRegister(left), ToOperand(right));
1627 } 1625 }
1628 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1626 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1629 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1627 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
1630 } 1628 }
1631 } 1629 }
1632 } 1630 }
1633 1631
1634 1632
1635 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 1633 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1636 LOperand* left = instr->left(); 1634 LOperand* left = instr->left();
1637 LOperand* right = instr->right(); 1635 LOperand* right = instr->right();
1638 DCHECK(left->Equals(instr->result())); 1636 DCHECK(left->Equals(instr->result()));
1639 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 1637 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1878 } 1876 }
1879 1877
1880 if (expected.Contains(ToBooleanICStub::SMI)) { 1878 if (expected.Contains(ToBooleanICStub::SMI)) {
1881 // Smis: 0 -> false, all other -> true. 1879 // Smis: 0 -> false, all other -> true.
1882 __ test(reg, Operand(reg)); 1880 __ test(reg, Operand(reg));
1883 __ j(equal, instr->FalseLabel(chunk_)); 1881 __ j(equal, instr->FalseLabel(chunk_));
1884 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 1882 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
1885 } else if (expected.NeedsMap()) { 1883 } else if (expected.NeedsMap()) {
1886 // If we need a map later and have a Smi -> deopt. 1884 // If we need a map later and have a Smi -> deopt.
1887 __ test(reg, Immediate(kSmiTagMask)); 1885 __ test(reg, Immediate(kSmiTagMask));
1888 DeoptimizeIf(zero, instr, Deoptimizer::kSmi); 1886 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi);
1889 } 1887 }
1890 1888
1891 Register map = no_reg; // Keep the compiler happy. 1889 Register map = no_reg; // Keep the compiler happy.
1892 if (expected.NeedsMap()) { 1890 if (expected.NeedsMap()) {
1893 map = ToRegister(instr->temp()); 1891 map = ToRegister(instr->temp());
1894 DCHECK(!map.is(reg)); 1892 DCHECK(!map.is(reg));
1895 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); 1893 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset));
1896 1894
1897 if (expected.CanBeUndetectable()) { 1895 if (expected.CanBeUndetectable()) {
1898 // Undetectable -> false. 1896 // Undetectable -> false.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1941 __ xorps(xmm_scratch, xmm_scratch); 1939 __ xorps(xmm_scratch, xmm_scratch);
1942 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 1940 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
1943 __ j(zero, instr->FalseLabel(chunk_)); 1941 __ j(zero, instr->FalseLabel(chunk_));
1944 __ jmp(instr->TrueLabel(chunk_)); 1942 __ jmp(instr->TrueLabel(chunk_));
1945 __ bind(&not_heap_number); 1943 __ bind(&not_heap_number);
1946 } 1944 }
1947 1945
1948 if (!expected.IsGeneric()) { 1946 if (!expected.IsGeneric()) {
1949 // We've seen something for the first time -> deopt. 1947 // We've seen something for the first time -> deopt.
1950 // This can only happen if we are not generic already. 1948 // This can only happen if we are not generic already.
1951 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject); 1949 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kUnexpectedObject);
1952 } 1950 }
1953 } 1951 }
1954 } 1952 }
1955 } 1953 }
1956 1954
1957 1955
1958 void LCodeGen::EmitGoto(int block) { 1956 void LCodeGen::EmitGoto(int block) {
1959 if (!IsNextEmittedBlock(block)) { 1957 if (!IsNextEmittedBlock(block)) {
1960 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 1958 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
1961 } 1959 }
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
2299 } 2297 }
2300 2298
2301 // Loop through the {object}s prototype chain looking for the {prototype}. 2299 // Loop through the {object}s prototype chain looking for the {prototype}.
2302 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset)); 2300 __ mov(object_map, FieldOperand(object, HeapObject::kMapOffset));
2303 Label loop; 2301 Label loop;
2304 __ bind(&loop); 2302 __ bind(&loop);
2305 2303
2306 // Deoptimize if the object needs to be access checked. 2304 // Deoptimize if the object needs to be access checked.
2307 __ test_b(FieldOperand(object_map, Map::kBitFieldOffset), 2305 __ test_b(FieldOperand(object_map, Map::kBitFieldOffset),
2308 Immediate(1 << Map::kIsAccessCheckNeeded)); 2306 Immediate(1 << Map::kIsAccessCheckNeeded));
2309 DeoptimizeIf(not_zero, instr, Deoptimizer::kAccessCheck); 2307 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kAccessCheck);
2310 // Deoptimize for proxies. 2308 // Deoptimize for proxies.
2311 __ CmpInstanceType(object_map, JS_PROXY_TYPE); 2309 __ CmpInstanceType(object_map, JS_PROXY_TYPE);
2312 DeoptimizeIf(equal, instr, Deoptimizer::kProxy); 2310 DeoptimizeIf(equal, instr, DeoptimizeReason::kProxy);
2313 2311
2314 __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset)); 2312 __ mov(object_prototype, FieldOperand(object_map, Map::kPrototypeOffset));
2315 __ cmp(object_prototype, factory()->null_value()); 2313 __ cmp(object_prototype, factory()->null_value());
2316 EmitFalseBranch(instr, equal); 2314 EmitFalseBranch(instr, equal);
2317 __ cmp(object_prototype, prototype); 2315 __ cmp(object_prototype, prototype);
2318 EmitTrueBranch(instr, equal); 2316 EmitTrueBranch(instr, equal);
2319 __ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset)); 2317 __ mov(object_map, FieldOperand(object_prototype, HeapObject::kMapOffset));
2320 __ jmp(&loop); 2318 __ jmp(&loop);
2321 } 2319 }
2322 2320
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2424 2422
2425 2423
2426 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2424 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2427 Register context = ToRegister(instr->context()); 2425 Register context = ToRegister(instr->context());
2428 Register result = ToRegister(instr->result()); 2426 Register result = ToRegister(instr->result());
2429 __ mov(result, ContextOperand(context, instr->slot_index())); 2427 __ mov(result, ContextOperand(context, instr->slot_index()));
2430 2428
2431 if (instr->hydrogen()->RequiresHoleCheck()) { 2429 if (instr->hydrogen()->RequiresHoleCheck()) {
2432 __ cmp(result, factory()->the_hole_value()); 2430 __ cmp(result, factory()->the_hole_value());
2433 if (instr->hydrogen()->DeoptimizesOnHole()) { 2431 if (instr->hydrogen()->DeoptimizesOnHole()) {
2434 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2432 DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2435 } else { 2433 } else {
2436 Label is_not_hole; 2434 Label is_not_hole;
2437 __ j(not_equal, &is_not_hole, Label::kNear); 2435 __ j(not_equal, &is_not_hole, Label::kNear);
2438 __ mov(result, factory()->undefined_value()); 2436 __ mov(result, factory()->undefined_value());
2439 __ bind(&is_not_hole); 2437 __ bind(&is_not_hole);
2440 } 2438 }
2441 } 2439 }
2442 } 2440 }
2443 2441
2444 2442
2445 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2443 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2446 Register context = ToRegister(instr->context()); 2444 Register context = ToRegister(instr->context());
2447 Register value = ToRegister(instr->value()); 2445 Register value = ToRegister(instr->value());
2448 2446
2449 Label skip_assignment; 2447 Label skip_assignment;
2450 2448
2451 Operand target = ContextOperand(context, instr->slot_index()); 2449 Operand target = ContextOperand(context, instr->slot_index());
2452 if (instr->hydrogen()->RequiresHoleCheck()) { 2450 if (instr->hydrogen()->RequiresHoleCheck()) {
2453 __ cmp(target, factory()->the_hole_value()); 2451 __ cmp(target, factory()->the_hole_value());
2454 if (instr->hydrogen()->DeoptimizesOnHole()) { 2452 if (instr->hydrogen()->DeoptimizesOnHole()) {
2455 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2453 DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2456 } else { 2454 } else {
2457 __ j(not_equal, &skip_assignment, Label::kNear); 2455 __ j(not_equal, &skip_assignment, Label::kNear);
2458 } 2456 }
2459 } 2457 }
2460 2458
2461 __ mov(target, value); 2459 __ mov(target, value);
2462 if (instr->hydrogen()->NeedsWriteBarrier()) { 2460 if (instr->hydrogen()->NeedsWriteBarrier()) {
2463 SmiCheck check_needed = 2461 SmiCheck check_needed =
2464 instr->hydrogen()->value()->type().IsHeapObject() 2462 instr->hydrogen()->value()->type().IsHeapObject()
2465 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2463 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2542 Register function = ToRegister(instr->function()); 2540 Register function = ToRegister(instr->function());
2543 Register temp = ToRegister(instr->temp()); 2541 Register temp = ToRegister(instr->temp());
2544 Register result = ToRegister(instr->result()); 2542 Register result = ToRegister(instr->result());
2545 2543
2546 // Get the prototype or initial map from the function. 2544 // Get the prototype or initial map from the function.
2547 __ mov(result, 2545 __ mov(result,
2548 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 2546 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
2549 2547
2550 // Check that the function has a prototype or an initial map. 2548 // Check that the function has a prototype or an initial map.
2551 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); 2549 __ cmp(Operand(result), Immediate(factory()->the_hole_value()));
2552 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2550 DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2553 2551
2554 // If the function does not have an initial map, we're done. 2552 // If the function does not have an initial map, we're done.
2555 Label done; 2553 Label done;
2556 __ CmpObjectType(result, MAP_TYPE, temp); 2554 __ CmpObjectType(result, MAP_TYPE, temp);
2557 __ j(not_equal, &done, Label::kNear); 2555 __ j(not_equal, &done, Label::kNear);
2558 2556
2559 // Get the prototype from the initial map. 2557 // Get the prototype from the initial map.
2560 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); 2558 __ mov(result, FieldOperand(result, Map::kPrototypeOffset));
2561 2559
2562 // All done. 2560 // All done.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 case UINT16_ELEMENTS: 2624 case UINT16_ELEMENTS:
2627 __ movzx_w(result, operand); 2625 __ movzx_w(result, operand);
2628 break; 2626 break;
2629 case INT32_ELEMENTS: 2627 case INT32_ELEMENTS:
2630 __ mov(result, operand); 2628 __ mov(result, operand);
2631 break; 2629 break;
2632 case UINT32_ELEMENTS: 2630 case UINT32_ELEMENTS:
2633 __ mov(result, operand); 2631 __ mov(result, operand);
2634 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 2632 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
2635 __ test(result, Operand(result)); 2633 __ test(result, Operand(result));
2636 DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue); 2634 DeoptimizeIf(negative, instr, DeoptimizeReason::kNegativeValue);
2637 } 2635 }
2638 break; 2636 break;
2639 case FLOAT32_ELEMENTS: 2637 case FLOAT32_ELEMENTS:
2640 case FLOAT64_ELEMENTS: 2638 case FLOAT64_ELEMENTS:
2641 case FAST_SMI_ELEMENTS: 2639 case FAST_SMI_ELEMENTS:
2642 case FAST_ELEMENTS: 2640 case FAST_ELEMENTS:
2643 case FAST_DOUBLE_ELEMENTS: 2641 case FAST_DOUBLE_ELEMENTS:
2644 case FAST_HOLEY_SMI_ELEMENTS: 2642 case FAST_HOLEY_SMI_ELEMENTS:
2645 case FAST_HOLEY_ELEMENTS: 2643 case FAST_HOLEY_ELEMENTS:
2646 case FAST_HOLEY_DOUBLE_ELEMENTS: 2644 case FAST_HOLEY_DOUBLE_ELEMENTS:
(...skipping 11 matching lines...) Expand all
2658 2656
2659 2657
2660 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 2658 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
2661 if (instr->hydrogen()->RequiresHoleCheck()) { 2659 if (instr->hydrogen()->RequiresHoleCheck()) {
2662 Operand hole_check_operand = BuildFastArrayOperand( 2660 Operand hole_check_operand = BuildFastArrayOperand(
2663 instr->elements(), instr->key(), 2661 instr->elements(), instr->key(),
2664 instr->hydrogen()->key()->representation(), 2662 instr->hydrogen()->key()->representation(),
2665 FAST_DOUBLE_ELEMENTS, 2663 FAST_DOUBLE_ELEMENTS,
2666 instr->base_offset() + sizeof(kHoleNanLower32)); 2664 instr->base_offset() + sizeof(kHoleNanLower32));
2667 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); 2665 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
2668 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2666 DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2669 } 2667 }
2670 2668
2671 Operand double_load_operand = BuildFastArrayOperand( 2669 Operand double_load_operand = BuildFastArrayOperand(
2672 instr->elements(), 2670 instr->elements(),
2673 instr->key(), 2671 instr->key(),
2674 instr->hydrogen()->key()->representation(), 2672 instr->hydrogen()->key()->representation(),
2675 FAST_DOUBLE_ELEMENTS, 2673 FAST_DOUBLE_ELEMENTS,
2676 instr->base_offset()); 2674 instr->base_offset());
2677 XMMRegister result = ToDoubleRegister(instr->result()); 2675 XMMRegister result = ToDoubleRegister(instr->result());
2678 __ movsd(result, double_load_operand); 2676 __ movsd(result, double_load_operand);
2679 } 2677 }
2680 2678
2681 2679
2682 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 2680 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
2683 Register result = ToRegister(instr->result()); 2681 Register result = ToRegister(instr->result());
2684 2682
2685 // Load the result. 2683 // Load the result.
2686 __ mov(result, 2684 __ mov(result,
2687 BuildFastArrayOperand(instr->elements(), instr->key(), 2685 BuildFastArrayOperand(instr->elements(), instr->key(),
2688 instr->hydrogen()->key()->representation(), 2686 instr->hydrogen()->key()->representation(),
2689 FAST_ELEMENTS, instr->base_offset())); 2687 FAST_ELEMENTS, instr->base_offset()));
2690 2688
2691 // Check for the hole value. 2689 // Check for the hole value.
2692 if (instr->hydrogen()->RequiresHoleCheck()) { 2690 if (instr->hydrogen()->RequiresHoleCheck()) {
2693 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 2691 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
2694 __ test(result, Immediate(kSmiTagMask)); 2692 __ test(result, Immediate(kSmiTagMask));
2695 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotASmi); 2693 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotASmi);
2696 } else { 2694 } else {
2697 __ cmp(result, factory()->the_hole_value()); 2695 __ cmp(result, factory()->the_hole_value());
2698 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2696 DeoptimizeIf(equal, instr, DeoptimizeReason::kHole);
2699 } 2697 }
2700 } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) { 2698 } else if (instr->hydrogen()->hole_mode() == CONVERT_HOLE_TO_UNDEFINED) {
2701 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS); 2699 DCHECK(instr->hydrogen()->elements_kind() == FAST_HOLEY_ELEMENTS);
2702 Label done; 2700 Label done;
2703 __ cmp(result, factory()->the_hole_value()); 2701 __ cmp(result, factory()->the_hole_value());
2704 __ j(not_equal, &done); 2702 __ j(not_equal, &done);
2705 if (info()->IsStub()) { 2703 if (info()->IsStub()) {
2706 // A stub can safely convert the hole to undefined only if the array 2704 // A stub can safely convert the hole to undefined only if the array
2707 // protector cell contains (Smi) Isolate::kArrayProtectorValid. 2705 // protector cell contains (Smi) Isolate::kArrayProtectorValid.
2708 // Otherwise it needs to bail out. 2706 // Otherwise it needs to bail out.
2709 __ LoadRoot(result, Heap::kArrayProtectorRootIndex); 2707 __ LoadRoot(result, Heap::kArrayProtectorRootIndex);
2710 __ cmp(FieldOperand(result, PropertyCell::kValueOffset), 2708 __ cmp(FieldOperand(result, PropertyCell::kValueOffset),
2711 Immediate(Smi::FromInt(Isolate::kArrayProtectorValid))); 2709 Immediate(Smi::FromInt(Isolate::kArrayProtectorValid)));
2712 DeoptimizeIf(not_equal, instr, Deoptimizer::kHole); 2710 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kHole);
2713 } 2711 }
2714 __ mov(result, isolate()->factory()->undefined_value()); 2712 __ mov(result, isolate()->factory()->undefined_value());
2715 __ bind(&done); 2713 __ bind(&done);
2716 } 2714 }
2717 } 2715 }
2718 2716
2719 2717
2720 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 2718 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
2721 if (instr->is_fixed_typed_array()) { 2719 if (instr->is_fixed_typed_array()) {
2722 DoLoadKeyedExternalArray(instr); 2720 DoLoadKeyedExternalArray(instr);
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
2852 } 2850 }
2853 2851
2854 // Normal function. Replace undefined or null with global receiver. 2852 // Normal function. Replace undefined or null with global receiver.
2855 __ cmp(receiver, factory()->null_value()); 2853 __ cmp(receiver, factory()->null_value());
2856 __ j(equal, &global_object, Label::kNear); 2854 __ j(equal, &global_object, Label::kNear);
2857 __ cmp(receiver, factory()->undefined_value()); 2855 __ cmp(receiver, factory()->undefined_value());
2858 __ j(equal, &global_object, Label::kNear); 2856 __ j(equal, &global_object, Label::kNear);
2859 2857
2860 // The receiver should be a JS object. 2858 // The receiver should be a JS object.
2861 __ test(receiver, Immediate(kSmiTagMask)); 2859 __ test(receiver, Immediate(kSmiTagMask));
2862 DeoptimizeIf(equal, instr, Deoptimizer::kSmi); 2860 DeoptimizeIf(equal, instr, DeoptimizeReason::kSmi);
2863 __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, scratch); 2861 __ CmpObjectType(receiver, FIRST_JS_RECEIVER_TYPE, scratch);
2864 DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject); 2862 DeoptimizeIf(below, instr, DeoptimizeReason::kNotAJavaScriptObject);
2865 2863
2866 __ jmp(&receiver_ok, Label::kNear); 2864 __ jmp(&receiver_ok, Label::kNear);
2867 __ bind(&global_object); 2865 __ bind(&global_object);
2868 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); 2866 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset));
2869 __ mov(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX)); 2867 __ mov(receiver, ContextOperand(receiver, Context::NATIVE_CONTEXT_INDEX));
2870 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX)); 2868 __ mov(receiver, ContextOperand(receiver, Context::GLOBAL_PROXY_INDEX));
2871 __ bind(&receiver_ok); 2869 __ bind(&receiver_ok);
2872 } 2870 }
2873 2871
2874 2872
2875 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 2873 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
2876 Register receiver = ToRegister(instr->receiver()); 2874 Register receiver = ToRegister(instr->receiver());
2877 Register function = ToRegister(instr->function()); 2875 Register function = ToRegister(instr->function());
2878 Register length = ToRegister(instr->length()); 2876 Register length = ToRegister(instr->length());
2879 Register elements = ToRegister(instr->elements()); 2877 Register elements = ToRegister(instr->elements());
2880 DCHECK(receiver.is(eax)); // Used for parameter count. 2878 DCHECK(receiver.is(eax)); // Used for parameter count.
2881 DCHECK(function.is(edi)); // Required by InvokeFunction. 2879 DCHECK(function.is(edi)); // Required by InvokeFunction.
2882 DCHECK(ToRegister(instr->result()).is(eax)); 2880 DCHECK(ToRegister(instr->result()).is(eax));
2883 2881
2884 // Copy the arguments to this function possibly from the 2882 // Copy the arguments to this function possibly from the
2885 // adaptor frame below it. 2883 // adaptor frame below it.
2886 const uint32_t kArgumentsLimit = 1 * KB; 2884 const uint32_t kArgumentsLimit = 1 * KB;
2887 __ cmp(length, kArgumentsLimit); 2885 __ cmp(length, kArgumentsLimit);
2888 DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments); 2886 DeoptimizeIf(above, instr, DeoptimizeReason::kTooManyArguments);
2889 2887
2890 __ push(receiver); 2888 __ push(receiver);
2891 __ mov(receiver, length); 2889 __ mov(receiver, length);
2892 2890
2893 // Loop through the arguments pushing them onto the execution 2891 // Loop through the arguments pushing them onto the execution
2894 // stack. 2892 // stack.
2895 Label invoke, loop; 2893 Label invoke, loop;
2896 // length is a small non-negative integer, due to the test above. 2894 // length is a small non-negative integer, due to the test above.
2897 __ test(length, Operand(length)); 2895 __ test(length, Operand(length));
2898 __ j(zero, &invoke, Label::kNear); 2896 __ j(zero, &invoke, Label::kNear);
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
3054 } 3052 }
3055 generator.AfterCall(); 3053 generator.AfterCall();
3056 } 3054 }
3057 } 3055 }
3058 3056
3059 3057
3060 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3058 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3061 Register input_reg = ToRegister(instr->value()); 3059 Register input_reg = ToRegister(instr->value());
3062 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 3060 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
3063 factory()->heap_number_map()); 3061 factory()->heap_number_map());
3064 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 3062 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
3065 3063
3066 Label slow, allocated, done; 3064 Label slow, allocated, done;
3067 uint32_t available_regs = eax.bit() | ecx.bit() | edx.bit() | ebx.bit(); 3065 uint32_t available_regs = eax.bit() | ecx.bit() | edx.bit() | ebx.bit();
3068 available_regs &= ~input_reg.bit(); 3066 available_regs &= ~input_reg.bit();
3069 if (instr->context()->IsRegister()) { 3067 if (instr->context()->IsRegister()) {
3070 // Make sure that the context isn't overwritten in the AllocateHeapNumber 3068 // Make sure that the context isn't overwritten in the AllocateHeapNumber
3071 // macro below. 3069 // macro below.
3072 available_regs &= ~ToRegister(instr->context()).bit(); 3070 available_regs &= ~ToRegister(instr->context()).bit();
3073 } 3071 }
3074 3072
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3112 __ bind(&done); 3110 __ bind(&done);
3113 } 3111 }
3114 3112
3115 3113
3116 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3114 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3117 Register input_reg = ToRegister(instr->value()); 3115 Register input_reg = ToRegister(instr->value());
3118 __ test(input_reg, Operand(input_reg)); 3116 __ test(input_reg, Operand(input_reg));
3119 Label is_positive; 3117 Label is_positive;
3120 __ j(not_sign, &is_positive, Label::kNear); 3118 __ j(not_sign, &is_positive, Label::kNear);
3121 __ neg(input_reg); // Sets flags. 3119 __ neg(input_reg); // Sets flags.
3122 DeoptimizeIf(negative, instr, Deoptimizer::kOverflow); 3120 DeoptimizeIf(negative, instr, DeoptimizeReason::kOverflow);
3123 __ bind(&is_positive); 3121 __ bind(&is_positive);
3124 } 3122 }
3125 3123
3126 3124
3127 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3125 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3128 // Class for deferred case. 3126 // Class for deferred case.
3129 class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode { 3127 class DeferredMathAbsTaggedHeapNumber final : public LDeferredCode {
3130 public: 3128 public:
3131 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3129 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3132 LMathAbs* instr) 3130 LMathAbs* instr)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 if (CpuFeatures::IsSupported(SSE4_1)) { 3175 if (CpuFeatures::IsSupported(SSE4_1)) {
3178 CpuFeatureScope scope(masm(), SSE4_1); 3176 CpuFeatureScope scope(masm(), SSE4_1);
3179 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3177 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3180 // Deoptimize on negative zero. 3178 // Deoptimize on negative zero.
3181 Label non_zero; 3179 Label non_zero;
3182 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3180 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3183 __ ucomisd(input_reg, xmm_scratch); 3181 __ ucomisd(input_reg, xmm_scratch);
3184 __ j(not_equal, &non_zero, Label::kNear); 3182 __ j(not_equal, &non_zero, Label::kNear);
3185 __ movmskpd(output_reg, input_reg); 3183 __ movmskpd(output_reg, input_reg);
3186 __ test(output_reg, Immediate(1)); 3184 __ test(output_reg, Immediate(1));
3187 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 3185 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
3188 __ bind(&non_zero); 3186 __ bind(&non_zero);
3189 } 3187 }
3190 __ roundsd(xmm_scratch, input_reg, kRoundDown); 3188 __ roundsd(xmm_scratch, input_reg, kRoundDown);
3191 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 3189 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3192 // Overflow is signalled with minint. 3190 // Overflow is signalled with minint.
3193 __ cmp(output_reg, 0x1); 3191 __ cmp(output_reg, 0x1);
3194 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3192 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
3195 } else { 3193 } else {
3196 Label negative_sign, done; 3194 Label negative_sign, done;
3197 // Deoptimize on unordered. 3195 // Deoptimize on unordered.
3198 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3196 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3199 __ ucomisd(input_reg, xmm_scratch); 3197 __ ucomisd(input_reg, xmm_scratch);
3200 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 3198 DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
3201 __ j(below, &negative_sign, Label::kNear); 3199 __ j(below, &negative_sign, Label::kNear);
3202 3200
3203 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3201 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3204 // Check for negative zero. 3202 // Check for negative zero.
3205 Label positive_sign; 3203 Label positive_sign;
3206 __ j(above, &positive_sign, Label::kNear); 3204 __ j(above, &positive_sign, Label::kNear);
3207 __ movmskpd(output_reg, input_reg); 3205 __ movmskpd(output_reg, input_reg);
3208 __ test(output_reg, Immediate(1)); 3206 __ test(output_reg, Immediate(1));
3209 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 3207 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
3210 __ Move(output_reg, Immediate(0)); 3208 __ Move(output_reg, Immediate(0));
3211 __ jmp(&done, Label::kNear); 3209 __ jmp(&done, Label::kNear);
3212 __ bind(&positive_sign); 3210 __ bind(&positive_sign);
3213 } 3211 }
3214 3212
3215 // Use truncating instruction (OK because input is positive). 3213 // Use truncating instruction (OK because input is positive).
3216 __ cvttsd2si(output_reg, Operand(input_reg)); 3214 __ cvttsd2si(output_reg, Operand(input_reg));
3217 // Overflow is signalled with minint. 3215 // Overflow is signalled with minint.
3218 __ cmp(output_reg, 0x1); 3216 __ cmp(output_reg, 0x1);
3219 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3217 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
3220 __ jmp(&done, Label::kNear); 3218 __ jmp(&done, Label::kNear);
3221 3219
3222 // Non-zero negative reaches here. 3220 // Non-zero negative reaches here.
3223 __ bind(&negative_sign); 3221 __ bind(&negative_sign);
3224 // Truncate, then compare and compensate. 3222 // Truncate, then compare and compensate.
3225 __ cvttsd2si(output_reg, Operand(input_reg)); 3223 __ cvttsd2si(output_reg, Operand(input_reg));
3226 __ Cvtsi2sd(xmm_scratch, output_reg); 3224 __ Cvtsi2sd(xmm_scratch, output_reg);
3227 __ ucomisd(input_reg, xmm_scratch); 3225 __ ucomisd(input_reg, xmm_scratch);
3228 __ j(equal, &done, Label::kNear); 3226 __ j(equal, &done, Label::kNear);
3229 __ sub(output_reg, Immediate(1)); 3227 __ sub(output_reg, Immediate(1));
3230 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3228 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
3231 3229
3232 __ bind(&done); 3230 __ bind(&done);
3233 } 3231 }
3234 } 3232 }
3235 3233
3236 void LCodeGen::DoMathRoundD(LMathRoundD* instr) { 3234 void LCodeGen::DoMathRoundD(LMathRoundD* instr) {
3237 XMMRegister xmm_scratch = double_scratch0(); 3235 XMMRegister xmm_scratch = double_scratch0();
3238 XMMRegister output_reg = ToDoubleRegister(instr->result()); 3236 XMMRegister output_reg = ToDoubleRegister(instr->result());
3239 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3237 XMMRegister input_reg = ToDoubleRegister(instr->value());
3240 CpuFeatureScope scope(masm(), SSE4_1); 3238 CpuFeatureScope scope(masm(), SSE4_1);
(...skipping 22 matching lines...) Expand all
3263 3261
3264 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); 3262 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3265 __ ucomisd(xmm_scratch, input_reg); 3263 __ ucomisd(xmm_scratch, input_reg);
3266 __ j(above, &below_one_half, Label::kNear); 3264 __ j(above, &below_one_half, Label::kNear);
3267 3265
3268 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3266 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3269 __ addsd(xmm_scratch, input_reg); 3267 __ addsd(xmm_scratch, input_reg);
3270 __ cvttsd2si(output_reg, Operand(xmm_scratch)); 3268 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3271 // Overflow is signalled with minint. 3269 // Overflow is signalled with minint.
3272 __ cmp(output_reg, 0x1); 3270 __ cmp(output_reg, 0x1);
3273 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3271 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
3274 __ jmp(&done, dist); 3272 __ jmp(&done, dist);
3275 3273
3276 __ bind(&below_one_half); 3274 __ bind(&below_one_half);
3277 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); 3275 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3278 __ ucomisd(xmm_scratch, input_reg); 3276 __ ucomisd(xmm_scratch, input_reg);
3279 __ j(below_equal, &round_to_zero, Label::kNear); 3277 __ j(below_equal, &round_to_zero, Label::kNear);
3280 3278
3281 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3279 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3282 // compare and compensate. 3280 // compare and compensate.
3283 __ movaps(input_temp, input_reg); // Do not alter input_reg. 3281 __ movaps(input_temp, input_reg); // Do not alter input_reg.
3284 __ subsd(input_temp, xmm_scratch); 3282 __ subsd(input_temp, xmm_scratch);
3285 __ cvttsd2si(output_reg, Operand(input_temp)); 3283 __ cvttsd2si(output_reg, Operand(input_temp));
3286 // Catch minint due to overflow, and to prevent overflow when compensating. 3284 // Catch minint due to overflow, and to prevent overflow when compensating.
3287 __ cmp(output_reg, 0x1); 3285 __ cmp(output_reg, 0x1);
3288 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3286 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
3289 3287
3290 __ Cvtsi2sd(xmm_scratch, output_reg); 3288 __ Cvtsi2sd(xmm_scratch, output_reg);
3291 __ ucomisd(xmm_scratch, input_temp); 3289 __ ucomisd(xmm_scratch, input_temp);
3292 __ j(equal, &done, dist); 3290 __ j(equal, &done, dist);
3293 __ sub(output_reg, Immediate(1)); 3291 __ sub(output_reg, Immediate(1));
3294 // No overflow because we already ruled out minint. 3292 // No overflow because we already ruled out minint.
3295 __ jmp(&done, dist); 3293 __ jmp(&done, dist);
3296 3294
3297 __ bind(&round_to_zero); 3295 __ bind(&round_to_zero);
3298 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3296 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3299 // we can ignore the difference between a result of -0 and +0. 3297 // we can ignore the difference between a result of -0 and +0.
3300 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3298 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3301 // If the sign is positive, we return +0. 3299 // If the sign is positive, we return +0.
3302 __ movmskpd(output_reg, input_reg); 3300 __ movmskpd(output_reg, input_reg);
3303 __ test(output_reg, Immediate(1)); 3301 __ test(output_reg, Immediate(1));
3304 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 3302 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
3305 } 3303 }
3306 __ Move(output_reg, Immediate(0)); 3304 __ Move(output_reg, Immediate(0));
3307 __ bind(&done); 3305 __ bind(&done);
3308 } 3306 }
3309 3307
3310 3308
3311 void LCodeGen::DoMathFround(LMathFround* instr) { 3309 void LCodeGen::DoMathFround(LMathFround* instr) {
3312 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3310 XMMRegister input_reg = ToDoubleRegister(instr->value());
3313 XMMRegister output_reg = ToDoubleRegister(instr->result()); 3311 XMMRegister output_reg = ToDoubleRegister(instr->result());
3314 __ cvtsd2ss(output_reg, input_reg); 3312 __ cvtsd2ss(output_reg, input_reg);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3370 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); 3368 DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
3371 3369
3372 if (exponent_type.IsSmi()) { 3370 if (exponent_type.IsSmi()) {
3373 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3371 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3374 __ CallStub(&stub); 3372 __ CallStub(&stub);
3375 } else if (exponent_type.IsTagged()) { 3373 } else if (exponent_type.IsTagged()) {
3376 Label no_deopt; 3374 Label no_deopt;
3377 __ JumpIfSmi(tagged_exponent, &no_deopt); 3375 __ JumpIfSmi(tagged_exponent, &no_deopt);
3378 DCHECK(!ecx.is(tagged_exponent)); 3376 DCHECK(!ecx.is(tagged_exponent));
3379 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx); 3377 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx);
3380 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 3378 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
3381 __ bind(&no_deopt); 3379 __ bind(&no_deopt);
3382 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3380 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3383 __ CallStub(&stub); 3381 __ CallStub(&stub);
3384 } else if (exponent_type.IsInteger32()) { 3382 } else if (exponent_type.IsInteger32()) {
3385 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3383 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3386 __ CallStub(&stub); 3384 __ CallStub(&stub);
3387 } else { 3385 } else {
3388 DCHECK(exponent_type.IsDouble()); 3386 DCHECK(exponent_type.IsDouble());
3389 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3387 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3390 __ CallStub(&stub); 3388 __ CallStub(&stub);
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
3731 instr->hydrogen()->index()->representation())); 3729 instr->hydrogen()->index()->representation()));
3732 } else { 3730 } else {
3733 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); 3731 __ cmp(ToRegister(instr->index()), ToOperand(instr->length()));
3734 } 3732 }
3735 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 3733 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
3736 Label done; 3734 Label done;
3737 __ j(NegateCondition(cc), &done, Label::kNear); 3735 __ j(NegateCondition(cc), &done, Label::kNear);
3738 __ int3(); 3736 __ int3();
3739 __ bind(&done); 3737 __ bind(&done);
3740 } else { 3738 } else {
3741 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds); 3739 DeoptimizeIf(cc, instr, DeoptimizeReason::kOutOfBounds);
3742 } 3740 }
3743 } 3741 }
3744 3742
3745 3743
3746 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 3744 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
3747 ElementsKind elements_kind = instr->elements_kind(); 3745 ElementsKind elements_kind = instr->elements_kind();
3748 LOperand* key = instr->key(); 3746 LOperand* key = instr->key();
3749 if (!key->IsConstantOperand() && 3747 if (!key->IsConstantOperand() &&
3750 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), 3748 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(),
3751 elements_kind)) { 3749 elements_kind)) {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
3890 .code(); 3888 .code();
3891 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3889 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3892 } 3890 }
3893 3891
3894 3892
3895 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 3893 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
3896 Register object = ToRegister(instr->object()); 3894 Register object = ToRegister(instr->object());
3897 Register temp = ToRegister(instr->temp()); 3895 Register temp = ToRegister(instr->temp());
3898 Label no_memento_found; 3896 Label no_memento_found;
3899 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 3897 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
3900 DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound); 3898 DeoptimizeIf(equal, instr, DeoptimizeReason::kMementoFound);
3901 __ bind(&no_memento_found); 3899 __ bind(&no_memento_found);
3902 } 3900 }
3903 3901
3904 3902
3905 void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) { 3903 void LCodeGen::DoMaybeGrowElements(LMaybeGrowElements* instr) {
3906 class DeferredMaybeGrowElements final : public LDeferredCode { 3904 class DeferredMaybeGrowElements final : public LDeferredCode {
3907 public: 3905 public:
3908 DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr) 3906 DeferredMaybeGrowElements(LCodeGen* codegen, LMaybeGrowElements* instr)
3909 : LDeferredCode(codegen), instr_(instr) {} 3907 : LDeferredCode(codegen), instr_(instr) {}
3910 void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); } 3908 void Generate() override { codegen()->DoDeferredMaybeGrowElements(instr_); }
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3988 GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(), 3986 GrowArrayElementsStub stub(isolate(), instr->hydrogen()->is_js_array(),
3989 instr->hydrogen()->kind()); 3987 instr->hydrogen()->kind());
3990 __ CallStub(&stub); 3988 __ CallStub(&stub);
3991 RecordSafepointWithLazyDeopt( 3989 RecordSafepointWithLazyDeopt(
3992 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 3990 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
3993 __ StoreToSafepointRegisterSlot(result, result); 3991 __ StoreToSafepointRegisterSlot(result, result);
3994 } 3992 }
3995 3993
3996 // Deopt on smi, which means the elements array changed to dictionary mode. 3994 // Deopt on smi, which means the elements array changed to dictionary mode.
3997 __ test(result, Immediate(kSmiTagMask)); 3995 __ test(result, Immediate(kSmiTagMask));
3998 DeoptimizeIf(equal, instr, Deoptimizer::kSmi); 3996 DeoptimizeIf(equal, instr, DeoptimizeReason::kSmi);
3999 } 3997 }
4000 3998
4001 3999
4002 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4000 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4003 Register object_reg = ToRegister(instr->object()); 4001 Register object_reg = ToRegister(instr->object());
4004 4002
4005 Handle<Map> from_map = instr->original_map(); 4003 Handle<Map> from_map = instr->original_map();
4006 Handle<Map> to_map = instr->transitioned_map(); 4004 Handle<Map> to_map = instr->transitioned_map();
4007 ElementsKind from_kind = instr->from_kind(); 4005 ElementsKind from_kind = instr->from_kind();
4008 ElementsKind to_kind = instr->to_kind(); 4006 ElementsKind to_kind = instr->to_kind();
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
4328 __ StoreToSafepointRegisterSlot(reg, eax); 4326 __ StoreToSafepointRegisterSlot(reg, eax);
4329 } 4327 }
4330 4328
4331 4329
4332 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4330 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4333 HChange* hchange = instr->hydrogen(); 4331 HChange* hchange = instr->hydrogen();
4334 Register input = ToRegister(instr->value()); 4332 Register input = ToRegister(instr->value());
4335 if (hchange->CheckFlag(HValue::kCanOverflow) && 4333 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4336 hchange->value()->CheckFlag(HValue::kUint32)) { 4334 hchange->value()->CheckFlag(HValue::kUint32)) {
4337 __ test(input, Immediate(0xc0000000)); 4335 __ test(input, Immediate(0xc0000000));
4338 DeoptimizeIf(not_zero, instr, Deoptimizer::kOverflow); 4336 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kOverflow);
4339 } 4337 }
4340 __ SmiTag(input); 4338 __ SmiTag(input);
4341 if (hchange->CheckFlag(HValue::kCanOverflow) && 4339 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4342 !hchange->value()->CheckFlag(HValue::kUint32)) { 4340 !hchange->value()->CheckFlag(HValue::kUint32)) {
4343 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 4341 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
4344 } 4342 }
4345 } 4343 }
4346 4344
4347 4345
4348 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4346 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4349 LOperand* input = instr->value(); 4347 LOperand* input = instr->value();
4350 Register result = ToRegister(input); 4348 Register result = ToRegister(input);
4351 DCHECK(input->IsRegister() && input->Equals(instr->result())); 4349 DCHECK(input->IsRegister() && input->Equals(instr->result()));
4352 if (instr->needs_check()) { 4350 if (instr->needs_check()) {
4353 __ test(result, Immediate(kSmiTagMask)); 4351 __ test(result, Immediate(kSmiTagMask));
4354 DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi); 4352 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kNotASmi);
4355 } else { 4353 } else {
4356 __ AssertSmi(result); 4354 __ AssertSmi(result);
4357 } 4355 }
4358 __ SmiUntag(result); 4356 __ SmiUntag(result);
4359 } 4357 }
4360 4358
4361 4359
4362 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4360 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4363 Register temp_reg, XMMRegister result_reg, 4361 Register temp_reg, XMMRegister result_reg,
4364 NumberUntagDMode mode) { 4362 NumberUntagDMode mode) {
4365 bool can_convert_undefined_to_nan = 4363 bool can_convert_undefined_to_nan =
4366 instr->hydrogen()->can_convert_undefined_to_nan(); 4364 instr->hydrogen()->can_convert_undefined_to_nan();
4367 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 4365 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4368 4366
4369 Label convert, load_smi, done; 4367 Label convert, load_smi, done;
4370 4368
4371 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4369 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4372 // Smi check. 4370 // Smi check.
4373 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 4371 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4374 4372
4375 // Heap number map check. 4373 // Heap number map check.
4376 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4374 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4377 factory()->heap_number_map()); 4375 factory()->heap_number_map());
4378 if (can_convert_undefined_to_nan) { 4376 if (can_convert_undefined_to_nan) {
4379 __ j(not_equal, &convert, Label::kNear); 4377 __ j(not_equal, &convert, Label::kNear);
4380 } else { 4378 } else {
4381 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 4379 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
4382 } 4380 }
4383 4381
4384 // Heap number to XMM conversion. 4382 // Heap number to XMM conversion.
4385 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4383 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
4386 4384
4387 if (deoptimize_on_minus_zero) { 4385 if (deoptimize_on_minus_zero) {
4388 XMMRegister xmm_scratch = double_scratch0(); 4386 XMMRegister xmm_scratch = double_scratch0();
4389 __ xorps(xmm_scratch, xmm_scratch); 4387 __ xorps(xmm_scratch, xmm_scratch);
4390 __ ucomisd(result_reg, xmm_scratch); 4388 __ ucomisd(result_reg, xmm_scratch);
4391 __ j(not_zero, &done, Label::kNear); 4389 __ j(not_zero, &done, Label::kNear);
4392 __ movmskpd(temp_reg, result_reg); 4390 __ movmskpd(temp_reg, result_reg);
4393 __ test_b(temp_reg, Immediate(1)); 4391 __ test_b(temp_reg, Immediate(1));
4394 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 4392 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
4395 } 4393 }
4396 __ jmp(&done, Label::kNear); 4394 __ jmp(&done, Label::kNear);
4397 4395
4398 if (can_convert_undefined_to_nan) { 4396 if (can_convert_undefined_to_nan) {
4399 __ bind(&convert); 4397 __ bind(&convert);
4400 4398
4401 // Convert undefined to NaN. 4399 // Convert undefined to NaN.
4402 __ cmp(input_reg, factory()->undefined_value()); 4400 __ cmp(input_reg, factory()->undefined_value());
4403 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined); 4401 DeoptimizeIf(not_equal, instr,
4402 DeoptimizeReason::kNotAHeapNumberUndefined);
4404 4403
4405 __ pcmpeqd(result_reg, result_reg); 4404 __ pcmpeqd(result_reg, result_reg);
4406 __ jmp(&done, Label::kNear); 4405 __ jmp(&done, Label::kNear);
4407 } 4406 }
4408 } else { 4407 } else {
4409 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4408 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4410 } 4409 }
4411 4410
4412 __ bind(&load_smi); 4411 __ bind(&load_smi);
4413 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the 4412 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
4446 4445
4447 __ bind(&check_bools); 4446 __ bind(&check_bools);
4448 __ cmp(input_reg, factory()->true_value()); 4447 __ cmp(input_reg, factory()->true_value());
4449 __ j(not_equal, &check_false, Label::kNear); 4448 __ j(not_equal, &check_false, Label::kNear);
4450 __ Move(input_reg, Immediate(1)); 4449 __ Move(input_reg, Immediate(1));
4451 __ jmp(done); 4450 __ jmp(done);
4452 4451
4453 __ bind(&check_false); 4452 __ bind(&check_false);
4454 __ cmp(input_reg, factory()->false_value()); 4453 __ cmp(input_reg, factory()->false_value());
4455 DeoptimizeIf(not_equal, instr, 4454 DeoptimizeIf(not_equal, instr,
4456 Deoptimizer::kNotAHeapNumberUndefinedBoolean); 4455 DeoptimizeReason::kNotAHeapNumberUndefinedBoolean);
4457 __ Move(input_reg, Immediate(0)); 4456 __ Move(input_reg, Immediate(0));
4458 } else { 4457 } else {
4459 XMMRegister scratch = ToDoubleRegister(instr->temp()); 4458 XMMRegister scratch = ToDoubleRegister(instr->temp());
4460 DCHECK(!scratch.is(xmm0)); 4459 DCHECK(!scratch.is(xmm0));
4461 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4460 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4462 isolate()->factory()->heap_number_map()); 4461 isolate()->factory()->heap_number_map());
4463 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 4462 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumber);
4464 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4463 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4465 __ cvttsd2si(input_reg, Operand(xmm0)); 4464 __ cvttsd2si(input_reg, Operand(xmm0));
4466 __ Cvtsi2sd(scratch, Operand(input_reg)); 4465 __ Cvtsi2sd(scratch, Operand(input_reg));
4467 __ ucomisd(xmm0, scratch); 4466 __ ucomisd(xmm0, scratch);
4468 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); 4467 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kLostPrecision);
4469 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 4468 DeoptimizeIf(parity_even, instr, DeoptimizeReason::kNaN);
4470 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 4469 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
4471 __ test(input_reg, Operand(input_reg)); 4470 __ test(input_reg, Operand(input_reg));
4472 __ j(not_zero, done); 4471 __ j(not_zero, done);
4473 __ movmskpd(input_reg, xmm0); 4472 __ movmskpd(input_reg, xmm0);
4474 __ and_(input_reg, 1); 4473 __ and_(input_reg, 1);
4475 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 4474 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kMinusZero);
4476 } 4475 }
4477 } 4476 }
4478 } 4477 }
4479 4478
4480 4479
4481 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 4480 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4482 class DeferredTaggedToI final : public LDeferredCode { 4481 class DeferredTaggedToI final : public LDeferredCode {
4483 public: 4482 public:
4484 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 4483 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
4485 : LDeferredCode(codegen), instr_(instr) { } 4484 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4545 } else { 4544 } else {
4546 Label lost_precision, is_nan, minus_zero, done; 4545 Label lost_precision, is_nan, minus_zero, done;
4547 XMMRegister input_reg = ToDoubleRegister(input); 4546 XMMRegister input_reg = ToDoubleRegister(input);
4548 XMMRegister xmm_scratch = double_scratch0(); 4547 XMMRegister xmm_scratch = double_scratch0();
4549 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 4548 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
4550 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4549 __ DoubleToI(result_reg, input_reg, xmm_scratch,
4551 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, 4550 instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
4552 &is_nan, &minus_zero, dist); 4551 &is_nan, &minus_zero, dist);
4553 __ jmp(&done, dist); 4552 __ jmp(&done, dist);
4554 __ bind(&lost_precision); 4553 __ bind(&lost_precision);
4555 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision); 4554 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
4556 __ bind(&is_nan); 4555 __ bind(&is_nan);
4557 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN); 4556 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
4558 __ bind(&minus_zero); 4557 __ bind(&minus_zero);
4559 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 4558 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
4560 __ bind(&done); 4559 __ bind(&done);
4561 } 4560 }
4562 } 4561 }
4563 4562
4564 4563
4565 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 4564 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4566 LOperand* input = instr->value(); 4565 LOperand* input = instr->value();
4567 DCHECK(input->IsDoubleRegister()); 4566 DCHECK(input->IsDoubleRegister());
4568 LOperand* result = instr->result(); 4567 LOperand* result = instr->result();
4569 DCHECK(result->IsRegister()); 4568 DCHECK(result->IsRegister());
4570 Register result_reg = ToRegister(result); 4569 Register result_reg = ToRegister(result);
4571 4570
4572 Label lost_precision, is_nan, minus_zero, done; 4571 Label lost_precision, is_nan, minus_zero, done;
4573 XMMRegister input_reg = ToDoubleRegister(input); 4572 XMMRegister input_reg = ToDoubleRegister(input);
4574 XMMRegister xmm_scratch = double_scratch0(); 4573 XMMRegister xmm_scratch = double_scratch0();
4575 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 4574 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
4576 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4575 __ DoubleToI(result_reg, input_reg, xmm_scratch,
4577 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan, 4576 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
4578 &minus_zero, dist); 4577 &minus_zero, dist);
4579 __ jmp(&done, dist); 4578 __ jmp(&done, dist);
4580 __ bind(&lost_precision); 4579 __ bind(&lost_precision);
4581 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision); 4580 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kLostPrecision);
4582 __ bind(&is_nan); 4581 __ bind(&is_nan);
4583 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN); 4582 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kNaN);
4584 __ bind(&minus_zero); 4583 __ bind(&minus_zero);
4585 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 4584 DeoptimizeIf(no_condition, instr, DeoptimizeReason::kMinusZero);
4586 __ bind(&done); 4585 __ bind(&done);
4587 __ SmiTag(result_reg); 4586 __ SmiTag(result_reg);
4588 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 4587 DeoptimizeIf(overflow, instr, DeoptimizeReason::kOverflow);
4589 } 4588 }
4590 4589
4591 4590
4592 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 4591 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
4593 LOperand* input = instr->value(); 4592 LOperand* input = instr->value();
4594 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4593 __ test(ToOperand(input), Immediate(kSmiTagMask));
4595 DeoptimizeIf(not_zero, instr, Deoptimizer::kNotASmi); 4594 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kNotASmi);
4596 } 4595 }
4597 4596
4598 4597
4599 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 4598 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
4600 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 4599 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
4601 LOperand* input = instr->value(); 4600 LOperand* input = instr->value();
4602 __ test(ToOperand(input), Immediate(kSmiTagMask)); 4601 __ test(ToOperand(input), Immediate(kSmiTagMask));
4603 DeoptimizeIf(zero, instr, Deoptimizer::kSmi); 4602 DeoptimizeIf(zero, instr, DeoptimizeReason::kSmi);
4604 } 4603 }
4605 } 4604 }
4606 4605
4607 4606
4608 void LCodeGen::DoCheckArrayBufferNotNeutered( 4607 void LCodeGen::DoCheckArrayBufferNotNeutered(
4609 LCheckArrayBufferNotNeutered* instr) { 4608 LCheckArrayBufferNotNeutered* instr) {
4610 Register view = ToRegister(instr->view()); 4609 Register view = ToRegister(instr->view());
4611 Register scratch = ToRegister(instr->scratch()); 4610 Register scratch = ToRegister(instr->scratch());
4612 4611
4613 __ mov(scratch, FieldOperand(view, JSArrayBufferView::kBufferOffset)); 4612 __ mov(scratch, FieldOperand(view, JSArrayBufferView::kBufferOffset));
4614 __ test_b(FieldOperand(scratch, JSArrayBuffer::kBitFieldOffset), 4613 __ test_b(FieldOperand(scratch, JSArrayBuffer::kBitFieldOffset),
4615 Immediate(1 << JSArrayBuffer::WasNeutered::kShift)); 4614 Immediate(1 << JSArrayBuffer::WasNeutered::kShift));
4616 DeoptimizeIf(not_zero, instr, Deoptimizer::kOutOfBounds); 4615 DeoptimizeIf(not_zero, instr, DeoptimizeReason::kOutOfBounds);
4617 } 4616 }
4618 4617
4619 4618
4620 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 4619 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
4621 Register input = ToRegister(instr->value()); 4620 Register input = ToRegister(instr->value());
4622 Register temp = ToRegister(instr->temp()); 4621 Register temp = ToRegister(instr->temp());
4623 4622
4624 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); 4623 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset));
4625 4624
4626 if (instr->hydrogen()->is_interval_check()) { 4625 if (instr->hydrogen()->is_interval_check()) {
4627 InstanceType first; 4626 InstanceType first;
4628 InstanceType last; 4627 InstanceType last;
4629 instr->hydrogen()->GetCheckInterval(&first, &last); 4628 instr->hydrogen()->GetCheckInterval(&first, &last);
4630 4629
4631 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(first)); 4630 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(first));
4632 4631
4633 // If there is only one type in the interval check for equality. 4632 // If there is only one type in the interval check for equality.
4634 if (first == last) { 4633 if (first == last) {
4635 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType); 4634 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
4636 } else { 4635 } else {
4637 DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType); 4636 DeoptimizeIf(below, instr, DeoptimizeReason::kWrongInstanceType);
4638 // Omit check for the last type. 4637 // Omit check for the last type.
4639 if (last != LAST_TYPE) { 4638 if (last != LAST_TYPE) {
4640 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(last)); 4639 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(last));
4641 DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType); 4640 DeoptimizeIf(above, instr, DeoptimizeReason::kWrongInstanceType);
4642 } 4641 }
4643 } 4642 }
4644 } else { 4643 } else {
4645 uint8_t mask; 4644 uint8_t mask;
4646 uint8_t tag; 4645 uint8_t tag;
4647 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 4646 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
4648 4647
4649 if (base::bits::IsPowerOfTwo32(mask)) { 4648 if (base::bits::IsPowerOfTwo32(mask)) {
4650 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 4649 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
4651 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(mask)); 4650 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), Immediate(mask));
4652 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, 4651 DeoptimizeIf(tag == 0 ? not_zero : zero, instr,
4653 Deoptimizer::kWrongInstanceType); 4652 DeoptimizeReason::kWrongInstanceType);
4654 } else { 4653 } else {
4655 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); 4654 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset));
4656 __ and_(temp, mask); 4655 __ and_(temp, mask);
4657 __ cmp(temp, tag); 4656 __ cmp(temp, tag);
4658 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType); 4657 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongInstanceType);
4659 } 4658 }
4660 } 4659 }
4661 } 4660 }
4662 4661
4663 4662
4664 void LCodeGen::DoCheckValue(LCheckValue* instr) { 4663 void LCodeGen::DoCheckValue(LCheckValue* instr) {
4665 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 4664 Handle<HeapObject> object = instr->hydrogen()->object().handle();
4666 if (instr->hydrogen()->object_in_new_space()) { 4665 if (instr->hydrogen()->object_in_new_space()) {
4667 Register reg = ToRegister(instr->value()); 4666 Register reg = ToRegister(instr->value());
4668 Handle<Cell> cell = isolate()->factory()->NewCell(object); 4667 Handle<Cell> cell = isolate()->factory()->NewCell(object);
4669 __ cmp(reg, Operand::ForCell(cell)); 4668 __ cmp(reg, Operand::ForCell(cell));
4670 } else { 4669 } else {
4671 Operand operand = ToOperand(instr->value()); 4670 Operand operand = ToOperand(instr->value());
4672 __ cmp(operand, object); 4671 __ cmp(operand, object);
4673 } 4672 }
4674 DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch); 4673 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kValueMismatch);
4675 } 4674 }
4676 4675
4677 4676
4678 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 4677 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
4679 { 4678 {
4680 PushSafepointRegistersScope scope(this); 4679 PushSafepointRegistersScope scope(this);
4681 __ push(object); 4680 __ push(object);
4682 __ xor_(esi, esi); 4681 __ xor_(esi, esi);
4683 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 4682 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
4684 RecordSafepointWithRegisters( 4683 RecordSafepointWithRegisters(
4685 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 4684 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4686 4685
4687 __ test(eax, Immediate(kSmiTagMask)); 4686 __ test(eax, Immediate(kSmiTagMask));
4688 } 4687 }
4689 DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed); 4688 DeoptimizeIf(zero, instr, DeoptimizeReason::kInstanceMigrationFailed);
4690 } 4689 }
4691 4690
4692 4691
4693 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 4692 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4694 class DeferredCheckMaps final : public LDeferredCode { 4693 class DeferredCheckMaps final : public LDeferredCode {
4695 public: 4694 public:
4696 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 4695 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
4697 : LDeferredCode(codegen), instr_(instr), object_(object) { 4696 : LDeferredCode(codegen), instr_(instr), object_(object) {
4698 SetExit(check_maps()); 4697 SetExit(check_maps());
4699 } 4698 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4733 Handle<Map> map = maps->at(i).handle(); 4732 Handle<Map> map = maps->at(i).handle();
4734 __ CompareMap(reg, map); 4733 __ CompareMap(reg, map);
4735 __ j(equal, &success, Label::kNear); 4734 __ j(equal, &success, Label::kNear);
4736 } 4735 }
4737 4736
4738 Handle<Map> map = maps->at(maps->size() - 1).handle(); 4737 Handle<Map> map = maps->at(maps->size() - 1).handle();
4739 __ CompareMap(reg, map); 4738 __ CompareMap(reg, map);
4740 if (instr->hydrogen()->HasMigrationTarget()) { 4739 if (instr->hydrogen()->HasMigrationTarget()) {
4741 __ j(not_equal, deferred->entry()); 4740 __ j(not_equal, deferred->entry());
4742 } else { 4741 } else {
4743 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap); 4742 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
4744 } 4743 }
4745 4744
4746 __ bind(&success); 4745 __ bind(&success);
4747 } 4746 }
4748 4747
4749 4748
4750 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 4749 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
4751 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 4750 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
4752 XMMRegister xmm_scratch = double_scratch0(); 4751 XMMRegister xmm_scratch = double_scratch0();
4753 Register result_reg = ToRegister(instr->result()); 4752 Register result_reg = ToRegister(instr->result());
(...skipping 18 matching lines...) Expand all
4772 __ JumpIfSmi(input_reg, &is_smi); 4771 __ JumpIfSmi(input_reg, &is_smi);
4773 4772
4774 // Check for heap number 4773 // Check for heap number
4775 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4774 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4776 factory()->heap_number_map()); 4775 factory()->heap_number_map());
4777 __ j(equal, &heap_number, Label::kNear); 4776 __ j(equal, &heap_number, Label::kNear);
4778 4777
4779 // Check for undefined. Undefined is converted to zero for clamping 4778 // Check for undefined. Undefined is converted to zero for clamping
4780 // conversions. 4779 // conversions.
4781 __ cmp(input_reg, factory()->undefined_value()); 4780 __ cmp(input_reg, factory()->undefined_value());
4782 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined); 4781 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kNotAHeapNumberUndefined);
4783 __ mov(input_reg, 0); 4782 __ mov(input_reg, 0);
4784 __ jmp(&done, Label::kNear); 4783 __ jmp(&done, Label::kNear);
4785 4784
4786 // Heap number 4785 // Heap number
4787 __ bind(&heap_number); 4786 __ bind(&heap_number);
4788 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4787 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
4789 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 4788 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
4790 __ jmp(&done, Label::kNear); 4789 __ jmp(&done, Label::kNear);
4791 4790
4792 // smi 4791 // smi
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
5197 __ jmp(&done, Label::kNear); 5196 __ jmp(&done, Label::kNear);
5198 5197
5199 __ bind(&load_cache); 5198 __ bind(&load_cache);
5200 __ LoadInstanceDescriptors(map, result); 5199 __ LoadInstanceDescriptors(map, result);
5201 __ mov(result, 5200 __ mov(result,
5202 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5201 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5203 __ mov(result, 5202 __ mov(result,
5204 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5203 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5205 __ bind(&done); 5204 __ bind(&done);
5206 __ test(result, result); 5205 __ test(result, result);
5207 DeoptimizeIf(equal, instr, Deoptimizer::kNoCache); 5206 DeoptimizeIf(equal, instr, DeoptimizeReason::kNoCache);
5208 } 5207 }
5209 5208
5210 5209
5211 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5210 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5212 Register object = ToRegister(instr->value()); 5211 Register object = ToRegister(instr->value());
5213 __ cmp(ToRegister(instr->map()), 5212 __ cmp(ToRegister(instr->map()),
5214 FieldOperand(object, HeapObject::kMapOffset)); 5213 FieldOperand(object, HeapObject::kMapOffset));
5215 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap); 5214 DeoptimizeIf(not_equal, instr, DeoptimizeReason::kWrongMap);
5216 } 5215 }
5217 5216
5218 5217
5219 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5218 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5220 Register object, 5219 Register object,
5221 Register index) { 5220 Register index) {
5222 PushSafepointRegistersScope scope(this); 5221 PushSafepointRegistersScope scope(this);
5223 __ push(object); 5222 __ push(object);
5224 __ push(index); 5223 __ push(index);
5225 __ xor_(esi, esi); 5224 __ xor_(esi, esi);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
5285 __ bind(deferred->exit()); 5284 __ bind(deferred->exit());
5286 __ bind(&done); 5285 __ bind(&done);
5287 } 5286 }
5288 5287
5289 #undef __ 5288 #undef __
5290 5289
5291 } // namespace internal 5290 } // namespace internal
5292 } // namespace v8 5291 } // namespace v8
5293 5292
5294 #endif // V8_TARGET_ARCH_IA32 5293 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/crankshaft/ia32/lithium-codegen-ia32.h ('k') | src/crankshaft/lithium-codegen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698