OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/interpreter.h" | 5 #include "src/interpreter/interpreter.h" |
6 | 6 |
7 #include <fstream> | 7 #include <fstream> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "src/ast/prettyprinter.h" | 10 #include "src/ast/prettyprinter.h" |
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 } | 803 } |
804 | 804 |
805 template <class Generator> | 805 template <class Generator> |
806 void Interpreter::DoBinaryOpWithFeedback(InterpreterAssembler* assembler) { | 806 void Interpreter::DoBinaryOpWithFeedback(InterpreterAssembler* assembler) { |
807 Node* reg_index = __ BytecodeOperandReg(0); | 807 Node* reg_index = __ BytecodeOperandReg(0); |
808 Node* lhs = __ LoadRegister(reg_index); | 808 Node* lhs = __ LoadRegister(reg_index); |
809 Node* rhs = __ GetAccumulator(); | 809 Node* rhs = __ GetAccumulator(); |
810 Node* context = __ GetContext(); | 810 Node* context = __ GetContext(); |
811 Node* slot_index = __ BytecodeOperandIdx(1); | 811 Node* slot_index = __ BytecodeOperandIdx(1); |
812 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); | 812 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
813 Node* result = Generator::Generate(assembler, lhs, rhs, context, | 813 Node* result = Generator::Generate(assembler, lhs, rhs, slot_index, |
814 type_feedback_vector, slot_index); | 814 type_feedback_vector, context); |
815 __ SetAccumulator(result); | 815 __ SetAccumulator(result); |
816 __ Dispatch(); | 816 __ Dispatch(); |
817 } | 817 } |
818 | 818 |
819 // Add <src> | 819 // Add <src> |
820 // | 820 // |
821 // Add register <src> to accumulator. | 821 // Add register <src> to accumulator. |
822 void Interpreter::DoAdd(InterpreterAssembler* assembler) { | 822 void Interpreter::DoAdd(InterpreterAssembler* assembler) { |
823 DoBinaryOpWithFeedback<AddWithFeedbackStub>(assembler); | 823 DoBinaryOpWithFeedback<AddWithFeedbackStub>(assembler); |
824 } | 824 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 // operation <reg> is the lhs operand and <imm> is the <rhs> operand. | 980 // operation <reg> is the lhs operand and <imm> is the <rhs> operand. |
981 void Interpreter::DoAddSmi(InterpreterAssembler* assembler) { | 981 void Interpreter::DoAddSmi(InterpreterAssembler* assembler) { |
982 Variable var_result(assembler, MachineRepresentation::kTagged); | 982 Variable var_result(assembler, MachineRepresentation::kTagged); |
983 Label fastpath(assembler), slowpath(assembler, Label::kDeferred), | 983 Label fastpath(assembler), slowpath(assembler, Label::kDeferred), |
984 end(assembler); | 984 end(assembler); |
985 | 985 |
986 Node* reg_index = __ BytecodeOperandReg(1); | 986 Node* reg_index = __ BytecodeOperandReg(1); |
987 Node* left = __ LoadRegister(reg_index); | 987 Node* left = __ LoadRegister(reg_index); |
988 Node* raw_int = __ BytecodeOperandImm(0); | 988 Node* raw_int = __ BytecodeOperandImm(0); |
989 Node* right = __ SmiTag(raw_int); | 989 Node* right = __ SmiTag(raw_int); |
| 990 Node* slot_index = __ BytecodeOperandIdx(2); |
| 991 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
990 | 992 |
991 // {right} is known to be a Smi. | 993 // {right} is known to be a Smi. |
992 // Check if the {left} is a Smi take the fast path. | 994 // Check if the {left} is a Smi take the fast path. |
993 __ BranchIf(__ WordIsSmi(left), &fastpath, &slowpath); | 995 __ BranchIf(__ WordIsSmi(left), &fastpath, &slowpath); |
994 __ Bind(&fastpath); | 996 __ Bind(&fastpath); |
995 { | 997 { |
996 // Try fast Smi addition first. | 998 // Try fast Smi addition first. |
997 Node* pair = __ SmiAddWithOverflow(left, right); | 999 Node* pair = __ SmiAddWithOverflow(left, right); |
998 Node* overflow = __ Projection(1, pair); | 1000 Node* overflow = __ Projection(1, pair); |
999 | 1001 |
1000 // Check if the Smi additon overflowed. | 1002 // Check if the Smi additon overflowed. |
1001 Label if_notoverflow(assembler); | 1003 Label if_notoverflow(assembler); |
1002 __ BranchIf(overflow, &slowpath, &if_notoverflow); | 1004 __ BranchIf(overflow, &slowpath, &if_notoverflow); |
1003 __ Bind(&if_notoverflow); | 1005 __ Bind(&if_notoverflow); |
1004 { | 1006 { |
| 1007 __ UpdateFeedback(__ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1008 type_feedback_vector, slot_index); |
1005 var_result.Bind(__ Projection(0, pair)); | 1009 var_result.Bind(__ Projection(0, pair)); |
1006 __ Goto(&end); | 1010 __ Goto(&end); |
1007 } | 1011 } |
1008 } | 1012 } |
1009 __ Bind(&slowpath); | 1013 __ Bind(&slowpath); |
1010 { | 1014 { |
1011 Node* context = __ GetContext(); | 1015 Node* context = __ GetContext(); |
1012 Callable callable = CodeFactory::Add(__ isolate()); | 1016 AddWithFeedbackStub stub(__ isolate()); |
1013 var_result.Bind(__ CallStub(callable, context, left, right)); | 1017 Callable callable = |
| 1018 Callable(stub.GetCode(), AddWithFeedbackStub::Descriptor(__ isolate())); |
| 1019 Node* args[] = {left, right, slot_index, type_feedback_vector, context}; |
| 1020 var_result.Bind(__ CallStubN(callable, args, 1)); |
1014 __ Goto(&end); | 1021 __ Goto(&end); |
1015 } | 1022 } |
1016 __ Bind(&end); | 1023 __ Bind(&end); |
1017 { | 1024 { |
1018 __ SetAccumulator(var_result.value()); | 1025 __ SetAccumulator(var_result.value()); |
1019 __ Dispatch(); | 1026 __ Dispatch(); |
1020 } | 1027 } |
1021 } | 1028 } |
1022 | 1029 |
1023 // SubSmi <imm> <reg> | 1030 // SubSmi <imm> <reg> |
1024 // | 1031 // |
1025 // Subtracts an immediate value <imm> to register <reg>. For this | 1032 // Subtracts an immediate value <imm> to register <reg>. For this |
1026 // operation <reg> is the lhs operand and <imm> is the rhs operand. | 1033 // operation <reg> is the lhs operand and <imm> is the rhs operand. |
1027 void Interpreter::DoSubSmi(InterpreterAssembler* assembler) { | 1034 void Interpreter::DoSubSmi(InterpreterAssembler* assembler) { |
1028 Variable var_result(assembler, MachineRepresentation::kTagged); | 1035 Variable var_result(assembler, MachineRepresentation::kTagged); |
1029 Label fastpath(assembler), slowpath(assembler, Label::kDeferred), | 1036 Label fastpath(assembler), slowpath(assembler, Label::kDeferred), |
1030 end(assembler); | 1037 end(assembler); |
1031 | 1038 |
1032 Node* reg_index = __ BytecodeOperandReg(1); | 1039 Node* reg_index = __ BytecodeOperandReg(1); |
1033 Node* left = __ LoadRegister(reg_index); | 1040 Node* left = __ LoadRegister(reg_index); |
1034 Node* raw_int = __ BytecodeOperandImm(0); | 1041 Node* raw_int = __ BytecodeOperandImm(0); |
1035 Node* right = __ SmiTag(raw_int); | 1042 Node* right = __ SmiTag(raw_int); |
| 1043 Node* slot_index = __ BytecodeOperandIdx(2); |
| 1044 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
1036 | 1045 |
1037 // {right} is known to be a Smi. | 1046 // {right} is known to be a Smi. |
1038 // Check if the {left} is a Smi take the fast path. | 1047 // Check if the {left} is a Smi take the fast path. |
1039 __ BranchIf(__ WordIsSmi(left), &fastpath, &slowpath); | 1048 __ BranchIf(__ WordIsSmi(left), &fastpath, &slowpath); |
1040 __ Bind(&fastpath); | 1049 __ Bind(&fastpath); |
1041 { | 1050 { |
1042 // Try fast Smi subtraction first. | 1051 // Try fast Smi subtraction first. |
1043 Node* pair = __ SmiSubWithOverflow(left, right); | 1052 Node* pair = __ SmiSubWithOverflow(left, right); |
1044 Node* overflow = __ Projection(1, pair); | 1053 Node* overflow = __ Projection(1, pair); |
1045 | 1054 |
1046 // Check if the Smi subtraction overflowed. | 1055 // Check if the Smi subtraction overflowed. |
1047 Label if_notoverflow(assembler); | 1056 Label if_notoverflow(assembler); |
1048 __ BranchIf(overflow, &slowpath, &if_notoverflow); | 1057 __ BranchIf(overflow, &slowpath, &if_notoverflow); |
1049 __ Bind(&if_notoverflow); | 1058 __ Bind(&if_notoverflow); |
1050 { | 1059 { |
| 1060 __ UpdateFeedback(__ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1061 type_feedback_vector, slot_index); |
1051 var_result.Bind(__ Projection(0, pair)); | 1062 var_result.Bind(__ Projection(0, pair)); |
1052 __ Goto(&end); | 1063 __ Goto(&end); |
1053 } | 1064 } |
1054 } | 1065 } |
1055 __ Bind(&slowpath); | 1066 __ Bind(&slowpath); |
1056 { | 1067 { |
1057 Node* context = __ GetContext(); | 1068 Node* context = __ GetContext(); |
1058 Callable callable = CodeFactory::Subtract(__ isolate()); | 1069 SubtractWithFeedbackStub stub(__ isolate()); |
1059 var_result.Bind(__ CallStub(callable, context, left, right)); | 1070 Callable callable = Callable( |
| 1071 stub.GetCode(), SubtractWithFeedbackStub::Descriptor(__ isolate())); |
| 1072 Node* args[] = {left, right, slot_index, type_feedback_vector, context}; |
| 1073 var_result.Bind(__ CallStubN(callable, args, 1)); |
1060 __ Goto(&end); | 1074 __ Goto(&end); |
1061 } | 1075 } |
1062 __ Bind(&end); | 1076 __ Bind(&end); |
1063 { | 1077 { |
1064 __ SetAccumulator(var_result.value()); | 1078 __ SetAccumulator(var_result.value()); |
1065 __ Dispatch(); | 1079 __ Dispatch(); |
1066 } | 1080 } |
1067 } | 1081 } |
1068 | 1082 |
1069 // BitwiseOr <imm> <reg> | 1083 // BitwiseOr <imm> <reg> |
1070 // | 1084 // |
1071 // BitwiseOr <reg> with <imm>. For this operation <reg> is the lhs | 1085 // BitwiseOr <reg> with <imm>. For this operation <reg> is the lhs |
1072 // operand and <imm> is the rhs operand. | 1086 // operand and <imm> is the rhs operand. |
1073 void Interpreter::DoBitwiseOrSmi(InterpreterAssembler* assembler) { | 1087 void Interpreter::DoBitwiseOrSmi(InterpreterAssembler* assembler) { |
1074 Node* reg_index = __ BytecodeOperandReg(1); | 1088 Node* reg_index = __ BytecodeOperandReg(1); |
1075 Node* left = __ LoadRegister(reg_index); | 1089 Node* left = __ LoadRegister(reg_index); |
1076 Node* raw_int = __ BytecodeOperandImm(0); | 1090 Node* raw_int = __ BytecodeOperandImm(0); |
1077 Node* right = __ SmiTag(raw_int); | 1091 Node* right = __ SmiTag(raw_int); |
1078 Node* context = __ GetContext(); | 1092 Node* context = __ GetContext(); |
1079 Node* lhs_value = __ TruncateTaggedToWord32(context, left); | 1093 Node* slot_index = __ BytecodeOperandIdx(2); |
| 1094 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1095 Variable var_lhs_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1096 Node* lhs_value = __ TruncateTaggedToWord32WithFeedback( |
| 1097 context, left, &var_lhs_type_feedback); |
1080 Node* rhs_value = __ SmiToWord32(right); | 1098 Node* rhs_value = __ SmiToWord32(right); |
1081 Node* value = __ Word32Or(lhs_value, rhs_value); | 1099 Node* value = __ Word32Or(lhs_value, rhs_value); |
1082 Node* result = __ ChangeInt32ToTagged(value); | 1100 Node* result = __ ChangeInt32ToTagged(value); |
| 1101 Node* result_type = |
| 1102 __ Select(__ WordIsSmi(result), |
| 1103 __ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1104 __ Int32Constant(BinaryOperationFeedback::kNumber)); |
| 1105 __ UpdateFeedback(__ Word32Or(result_type, var_lhs_type_feedback.value()), |
| 1106 type_feedback_vector, slot_index); |
1083 __ SetAccumulator(result); | 1107 __ SetAccumulator(result); |
1084 __ Dispatch(); | 1108 __ Dispatch(); |
1085 } | 1109 } |
1086 | 1110 |
1087 // BitwiseAnd <imm> <reg> | 1111 // BitwiseAnd <imm> <reg> |
1088 // | 1112 // |
1089 // BitwiseAnd <reg> with <imm>. For this operation <reg> is the lhs | 1113 // BitwiseAnd <reg> with <imm>. For this operation <reg> is the lhs |
1090 // operand and <imm> is the rhs operand. | 1114 // operand and <imm> is the rhs operand. |
1091 void Interpreter::DoBitwiseAndSmi(InterpreterAssembler* assembler) { | 1115 void Interpreter::DoBitwiseAndSmi(InterpreterAssembler* assembler) { |
1092 Node* reg_index = __ BytecodeOperandReg(1); | 1116 Node* reg_index = __ BytecodeOperandReg(1); |
1093 Node* left = __ LoadRegister(reg_index); | 1117 Node* left = __ LoadRegister(reg_index); |
1094 Node* raw_int = __ BytecodeOperandImm(0); | 1118 Node* raw_int = __ BytecodeOperandImm(0); |
1095 Node* right = __ SmiTag(raw_int); | 1119 Node* right = __ SmiTag(raw_int); |
1096 Node* context = __ GetContext(); | 1120 Node* context = __ GetContext(); |
1097 Node* lhs_value = __ TruncateTaggedToWord32(context, left); | 1121 Node* slot_index = __ BytecodeOperandIdx(2); |
| 1122 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1123 Variable var_lhs_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1124 Node* lhs_value = __ TruncateTaggedToWord32WithFeedback( |
| 1125 context, left, &var_lhs_type_feedback); |
1098 Node* rhs_value = __ SmiToWord32(right); | 1126 Node* rhs_value = __ SmiToWord32(right); |
1099 Node* value = __ Word32And(lhs_value, rhs_value); | 1127 Node* value = __ Word32And(lhs_value, rhs_value); |
1100 Node* result = __ ChangeInt32ToTagged(value); | 1128 Node* result = __ ChangeInt32ToTagged(value); |
| 1129 Node* result_type = |
| 1130 __ Select(__ WordIsSmi(result), |
| 1131 __ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1132 __ Int32Constant(BinaryOperationFeedback::kNumber)); |
| 1133 __ UpdateFeedback(__ Word32Or(result_type, var_lhs_type_feedback.value()), |
| 1134 type_feedback_vector, slot_index); |
1101 __ SetAccumulator(result); | 1135 __ SetAccumulator(result); |
1102 __ Dispatch(); | 1136 __ Dispatch(); |
1103 } | 1137 } |
1104 | 1138 |
1105 // ShiftLeftSmi <imm> <reg> | 1139 // ShiftLeftSmi <imm> <reg> |
1106 // | 1140 // |
1107 // Left shifts register <src> by the count specified in <imm>. | 1141 // Left shifts register <src> by the count specified in <imm>. |
1108 // Register <src> is converted to an int32 before the operation. The 5 | 1142 // Register <src> is converted to an int32 before the operation. The 5 |
1109 // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F). | 1143 // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F). |
1110 void Interpreter::DoShiftLeftSmi(InterpreterAssembler* assembler) { | 1144 void Interpreter::DoShiftLeftSmi(InterpreterAssembler* assembler) { |
1111 Node* reg_index = __ BytecodeOperandReg(1); | 1145 Node* reg_index = __ BytecodeOperandReg(1); |
1112 Node* left = __ LoadRegister(reg_index); | 1146 Node* left = __ LoadRegister(reg_index); |
1113 Node* raw_int = __ BytecodeOperandImm(0); | 1147 Node* raw_int = __ BytecodeOperandImm(0); |
1114 Node* right = __ SmiTag(raw_int); | 1148 Node* right = __ SmiTag(raw_int); |
1115 Node* context = __ GetContext(); | 1149 Node* context = __ GetContext(); |
1116 Node* lhs_value = __ TruncateTaggedToWord32(context, left); | 1150 Node* slot_index = __ BytecodeOperandIdx(2); |
| 1151 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1152 Variable var_lhs_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1153 Node* lhs_value = __ TruncateTaggedToWord32WithFeedback( |
| 1154 context, left, &var_lhs_type_feedback); |
1117 Node* rhs_value = __ SmiToWord32(right); | 1155 Node* rhs_value = __ SmiToWord32(right); |
1118 Node* shift_count = __ Word32And(rhs_value, __ Int32Constant(0x1f)); | 1156 Node* shift_count = __ Word32And(rhs_value, __ Int32Constant(0x1f)); |
1119 Node* value = __ Word32Shl(lhs_value, shift_count); | 1157 Node* value = __ Word32Shl(lhs_value, shift_count); |
1120 Node* result = __ ChangeInt32ToTagged(value); | 1158 Node* result = __ ChangeInt32ToTagged(value); |
| 1159 Node* result_type = |
| 1160 __ Select(__ WordIsSmi(result), |
| 1161 __ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1162 __ Int32Constant(BinaryOperationFeedback::kNumber)); |
| 1163 __ UpdateFeedback(__ Word32Or(result_type, var_lhs_type_feedback.value()), |
| 1164 type_feedback_vector, slot_index); |
1121 __ SetAccumulator(result); | 1165 __ SetAccumulator(result); |
1122 __ Dispatch(); | 1166 __ Dispatch(); |
1123 } | 1167 } |
1124 | 1168 |
1125 // ShiftRightSmi <imm> <reg> | 1169 // ShiftRightSmi <imm> <reg> |
1126 // | 1170 // |
1127 // Right shifts register <src> by the count specified in <imm>. | 1171 // Right shifts register <src> by the count specified in <imm>. |
1128 // Register <src> is converted to an int32 before the operation. The 5 | 1172 // Register <src> is converted to an int32 before the operation. The 5 |
1129 // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F). | 1173 // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F). |
1130 void Interpreter::DoShiftRightSmi(InterpreterAssembler* assembler) { | 1174 void Interpreter::DoShiftRightSmi(InterpreterAssembler* assembler) { |
1131 Node* reg_index = __ BytecodeOperandReg(1); | 1175 Node* reg_index = __ BytecodeOperandReg(1); |
1132 Node* left = __ LoadRegister(reg_index); | 1176 Node* left = __ LoadRegister(reg_index); |
1133 Node* raw_int = __ BytecodeOperandImm(0); | 1177 Node* raw_int = __ BytecodeOperandImm(0); |
1134 Node* right = __ SmiTag(raw_int); | 1178 Node* right = __ SmiTag(raw_int); |
1135 Node* context = __ GetContext(); | 1179 Node* context = __ GetContext(); |
1136 Node* lhs_value = __ TruncateTaggedToWord32(context, left); | 1180 Node* slot_index = __ BytecodeOperandIdx(2); |
| 1181 Node* type_feedback_vector = __ LoadTypeFeedbackVector(); |
| 1182 Variable var_lhs_type_feedback(assembler, MachineRepresentation::kWord32); |
| 1183 Node* lhs_value = __ TruncateTaggedToWord32WithFeedback( |
| 1184 context, left, &var_lhs_type_feedback); |
1137 Node* rhs_value = __ SmiToWord32(right); | 1185 Node* rhs_value = __ SmiToWord32(right); |
1138 Node* shift_count = __ Word32And(rhs_value, __ Int32Constant(0x1f)); | 1186 Node* shift_count = __ Word32And(rhs_value, __ Int32Constant(0x1f)); |
1139 Node* value = __ Word32Sar(lhs_value, shift_count); | 1187 Node* value = __ Word32Sar(lhs_value, shift_count); |
1140 Node* result = __ ChangeInt32ToTagged(value); | 1188 Node* result = __ ChangeInt32ToTagged(value); |
| 1189 Node* result_type = |
| 1190 __ Select(__ WordIsSmi(result), |
| 1191 __ Int32Constant(BinaryOperationFeedback::kSignedSmall), |
| 1192 __ Int32Constant(BinaryOperationFeedback::kNumber)); |
| 1193 __ UpdateFeedback(__ Word32Or(result_type, var_lhs_type_feedback.value()), |
| 1194 type_feedback_vector, slot_index); |
1141 __ SetAccumulator(result); | 1195 __ SetAccumulator(result); |
1142 __ Dispatch(); | 1196 __ Dispatch(); |
1143 } | 1197 } |
1144 | 1198 |
1145 Node* Interpreter::BuildUnaryOp(Callable callable, | 1199 Node* Interpreter::BuildUnaryOp(Callable callable, |
1146 InterpreterAssembler* assembler) { | 1200 InterpreterAssembler* assembler) { |
1147 Node* target = __ HeapConstant(callable.code()); | 1201 Node* target = __ HeapConstant(callable.code()); |
1148 Node* accumulator = __ GetAccumulator(); | 1202 Node* accumulator = __ GetAccumulator(); |
1149 Node* context = __ GetContext(); | 1203 Node* context = __ GetContext(); |
1150 return __ CallStub(callable.descriptor(), target, context, accumulator); | 1204 return __ CallStub(callable.descriptor(), target, context, accumulator); |
(...skipping 1181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2332 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, | 2386 __ StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, |
2333 __ SmiTag(new_state)); | 2387 __ SmiTag(new_state)); |
2334 __ SetAccumulator(old_state); | 2388 __ SetAccumulator(old_state); |
2335 | 2389 |
2336 __ Dispatch(); | 2390 __ Dispatch(); |
2337 } | 2391 } |
2338 | 2392 |
2339 } // namespace interpreter | 2393 } // namespace interpreter |
2340 } // namespace internal | 2394 } // namespace internal |
2341 } // namespace v8 | 2395 } // namespace v8 |
OLD | NEW |