| 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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 644 | 644 |
| 645 HConstant* HGraph::GetConstantMinus1() { | 645 HConstant* HGraph::GetConstantMinus1() { |
| 646 return GetConstant(&constant_minus1_, -1); | 646 return GetConstant(&constant_minus1_, -1); |
| 647 } | 647 } |
| 648 | 648 |
| 649 | 649 |
| 650 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ | 650 #define DEFINE_GET_CONSTANT(Name, name, htype, boolean_value) \ |
| 651 HConstant* HGraph::GetConstant##Name() { \ | 651 HConstant* HGraph::GetConstant##Name() { \ |
| 652 if (!constant_##name##_.is_set()) { \ | 652 if (!constant_##name##_.is_set()) { \ |
| 653 HConstant* constant = new(zone()) HConstant( \ | 653 HConstant* constant = new(zone()) HConstant( \ |
| 654 isolate()->factory()->name##_value(), \ | 654 Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \ |
| 655 UniqueValueId::name##_value(isolate()->heap()), \ | |
| 656 Representation::Tagged(), \ | 655 Representation::Tagged(), \ |
| 657 htype, \ | 656 htype, \ |
| 658 false, \ | 657 false, \ |
| 659 true, \ | 658 true, \ |
| 660 false, \ | 659 false, \ |
| 661 boolean_value); \ | 660 boolean_value); \ |
| 662 constant->InsertAfter(GetConstantUndefined()); \ | 661 constant->InsertAfter(GetConstantUndefined()); \ |
| 663 constant_##name##_.set(constant); \ | 662 constant_##name##_.set(constant); \ |
| 664 } \ | 663 } \ |
| 665 return constant_##name##_.get(); \ | 664 return constant_##name##_.get(); \ |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 : last_true_block_; | 800 : last_true_block_; |
| 802 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) | 801 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
| 803 ? builder_->current_block() | 802 ? builder_->current_block() |
| 804 : first_false_block_; | 803 : first_false_block_; |
| 805 continuation->Capture(true_block, false_block, position_); | 804 continuation->Capture(true_block, false_block, position_); |
| 806 captured_ = true; | 805 captured_ = true; |
| 807 End(); | 806 End(); |
| 808 } | 807 } |
| 809 | 808 |
| 810 | 809 |
| 810 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) { |
| 811 ASSERT(!finished_); |
| 812 ASSERT(!captured_); |
| 813 HBasicBlock* true_block = last_true_block_ == NULL |
| 814 ? first_true_block_ |
| 815 : last_true_block_; |
| 816 HBasicBlock* false_block = did_else_ && (first_false_block_ != NULL) |
| 817 ? builder_->current_block() |
| 818 : first_false_block_; |
| 819 if (true_block != NULL && !true_block->IsFinished()) { |
| 820 ASSERT(continuation->IsTrueReachable()); |
| 821 true_block->GotoNoSimulate(continuation->true_branch()); |
| 822 } |
| 823 if (false_block != NULL && !false_block->IsFinished()) { |
| 824 ASSERT(continuation->IsFalseReachable()); |
| 825 false_block->GotoNoSimulate(continuation->false_branch()); |
| 826 } |
| 827 captured_ = true; |
| 828 End(); |
| 829 } |
| 830 |
| 831 |
| 811 void HGraphBuilder::IfBuilder::Then() { | 832 void HGraphBuilder::IfBuilder::Then() { |
| 812 ASSERT(!captured_); | 833 ASSERT(!captured_); |
| 813 ASSERT(!finished_); | 834 ASSERT(!finished_); |
| 814 did_then_ = true; | 835 did_then_ = true; |
| 815 if (needs_compare_) { | 836 if (needs_compare_) { |
| 816 // Handle if's without any expressions, they jump directly to the "else" | 837 // Handle if's without any expressions, they jump directly to the "else" |
| 817 // branch. However, we must pretend that the "then" branch is reachable, | 838 // branch. However, we must pretend that the "then" branch is reachable, |
| 818 // so that the graph builder visits it and sees any live range extending | 839 // so that the graph builder visits it and sees any live range extending |
| 819 // constructs within it. | 840 // constructs within it. |
| 820 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 841 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 finished_ = true; | 1033 finished_ = true; |
| 1013 } | 1034 } |
| 1014 | 1035 |
| 1015 | 1036 |
| 1016 HGraph* HGraphBuilder::CreateGraph() { | 1037 HGraph* HGraphBuilder::CreateGraph() { |
| 1017 graph_ = new(zone()) HGraph(info_); | 1038 graph_ = new(zone()) HGraph(info_); |
| 1018 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 1039 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
| 1019 CompilationPhase phase("H_Block building", info_); | 1040 CompilationPhase phase("H_Block building", info_); |
| 1020 set_current_block(graph()->entry_block()); | 1041 set_current_block(graph()->entry_block()); |
| 1021 if (!BuildGraph()) return NULL; | 1042 if (!BuildGraph()) return NULL; |
| 1022 graph()->FinalizeUniqueValueIds(); | 1043 graph()->FinalizeUniqueness(); |
| 1023 return graph_; | 1044 return graph_; |
| 1024 } | 1045 } |
| 1025 | 1046 |
| 1026 | 1047 |
| 1027 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 1048 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 1028 ASSERT(current_block() != NULL); | 1049 ASSERT(current_block() != NULL); |
| 1029 current_block()->AddInstruction(instr); | 1050 current_block()->AddInstruction(instr); |
| 1030 if (graph()->IsInsideNoSideEffectsScope()) { | 1051 if (graph()->IsInsideNoSideEffectsScope()) { |
| 1031 instr->SetFlag(HValue::kHasNoObservableSideEffects); | 1052 instr->SetFlag(HValue::kHasNoObservableSideEffects); |
| 1032 } | 1053 } |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, | 1267 BuildGrowElementsCapacity(object, elements, from_kind, to_kind, |
| 1247 array_length, elements_length); | 1268 array_length, elements_length); |
| 1248 | 1269 |
| 1249 if_builder.End(); | 1270 if_builder.End(); |
| 1250 } | 1271 } |
| 1251 | 1272 |
| 1252 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); | 1273 Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map); |
| 1253 } | 1274 } |
| 1254 | 1275 |
| 1255 | 1276 |
| 1277 HValue* HGraphBuilder::BuildLookupNumberStringCache( |
| 1278 HValue* object, |
| 1279 HIfContinuation* continuation) { |
| 1280 // Create a joinable continuation. |
| 1281 HIfContinuation found(graph()->CreateBasicBlock(), |
| 1282 graph()->CreateBasicBlock()); |
| 1283 |
| 1284 // Load the number string cache. |
| 1285 HValue* number_string_cache = |
| 1286 Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex); |
| 1287 |
| 1288 // Make the hash maks from the length of the number string cache. It |
| 1289 // contains two elements (number and string) for each cache entry. |
| 1290 HValue* mask = AddLoadFixedArrayLength(number_string_cache); |
| 1291 mask->set_type(HType::Smi()); |
| 1292 mask = Add<HSar>(mask, graph()->GetConstant1()); |
| 1293 mask = Add<HSub>(mask, graph()->GetConstant1()); |
| 1294 |
| 1295 // Check whether object is a smi. |
| 1296 IfBuilder if_objectissmi(this); |
| 1297 if_objectissmi.If<HIsSmiAndBranch>(object); |
| 1298 if_objectissmi.Then(); |
| 1299 { |
| 1300 // Compute hash for smi similar to smi_get_hash(). |
| 1301 HValue* hash = Add<HBitwise>(Token::BIT_AND, object, mask); |
| 1302 |
| 1303 // Load the key. |
| 1304 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
| 1305 HValue* key = AddFastElementAccess(number_string_cache, key_index, |
| 1306 NULL, NULL, FAST_ELEMENTS, false, |
| 1307 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1308 |
| 1309 // Check if object == key. |
| 1310 IfBuilder if_objectiskey(this); |
| 1311 if_objectiskey.If<HCompareObjectEqAndBranch>(key, object); |
| 1312 if_objectiskey.Then(); |
| 1313 { |
| 1314 // Make the key_index available. |
| 1315 Push(key_index); |
| 1316 } |
| 1317 if_objectiskey.JoinContinuation(&found); |
| 1318 } |
| 1319 if_objectissmi.Else(); |
| 1320 { |
| 1321 // Check if object is a heap number. |
| 1322 IfBuilder if_objectisnumber(this); |
| 1323 if_objectisnumber.If<HCompareMap>( |
| 1324 object, isolate()->factory()->heap_number_map()); |
| 1325 if_objectisnumber.Then(); |
| 1326 { |
| 1327 // Compute hash for heap number similar to double_get_hash(). |
| 1328 HValue* low = Add<HLoadNamedField>( |
| 1329 object, HObjectAccess::ForHeapNumberValueLowestBits()); |
| 1330 HValue* high = Add<HLoadNamedField>( |
| 1331 object, HObjectAccess::ForHeapNumberValueHighestBits()); |
| 1332 HValue* hash = Add<HBitwise>(Token::BIT_XOR, low, high); |
| 1333 hash = Add<HBitwise>(Token::BIT_AND, hash, mask); |
| 1334 |
| 1335 // Load the key. |
| 1336 HValue* key_index = Add<HShl>(hash, graph()->GetConstant1()); |
| 1337 HValue* key = AddFastElementAccess(number_string_cache, key_index, |
| 1338 NULL, NULL, FAST_ELEMENTS, false, |
| 1339 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1340 |
| 1341 // Check if key is a heap number. |
| 1342 IfBuilder if_keyisnumber(this); |
| 1343 if_keyisnumber.IfNot<HIsSmiAndBranch>(key); |
| 1344 if_keyisnumber.AndIf<HCompareMap>( |
| 1345 key, isolate()->factory()->heap_number_map()); |
| 1346 if_keyisnumber.Then(); |
| 1347 { |
| 1348 // Check if values of key and object match. |
| 1349 IfBuilder if_keyeqobject(this); |
| 1350 if_keyeqobject.If<HCompareNumericAndBranch>( |
| 1351 Add<HLoadNamedField>(key, HObjectAccess::ForHeapNumberValue()), |
| 1352 Add<HLoadNamedField>(object, HObjectAccess::ForHeapNumberValue()), |
| 1353 Token::EQ); |
| 1354 if_keyeqobject.Then(); |
| 1355 { |
| 1356 // Make the key_index available. |
| 1357 Push(key_index); |
| 1358 } |
| 1359 if_keyeqobject.JoinContinuation(&found); |
| 1360 } |
| 1361 if_keyisnumber.JoinContinuation(&found); |
| 1362 } |
| 1363 if_objectisnumber.JoinContinuation(&found); |
| 1364 } |
| 1365 if_objectissmi.End(); |
| 1366 |
| 1367 // Check for cache hit. |
| 1368 IfBuilder if_found(this, &found); |
| 1369 if_found.Then(); |
| 1370 |
| 1371 // Load the value in case of cache hit. |
| 1372 HValue* key_index = Pop(); |
| 1373 HValue* value_index = Add<HAdd>(key_index, graph()->GetConstant1()); |
| 1374 HValue* value = AddFastElementAccess(number_string_cache, value_index, |
| 1375 NULL, NULL, FAST_ELEMENTS, false, |
| 1376 ALLOW_RETURN_HOLE, STANDARD_STORE); |
| 1377 AddIncrementCounter(isolate()->counters()->number_to_string_native()); |
| 1378 |
| 1379 if_found.CaptureContinuation(continuation); |
| 1380 |
| 1381 // The value is only available in true branch of continuation. |
| 1382 return value; |
| 1383 } |
| 1384 |
| 1385 |
| 1386 HValue* HGraphBuilder::BuildNumberToString(HValue* number) { |
| 1387 NoObservableSideEffectsScope scope(this); |
| 1388 |
| 1389 // Lookup the number in the number string cache. |
| 1390 HIfContinuation continuation; |
| 1391 HValue* value = BuildLookupNumberStringCache(number, &continuation); |
| 1392 IfBuilder if_found(this, &continuation); |
| 1393 if_found.Then(); |
| 1394 |
| 1395 // Cache hit. |
| 1396 Push(value); |
| 1397 |
| 1398 if_found.Else(); |
| 1399 |
| 1400 // Cache miss, fallback to runtime. |
| 1401 Add<HPushArgument>(number); |
| 1402 Push(Add<HCallRuntime>( |
| 1403 isolate()->factory()->empty_string(), |
| 1404 Runtime::FunctionForId(Runtime::kNumberToStringSkipCache), |
| 1405 1)); |
| 1406 |
| 1407 if_found.End(); |
| 1408 |
| 1409 return Pop(); |
| 1410 } |
| 1411 |
| 1412 |
| 1256 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 1413 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 1257 HValue* checked_object, | 1414 HValue* checked_object, |
| 1258 HValue* key, | 1415 HValue* key, |
| 1259 HValue* val, | 1416 HValue* val, |
| 1260 bool is_js_array, | 1417 bool is_js_array, |
| 1261 ElementsKind elements_kind, | 1418 ElementsKind elements_kind, |
| 1262 bool is_store, | 1419 bool is_store, |
| 1263 LoadKeyedHoleMode load_mode, | 1420 LoadKeyedHoleMode load_mode, |
| 1264 KeyedAccessStoreMode store_mode) { | 1421 KeyedAccessStoreMode store_mode) { |
| 1265 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 1422 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1821 if_nil.CaptureContinuation(continuation); | 1978 if_nil.CaptureContinuation(continuation); |
| 1822 } | 1979 } |
| 1823 | 1980 |
| 1824 | 1981 |
| 1825 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, | 1982 HValue* HGraphBuilder::BuildCreateAllocationMemento(HValue* previous_object, |
| 1826 int previous_object_size, | 1983 int previous_object_size, |
| 1827 HValue* alloc_site) { | 1984 HValue* alloc_site) { |
| 1828 ASSERT(alloc_site != NULL); | 1985 ASSERT(alloc_site != NULL); |
| 1829 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( | 1986 HInnerAllocatedObject* alloc_memento = Add<HInnerAllocatedObject>( |
| 1830 previous_object, previous_object_size); | 1987 previous_object, previous_object_size); |
| 1831 Handle<Map> alloc_memento_map( | 1988 Handle<Map> alloc_memento_map = |
| 1832 isolate()->heap()->allocation_memento_map()); | 1989 isolate()->factory()->allocation_memento_map(); |
| 1833 AddStoreMapConstant(alloc_memento, alloc_memento_map); | 1990 AddStoreMapConstant(alloc_memento, alloc_memento_map); |
| 1834 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); | 1991 HObjectAccess access = HObjectAccess::ForAllocationMementoSite(); |
| 1835 Add<HStoreNamedField>(alloc_memento, access, alloc_site); | 1992 Add<HStoreNamedField>(alloc_memento, access, alloc_site); |
| 1836 return alloc_memento; | 1993 return alloc_memento; |
| 1837 } | 1994 } |
| 1838 | 1995 |
| 1839 | 1996 |
| 1840 HInstruction* HGraphBuilder::BuildGetNativeContext() { | 1997 HInstruction* HGraphBuilder::BuildGetNativeContext() { |
| 1841 // Get the global context, then the native context | 1998 // Get the global context, then the native context |
| 1842 HInstruction* global_object = Add<HGlobalObject>(); | 1999 HInstruction* global_object = Add<HGlobalObject>(); |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2130 } | 2287 } |
| 2131 | 2288 |
| 2132 | 2289 |
| 2133 HBasicBlock* HGraph::CreateBasicBlock() { | 2290 HBasicBlock* HGraph::CreateBasicBlock() { |
| 2134 HBasicBlock* result = new(zone()) HBasicBlock(this); | 2291 HBasicBlock* result = new(zone()) HBasicBlock(this); |
| 2135 blocks_.Add(result, zone()); | 2292 blocks_.Add(result, zone()); |
| 2136 return result; | 2293 return result; |
| 2137 } | 2294 } |
| 2138 | 2295 |
| 2139 | 2296 |
| 2140 void HGraph::FinalizeUniqueValueIds() { | 2297 void HGraph::FinalizeUniqueness() { |
| 2141 DisallowHeapAllocation no_gc; | 2298 DisallowHeapAllocation no_gc; |
| 2142 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); | 2299 ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread()); |
| 2143 for (int i = 0; i < blocks()->length(); ++i) { | 2300 for (int i = 0; i < blocks()->length(); ++i) { |
| 2144 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { | 2301 for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) { |
| 2145 it.Current()->FinalizeUniqueValueId(); | 2302 it.Current()->FinalizeUniqueness(); |
| 2146 } | 2303 } |
| 2147 } | 2304 } |
| 2148 } | 2305 } |
| 2149 | 2306 |
| 2150 | 2307 |
| 2151 // Block ordering was implemented with two mutually recursive methods, | 2308 // Block ordering was implemented with two mutually recursive methods, |
| 2152 // HGraph::Postorder and HGraph::PostorderLoopBlocks. | 2309 // HGraph::Postorder and HGraph::PostorderLoopBlocks. |
| 2153 // The recursion could lead to stack overflow so the algorithm has been | 2310 // The recursion could lead to stack overflow so the algorithm has been |
| 2154 // implemented iteratively. | 2311 // implemented iteratively. |
| 2155 // At a high level the algorithm looks like this: | 2312 // At a high level the algorithm looks like this: |
| (...skipping 1923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4079 | 4236 |
| 4080 | 4237 |
| 4081 // Determines whether the given array or object literal boilerplate satisfies | 4238 // Determines whether the given array or object literal boilerplate satisfies |
| 4082 // all limits to be considered for fast deep-copying and computes the total | 4239 // all limits to be considered for fast deep-copying and computes the total |
| 4083 // size of all objects that are part of the graph. | 4240 // size of all objects that are part of the graph. |
| 4084 static bool IsFastLiteral(Handle<JSObject> boilerplate, | 4241 static bool IsFastLiteral(Handle<JSObject> boilerplate, |
| 4085 int max_depth, | 4242 int max_depth, |
| 4086 int* max_properties) { | 4243 int* max_properties) { |
| 4087 if (boilerplate->map()->is_deprecated()) { | 4244 if (boilerplate->map()->is_deprecated()) { |
| 4088 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); | 4245 Handle<Object> result = JSObject::TryMigrateInstance(boilerplate); |
| 4089 if (result->IsSmi()) return false; | 4246 if (result.is_null()) return false; |
| 4090 } | 4247 } |
| 4091 | 4248 |
| 4092 ASSERT(max_depth >= 0 && *max_properties >= 0); | 4249 ASSERT(max_depth >= 0 && *max_properties >= 0); |
| 4093 if (max_depth == 0) return false; | 4250 if (max_depth == 0) return false; |
| 4094 | 4251 |
| 4095 Isolate* isolate = boilerplate->GetIsolate(); | 4252 Isolate* isolate = boilerplate->GetIsolate(); |
| 4096 Handle<FixedArrayBase> elements(boilerplate->elements()); | 4253 Handle<FixedArrayBase> elements(boilerplate->elements()); |
| 4097 if (elements->length() > 0 && | 4254 if (elements->length() > 0 && |
| 4098 elements->map() != isolate->heap()->fixed_cow_array_map()) { | 4255 elements->map() != isolate->heap()->fixed_cow_array_map()) { |
| 4099 if (boilerplate->HasFastObjectElements()) { | 4256 if (boilerplate->HasFastObjectElements()) { |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4292 } | 4449 } |
| 4293 | 4450 |
| 4294 ASSERT(!raw_boilerplate.is_null()); | 4451 ASSERT(!raw_boilerplate.is_null()); |
| 4295 ASSERT(site->IsLiteralSite()); | 4452 ASSERT(site->IsLiteralSite()); |
| 4296 | 4453 |
| 4297 Handle<JSObject> boilerplate_object = | 4454 Handle<JSObject> boilerplate_object = |
| 4298 Handle<JSObject>::cast(raw_boilerplate); | 4455 Handle<JSObject>::cast(raw_boilerplate); |
| 4299 ElementsKind boilerplate_elements_kind = | 4456 ElementsKind boilerplate_elements_kind = |
| 4300 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind(); | 4457 Handle<JSObject>::cast(boilerplate_object)->GetElementsKind(); |
| 4301 | 4458 |
| 4302 // TODO(mvstanton): This heuristic is only a temporary solution. In the | 4459 ASSERT(AllocationSite::CanTrack(boilerplate_object->map()->instance_type())); |
| 4303 // end, we want to quit creating allocation site info after a certain number | |
| 4304 // of GCs for a call site. | |
| 4305 AllocationSiteMode mode = AllocationSite::GetMode( | |
| 4306 boilerplate_elements_kind); | |
| 4307 | 4460 |
| 4308 // Check whether to use fast or slow deep-copying for boilerplate. | 4461 // Check whether to use fast or slow deep-copying for boilerplate. |
| 4309 int max_properties = kMaxFastLiteralProperties; | 4462 int max_properties = kMaxFastLiteralProperties; |
| 4310 if (IsFastLiteral(boilerplate_object, | 4463 if (IsFastLiteral(boilerplate_object, |
| 4311 kMaxFastLiteralDepth, | 4464 kMaxFastLiteralDepth, |
| 4312 &max_properties)) { | 4465 &max_properties)) { |
| 4466 // TODO(mvstanton): This heuristic is only a temporary solution. In the |
| 4467 // end, we want to quit creating allocation site info after a certain number |
| 4468 // of GCs for a call site. |
| 4469 AllocationSiteMode mode = AllocationSite::GetMode( |
| 4470 boilerplate_elements_kind); |
| 4471 |
| 4472 // it doesn't make sense to create allocation mementos if we are going to |
| 4473 // create in old space. |
| 4474 if (mode == TRACK_ALLOCATION_SITE && |
| 4475 isolate()->heap()->GetPretenureMode() == TENURED) { |
| 4476 mode = DONT_TRACK_ALLOCATION_SITE; |
| 4477 } |
| 4478 |
| 4313 literal = BuildFastLiteral(boilerplate_object, | 4479 literal = BuildFastLiteral(boilerplate_object, |
| 4314 site, | 4480 site, |
| 4315 mode); | 4481 mode); |
| 4316 } else { | 4482 } else { |
| 4317 NoObservableSideEffectsScope no_effects(this); | 4483 NoObservableSideEffectsScope no_effects(this); |
| 4318 // Boilerplate already exists and constant elements are never accessed, | 4484 // Boilerplate already exists and constant elements are never accessed, |
| 4319 // pass an empty fixed array to the runtime function instead. | 4485 // pass an empty fixed array to the runtime function instead. |
| 4320 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 4486 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 4321 int literal_index = expr->literal_index(); | 4487 int literal_index = expr->literal_index(); |
| 4322 | 4488 |
| (...skipping 1794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6117 set_current_block(if_false); | 6283 set_current_block(if_false); |
| 6118 } | 6284 } |
| 6119 | 6285 |
| 6120 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6286 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6121 // know about and do not want to handle ones we've never seen. Otherwise | 6287 // know about and do not want to handle ones we've never seen. Otherwise |
| 6122 // use a generic IC. | 6288 // use a generic IC. |
| 6123 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6289 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6124 // Because the deopt may be the only path in the polymorphic call, make sure | 6290 // Because the deopt may be the only path in the polymorphic call, make sure |
| 6125 // that the environment stack matches the depth on deopt that it otherwise | 6291 // that the environment stack matches the depth on deopt that it otherwise |
| 6126 // would have had after a successful call. | 6292 // would have had after a successful call. |
| 6127 Drop(argument_count - (ast_context()->IsEffect() ? 0 : 1)); | 6293 Drop(argument_count); |
| 6294 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
| 6128 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6295 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
| 6129 } else { | 6296 } else { |
| 6130 HValue* context = environment()->context(); | 6297 HValue* context = environment()->context(); |
| 6131 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 6298 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
| 6132 call->set_position(expr->position()); | 6299 call->set_position(expr->position()); |
| 6133 PreProcessCall(call); | 6300 PreProcessCall(call); |
| 6134 | 6301 |
| 6135 if (join != NULL) { | 6302 if (join != NULL) { |
| 6136 AddInstruction(call); | 6303 AddInstruction(call); |
| 6137 if (!ast_context()->IsEffect()) Push(call); | 6304 if (!ast_context()->IsEffect()) Push(call); |
| (...skipping 1501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7639 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 7806 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| 7640 if (value->IsConstant()) { | 7807 if (value->IsConstant()) { |
| 7641 HConstant* constant = HConstant::cast(value); | 7808 HConstant* constant = HConstant::cast(value); |
| 7642 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 7809 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 7643 if (number.has_value) { | 7810 if (number.has_value) { |
| 7644 *expected = handle(Type::Number(), isolate()); | 7811 *expected = handle(Type::Number(), isolate()); |
| 7645 return AddInstruction(number.value); | 7812 return AddInstruction(number.value); |
| 7646 } | 7813 } |
| 7647 } | 7814 } |
| 7648 | 7815 |
| 7816 // We put temporary values on the stack, which don't correspond to anything |
| 7817 // in baseline code. Since nothing is observable we avoid recording those |
| 7818 // pushes with a NoObservableSideEffectsScope. |
| 7819 NoObservableSideEffectsScope no_effects(this); |
| 7820 |
| 7649 Handle<Type> expected_type = *expected; | 7821 Handle<Type> expected_type = *expected; |
| 7650 | 7822 |
| 7651 // Separate the number type from the rest. | 7823 // Separate the number type from the rest. |
| 7652 Handle<Type> expected_obj = handle(Type::Intersect( | 7824 Handle<Type> expected_obj = handle(Type::Intersect( |
| 7653 expected_type, handle(Type::NonNumber(), isolate())), isolate()); | 7825 expected_type, handle(Type::NonNumber(), isolate())), isolate()); |
| 7654 Handle<Type> expected_number = handle(Type::Intersect( | 7826 Handle<Type> expected_number = handle(Type::Intersect( |
| 7655 expected_type, handle(Type::Number(), isolate())), isolate()); | 7827 expected_type, handle(Type::Number(), isolate())), isolate()); |
| 7656 | 7828 |
| 7657 // We expect to get a number. | 7829 // We expect to get a number. |
| 7658 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 7830 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7704 } | 7876 } |
| 7705 | 7877 |
| 7706 return value; | 7878 return value; |
| 7707 } | 7879 } |
| 7708 | 7880 |
| 7709 | 7881 |
| 7710 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7882 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 7711 BinaryOperation* expr, | 7883 BinaryOperation* expr, |
| 7712 HValue* left, | 7884 HValue* left, |
| 7713 HValue* right) { | 7885 HValue* right) { |
| 7714 HValue* context = environment()->context(); | |
| 7715 Handle<Type> left_type = expr->left()->bounds().lower; | 7886 Handle<Type> left_type = expr->left()->bounds().lower; |
| 7716 Handle<Type> right_type = expr->right()->bounds().lower; | 7887 Handle<Type> right_type = expr->right()->bounds().lower; |
| 7717 Handle<Type> result_type = expr->bounds().lower; | 7888 Handle<Type> result_type = expr->bounds().lower; |
| 7718 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7889 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7719 | 7890 |
| 7720 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, | 7891 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, |
| 7721 left_type, right_type, result_type, fixed_right_arg, context); | 7892 left_type, right_type, result_type, fixed_right_arg); |
| 7722 } | 7893 } |
| 7723 | 7894 |
| 7724 | 7895 |
| 7725 HInstruction* HGraphBuilder::BuildBinaryOperation( | 7896 HInstruction* HGraphBuilder::BuildBinaryOperation( |
| 7726 Token::Value op, | 7897 Token::Value op, |
| 7727 HValue* left, | 7898 HValue* left, |
| 7728 HValue* right, | 7899 HValue* right, |
| 7729 Handle<Type> left_type, | 7900 Handle<Type> left_type, |
| 7730 Handle<Type> right_type, | 7901 Handle<Type> right_type, |
| 7731 Handle<Type> result_type, | 7902 Handle<Type> result_type, |
| 7732 Maybe<int> fixed_right_arg, | 7903 Maybe<int> fixed_right_arg) { |
| 7733 HValue* context) { | |
| 7734 | 7904 |
| 7735 Representation left_rep = Representation::FromType(left_type); | 7905 Representation left_rep = Representation::FromType(left_type); |
| 7736 Representation right_rep = Representation::FromType(right_type); | 7906 Representation right_rep = Representation::FromType(right_type); |
| 7737 | 7907 |
| 7738 bool maybe_string_add = op == Token::ADD && | 7908 bool maybe_string_add = op == Token::ADD && |
| 7739 (left_type->Maybe(Type::String()) || | 7909 (left_type->Maybe(Type::String()) || |
| 7740 right_type->Maybe(Type::String())); | 7910 right_type->Maybe(Type::String())); |
| 7741 | 7911 |
| 7742 if (left_type->Is(Type::None())) { | 7912 if (left_type->Is(Type::None())) { |
| 7743 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 7913 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| (...skipping 30 matching lines...) Expand all Loading... |
| 7774 BuildCheckHeapObject(left); | 7944 BuildCheckHeapObject(left); |
| 7775 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7945 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 7776 flags = STRING_ADD_CHECK_RIGHT; | 7946 flags = STRING_ADD_CHECK_RIGHT; |
| 7777 } | 7947 } |
| 7778 if (right_type->Is(Type::String())) { | 7948 if (right_type->Is(Type::String())) { |
| 7779 BuildCheckHeapObject(right); | 7949 BuildCheckHeapObject(right); |
| 7780 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7950 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7781 flags = (flags == STRING_ADD_CHECK_BOTH) | 7951 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7782 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; | 7952 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7783 } | 7953 } |
| 7784 instr = HStringAdd::New(zone(), context, left, right, flags); | 7954 instr = NewUncasted<HStringAdd>(left, right, flags); |
| 7785 } else { | 7955 } else { |
| 7786 instr = HAdd::New(zone(), context, left, right); | 7956 instr = NewUncasted<HAdd>(left, right); |
| 7787 } | 7957 } |
| 7788 break; | 7958 break; |
| 7789 case Token::SUB: | 7959 case Token::SUB: |
| 7790 instr = HSub::New(zone(), context, left, right); | 7960 instr = NewUncasted<HSub>(left, right); |
| 7791 break; | 7961 break; |
| 7792 case Token::MUL: | 7962 case Token::MUL: |
| 7793 instr = HMul::New(zone(), context, left, right); | 7963 instr = NewUncasted<HMul>(left, right); |
| 7794 break; | 7964 break; |
| 7795 case Token::MOD: | 7965 case Token::MOD: |
| 7796 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7966 instr = NewUncasted<HMod>(left, right, fixed_right_arg); |
| 7797 break; | 7967 break; |
| 7798 case Token::DIV: | 7968 case Token::DIV: |
| 7799 instr = HDiv::New(zone(), context, left, right); | 7969 instr = NewUncasted<HDiv>(left, right); |
| 7800 break; | 7970 break; |
| 7801 case Token::BIT_XOR: | 7971 case Token::BIT_XOR: |
| 7802 case Token::BIT_AND: | 7972 case Token::BIT_AND: |
| 7803 instr = NewUncasted<HBitwise>(op, left, right); | 7973 instr = NewUncasted<HBitwise>(op, left, right); |
| 7804 break; | 7974 break; |
| 7805 case Token::BIT_OR: { | 7975 case Token::BIT_OR: { |
| 7806 HValue* operand, *shift_amount; | 7976 HValue* operand, *shift_amount; |
| 7807 if (left_type->Is(Type::Signed32()) && | 7977 if (left_type->Is(Type::Signed32()) && |
| 7808 right_type->Is(Type::Signed32()) && | 7978 right_type->Is(Type::Signed32()) && |
| 7809 MatchRotateRight(left, right, &operand, &shift_amount)) { | 7979 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 7810 instr = new(zone()) HRor(context, operand, shift_amount); | 7980 instr = NewUncasted<HRor>(operand, shift_amount); |
| 7811 } else { | 7981 } else { |
| 7812 instr = NewUncasted<HBitwise>(op, left, right); | 7982 instr = NewUncasted<HBitwise>(op, left, right); |
| 7813 } | 7983 } |
| 7814 break; | 7984 break; |
| 7815 } | 7985 } |
| 7816 case Token::SAR: | 7986 case Token::SAR: |
| 7817 instr = HSar::New(zone(), context, left, right); | 7987 instr = NewUncasted<HSar>(left, right); |
| 7818 break; | 7988 break; |
| 7819 case Token::SHR: | 7989 case Token::SHR: |
| 7820 instr = HShr::New(zone(), context, left, right); | 7990 instr = NewUncasted<HShr>(left, right); |
| 7821 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 7991 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
| 7822 CanBeZero(right)) { | 7992 CanBeZero(right)) { |
| 7823 graph()->RecordUint32Instruction(instr); | 7993 graph()->RecordUint32Instruction(instr); |
| 7824 } | 7994 } |
| 7825 break; | 7995 break; |
| 7826 case Token::SHL: | 7996 case Token::SHL: |
| 7827 instr = HShl::New(zone(), context, left, right); | 7997 instr = NewUncasted<HShl>(left, right); |
| 7828 break; | 7998 break; |
| 7829 default: | 7999 default: |
| 7830 UNREACHABLE(); | 8000 UNREACHABLE(); |
| 7831 } | 8001 } |
| 7832 | 8002 |
| 7833 if (instr->IsBinaryOperation()) { | 8003 if (instr->IsBinaryOperation()) { |
| 7834 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 8004 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
| 7835 binop->set_observed_input_representation(1, left_rep); | 8005 binop->set_observed_input_representation(1, left_rep); |
| 7836 binop->set_observed_input_representation(2, right_rep); | 8006 binop->set_observed_input_representation(2, right_rep); |
| 7837 binop->initialize_output_representation(result_rep); | 8007 binop->initialize_output_representation(result_rep); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8230 Handle<JSObject> boilerplate_object, | 8400 Handle<JSObject> boilerplate_object, |
| 8231 Handle<Object> allocation_site_object, | 8401 Handle<Object> allocation_site_object, |
| 8232 AllocationSiteMode mode) { | 8402 AllocationSiteMode mode) { |
| 8233 NoObservableSideEffectsScope no_effects(this); | 8403 NoObservableSideEffectsScope no_effects(this); |
| 8234 | 8404 |
| 8235 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 8405 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 8236 int object_size = boilerplate_object->map()->instance_size(); | 8406 int object_size = boilerplate_object->map()->instance_size(); |
| 8237 int object_offset = object_size; | 8407 int object_offset = object_size; |
| 8238 | 8408 |
| 8239 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 8409 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| 8240 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE && | 8410 bool create_allocation_site_info = mode == TRACK_ALLOCATION_SITE; |
| 8241 AllocationSite::CanTrack(instance_type); | |
| 8242 | 8411 |
| 8243 // If using allocation sites, then the payload on the site should already | 8412 // If using allocation sites, then |
| 8244 // be filled in as a valid (boilerplate) array. | 8413 // 1) the payload on the site should already be filled in as a valid |
| 8414 // (boilerplate) array, and |
| 8415 // 2) we shouldn't be pretenuring the allocations. |
| 8245 ASSERT(!create_allocation_site_info || | 8416 ASSERT(!create_allocation_site_info || |
| 8246 AllocationSite::cast(*allocation_site_object)->IsLiteralSite()); | 8417 (AllocationSite::cast(*allocation_site_object)->IsLiteralSite() && |
| 8418 isolate()->heap()->GetPretenureMode() == NOT_TENURED)); |
| 8247 | 8419 |
| 8248 if (create_allocation_site_info) { | 8420 if (create_allocation_site_info) { |
| 8249 object_size += AllocationMemento::kSize; | 8421 object_size += AllocationMemento::kSize; |
| 8250 } | 8422 } |
| 8251 | 8423 |
| 8252 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 8424 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| 8253 HType type = instance_type == JS_ARRAY_TYPE | 8425 HType type = instance_type == JS_ARRAY_TYPE |
| 8254 ? HType::JSArray() : HType::JSObject(); | 8426 ? HType::JSArray() : HType::JSObject(); |
| 8255 HValue* object_size_constant = Add<HConstant>(object_size); | 8427 HValue* object_size_constant = Add<HConstant>(object_size); |
| 8256 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 8428 HInstruction* object = Add<HAllocate>(object_size_constant, type, |
| 8257 isolate()->heap()->GetPretenureMode(), instance_type); | 8429 isolate()->heap()->GetPretenureMode(), instance_type); |
| 8258 | 8430 |
| 8259 | |
| 8260 BuildEmitObjectHeader(boilerplate_object, object); | 8431 BuildEmitObjectHeader(boilerplate_object, object); |
| 8261 | 8432 |
| 8262 if (create_allocation_site_info) { | 8433 if (create_allocation_site_info) { |
| 8263 HInstruction* allocation_site = Add<HConstant>(allocation_site_object); | 8434 HInstruction* allocation_site = Add<HConstant>(allocation_site_object); |
| 8264 BuildCreateAllocationMemento(object, object_offset, allocation_site); | 8435 BuildCreateAllocationMemento(object, object_offset, allocation_site); |
| 8265 } | 8436 } |
| 8266 | 8437 |
| 8267 int elements_size = (elements->length() > 0 && | 8438 int elements_size = (elements->length() > 0 && |
| 8268 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 8439 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 8269 elements->Size() : 0; | 8440 elements->Size() : 0; |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8968 | 9139 |
| 8969 // Support for fast native caches. | 9140 // Support for fast native caches. |
| 8970 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 9141 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 8971 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 9142 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
| 8972 } | 9143 } |
| 8973 | 9144 |
| 8974 | 9145 |
| 8975 // Fast support for number to string. | 9146 // Fast support for number to string. |
| 8976 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 9147 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 8977 ASSERT_EQ(1, call->arguments()->length()); | 9148 ASSERT_EQ(1, call->arguments()->length()); |
| 8978 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 9149 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 8979 HValue* context = environment()->context(); | 9150 HValue* number = Pop(); |
| 8980 HCallStub* result = | 9151 HValue* result = BuildNumberToString(number); |
| 8981 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 9152 return ast_context()->ReturnValue(result); |
| 8982 Drop(1); | |
| 8983 return ast_context()->ReturnInstruction(result, call->id()); | |
| 8984 } | 9153 } |
| 8985 | 9154 |
| 8986 | 9155 |
| 8987 // Fast call for custom callbacks. | 9156 // Fast call for custom callbacks. |
| 8988 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 9157 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 8989 // 1 ~ The function to call is not itself an argument to the call. | 9158 // 1 ~ The function to call is not itself an argument to the call. |
| 8990 int arg_count = call->arguments()->length() - 1; | 9159 int arg_count = call->arguments()->length() - 1; |
| 8991 ASSERT(arg_count >= 1); // There's always at least a receiver. | 9160 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 8992 | 9161 |
| 8993 for (int i = 0; i < arg_count; ++i) { | 9162 for (int i = 0; i < arg_count; ++i) { |
| (...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9740 if (ShouldProduceTraceOutput()) { | 9909 if (ShouldProduceTraceOutput()) { |
| 9741 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9910 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 9742 } | 9911 } |
| 9743 | 9912 |
| 9744 #ifdef DEBUG | 9913 #ifdef DEBUG |
| 9745 graph_->Verify(false); // No full verify. | 9914 graph_->Verify(false); // No full verify. |
| 9746 #endif | 9915 #endif |
| 9747 } | 9916 } |
| 9748 | 9917 |
| 9749 } } // namespace v8::internal | 9918 } } // namespace v8::internal |
| OLD | NEW |