OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1266 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1267 array_length, elements_length); | 1267 array_length, elements_length); |
1268 | 1268 |
1269 if_builder.End(); | 1269 if_builder.End(); |
1270 } | 1270 } |
1271 | 1271 |
1272 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1272 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
1273 } | 1273 } |
1274 | 1274 |
1275 | 1275 |
| 1276 HValue* HGraphBuilder::BuildLookupNumberStringCache( |
| 1277 HValue* object, |
| 1278 HIfContinuation* continuation) { |
| 1279 // Create a joinable continuation. |
| 1280 HIfContinuation found(graph()->CreateBasicBlock(), |
| 1281 graph()->CreateBasicBlock()); |
| 1282 |
| 1283 // Load the number string cache. |
| 1284 HValue* number_string_cache = |
| 1285 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); |
| 1286 |
| 1287 // Make the hash maks from the length of the number string cache. It |
| 1288 // contains two elements (number and string) for each cache entry. |
| 1289 HValue* mask = AddLoadFixedArrayLength(number_string_cache); |
| 1290 mask->set_type(HType::Smi()); |
| 1291 mask = Add<HSar>(mask, graph()->GetConstant1()); |
| 1292 mask = Add<HSub>(mask, graph()->GetConstant1()); |
| 1293 |
| 1294 // Check whether object is a smi. |
| 1295 IfBuilder if_objectissmi(this); |
| 1296 if_objectissmi.If<HIsSmiAndBranch>(object); |
| 1297 if_objectissmi.Then(); |
| 1298 { |
| 1299 // Compute hash for smi similar to smi_get_hash(). |
| 1300 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); |
| 1301 |
| 1302 // Load the key. |
| 1303 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
| 1304 HValue* key = AddFastElementAccess(number_string_cache, key_index, |
| 1305 NULL, NULL, FAST_ELEMENTS, false, |
| 1306 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1307 |
| 1308 // Check if object == key. |
| 1309 IfBuilder if_objectiskey(this); |
| 1310 if_objectiskey.If<HCompareObjectEqAndBranch>(key, object); |
| 1311 if_objectiskey.Then(); |
| 1312 { |
| 1313 // Make the key_index available. |
| 1314 Push(key_index); |
| 1315 } |
| 1316 if_objectiskey.JoinContinuation(&found); |
| 1317 } |
| 1318 if_objectissmi.Else(); |
| 1319 { |
| 1320 // Check if object is a heap number. |
| 1321 IfBuilder if_objectisnumber(this); |
| 1322 if_objectisnumber.If<HCompareMap>( |
| 1323 object, isolate()->factory()->heap_number_map()); |
| 1324 if_objectisnumber.Then(); |
| 1325 { |
| 1326 // Compute hash for heap number similar to double_get_hash(). |
| 1327 HValue* low = Add<HLoadNamedField>( |
| 1328 object, HObjectAccess::ForHeapNumberValueLowestBits()); |
| 1329 HValue* high = Add<HLoadNamedField>( |
| 1330 object, HObjectAccess::ForHeapNumberValueHighestBits()); |
| 1331 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); |
| 1332 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); |
| 1333 |
| 1334 // Load the key. |
| 1335 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
| 1336 HValue* key = AddFastElementAccess(number_string_cache, key_index, |
| 1337 NULL, NULL, FAST_ELEMENTS, false, |
| 1338 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1339 |
| 1340 // Check if key is a heap number. |
| 1341 IfBuilder if_keyisnumber(this); |
| 1342 if_keyisnumber.IfNot<HIsSmiAndBranch>(key); |
| 1343 if_keyisnumber.AndIf<HCompareMap>( |
| 1344 key, isolate()->factory()->heap_number_map()); |
| 1345 if_keyisnumber.Then(); |
| 1346 { |
| 1347 // Check if values of key and object match. |
| 1348 IfBuilder if_keyeqobject(this); |
| 1349 if_keyeqobject.If<HCompareNumericAndBranch>( |
| 1350 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()), |
| 1351 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()), |
| 1352 Token::EQ); |
| 1353 if_keyeqobject.Then(); |
| 1354 { |
| 1355 // Make the key_index available. |
| 1356 Push(key_index); |
| 1357 } |
| 1358 if_keyeqobject.JoinContinuation(&found); |
| 1359 } |
| 1360 if_keyisnumber.JoinContinuation(&found); |
| 1361 } |
| 1362 if_objectisnumber.JoinContinuation(&found); |
| 1363 } |
| 1364 if_objectissmi.End(); |
| 1365 |
| 1366 // Check for cache hit. |
| 1367 IfBuilder if_found(this, &found); |
| 1368 if_found.Then(); |
| 1369 |
| 1370 // Load the value in case of cache hit. |
| 1371 HValue* key_index = Pop(); |
| 1372 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); |
| 1373 HValue* value = AddFastElementAccess(number_string_cache, value_index, |
| 1374 NULL, NULL, FAST_ELEMENTS, false, |
| 1375 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1376 AddIncrementCounter(isolate()->counters()->number_to_string_native()); |
| 1377 |
| 1378 if_found.CaptureContinuation(continuation); |
| 1379 |
| 1380 // The value is only available in true branch of continuation. |
| 1381 return value; |
| 1382 } |
| 1383 |
| 1384 |
| 1385 HValue* HGraphBuilder::BuildNumberToString(HValue* number) { |
| 1386 NoObservableSideEffectsScope scope(this); |
| 1387 |
| 1388 // Lookup the number in the number string cache. |
| 1389 HIfContinuation continuation; |
| 1390 HValue* value = BuildLookupNumberStringCache(number, &continuation); |
| 1391 IfBuilder if_found(this, &continuation); |
| 1392 if_found.Then(); |
| 1393 |
| 1394 // Cache hit. |
| 1395 Push(value); |
| 1396 |
| 1397 if_found.Else(); |
| 1398 |
| 1399 // Cache miss, fallback to runtime. |
| 1400 Add<HPushArgument>(number); |
| 1401 Push(Add<HCallRuntime>( |
| 1402 isolate()->factory()->empty_string(), |
| 1403 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
| 1404 1)); |
| 1405 |
| 1406 if_found.End(); |
| 1407 |
| 1408 return Pop(); |
| 1409 } |
| 1410 |
| 1411 |
1276 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1412 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1277 HValue* checked_object, | 1413 HValue* checked_object, |
1278 HValue* key, | 1414 HValue* key, |
1279 HValue* val, | 1415 HValue* val, |
1280 bool is_js_array, | 1416 bool is_js_array, |
1281 ElementsKind elements_kind, | 1417 ElementsKind elements_kind, |
1282 bool is_store, | 1418 bool is_store, |
1283 LoadKeyedHoleMode load_mode, | 1419 LoadKeyedHoleMode load_mode, |
1284 KeyedAccessStoreMode store_mode) { | 1420 KeyedAccessStoreMode store_mode) { |
1285 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1421 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
(...skipping 7716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9002 | 9138 |
9003 // Support for fast native caches. | 9139 // Support for fast native caches. |
9004 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9140 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9005 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9141 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
9006 } | 9142 } |
9007 | 9143 |
9008 | 9144 |
9009 // Fast support for number to string. | 9145 // Fast support for number to string. |
9010 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9146 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9011 ASSERT_EQ(1, call->arguments()->length()); | 9147 ASSERT_EQ(1, call->arguments()->length()); |
9012 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9148 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
9013 HValue* context = environment()->context(); | 9149 HValue* number = Pop(); |
9014 HCallStub* result = | 9150 HValue* result = BuildNumberToString(number); |
9015 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9151 return ast_context()->ReturnValue(result); |
9016 Drop(1); | |
9017 return ast_context()->ReturnInstruction(result, call->id()); | |
9018 } | 9152 } |
9019 | 9153 |
9020 | 9154 |
9021 // Fast call for custom callbacks. | 9155 // Fast call for custom callbacks. |
9022 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9156 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9023 // 1 ~ The function to call is not itself an argument to the call. | 9157 // 1 ~ The function to call is not itself an argument to the call. |
9024 int arg_count = call->arguments()->length() - 1; | 9158 int arg_count = call->arguments()->length() - 1; |
9025 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9159 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9026 | 9160 |
9027 for (int i = 0; i < arg_count; ++i) { | 9161 for (int i = 0; i < arg_count; ++i) { |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9774 if (ShouldProduceTraceOutput()) { | 9908 if (ShouldProduceTraceOutput()) { |
9775 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9909 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9776 } | 9910 } |
9777 | 9911 |
9778 #ifdef DEBUG | 9912 #ifdef DEBUG |
9779 graph_->Verify(false); // No full verify. | 9913 graph_->Verify(false); // No full verify. |
9780 #endif | 9914 #endif |
9781 } | 9915 } |
9782 | 9916 |
9783 } } // namespace v8::internal | 9917 } } // namespace v8::internal |
OLD | NEW |