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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
797 : last_true_block_; | 797 : last_true_block_; |
798 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 798 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
799 ? builder_->current_block() | 799 ? builder_->current_block() |
800 : first_false_block_; | 800 : first_false_block_; |
801 continuation->Capture(true_block, false_block, position_); | 801 continuation->Capture(true_block, false_block, position_); |
802 captured_ = true; | 802 captured_ = true; |
803 End(); | 803 End(); |
804 } | 804 } |
805 | 805 |
806 | 806 |
807 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { | |
808 ASSERT(!finished_); | |
809 ASSERT(!captured_); | |
810 HBasicBlock* true_block = last_true_block_ == NULL | |
811 ? first_true_block_ | |
812 : last_true_block_; | |
813 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | |
814 ? builder_->current_block() | |
815 : first_false_block_; | |
816 if (true_block != NULL && !true_block->IsFinished()) { | |
817 ASSERT(continuation->IsTrueReachable()); | |
818 true_block->GotoNoSimulate(continuation->true_branch()); | |
819 } | |
820 if (false_block != NULL && !false_block->IsFinished()) { | |
821 ASSERT(continuation->IsFalseReachable()); | |
822 false_block->GotoNoSimulate(continuation->false_branch()); | |
823 } | |
824 captured_ = true; | |
825 End(); | |
826 } | |
827 | |
828 | |
807 void HGraphBuilder::IfBuilder::Then() { | 829 void HGraphBuilder::IfBuilder::Then() { |
808 ASSERT(!captured_); | 830 ASSERT(!captured_); |
809 ASSERT(!finished_); | 831 ASSERT(!finished_); |
810 did_then_ = true; | 832 did_then_ = true; |
811 if (needs_compare_) { | 833 if (needs_compare_) { |
812 // Handle if's without any expressions, they jump directly to the "else" | 834 // Handle if's without any expressions, they jump directly to the "else" |
813 // branch. However, we must pretend that the "then" branch is reachable, | 835 // branch. However, we must pretend that the "then" branch is reachable, |
814 // so that the graph builder visits it and sees any live range extending | 836 // so that the graph builder visits it and sees any live range extending |
815 // constructs within it. | 837 // constructs within it. |
816 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 838 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1242 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1264 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
1243 array_length, elements_length); | 1265 array_length, elements_length); |
1244 | 1266 |
1245 if_builder.End(); | 1267 if_builder.End(); |
1246 } | 1268 } |
1247 | 1269 |
1248 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1270 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
1249 } | 1271 } |
1250 | 1272 |
1251 | 1273 |
1274 HValue* HGraphBuilder::BuildLookupNumberStringCache( | |
1275 HValue* object, | |
1276 HIfContinuation* continuation) { | |
1277 // Create a joinable continuation. | |
1278 HIfContinuation found(graph()->CreateBasicBlock(), | |
1279 graph()->CreateBasicBlock()); | |
1280 | |
1281 // Load the number string cache. | |
1282 HValue* number_string_cache = | |
1283 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); | |
1284 | |
1285 // Make the hash maks from the length of the number string cache. It | |
1286 // contains two elements (number and string) for each cache entry. | |
1287 HValue* mask = AddLoadFixedArrayLength(number_string_cache); | |
1288 mask->set_type(HType::Smi()); | |
1289 mask = Add<HSar>(mask, graph()->GetConstant1()); | |
1290 mask = Add<HSub>(mask, graph()->GetConstant1()); | |
1291 | |
1292 // Check whether object is a smi. | |
1293 IfBuilder if_objectissmi(this); | |
1294 if_objectissmi.If<HIsSmiAndBranch>(object); | |
1295 if_objectissmi.Then(); | |
1296 { | |
1297 // Compute hash for smi similar to smi_get_hash(). | |
1298 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); | |
1299 | |
1300 // Load the key. | |
1301 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); | |
1302 HValue* key = AddFastElementAccess(number_string_cache, key_index, | |
1303 NULL, NULL, FAST_ELEMENTS, false, | |
1304 ALLOW_RETURN_HOLE, STANDARD_STORE); | |
1305 | |
1306 // Check if object == key. | |
1307 IfBuilder if_objectiskey(this); | |
1308 if_objectiskey.If<HCompareObjectEqAndBranch>(key, object); | |
1309 if_objectiskey.Then(); | |
1310 { | |
1311 // Make the key_index available. | |
1312 Push(key_index); | |
1313 } | |
1314 if_objectiskey.JoinContinuation(&found); | |
1315 } | |
1316 if_objectissmi.Else(); | |
mvstanton
2013/09/23 09:32:34
All this is really nice that you can use the IfBui
| |
1317 { | |
1318 // Check if object is a heap number. | |
1319 IfBuilder if_objectisnumber(this); | |
1320 if_objectisnumber.If<HCompareMap>( | |
1321 object, isolate()->factory()->heap_number_map()); | |
1322 if_objectisnumber.Then(); | |
1323 { | |
1324 // Compute hash for heap number similar to double_get_hash(). | |
1325 HValue* low = Add<HLoadNamedField>( | |
1326 object, HObjectAccess::ForHeapNumberValueLowestBits()); | |
1327 HValue* high = Add<HLoadNamedField>( | |
1328 object, HObjectAccess::ForHeapNumberValueHighestBits()); | |
1329 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); | |
1330 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); | |
1331 | |
1332 // Load the key. | |
1333 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); | |
1334 HValue* key = AddFastElementAccess(number_string_cache, key_index, | |
1335 NULL, NULL, FAST_ELEMENTS, false, | |
1336 ALLOW_RETURN_HOLE, STANDARD_STORE); | |
1337 | |
1338 // Check if key is a heap number. | |
1339 IfBuilder if_keyisnumber(this); | |
1340 if_keyisnumber.IfNot<HIsSmiAndBranch>(key); | |
1341 if_keyisnumber.AndIf<HCompareMap>( | |
1342 key, isolate()->factory()->heap_number_map()); | |
1343 if_keyisnumber.Then(); | |
1344 { | |
1345 // Check if values of key and object match. | |
1346 IfBuilder if_keyeqobject(this); | |
1347 if_keyeqobject.If<HCompareNumericAndBranch>( | |
1348 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()), | |
1349 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()), | |
1350 Token::EQ); | |
1351 if_keyeqobject.Then(); | |
1352 { | |
1353 // Make the key_index available. | |
1354 Push(key_index); | |
1355 } | |
1356 if_keyeqobject.JoinContinuation(&found); | |
1357 } | |
1358 if_keyisnumber.JoinContinuation(&found); | |
1359 } | |
1360 if_objectisnumber.JoinContinuation(&found); | |
1361 } | |
1362 if_objectissmi.End(); | |
1363 | |
1364 // Check for cache hit. | |
1365 IfBuilder if_found(this, &found); | |
1366 if_found.Then(); | |
1367 | |
1368 // Load the value in case of cache hit. | |
1369 HValue* key_index = Pop(); | |
1370 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); | |
1371 HValue* value = AddFastElementAccess(number_string_cache, value_index, | |
1372 NULL, NULL, FAST_ELEMENTS, false, | |
1373 ALLOW_RETURN_HOLE, STANDARD_STORE); | |
1374 AddIncrementCounter(isolate()->counters()->number_to_string_native()); | |
1375 | |
1376 if_found.CaptureContinuation(continuation); | |
1377 | |
1378 // The value is only available in true branch of continuation. | |
1379 return value; | |
1380 } | |
1381 | |
1382 | |
1383 HValue* HGraphBuilder::BuildNumberToString(HValue* number) { | |
1384 NoObservableSideEffectsScope scope(this); | |
1385 | |
1386 // Lookup the number in the number string cache. | |
1387 HIfContinuation continuation; | |
1388 HValue* value = BuildLookupNumberStringCache(number, &continuation); | |
1389 IfBuilder if_found(this, &continuation); | |
1390 if_found.Then(); | |
1391 | |
1392 // Cache hit. | |
1393 Push(value); | |
1394 | |
1395 if_found.Else(); | |
1396 | |
1397 // Cache miss, fallback to runtime. | |
1398 Add<HPushArgument>(number); | |
1399 Push(Add<HCallRuntime>( | |
1400 isolate()->factory()->empty_string(), | |
1401 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), | |
1402 1)); | |
1403 | |
1404 if_found.End(); | |
1405 | |
1406 return Pop(); | |
1407 } | |
1408 | |
1409 | |
1252 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1410 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
1253 HValue* checked_object, | 1411 HValue* checked_object, |
1254 HValue* key, | 1412 HValue* key, |
1255 HValue* val, | 1413 HValue* val, |
1256 bool is_js_array, | 1414 bool is_js_array, |
1257 ElementsKind elements_kind, | 1415 ElementsKind elements_kind, |
1258 bool is_store, | 1416 bool is_store, |
1259 LoadKeyedHoleMode load_mode, | 1417 LoadKeyedHoleMode load_mode, |
1260 KeyedAccessStoreMode store_mode) { | 1418 KeyedAccessStoreMode store_mode) { |
1261 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1419 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
(...skipping 7599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8861 | 9019 |
8862 // Support for fast native caches. | 9020 // Support for fast native caches. |
8863 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9021 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
8864 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9022 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
8865 } | 9023 } |
8866 | 9024 |
8867 | 9025 |
8868 // Fast support for number to string. | 9026 // Fast support for number to string. |
8869 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9027 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
8870 ASSERT_EQ(1, call->arguments()->length()); | 9028 ASSERT_EQ(1, call->arguments()->length()); |
8871 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9029 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
8872 HValue* context = environment()->context(); | 9030 return ast_context()->ReturnValue(BuildNumberToString(Pop())); |
mvstanton
2013/09/23 09:32:34
Paranoia: This code reminds me of the problem that
Benedikt Meurer
2013/09/23 10:53:31
Done.
| |
8873 HCallStub* result = | |
8874 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | |
8875 Drop(1); | |
8876 return ast_context()->ReturnInstruction(result, call->id()); | |
8877 } | 9031 } |
8878 | 9032 |
8879 | 9033 |
8880 // Fast call for custom callbacks. | 9034 // Fast call for custom callbacks. |
8881 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9035 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
8882 // 1 ~ The function to call is not itself an argument to the call. | 9036 // 1 ~ The function to call is not itself an argument to the call. |
8883 int arg_count = call->arguments()->length() - 1; | 9037 int arg_count = call->arguments()->length() - 1; |
8884 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9038 ASSERT(arg_count >= 1); // There's always at least a receiver. |
8885 | 9039 |
8886 for (int i = 0; i < arg_count; ++i) { | 9040 for (int i = 0; i < arg_count; ++i) { |
(...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9633 if (ShouldProduceTraceOutput()) { | 9787 if (ShouldProduceTraceOutput()) { |
9634 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9788 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9635 } | 9789 } |
9636 | 9790 |
9637 #ifdef DEBUG | 9791 #ifdef DEBUG |
9638 graph_->Verify(false); // No full verify. | 9792 graph_->Verify(false); // No full verify. |
9639 #endif | 9793 #endif |
9640 } | 9794 } |
9641 | 9795 |
9642 } } // namespace v8::internal | 9796 } } // namespace v8::internal |
OLD | NEW |