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