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

Side by Side Diff: test/cctest/interpreter/test-interpreter.cc

Issue 1369123002: [Interpreter] Add interpreter support for compare ops and ToBoolean. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Previous change dropped exception, this adds it back. Created 5 years, 2 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
OLDNEW
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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/execution.h" 7 #include "src/execution.h"
8 #include "src/handles.h" 8 #include "src/handles.h"
9 #include "src/interpreter/bytecode-array-builder.h" 9 #include "src/interpreter/bytecode-array-builder.h"
10 #include "src/interpreter/interpreter.h" 10 #include "src/interpreter/interpreter.h"
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 144
145 DISALLOW_COPY_AND_ASSIGN(InterpreterTester); 145 DISALLOW_COPY_AND_ASSIGN(InterpreterTester);
146 }; 146 };
147 147
148 } // namespace interpreter 148 } // namespace interpreter
149 } // namespace internal 149 } // namespace internal
150 } // namespace v8 150 } // namespace v8
151 151
152 using v8::internal::BytecodeArray; 152 using v8::internal::BytecodeArray;
153 using v8::internal::Handle; 153 using v8::internal::Handle;
154 using v8::internal::LanguageMode;
154 using v8::internal::Object; 155 using v8::internal::Object;
155 using v8::internal::Runtime; 156 using v8::internal::Runtime;
156 using v8::internal::Smi; 157 using v8::internal::Smi;
157 using v8::internal::Token; 158 using v8::internal::Token;
158 using namespace v8::internal::interpreter; 159 using namespace v8::internal::interpreter;
159 160
160 TEST(InterpreterReturn) { 161 TEST(InterpreterReturn) {
161 HandleAndZoneScope handles; 162 HandleAndZoneScope handles;
162 Handle<Object> undefined_value = 163 Handle<Object> undefined_value =
163 handles.main_isolate()->factory()->undefined_value(); 164 handles.main_isolate()->factory()->undefined_value();
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 .Bind(&done) 968 .Bind(&done)
968 .Bind(&done1) 969 .Bind(&done1)
969 .Return(); 970 .Return();
970 971
971 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); 972 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
972 InterpreterTester tester(handles.main_isolate(), bytecode_array); 973 InterpreterTester tester(handles.main_isolate(), bytecode_array);
973 auto callable = tester.GetCallable<>(); 974 auto callable = tester.GetCallable<>();
974 Handle<Object> return_value = callable().ToHandleChecked(); 975 Handle<Object> return_value = callable().ToHandleChecked();
975 CHECK_EQ(Smi::cast(*return_value)->value(), 7); 976 CHECK_EQ(Smi::cast(*return_value)->value(), 7);
976 } 977 }
978
979
980 static const Token::Value kComparisonTypes[] = {
981 Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT,
982 Token::Value::NE_STRICT, Token::Value::LTE, Token::Value::LTE,
983 Token::Value::GT, Token::Value::GTE};
984
985
986 template <typename T>
987 bool CompareC(Token::Value op, T lhs, T rhs, bool types_differed = false) {
988 switch (op) {
989 case Token::Value::EQ:
990 return lhs == rhs;
991 case Token::Value::NE:
992 return lhs != rhs;
993 case Token::Value::EQ_STRICT:
994 return (lhs == rhs) && !types_differed;
995 case Token::Value::NE_STRICT:
996 return (lhs != rhs) || types_differed;
997 case Token::Value::LT:
998 return lhs < rhs;
999 case Token::Value::LTE:
1000 return lhs <= rhs;
1001 case Token::Value::GT:
1002 return lhs > rhs;
1003 case Token::Value::GTE:
1004 return lhs >= rhs;
1005 default:
1006 UNREACHABLE();
1007 return false;
1008 }
1009 }
1010
1011
1012 TEST(InterpreterSmiComparisons) {
1013 // NB Constants cover 31-bit space.
1014 int inputs[] = {v8::internal::kMinInt / 2,
1015 v8::internal::kMinInt / 4,
1016 -108733832,
1017 -999,
1018 -42,
1019 -2,
1020 -1,
1021 0,
1022 +1,
1023 +2,
1024 42,
1025 12345678,
1026 v8::internal::kMaxInt / 4,
1027 v8::internal::kMaxInt / 2};
1028
1029 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1030 Token::Value comparison = kComparisonTypes[c];
1031 for (size_t i = 0; i < arraysize(inputs); i++) {
1032 for (size_t j = 0; j < arraysize(inputs); j++) {
1033 HandleAndZoneScope handles;
1034 BytecodeArrayBuilder builder(handles.main_isolate(),
1035 handles.main_zone());
1036 Register r0(0);
1037 builder.set_locals_count(1);
1038 builder.set_parameter_count(0);
1039 builder.LoadLiteral(Smi::FromInt(inputs[i]))
1040 .StoreAccumulatorInRegister(r0)
1041 .LoadLiteral(Smi::FromInt(inputs[j]))
1042 .CompareOperation(comparison, r0, LanguageMode::SLOPPY)
1043 .Return();
1044
1045 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1046 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1047 auto callable = tester.GetCallable<>();
1048 Handle<Object> return_value = callable().ToHandleChecked();
1049 CHECK(return_value->IsBoolean());
1050 CHECK_EQ(return_value->BooleanValue(),
1051 CompareC(comparison, inputs[i], inputs[j]));
1052 }
1053 }
1054 }
1055 }
1056
1057
1058 TEST(InterpreterHeapNumberComparisons) {
1059 double inputs[] = {std::numeric_limits<double>::min(),
1060 std::numeric_limits<double>::max(),
1061 -0.001,
1062 0.01,
1063 0.1000001,
1064 1e99,
1065 -1e-99};
1066 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1067 Token::Value comparison = kComparisonTypes[c];
1068 for (size_t i = 0; i < arraysize(inputs); i++) {
1069 for (size_t j = 0; j < arraysize(inputs); j++) {
1070 HandleAndZoneScope handles;
1071 i::Factory* factory = handles.main_isolate()->factory();
1072 BytecodeArrayBuilder builder(handles.main_isolate(),
1073 handles.main_zone());
1074 Register r0(0);
1075 builder.set_locals_count(1);
1076 builder.set_parameter_count(0);
1077 builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
1078 .StoreAccumulatorInRegister(r0)
1079 .LoadLiteral(factory->NewHeapNumber(inputs[j]))
1080 .CompareOperation(comparison, r0, LanguageMode::SLOPPY)
1081 .Return();
1082
1083 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1084 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1085 auto callable = tester.GetCallable<>();
1086 Handle<Object> return_value = callable().ToHandleChecked();
1087 CHECK(return_value->IsBoolean());
1088 CHECK_EQ(return_value->BooleanValue(),
1089 CompareC(comparison, inputs[i], inputs[j]));
1090 }
1091 }
1092 }
1093 }
1094
1095
1096 TEST(InterpreterStringComparisons) {
1097 std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"};
1098
1099 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1100 Token::Value comparison = kComparisonTypes[c];
1101 for (size_t i = 0; i < arraysize(inputs); i++) {
1102 for (size_t j = 0; j < arraysize(inputs); j++) {
1103 const char* lhs = inputs[i].c_str();
1104 const char* rhs = inputs[j].c_str();
1105 HandleAndZoneScope handles;
1106 i::Factory* factory = handles.main_isolate()->factory();
1107 BytecodeArrayBuilder builder(handles.main_isolate(),
1108 handles.main_zone());
1109 Register r0(0);
1110 builder.set_locals_count(1);
1111 builder.set_parameter_count(0);
1112 builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
1113 .StoreAccumulatorInRegister(r0)
1114 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
1115 .CompareOperation(comparison, r0, LanguageMode::SLOPPY)
1116 .Return();
1117
1118 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1119 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1120 auto callable = tester.GetCallable<>();
1121 Handle<Object> return_value = callable().ToHandleChecked();
1122 CHECK(return_value->IsBoolean());
1123 CHECK_EQ(return_value->BooleanValue(),
1124 CompareC(comparison, inputs[i], inputs[j]));
1125 }
1126 }
1127 }
1128 }
1129
1130
1131 TEST(InterpreterMixedComparisons) {
1132 // This test compares a HeapNumber with a String. The latter is
1133 // convertible to a HeapNumber so comparison will be between numeric
1134 // values except for the strict comparisons where no conversion is
1135 // performed.
1136 const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
1137
1138 i::UnicodeCache unicode_cache;
1139
1140 for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
1141 Token::Value comparison = kComparisonTypes[c];
1142 for (size_t i = 0; i < arraysize(inputs); i++) {
1143 for (size_t j = 0; j < arraysize(inputs); j++) {
1144 for (int pass = 0; pass < 2; pass++) {
1145 const char* lhs_cstr = inputs[i];
1146 const char* rhs_cstr = inputs[j];
1147 double lhs = StringToDouble(&unicode_cache, lhs_cstr,
1148 i::ConversionFlags::NO_FLAGS);
1149 double rhs = StringToDouble(&unicode_cache, rhs_cstr,
1150 i::ConversionFlags::NO_FLAGS);
1151 HandleAndZoneScope handles;
1152 i::Factory* factory = handles.main_isolate()->factory();
1153 BytecodeArrayBuilder builder(handles.main_isolate(),
1154 handles.main_zone());
1155 Register r0(0);
1156 builder.set_locals_count(1);
1157 builder.set_parameter_count(0);
1158 if (pass == 0) {
1159 // Comparison with HeapNumber on the lhs and String on the rhs
1160 builder.LoadLiteral(factory->NewNumber(lhs))
1161 .StoreAccumulatorInRegister(r0)
1162 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
1163 .CompareOperation(comparison, r0, LanguageMode::SLOPPY)
1164 .Return();
1165 } else {
1166 // Comparison with HeapNumber on the rhs and String on the lhs
1167 builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
1168 .StoreAccumulatorInRegister(r0)
1169 .LoadLiteral(factory->NewNumber(rhs))
1170 .CompareOperation(comparison, r0, LanguageMode::SLOPPY)
1171 .Return();
1172 }
1173
1174 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1175 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1176 auto callable = tester.GetCallable<>();
1177 Handle<Object> return_value = callable().ToHandleChecked();
1178 CHECK(return_value->IsBoolean());
1179 CHECK_EQ(return_value->BooleanValue(),
1180 CompareC(comparison, lhs, rhs, true));
1181 }
1182 }
1183 }
1184 }
1185 }
1186
1187
1188 TEST(InterpreterInstanceOf) {
1189 HandleAndZoneScope handles;
1190 i::Factory* factory = handles.main_isolate()->factory();
1191 Handle<i::String> name = factory->NewStringFromAsciiChecked("cons");
1192 Handle<i::JSFunction> func = factory->NewFunction(name);
1193 Handle<i::JSObject> instance = factory->NewJSObject(func);
1194 Handle<i::Object> other = factory->NewNumber(3.3333);
1195 Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
1196 for (size_t i = 0; i < arraysize(cases); i++) {
1197 bool expected_value = (i == 0);
1198 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
1199 Register r0(0);
1200 builder.set_locals_count(1);
1201 builder.set_parameter_count(0);
1202 builder.LoadLiteral(cases[i]);
1203 builder.StoreAccumulatorInRegister(r0)
1204 .LoadLiteral(func)
1205 .CompareOperation(Token::Value::INSTANCEOF, r0, LanguageMode::SLOPPY)
1206 .Return();
1207
1208 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1209 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1210 auto callable = tester.GetCallable<>();
1211 Handle<Object> return_value = callable().ToHandleChecked();
1212 CHECK(return_value->IsBoolean());
1213 CHECK_EQ(return_value->BooleanValue(), expected_value);
1214 }
1215 }
1216
1217
1218 TEST(InterpreterTestIn) {
1219 HandleAndZoneScope handles;
1220 i::Factory* factory = handles.main_isolate()->factory();
1221 Handle<i::String> name = factory->InternalizeUtf8String("Array");
1222 Handle<i::Object> fun_obj =
1223 Object::GetProperty(handles.main_isolate()->global_object(), name)
1224 .ToHandleChecked();
1225 Handle<i::JSFunction> function = Handle<i::JSFunction>::cast(fun_obj);
1226
1227 // Allocate an array
1228 Handle<i::JSObject> object = factory->NewJSObject(function);
1229 Handle<i::JSArray> array = Handle<i::JSArray>::cast(object);
1230 i::JSArray::Initialize(array, 0);
1231 i::JSArray::SetLength(array, 0);
1232
1233 // Check for these properties on the array object
1234 const char* properties[] = {"length", "fuzzle", "x", "0"};
1235 for (size_t i = 0; i < arraysize(properties); i++) {
1236 bool expected_value = (i == 0);
1237 BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone());
1238 Register r0(0);
1239 builder.set_locals_count(1);
1240 builder.set_parameter_count(0);
1241 builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
1242 .StoreAccumulatorInRegister(r0)
1243 .LoadLiteral(Handle<Object>::cast(array))
1244 .CompareOperation(Token::Value::IN, r0, LanguageMode::SLOPPY)
1245 .Return();
1246
1247 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
1248 InterpreterTester tester(handles.main_isolate(), bytecode_array);
1249 auto callable = tester.GetCallable<>();
1250 Handle<Object> return_value = callable().ToHandleChecked();
1251 CHECK(return_value->IsBoolean());
1252 CHECK_EQ(return_value->BooleanValue(), expected_value);
1253 }
1254 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698