| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 12095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12106 | 12106 |
| 12107 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { | 12107 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { |
| 12108 DCHECK(call->arguments()->length() == 1); | 12108 DCHECK(call->arguments()->length() == 1); |
| 12109 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12109 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12110 HValue* value = Pop(); | 12110 HValue* value = Pop(); |
| 12111 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); | 12111 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
| 12112 return ast_context()->ReturnInstruction(result, call->id()); | 12112 return ast_context()->ReturnInstruction(result, call->id()); |
| 12113 } | 12113 } |
| 12114 | 12114 |
| 12115 | 12115 |
| 12116 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToBucket( | |
| 12117 HValue* hash, HValue* num_buckets) { | |
| 12118 HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1()); | |
| 12119 mask->ChangeRepresentation(Representation::Integer32()); | |
| 12120 mask->ClearFlag(HValue::kCanOverflow); | |
| 12121 return AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); | |
| 12122 } | |
| 12123 | |
| 12124 | |
| 12125 template <typename CollectionType> | |
| 12126 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToEntry( | |
| 12127 HValue* table, HValue* hash, HValue* num_buckets) { | |
| 12128 HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets); | |
| 12129 HValue* entry_index = AddUncasted<HAdd>( | |
| 12130 bucket, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
| 12131 entry_index->ClearFlag(HValue::kCanOverflow); | |
| 12132 HValue* entry = Add<HLoadKeyed>(table, entry_index, | |
| 12133 static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 12134 entry->set_type(HType::Smi()); | |
| 12135 return entry; | |
| 12136 } | |
| 12137 | |
| 12138 | |
| 12139 template <typename CollectionType> | |
| 12140 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableEntryToIndex( | |
| 12141 HValue* entry, HValue* num_buckets) { | |
| 12142 HValue* index = | |
| 12143 AddUncasted<HMul>(entry, Add<HConstant>(CollectionType::kEntrySize)); | |
| 12144 index->ClearFlag(HValue::kCanOverflow); | |
| 12145 index = AddUncasted<HAdd>(index, num_buckets); | |
| 12146 index->ClearFlag(HValue::kCanOverflow); | |
| 12147 index = AddUncasted<HAdd>( | |
| 12148 index, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
| 12149 index->ClearFlag(HValue::kCanOverflow); | |
| 12150 return index; | |
| 12151 } | |
| 12152 | |
| 12153 | |
| 12154 template <typename CollectionType> | 12116 template <typename CollectionType> |
| 12155 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableFindEntry(HValue* table, | 12117 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableFindEntry(HValue* table, |
| 12156 HValue* key, | 12118 HValue* key, |
| 12157 HValue* hash) { | 12119 HValue* hash) { |
| 12158 HValue* num_buckets = Add<HLoadNamedField>( | 12120 HValue* num_buckets = Add<HLoadNamedField>( |
| 12159 table, static_cast<HValue*>(NULL), | 12121 table, static_cast<HValue*>(NULL), |
| 12160 HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>()); | 12122 HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>()); |
| 12161 | 12123 |
| 12162 HValue* entry = BuildOrderedHashTableHashToEntry<CollectionType>(table, hash, | 12124 // Some things that won't change inside the loop |
| 12163 num_buckets); | 12125 HValue* not_found = Add<HConstant>(CollectionType::kNotFound); |
| 12126 HValue* start_index = Add<HConstant>(CollectionType::kHashTableStartIndex); |
| 12127 HValue* entry_size = Add<HConstant>(CollectionType::kEntrySize); |
| 12128 HValue* chain_offset = Add<HConstant>(CollectionType::kChainOffset); |
| 12129 HValue* key_start = AddUncasted<HAdd>(start_index, num_buckets); |
| 12130 key_start->ClearFlag(HValue::kCanOverflow); |
| 12131 |
| 12132 // BuildHashToBucket |
| 12133 HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1()); |
| 12134 mask->ChangeRepresentation(Representation::Integer32()); |
| 12135 mask->ClearFlag(HValue::kCanOverflow); |
| 12136 |
| 12137 HValue* bucket = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); |
| 12138 |
| 12139 // BuildHashToEntry |
| 12140 HValue* entry_index = AddUncasted<HAdd>(start_index, bucket); |
| 12141 entry_index->ClearFlag(HValue::kCanOverflow); |
| 12142 HValue* entry = |
| 12143 Add<HLoadKeyed>(table, entry_index, static_cast<HValue*>(NULL), |
| 12144 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 12145 entry->set_type(HType::Smi()); |
| 12164 | 12146 |
| 12165 Push(entry); | 12147 Push(entry); |
| 12166 | 12148 |
| 12167 LoopBuilder loop(this); | 12149 LoopBuilder loop(this); |
| 12168 loop.BeginBody(1); | 12150 loop.BeginBody(1); |
| 12169 | 12151 |
| 12170 entry = Pop(); | 12152 entry = Pop(); |
| 12171 | 12153 |
| 12172 { | 12154 { |
| 12173 IfBuilder if_not_found(this); | 12155 IfBuilder if_not_found(this); |
| 12174 if_not_found.If<HCompareNumericAndBranch>( | 12156 if_not_found.If<HCompareNumericAndBranch>(entry, not_found, Token::EQ); |
| 12175 entry, Add<HConstant>(CollectionType::kNotFound), Token::EQ); | |
| 12176 if_not_found.Then(); | 12157 if_not_found.Then(); |
| 12177 Push(entry); | 12158 Push(entry); |
| 12178 loop.Break(); | 12159 loop.Break(); |
| 12179 } | 12160 } |
| 12180 | 12161 |
| 12181 HValue* key_index = | 12162 // BuildEntryToIndex |
| 12182 BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets); | 12163 HValue* key_index = AddUncasted<HMul>(entry, entry_size); |
| 12183 HValue* candidate_key = Add<HLoadKeyed>( | 12164 key_index->ClearFlag(HValue::kCanOverflow); |
| 12184 table, key_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | 12165 key_index = AddUncasted<HAdd>(key_index, key_start); |
| 12166 key_index->ClearFlag(HValue::kCanOverflow); |
| 12167 // BuildKeyAt |
| 12168 HValue* candidate_key = |
| 12169 Add<HLoadKeyed>(table, key_index, static_cast<HValue*>(NULL), |
| 12170 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 12185 | 12171 |
| 12186 { | 12172 { |
| 12187 IfBuilder if_keys_equal(this); | 12173 IfBuilder if_keys_equal(this); |
| 12188 if_keys_equal.If<HIsStringAndBranch>(candidate_key); | 12174 if_keys_equal.If<HIsStringAndBranch>(candidate_key); |
| 12189 if_keys_equal.AndIf<HStringCompareAndBranch>(candidate_key, key, | 12175 if_keys_equal.AndIf<HStringCompareAndBranch>(candidate_key, key, |
| 12190 Token::EQ_STRICT); | 12176 Token::EQ_STRICT); |
| 12191 if_keys_equal.Then(); | 12177 if_keys_equal.Then(); |
| 12192 Push(key_index); | 12178 Push(key_index); |
| 12193 loop.Break(); | 12179 loop.Break(); |
| 12194 } | 12180 } |
| 12195 | 12181 |
| 12196 // BuildChainAt | 12182 // BuildChainAt |
| 12197 HValue* chain_index = AddUncasted<HAdd>( | 12183 HValue* chain_index = AddUncasted<HMul>(entry, entry_size); |
| 12198 key_index, Add<HConstant>(CollectionType::kChainOffset)); | 12184 chain_index->ClearFlag(HValue::kCanOverflow); |
| 12185 chain_index = AddUncasted<HAdd>(chain_index, key_start); |
| 12186 chain_index->ClearFlag(HValue::kCanOverflow); |
| 12187 chain_index = AddUncasted<HAdd>(chain_index, chain_offset); |
| 12199 chain_index->ClearFlag(HValue::kCanOverflow); | 12188 chain_index->ClearFlag(HValue::kCanOverflow); |
| 12200 entry = Add<HLoadKeyed>(table, chain_index, static_cast<HValue*>(NULL), | 12189 entry = Add<HLoadKeyed>(table, chain_index, static_cast<HValue*>(NULL), |
| 12201 FAST_ELEMENTS); | 12190 FAST_ELEMENTS, ALLOW_RETURN_HOLE); |
| 12202 entry->set_type(HType::Smi()); | 12191 entry->set_type(HType::Smi()); |
| 12203 Push(entry); | 12192 Push(entry); |
| 12204 | 12193 |
| 12205 loop.EndBody(); | 12194 loop.EndBody(); |
| 12206 | 12195 |
| 12207 return Pop(); | 12196 return Pop(); |
| 12208 } | 12197 } |
| 12209 | 12198 |
| 12210 | 12199 |
| 12211 void HOptimizedGraphBuilder::GenerateMapGet(CallRuntime* call) { | 12200 void HOptimizedGraphBuilder::GenerateMapGet(CallRuntime* call) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12325 call, Runtime::FunctionForId(Runtime::kMapHas)); | 12314 call, Runtime::FunctionForId(Runtime::kMapHas)); |
| 12326 } | 12315 } |
| 12327 | 12316 |
| 12328 | 12317 |
| 12329 void HOptimizedGraphBuilder::GenerateSetHas(CallRuntime* call) { | 12318 void HOptimizedGraphBuilder::GenerateSetHas(CallRuntime* call) { |
| 12330 BuildJSCollectionHas<OrderedHashSet>( | 12319 BuildJSCollectionHas<OrderedHashSet>( |
| 12331 call, Runtime::FunctionForId(Runtime::kSetHas)); | 12320 call, Runtime::FunctionForId(Runtime::kSetHas)); |
| 12332 } | 12321 } |
| 12333 | 12322 |
| 12334 | 12323 |
| 12335 template <typename CollectionType> | |
| 12336 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableAddEntry( | |
| 12337 HValue* table, HValue* key, HValue* hash, | |
| 12338 HIfContinuation* join_continuation) { | |
| 12339 HValue* num_buckets = Add<HLoadNamedField>( | |
| 12340 table, static_cast<HValue*>(NULL), | |
| 12341 HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>()); | |
| 12342 HValue* capacity = AddUncasted<HMul>( | |
| 12343 num_buckets, Add<HConstant>(CollectionType::kLoadFactor)); | |
| 12344 capacity->ClearFlag(HValue::kCanOverflow); | |
| 12345 HValue* num_elements = Add<HLoadNamedField>( | |
| 12346 table, static_cast<HValue*>(NULL), | |
| 12347 HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>()); | |
| 12348 HValue* num_deleted = Add<HLoadNamedField>( | |
| 12349 table, static_cast<HValue*>(NULL), | |
| 12350 HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
| 12351 CollectionType>()); | |
| 12352 HValue* used = AddUncasted<HAdd>(num_elements, num_deleted); | |
| 12353 used->ClearFlag(HValue::kCanOverflow); | |
| 12354 IfBuilder if_space_available(this); | |
| 12355 if_space_available.If<HCompareNumericAndBranch>(capacity, used, Token::GT); | |
| 12356 if_space_available.Then(); | |
| 12357 HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets); | |
| 12358 HValue* entry = used; | |
| 12359 HValue* key_index = | |
| 12360 BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets); | |
| 12361 | |
| 12362 HValue* bucket_index = AddUncasted<HAdd>( | |
| 12363 bucket, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
| 12364 bucket_index->ClearFlag(HValue::kCanOverflow); | |
| 12365 HValue* chain_entry = Add<HLoadKeyed>( | |
| 12366 table, bucket_index, static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 12367 chain_entry->set_type(HType::Smi()); | |
| 12368 | |
| 12369 HValue* chain_index = AddUncasted<HAdd>( | |
| 12370 key_index, Add<HConstant>(CollectionType::kChainOffset)); | |
| 12371 | |
| 12372 Add<HStoreKeyed>(table, bucket_index, entry, FAST_ELEMENTS); | |
| 12373 Add<HStoreKeyed>(table, chain_index, chain_entry, FAST_ELEMENTS); | |
| 12374 Add<HStoreKeyed>(table, key_index, key, FAST_ELEMENTS); | |
| 12375 | |
| 12376 HValue* new_num_elements = | |
| 12377 AddUncasted<HAdd>(num_elements, graph()->GetConstant1()); | |
| 12378 new_num_elements->ClearFlag(HValue::kCanOverflow); | |
| 12379 Add<HStoreNamedField>( | |
| 12380 table, | |
| 12381 HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(), | |
| 12382 new_num_elements); | |
| 12383 if_space_available.JoinContinuation(join_continuation); | |
| 12384 return key_index; | |
| 12385 } | |
| 12386 | |
| 12387 | |
| 12388 void HOptimizedGraphBuilder::GenerateMapSet(CallRuntime* call) { | |
| 12389 DCHECK(call->arguments()->length() == 3); | |
| 12390 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12391 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
| 12392 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | |
| 12393 HValue* value = Pop(); | |
| 12394 HValue* key = Pop(); | |
| 12395 HValue* receiver = Pop(); | |
| 12396 | |
| 12397 NoObservableSideEffectsScope no_effects(this); | |
| 12398 | |
| 12399 HIfContinuation return_or_call_runtime_continuation( | |
| 12400 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
| 12401 HIfContinuation got_string_hash; | |
| 12402 HValue* hash = | |
| 12403 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
| 12404 IfBuilder string_checker(this, &got_string_hash); | |
| 12405 string_checker.Then(); | |
| 12406 { | |
| 12407 HValue* table = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | |
| 12408 HObjectAccess::ForJSCollectionTable()); | |
| 12409 HValue* key_index = | |
| 12410 BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash); | |
| 12411 { | |
| 12412 IfBuilder if_found(this); | |
| 12413 if_found.If<HCompareNumericAndBranch>( | |
| 12414 key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE); | |
| 12415 if_found.Then(); | |
| 12416 { | |
| 12417 HValue* value_index = AddUncasted<HAdd>( | |
| 12418 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
| 12419 value_index->ClearFlag(HValue::kCanOverflow); | |
| 12420 Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS); | |
| 12421 } | |
| 12422 if_found.Else(); | |
| 12423 { | |
| 12424 HIfContinuation did_add(graph()->CreateBasicBlock(), | |
| 12425 graph()->CreateBasicBlock()); | |
| 12426 HValue* key_index = BuildOrderedHashTableAddEntry<OrderedHashMap>( | |
| 12427 table, key, hash, &did_add); | |
| 12428 IfBuilder if_did_add(this, &did_add); | |
| 12429 if_did_add.Then(); | |
| 12430 { | |
| 12431 HValue* value_index = AddUncasted<HAdd>( | |
| 12432 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
| 12433 value_index->ClearFlag(HValue::kCanOverflow); | |
| 12434 Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS); | |
| 12435 } | |
| 12436 if_did_add.JoinContinuation(&return_or_call_runtime_continuation); | |
| 12437 } | |
| 12438 } | |
| 12439 } | |
| 12440 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
| 12441 | |
| 12442 { | |
| 12443 IfBuilder return_or_call_runtime(this, | |
| 12444 &return_or_call_runtime_continuation); | |
| 12445 return_or_call_runtime.Then(); | |
| 12446 Push(receiver); | |
| 12447 return_or_call_runtime.Else(); | |
| 12448 Add<HPushArguments>(receiver, key, value); | |
| 12449 Push(Add<HCallRuntime>(call->name(), | |
| 12450 Runtime::FunctionForId(Runtime::kMapSet), 3)); | |
| 12451 } | |
| 12452 | |
| 12453 return ast_context()->ReturnValue(Pop()); | |
| 12454 } | |
| 12455 | |
| 12456 | |
| 12457 void HOptimizedGraphBuilder::GenerateSetAdd(CallRuntime* call) { | |
| 12458 DCHECK(call->arguments()->length() == 2); | |
| 12459 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12460 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
| 12461 HValue* key = Pop(); | |
| 12462 HValue* receiver = Pop(); | |
| 12463 | |
| 12464 NoObservableSideEffectsScope no_effects(this); | |
| 12465 | |
| 12466 HIfContinuation return_or_call_runtime_continuation( | |
| 12467 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
| 12468 HIfContinuation got_string_hash; | |
| 12469 HValue* hash = | |
| 12470 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
| 12471 IfBuilder string_checker(this, &got_string_hash); | |
| 12472 string_checker.Then(); | |
| 12473 { | |
| 12474 HValue* table = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | |
| 12475 HObjectAccess::ForJSCollectionTable()); | |
| 12476 HValue* key_index = | |
| 12477 BuildOrderedHashTableFindEntry<OrderedHashSet>(table, key, hash); | |
| 12478 { | |
| 12479 IfBuilder if_not_found(this); | |
| 12480 if_not_found.If<HCompareNumericAndBranch>( | |
| 12481 key_index, Add<HConstant>(OrderedHashSet::kNotFound), Token::EQ); | |
| 12482 if_not_found.Then(); | |
| 12483 BuildOrderedHashTableAddEntry<OrderedHashSet>( | |
| 12484 table, key, hash, &return_or_call_runtime_continuation); | |
| 12485 } | |
| 12486 } | |
| 12487 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
| 12488 | |
| 12489 { | |
| 12490 IfBuilder return_or_call_runtime(this, | |
| 12491 &return_or_call_runtime_continuation); | |
| 12492 return_or_call_runtime.Then(); | |
| 12493 Push(receiver); | |
| 12494 return_or_call_runtime.Else(); | |
| 12495 Add<HPushArguments>(receiver, key); | |
| 12496 Push(Add<HCallRuntime>(call->name(), | |
| 12497 Runtime::FunctionForId(Runtime::kSetAdd), 2)); | |
| 12498 } | |
| 12499 | |
| 12500 return ast_context()->ReturnValue(Pop()); | |
| 12501 } | |
| 12502 | |
| 12503 | |
| 12504 template <typename CollectionType> | |
| 12505 void HOptimizedGraphBuilder::BuildJSCollectionDelete( | |
| 12506 CallRuntime* call, const Runtime::Function* c_function) { | |
| 12507 DCHECK(call->arguments()->length() == 2); | |
| 12508 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12509 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
| 12510 HValue* key = Pop(); | |
| 12511 HValue* receiver = Pop(); | |
| 12512 | |
| 12513 NoObservableSideEffectsScope no_effects(this); | |
| 12514 | |
| 12515 HIfContinuation return_or_call_runtime_continuation( | |
| 12516 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
| 12517 HIfContinuation got_string_hash; | |
| 12518 HValue* hash = | |
| 12519 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
| 12520 IfBuilder string_checker(this, &got_string_hash); | |
| 12521 string_checker.Then(); | |
| 12522 { | |
| 12523 HValue* table = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | |
| 12524 HObjectAccess::ForJSCollectionTable()); | |
| 12525 HValue* key_index = | |
| 12526 BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash); | |
| 12527 { | |
| 12528 IfBuilder if_found(this); | |
| 12529 if_found.If<HCompareNumericAndBranch>( | |
| 12530 key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE); | |
| 12531 if_found.Then(); | |
| 12532 { | |
| 12533 // If we're removing an element, we might need to shrink. | |
| 12534 // If we do need to shrink, we'll be bailing out to the runtime. | |
| 12535 HValue* num_elements = Add<HLoadNamedField>( | |
| 12536 table, static_cast<HValue*>(NULL), | |
| 12537 HObjectAccess::ForOrderedHashTableNumberOfElements< | |
| 12538 CollectionType>()); | |
| 12539 HValue* threshold = Add<HLoadNamedField>( | |
| 12540 table, static_cast<HValue*>(NULL), | |
| 12541 HObjectAccess::ForOrderedHashTableNumberOfElements< | |
| 12542 CollectionType>()); | |
| 12543 threshold = AddUncasted<HMul>( | |
| 12544 threshold, Add<HConstant>(CollectionType::kLoadFactor)); | |
| 12545 threshold->ClearFlag(HValue::kCanOverflow); | |
| 12546 threshold = AddUncasted<HShr>(threshold, Add<HConstant>(2)); | |
| 12547 | |
| 12548 IfBuilder if_need_not_shrink(this); | |
| 12549 if_need_not_shrink.If<HCompareNumericAndBranch>(num_elements, threshold, | |
| 12550 Token::GTE); | |
| 12551 if_need_not_shrink.Then(); | |
| 12552 { | |
| 12553 Add<HStoreKeyed>(table, key_index, graph()->GetConstantHole(), | |
| 12554 FAST_ELEMENTS); | |
| 12555 | |
| 12556 // For maps, also need to clear the value. | |
| 12557 if (CollectionType::kChainOffset > 1) { | |
| 12558 HValue* value_index = | |
| 12559 AddUncasted<HAdd>(key_index, graph()->GetConstant1()); | |
| 12560 Add<HStoreKeyed>(table, value_index, graph()->GetConstantHole(), | |
| 12561 FAST_ELEMENTS); | |
| 12562 } | |
| 12563 STATIC_ASSERT(CollectionType::kChainOffset <= 2); | |
| 12564 | |
| 12565 num_elements = | |
| 12566 AddUncasted<HSub>(num_elements, graph()->GetConstant1()); | |
| 12567 HValue* num_deleted = Add<HLoadNamedField>( | |
| 12568 table, static_cast<HValue*>(NULL), | |
| 12569 HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
| 12570 CollectionType>()); | |
| 12571 num_deleted = AddUncasted<HAdd>(num_deleted, graph()->GetConstant1()); | |
| 12572 Add<HStoreNamedField>( | |
| 12573 table, HObjectAccess::ForOrderedHashTableNumberOfElements< | |
| 12574 CollectionType>(), | |
| 12575 num_elements); | |
| 12576 Add<HStoreNamedField>( | |
| 12577 table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
| 12578 CollectionType>(), | |
| 12579 num_deleted); | |
| 12580 Push(graph()->GetConstantTrue()); | |
| 12581 } | |
| 12582 if_need_not_shrink.JoinContinuation( | |
| 12583 &return_or_call_runtime_continuation); | |
| 12584 } | |
| 12585 if_found.Else(); | |
| 12586 { | |
| 12587 // Not found, so we're done. | |
| 12588 Push(graph()->GetConstantFalse()); | |
| 12589 } | |
| 12590 } | |
| 12591 } | |
| 12592 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
| 12593 | |
| 12594 { | |
| 12595 IfBuilder return_or_call_runtime(this, | |
| 12596 &return_or_call_runtime_continuation); | |
| 12597 return_or_call_runtime.Then(); | |
| 12598 return_or_call_runtime.Else(); | |
| 12599 Add<HPushArguments>(receiver, key); | |
| 12600 Push(Add<HCallRuntime>(call->name(), c_function, 2)); | |
| 12601 } | |
| 12602 | |
| 12603 return ast_context()->ReturnValue(Pop()); | |
| 12604 } | |
| 12605 | |
| 12606 | |
| 12607 void HOptimizedGraphBuilder::GenerateMapDelete(CallRuntime* call) { | |
| 12608 BuildJSCollectionDelete<OrderedHashMap>( | |
| 12609 call, Runtime::FunctionForId(Runtime::kMapDelete)); | |
| 12610 } | |
| 12611 | |
| 12612 | |
| 12613 void HOptimizedGraphBuilder::GenerateSetDelete(CallRuntime* call) { | |
| 12614 BuildJSCollectionDelete<OrderedHashSet>( | |
| 12615 call, Runtime::FunctionForId(Runtime::kSetDelete)); | |
| 12616 } | |
| 12617 | |
| 12618 | |
| 12619 void HOptimizedGraphBuilder::GenerateSetGetSize(CallRuntime* call) { | 12324 void HOptimizedGraphBuilder::GenerateSetGetSize(CallRuntime* call) { |
| 12620 DCHECK(call->arguments()->length() == 1); | 12325 DCHECK(call->arguments()->length() == 1); |
| 12621 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12326 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12622 HValue* receiver = Pop(); | 12327 HValue* receiver = Pop(); |
| 12623 HValue* table = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), | 12328 HValue* table = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL), |
| 12624 HObjectAccess::ForJSCollectionTable()); | 12329 HObjectAccess::ForJSCollectionTable()); |
| 12625 HInstruction* result = New<HLoadNamedField>( | 12330 HInstruction* result = New<HLoadNamedField>( |
| 12626 table, static_cast<HValue*>(NULL), | 12331 table, static_cast<HValue*>(NULL), |
| 12627 HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashSet>()); | 12332 HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashSet>()); |
| 12628 return ast_context()->ReturnInstruction(result, call->id()); | 12333 return ast_context()->ReturnInstruction(result, call->id()); |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13314 if (ShouldProduceTraceOutput()) { | 13019 if (ShouldProduceTraceOutput()) { |
| 13315 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13020 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13316 } | 13021 } |
| 13317 | 13022 |
| 13318 #ifdef DEBUG | 13023 #ifdef DEBUG |
| 13319 graph_->Verify(false); // No full verify. | 13024 graph_->Verify(false); // No full verify. |
| 13320 #endif | 13025 #endif |
| 13321 } | 13026 } |
| 13322 | 13027 |
| 13323 } } // namespace v8::internal | 13028 } } // namespace v8::internal |
| OLD | NEW |