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

Side by Side Diff: src/hydrogen.cc

Issue 23726041: Turn the NumberToStringStub into a hydrogen stub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Using IfBuilder with JoinContinuation Created 7 years, 3 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
OLDNEW
« src/code-stubs-hydrogen.cc ('K') | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698