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 | |
1412 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1276 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1413 HValue* checked_object, | 1277 HValue* checked_object, |
1414 HValue* key, | 1278 HValue* key, |
1415 HValue* val, | 1279 HValue* val, |
1416 bool is_js_array, | 1280 bool is_js_array, |
1417 ElementsKind elements_kind, | 1281 ElementsKind elements_kind, |
1418 bool is_store, | 1282 bool is_store, |
1419 LoadKeyedHoleMode load_mode, | 1283 LoadKeyedHoleMode load_mode, |
1420 KeyedAccessStoreMode store_mode) { | 1284 KeyedAccessStoreMode store_mode) { |
1421 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1285 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
(...skipping 7716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9138 | 9002 |
9139 // Support for fast native caches. | 9003 // Support for fast native caches. |
9140 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9004 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
9141 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9005 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
9142 } | 9006 } |
9143 | 9007 |
9144 | 9008 |
9145 // Fast support for number to string. | 9009 // Fast support for number to string. |
9146 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9010 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
9147 ASSERT_EQ(1, call->arguments()->length()); | 9011 ASSERT_EQ(1, call->arguments()->length()); |
9148 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9012 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
9149 HValue* number = Pop(); | 9013 HValue* context = environment()->context(); |
9150 HValue* result = BuildNumberToString(number); | 9014 HCallStub* result = |
9151 return ast_context()->ReturnValue(result); | 9015 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| 9016 Drop(1); |
| 9017 return ast_context()->ReturnInstruction(result, call->id()); |
9152 } | 9018 } |
9153 | 9019 |
9154 | 9020 |
9155 // Fast call for custom callbacks. | 9021 // Fast call for custom callbacks. |
9156 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9022 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
9157 // 1 ~ The function to call is not itself an argument to the call. | 9023 // 1 ~ The function to call is not itself an argument to the call. |
9158 int arg_count = call->arguments()->length() - 1; | 9024 int arg_count = call->arguments()->length() - 1; |
9159 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9025 ASSERT(arg_count >= 1); // There's always at least a receiver. |
9160 | 9026 |
9161 for (int i = 0; i < arg_count; ++i) { | 9027 for (int i = 0; i < arg_count; ++i) { |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9908 if (ShouldProduceTraceOutput()) { | 9774 if (ShouldProduceTraceOutput()) { |
9909 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9775 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9910 } | 9776 } |
9911 | 9777 |
9912 #ifdef DEBUG | 9778 #ifdef DEBUG |
9913 graph_->Verify(false); // No full verify. | 9779 graph_->Verify(false); // No full verify. |
9914 #endif | 9780 #endif |
9915 } | 9781 } |
9916 | 9782 |
9917 } } // namespace v8::internal | 9783 } } // namespace v8::internal |
OLD | NEW |