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/base/utils/random-number-generator.h" | 5 #include "src/base/utils/random-number-generator.h" |
6 #include "src/ic/stub-cache.h" | 6 #include "src/ic/stub-cache.h" |
7 #include "src/isolate.h" | 7 #include "src/isolate.h" |
8 #include "test/cctest/compiler/code-assembler-tester.h" | 8 #include "test/cctest/compiler/code-assembler-tester.h" |
9 #include "test/cctest/compiler/function-tester.h" | 9 #include "test/cctest/compiler/function-tester.h" |
10 | 10 |
(...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1102 } | 1102 } |
1103 | 1103 |
1104 namespace { | 1104 namespace { |
1105 | 1105 |
1106 void TestStubCacheOffsetCalculation(StubCache::Table table, | 1106 void TestStubCacheOffsetCalculation(StubCache::Table table, |
1107 Code::Kind handler_kind) { | 1107 Code::Kind handler_kind) { |
1108 Isolate* isolate(CcTest::InitIsolateOnce()); | 1108 Isolate* isolate(CcTest::InitIsolateOnce()); |
1109 const int kNumParams = 2; | 1109 const int kNumParams = 2; |
1110 CodeStubAssemblerTester m(isolate, kNumParams); | 1110 CodeStubAssemblerTester m(isolate, kNumParams); |
1111 | 1111 |
| 1112 Code::Flags code_flags = |
| 1113 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(handler_kind)); |
1112 { | 1114 { |
1113 Node* name = m.Parameter(0); | 1115 Node* name = m.Parameter(0); |
1114 Node* map = m.Parameter(1); | 1116 Node* map = m.Parameter(1); |
1115 Node* primary_offset = m.StubCachePrimaryOffset(name, map); | 1117 Node* primary_offset = m.StubCachePrimaryOffset(name, code_flags, map); |
1116 Node* result; | 1118 Node* result; |
1117 if (table == StubCache::kPrimary) { | 1119 if (table == StubCache::kPrimary) { |
1118 result = primary_offset; | 1120 result = primary_offset; |
1119 } else { | 1121 } else { |
1120 CHECK_EQ(StubCache::kSecondary, table); | 1122 CHECK_EQ(StubCache::kSecondary, table); |
1121 result = m.StubCacheSecondaryOffset(name, primary_offset); | 1123 result = m.StubCacheSecondaryOffset(name, code_flags, primary_offset); |
1122 } | 1124 } |
1123 m.Return(m.SmiFromWord32(result)); | 1125 m.Return(m.SmiFromWord32(result)); |
1124 } | 1126 } |
1125 | 1127 |
1126 Handle<Code> code = m.GenerateCode(); | 1128 Handle<Code> code = m.GenerateCode(); |
1127 FunctionTester ft(code, kNumParams); | 1129 FunctionTester ft(code, kNumParams); |
1128 | 1130 |
1129 Factory* factory = isolate->factory(); | 1131 Factory* factory = isolate->factory(); |
1130 Handle<Name> names[] = { | 1132 Handle<Name> names[] = { |
1131 factory->NewSymbol(), | 1133 factory->NewSymbol(), |
(...skipping 22 matching lines...) Expand all Loading... |
1154 factory->sloppy_arguments_elements_map(), | 1156 factory->sloppy_arguments_elements_map(), |
1155 }; | 1157 }; |
1156 | 1158 |
1157 for (int name_index = 0; name_index < arraysize(names); name_index++) { | 1159 for (int name_index = 0; name_index < arraysize(names); name_index++) { |
1158 Handle<Name> name = names[name_index]; | 1160 Handle<Name> name = names[name_index]; |
1159 for (int map_index = 0; map_index < arraysize(maps); map_index++) { | 1161 for (int map_index = 0; map_index < arraysize(maps); map_index++) { |
1160 Handle<Map> map = maps[map_index]; | 1162 Handle<Map> map = maps[map_index]; |
1161 | 1163 |
1162 int expected_result; | 1164 int expected_result; |
1163 { | 1165 { |
1164 int primary_offset = StubCache::PrimaryOffsetForTesting(*name, *map); | 1166 int primary_offset = |
| 1167 StubCache::PrimaryOffsetForTesting(*name, code_flags, *map); |
1165 if (table == StubCache::kPrimary) { | 1168 if (table == StubCache::kPrimary) { |
1166 expected_result = primary_offset; | 1169 expected_result = primary_offset; |
1167 } else { | 1170 } else { |
1168 expected_result = | 1171 expected_result = StubCache::SecondaryOffsetForTesting( |
1169 StubCache::SecondaryOffsetForTesting(*name, primary_offset); | 1172 *name, code_flags, primary_offset); |
1170 } | 1173 } |
1171 } | 1174 } |
1172 Handle<Object> result = ft.Call(name, map).ToHandleChecked(); | 1175 Handle<Object> result = ft.Call(name, map).ToHandleChecked(); |
1173 | 1176 |
1174 Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue); | 1177 Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue); |
1175 CHECK_EQ(expected, Smi::cast(*result)); | 1178 CHECK_EQ(expected, Smi::cast(*result)); |
1176 } | 1179 } |
1177 } | 1180 } |
1178 } | 1181 } |
1179 | 1182 |
(...skipping 27 matching lines...) Expand all Loading... |
1207 } // namespace | 1210 } // namespace |
1208 | 1211 |
1209 TEST(TryProbeStubCache) { | 1212 TEST(TryProbeStubCache) { |
1210 typedef CodeStubAssembler::Label Label; | 1213 typedef CodeStubAssembler::Label Label; |
1211 typedef CodeStubAssembler::Variable Variable; | 1214 typedef CodeStubAssembler::Variable Variable; |
1212 Isolate* isolate(CcTest::InitIsolateOnce()); | 1215 Isolate* isolate(CcTest::InitIsolateOnce()); |
1213 const int kNumParams = 3; | 1216 const int kNumParams = 3; |
1214 CodeStubAssemblerTester m(isolate, kNumParams); | 1217 CodeStubAssemblerTester m(isolate, kNumParams); |
1215 | 1218 |
1216 Code::Kind ic_kind = Code::LOAD_IC; | 1219 Code::Kind ic_kind = Code::LOAD_IC; |
| 1220 Code::Flags flags_to_query = |
| 1221 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind)); |
| 1222 |
1217 StubCache stub_cache(isolate, ic_kind); | 1223 StubCache stub_cache(isolate, ic_kind); |
1218 stub_cache.Clear(); | 1224 stub_cache.Clear(); |
1219 | 1225 |
1220 { | 1226 { |
1221 Node* receiver = m.Parameter(0); | 1227 Node* receiver = m.Parameter(0); |
1222 Node* name = m.Parameter(1); | 1228 Node* name = m.Parameter(1); |
1223 Node* expected_handler = m.Parameter(2); | 1229 Node* expected_handler = m.Parameter(2); |
1224 | 1230 |
1225 Label passed(&m), failed(&m); | 1231 Label passed(&m), failed(&m); |
1226 | 1232 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1286 } | 1292 } |
1287 | 1293 |
1288 // Generate some number of receiver maps and receivers. | 1294 // Generate some number of receiver maps and receivers. |
1289 for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) { | 1295 for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) { |
1290 Handle<Map> map = Map::Create(isolate, 0); | 1296 Handle<Map> map = Map::Create(isolate, 0); |
1291 receivers.push_back(factory->NewJSObjectFromMap(map)); | 1297 receivers.push_back(factory->NewJSObjectFromMap(map)); |
1292 } | 1298 } |
1293 | 1299 |
1294 // Generate some number of handlers. | 1300 // Generate some number of handlers. |
1295 for (int i = 0; i < 30; i++) { | 1301 for (int i = 0; i < 30; i++) { |
| 1302 Code::Kind code_kind; |
| 1303 switch (rand_gen.NextInt(4)) { |
| 1304 case 0: |
| 1305 code_kind = Code::LOAD_IC; |
| 1306 break; |
| 1307 case 1: |
| 1308 code_kind = Code::KEYED_LOAD_IC; |
| 1309 break; |
| 1310 case 2: |
| 1311 code_kind = Code::STORE_IC; |
| 1312 break; |
| 1313 case 3: |
| 1314 code_kind = Code::KEYED_STORE_IC; |
| 1315 break; |
| 1316 default: |
| 1317 UNREACHABLE(); |
| 1318 } |
1296 Code::Flags flags = | 1319 Code::Flags flags = |
1297 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind)); | 1320 Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(code_kind)); |
1298 handlers.push_back(CreateCodeWithFlags(flags)); | 1321 handlers.push_back(CreateCodeWithFlags(flags)); |
1299 } | 1322 } |
1300 | 1323 |
1301 // Ensure that GC does happen because from now on we are going to fill our | 1324 // Ensure that GC does happen because from now on we are going to fill our |
1302 // own stub cache instance with raw values. | 1325 // own stub cache instance with raw values. |
1303 DisallowHeapAllocation no_gc; | 1326 DisallowHeapAllocation no_gc; |
1304 | 1327 |
1305 // Populate {stub_cache}. | 1328 // Populate {stub_cache}. |
1306 const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize; | 1329 const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize; |
1307 for (int i = 0; i < N; i++) { | 1330 for (int i = 0; i < N; i++) { |
1308 int index = rand_gen.NextInt(); | 1331 int index = rand_gen.NextInt(); |
1309 Handle<Name> name = names[index % names.size()]; | 1332 Handle<Name> name = names[index % names.size()]; |
1310 Handle<JSObject> receiver = receivers[index % receivers.size()]; | 1333 Handle<JSObject> receiver = receivers[index % receivers.size()]; |
1311 Handle<Code> handler = handlers[index % handlers.size()]; | 1334 Handle<Code> handler = handlers[index % handlers.size()]; |
1312 stub_cache.Set(*name, receiver->map(), *handler); | 1335 stub_cache.Set(*name, receiver->map(), *handler); |
1313 } | 1336 } |
1314 | 1337 |
1315 // Perform some queries. | 1338 // Perform some queries. |
1316 bool queried_existing = false; | 1339 bool queried_existing = false; |
1317 bool queried_non_existing = false; | 1340 bool queried_non_existing = false; |
1318 for (int i = 0; i < N; i++) { | 1341 for (int i = 0; i < N; i++) { |
1319 int index = rand_gen.NextInt(); | 1342 int index = rand_gen.NextInt(); |
1320 Handle<Name> name = names[index % names.size()]; | 1343 Handle<Name> name = names[index % names.size()]; |
1321 Handle<JSObject> receiver = receivers[index % receivers.size()]; | 1344 Handle<JSObject> receiver = receivers[index % receivers.size()]; |
1322 Code* handler = stub_cache.Get(*name, receiver->map()); | 1345 Code* handler = stub_cache.Get(*name, receiver->map(), flags_to_query); |
1323 if (handler == nullptr) { | 1346 if (handler == nullptr) { |
1324 queried_non_existing = true; | 1347 queried_non_existing = true; |
1325 } else { | 1348 } else { |
1326 queried_existing = true; | 1349 queried_existing = true; |
1327 } | 1350 } |
1328 | 1351 |
1329 Handle<Code> expected_handler(handler, isolate); | 1352 Handle<Code> expected_handler(handler, isolate); |
1330 ft.CheckTrue(receiver, name, expected_handler); | 1353 ft.CheckTrue(receiver, name, expected_handler); |
1331 } | 1354 } |
1332 | 1355 |
1333 for (int i = 0; i < N; i++) { | 1356 for (int i = 0; i < N; i++) { |
1334 int index1 = rand_gen.NextInt(); | 1357 int index1 = rand_gen.NextInt(); |
1335 int index2 = rand_gen.NextInt(); | 1358 int index2 = rand_gen.NextInt(); |
1336 Handle<Name> name = names[index1 % names.size()]; | 1359 Handle<Name> name = names[index1 % names.size()]; |
1337 Handle<JSObject> receiver = receivers[index2 % receivers.size()]; | 1360 Handle<JSObject> receiver = receivers[index2 % receivers.size()]; |
1338 Code* handler = stub_cache.Get(*name, receiver->map()); | 1361 Code* handler = stub_cache.Get(*name, receiver->map(), flags_to_query); |
1339 if (handler == nullptr) { | 1362 if (handler == nullptr) { |
1340 queried_non_existing = true; | 1363 queried_non_existing = true; |
1341 } else { | 1364 } else { |
1342 queried_existing = true; | 1365 queried_existing = true; |
1343 } | 1366 } |
1344 | 1367 |
1345 Handle<Code> expected_handler(handler, isolate); | 1368 Handle<Code> expected_handler(handler, isolate); |
1346 ft.CheckTrue(receiver, name, expected_handler); | 1369 ft.CheckTrue(receiver, name, expected_handler); |
1347 } | 1370 } |
1348 // Ensure we performed both kind of queries. | 1371 // Ensure we performed both kind of queries. |
1349 CHECK(queried_existing && queried_non_existing); | 1372 CHECK(queried_existing && queried_non_existing); |
1350 } | 1373 } |
1351 | 1374 |
1352 } // namespace internal | 1375 } // namespace internal |
1353 } // namespace v8 | 1376 } // namespace v8 |
OLD | NEW |