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 12015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12026 | 12026 |
12027 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 12027 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
12028 DCHECK(call->arguments()->length() == 1); | 12028 DCHECK(call->arguments()->length() == 1); |
12029 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12029 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12030 HValue* value = Pop(); | 12030 HValue* value = Pop(); |
12031 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); | 12031 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
12032 return ast_context()->ReturnInstruction(result, call->id()); | 12032 return ast_context()->ReturnInstruction(result, call->id()); |
12033 } | 12033 } |
12034 | 12034 |
12035 | 12035 |
12036 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToBucket( | 12036 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) { |
12037 HValue* hash, HValue* num_buckets) { | 12037 DCHECK(call->arguments()->length() == 2); |
12038 HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1()); | 12038 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12039 mask->ChangeRepresentation(Representation::Integer32()); | 12039 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
12040 mask->ClearFlag(HValue::kCanOverflow); | 12040 HValue* index = Pop(); |
12041 return AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); | 12041 HValue* object = Pop(); |
12042 HInstruction* result = New<HLoadKeyed>(object, index, nullptr, FAST_ELEMENTS); | |
Toon Verwaest
2015/03/30 12:55:42
Seems like it would be more honest to FAST_HOLEY_E
adamk
2015/03/30 18:44:54
Done.
arv (Not doing code reviews)
2015/03/30 18:55:22
Would that impact the performance?
adamk
2015/03/30 22:31:50
I don't believe so, but if it does, that's because
| |
12043 return ast_context()->ReturnInstruction(result, call->id()); | |
12042 } | 12044 } |
12043 | 12045 |
12044 | 12046 |
12045 template <typename CollectionType> | 12047 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) { |
12046 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableHashToEntry( | |
12047 HValue* table, HValue* hash, HValue* num_buckets) { | |
12048 HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets); | |
12049 HValue* entry_index = AddUncasted<HAdd>( | |
12050 bucket, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
12051 entry_index->ClearFlag(HValue::kCanOverflow); | |
12052 HValue* entry = Add<HLoadKeyed>(table, entry_index, nullptr, FAST_ELEMENTS); | |
12053 entry->set_type(HType::Smi()); | |
12054 return entry; | |
12055 } | |
12056 | |
12057 | |
12058 template <typename CollectionType> | |
12059 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableEntryToIndex( | |
12060 HValue* entry, HValue* num_buckets) { | |
12061 HValue* index = | |
12062 AddUncasted<HMul>(entry, Add<HConstant>(CollectionType::kEntrySize)); | |
12063 index->ClearFlag(HValue::kCanOverflow); | |
12064 index = AddUncasted<HAdd>(index, num_buckets); | |
12065 index->ClearFlag(HValue::kCanOverflow); | |
12066 index = AddUncasted<HAdd>( | |
12067 index, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
12068 index->ClearFlag(HValue::kCanOverflow); | |
12069 return index; | |
12070 } | |
12071 | |
12072 | |
12073 template <typename CollectionType> | |
12074 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableFindEntry(HValue* table, | |
12075 HValue* key, | |
12076 HValue* hash) { | |
12077 HValue* num_buckets = Add<HLoadNamedField>( | |
12078 table, nullptr, | |
12079 HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>()); | |
12080 | |
12081 HValue* entry = BuildOrderedHashTableHashToEntry<CollectionType>(table, hash, | |
12082 num_buckets); | |
12083 | |
12084 Push(entry); | |
12085 | |
12086 LoopBuilder loop(this); | |
12087 loop.BeginBody(1); | |
12088 | |
12089 entry = Pop(); | |
12090 | |
12091 { | |
12092 IfBuilder if_not_found(this); | |
12093 if_not_found.If<HCompareNumericAndBranch>( | |
12094 entry, Add<HConstant>(CollectionType::kNotFound), Token::EQ); | |
12095 if_not_found.Then(); | |
12096 Push(entry); | |
12097 loop.Break(); | |
12098 } | |
12099 | |
12100 HValue* key_index = | |
12101 BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets); | |
12102 HValue* candidate_key = | |
12103 Add<HLoadKeyed>(table, key_index, nullptr, FAST_ELEMENTS); | |
12104 | |
12105 { | |
12106 IfBuilder if_keys_equal(this); | |
12107 if_keys_equal.If<HIsStringAndBranch>(candidate_key); | |
12108 if_keys_equal.AndIf<HStringCompareAndBranch>(candidate_key, key, | |
12109 Token::EQ_STRICT); | |
12110 if_keys_equal.Then(); | |
12111 Push(key_index); | |
12112 loop.Break(); | |
12113 } | |
12114 | |
12115 // BuildChainAt | |
12116 HValue* chain_index = AddUncasted<HAdd>( | |
12117 key_index, Add<HConstant>(CollectionType::kChainOffset)); | |
12118 chain_index->ClearFlag(HValue::kCanOverflow); | |
12119 entry = Add<HLoadKeyed>(table, chain_index, nullptr, FAST_ELEMENTS); | |
12120 entry->set_type(HType::Smi()); | |
12121 Push(entry); | |
12122 | |
12123 loop.EndBody(); | |
12124 | |
12125 return Pop(); | |
12126 } | |
12127 | |
12128 | |
12129 void HOptimizedGraphBuilder::GenerateMapGet(CallRuntime* call) { | |
12130 DCHECK(call->arguments()->length() == 2); | |
12131 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
12132 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
12133 HValue* key = Pop(); | |
12134 HValue* receiver = Pop(); | |
12135 | |
12136 NoObservableSideEffectsScope no_effects(this); | |
12137 | |
12138 HIfContinuation continuation; | |
12139 HValue* hash = | |
12140 BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation); | |
12141 { | |
12142 IfBuilder string_checker(this, &continuation); | |
12143 string_checker.Then(); | |
12144 { | |
12145 HValue* table = Add<HLoadNamedField>( | |
12146 receiver, nullptr, HObjectAccess::ForJSCollectionTable()); | |
12147 HValue* key_index = | |
12148 BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash); | |
12149 IfBuilder if_found(this); | |
12150 if_found.If<HCompareNumericAndBranch>( | |
12151 key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE); | |
12152 if_found.Then(); | |
12153 { | |
12154 HValue* value_index = AddUncasted<HAdd>( | |
12155 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
12156 value_index->ClearFlag(HValue::kCanOverflow); | |
12157 Push(Add<HLoadKeyed>(table, value_index, nullptr, FAST_ELEMENTS)); | |
12158 } | |
12159 if_found.Else(); | |
12160 Push(graph()->GetConstantUndefined()); | |
12161 if_found.End(); | |
12162 } | |
12163 string_checker.Else(); | |
12164 { | |
12165 Add<HPushArguments>(receiver, key); | |
12166 Push(Add<HCallRuntime>(call->name(), | |
12167 Runtime::FunctionForId(Runtime::kMapGet), 2)); | |
12168 } | |
12169 } | |
12170 | |
12171 return ast_context()->ReturnValue(Pop()); | |
12172 } | |
12173 | |
12174 | |
12175 HValue* HOptimizedGraphBuilder::BuildStringHashLoadIfIsStringAndHashComputed( | |
12176 HValue* object, HIfContinuation* continuation) { | |
12177 IfBuilder string_checker(this); | |
12178 string_checker.If<HIsStringAndBranch>(object); | |
12179 string_checker.And(); | |
12180 HValue* hash = Add<HLoadNamedField>(object, nullptr, | |
12181 HObjectAccess::ForStringHashField()); | |
12182 HValue* hash_not_computed_mask = Add<HConstant>(String::kHashNotComputedMask); | |
12183 HValue* hash_computed_test = | |
12184 AddUncasted<HBitwise>(Token::BIT_AND, hash, hash_not_computed_mask); | |
12185 string_checker.If<HCompareNumericAndBranch>( | |
12186 hash_computed_test, graph()->GetConstant0(), Token::EQ); | |
12187 string_checker.Then(); | |
12188 HValue* shifted_hash = | |
12189 AddUncasted<HShr>(hash, Add<HConstant>(String::kHashShift)); | |
12190 string_checker.CaptureContinuation(continuation); | |
12191 return shifted_hash; | |
12192 } | |
12193 | |
12194 | |
12195 template <typename CollectionType> | |
12196 void HOptimizedGraphBuilder::BuildJSCollectionHas( | |
12197 CallRuntime* call, const Runtime::Function* c_function) { | |
12198 DCHECK(call->arguments()->length() == 2); | |
12199 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
12200 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
12201 HValue* key = Pop(); | |
12202 HValue* receiver = Pop(); | |
12203 | |
12204 NoObservableSideEffectsScope no_effects(this); | |
12205 | |
12206 HIfContinuation continuation; | |
12207 HValue* hash = | |
12208 BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation); | |
12209 { | |
12210 IfBuilder string_checker(this, &continuation); | |
12211 string_checker.Then(); | |
12212 { | |
12213 HValue* table = Add<HLoadNamedField>( | |
12214 receiver, nullptr, HObjectAccess::ForJSCollectionTable()); | |
12215 HValue* key_index = | |
12216 BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash); | |
12217 { | |
12218 IfBuilder if_found(this); | |
12219 if_found.If<HCompareNumericAndBranch>( | |
12220 key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE); | |
12221 if_found.Then(); | |
12222 Push(graph()->GetConstantTrue()); | |
12223 if_found.Else(); | |
12224 Push(graph()->GetConstantFalse()); | |
12225 } | |
12226 } | |
12227 string_checker.Else(); | |
12228 { | |
12229 Add<HPushArguments>(receiver, key); | |
12230 Push(Add<HCallRuntime>(call->name(), c_function, 2)); | |
12231 } | |
12232 } | |
12233 | |
12234 return ast_context()->ReturnValue(Pop()); | |
12235 } | |
12236 | |
12237 | |
12238 void HOptimizedGraphBuilder::GenerateMapHas(CallRuntime* call) { | |
12239 BuildJSCollectionHas<OrderedHashMap>( | |
12240 call, Runtime::FunctionForId(Runtime::kMapHas)); | |
12241 } | |
12242 | |
12243 | |
12244 void HOptimizedGraphBuilder::GenerateSetHas(CallRuntime* call) { | |
12245 BuildJSCollectionHas<OrderedHashSet>( | |
12246 call, Runtime::FunctionForId(Runtime::kSetHas)); | |
12247 } | |
12248 | |
12249 | |
12250 template <typename CollectionType> | |
12251 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableAddEntry( | |
12252 HValue* table, HValue* key, HValue* hash, | |
12253 HIfContinuation* join_continuation) { | |
12254 HValue* num_buckets = Add<HLoadNamedField>( | |
12255 table, nullptr, | |
12256 HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>()); | |
12257 HValue* capacity = AddUncasted<HMul>( | |
12258 num_buckets, Add<HConstant>(CollectionType::kLoadFactor)); | |
12259 capacity->ClearFlag(HValue::kCanOverflow); | |
12260 HValue* num_elements = Add<HLoadNamedField>( | |
12261 table, nullptr, | |
12262 HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>()); | |
12263 HValue* num_deleted = Add<HLoadNamedField>( | |
12264 table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
12265 CollectionType>()); | |
12266 HValue* used = AddUncasted<HAdd>(num_elements, num_deleted); | |
12267 used->ClearFlag(HValue::kCanOverflow); | |
12268 IfBuilder if_space_available(this); | |
12269 if_space_available.If<HCompareNumericAndBranch>(capacity, used, Token::GT); | |
12270 if_space_available.Then(); | |
12271 HValue* bucket = BuildOrderedHashTableHashToBucket(hash, num_buckets); | |
12272 HValue* entry = used; | |
12273 HValue* key_index = | |
12274 BuildOrderedHashTableEntryToIndex<CollectionType>(entry, num_buckets); | |
12275 | |
12276 HValue* bucket_index = AddUncasted<HAdd>( | |
12277 bucket, Add<HConstant>(CollectionType::kHashTableStartIndex)); | |
12278 bucket_index->ClearFlag(HValue::kCanOverflow); | |
12279 HValue* chain_entry = | |
12280 Add<HLoadKeyed>(table, bucket_index, nullptr, FAST_ELEMENTS); | |
12281 chain_entry->set_type(HType::Smi()); | |
12282 | |
12283 HValue* chain_index = AddUncasted<HAdd>( | |
12284 key_index, Add<HConstant>(CollectionType::kChainOffset)); | |
12285 chain_index->ClearFlag(HValue::kCanOverflow); | |
12286 | |
12287 Add<HStoreKeyed>(table, bucket_index, entry, FAST_ELEMENTS); | |
12288 Add<HStoreKeyed>(table, chain_index, chain_entry, FAST_ELEMENTS); | |
12289 Add<HStoreKeyed>(table, key_index, key, FAST_ELEMENTS); | |
12290 | |
12291 HValue* new_num_elements = | |
12292 AddUncasted<HAdd>(num_elements, graph()->GetConstant1()); | |
12293 new_num_elements->ClearFlag(HValue::kCanOverflow); | |
12294 Add<HStoreNamedField>( | |
12295 table, | |
12296 HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(), | |
12297 new_num_elements); | |
12298 if_space_available.JoinContinuation(join_continuation); | |
12299 return key_index; | |
12300 } | |
12301 | |
12302 | |
12303 void HOptimizedGraphBuilder::GenerateMapSet(CallRuntime* call) { | |
12304 DCHECK(call->arguments()->length() == 3); | 12048 DCHECK(call->arguments()->length() == 3); |
12305 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12049 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12306 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 12050 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
12307 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); | 12051 CHECK_ALIVE(VisitForValue(call->arguments()->at(2))); |
12308 HValue* value = Pop(); | 12052 HValue* value = Pop(); |
12309 HValue* key = Pop(); | 12053 HValue* index = Pop(); |
12310 HValue* receiver = Pop(); | 12054 HValue* object = Pop(); |
12311 | |
12312 NoObservableSideEffectsScope no_effects(this); | 12055 NoObservableSideEffectsScope no_effects(this); |
12313 | 12056 Add<HStoreKeyed>(object, index, value, FAST_ELEMENTS); |
Toon Verwaest
2015/03/30 12:55:42
FAST_HOLEY_ELEMENTS?
adamk
2015/03/30 18:44:54
Done.
| |
12314 HIfContinuation return_or_call_runtime_continuation( | 12057 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
12315 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
12316 HIfContinuation got_string_hash; | |
12317 HValue* hash = | |
12318 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
12319 IfBuilder string_checker(this, &got_string_hash); | |
12320 string_checker.Then(); | |
12321 { | |
12322 HValue* table = Add<HLoadNamedField>(receiver, nullptr, | |
12323 HObjectAccess::ForJSCollectionTable()); | |
12324 HValue* key_index = | |
12325 BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash); | |
12326 { | |
12327 IfBuilder if_found(this); | |
12328 if_found.If<HCompareNumericAndBranch>( | |
12329 key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE); | |
12330 if_found.Then(); | |
12331 { | |
12332 HValue* value_index = AddUncasted<HAdd>( | |
12333 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
12334 value_index->ClearFlag(HValue::kCanOverflow); | |
12335 Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS); | |
12336 } | |
12337 if_found.Else(); | |
12338 { | |
12339 HIfContinuation did_add(graph()->CreateBasicBlock(), | |
12340 graph()->CreateBasicBlock()); | |
12341 HValue* key_index = BuildOrderedHashTableAddEntry<OrderedHashMap>( | |
12342 table, key, hash, &did_add); | |
12343 IfBuilder if_did_add(this, &did_add); | |
12344 if_did_add.Then(); | |
12345 { | |
12346 HValue* value_index = AddUncasted<HAdd>( | |
12347 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
12348 value_index->ClearFlag(HValue::kCanOverflow); | |
12349 Add<HStoreKeyed>(table, value_index, value, FAST_ELEMENTS); | |
12350 } | |
12351 if_did_add.JoinContinuation(&return_or_call_runtime_continuation); | |
12352 } | |
12353 } | |
12354 } | |
12355 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
12356 | |
12357 { | |
12358 IfBuilder return_or_call_runtime(this, | |
12359 &return_or_call_runtime_continuation); | |
12360 return_or_call_runtime.Then(); | |
12361 Push(receiver); | |
12362 return_or_call_runtime.Else(); | |
12363 Add<HPushArguments>(receiver, key, value); | |
12364 Push(Add<HCallRuntime>(call->name(), | |
12365 Runtime::FunctionForId(Runtime::kMapSet), 3)); | |
12366 } | |
12367 | |
12368 return ast_context()->ReturnValue(Pop()); | |
12369 } | 12058 } |
12370 | 12059 |
12371 | 12060 |
12372 void HOptimizedGraphBuilder::GenerateSetAdd(CallRuntime* call) { | 12061 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) { |
12373 DCHECK(call->arguments()->length() == 2); | 12062 DCHECK(call->arguments()->length() == 0); |
12374 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12063 return ast_context()->ReturnValue(graph()->GetConstantHole()); |
12375 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
12376 HValue* key = Pop(); | |
12377 HValue* receiver = Pop(); | |
12378 | |
12379 NoObservableSideEffectsScope no_effects(this); | |
12380 | |
12381 HIfContinuation return_or_call_runtime_continuation( | |
12382 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
12383 HIfContinuation got_string_hash; | |
12384 HValue* hash = | |
12385 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
12386 IfBuilder string_checker(this, &got_string_hash); | |
12387 string_checker.Then(); | |
12388 { | |
12389 HValue* table = Add<HLoadNamedField>(receiver, nullptr, | |
12390 HObjectAccess::ForJSCollectionTable()); | |
12391 HValue* key_index = | |
12392 BuildOrderedHashTableFindEntry<OrderedHashSet>(table, key, hash); | |
12393 { | |
12394 IfBuilder if_not_found(this); | |
12395 if_not_found.If<HCompareNumericAndBranch>( | |
12396 key_index, Add<HConstant>(OrderedHashSet::kNotFound), Token::EQ); | |
12397 if_not_found.Then(); | |
12398 BuildOrderedHashTableAddEntry<OrderedHashSet>( | |
12399 table, key, hash, &return_or_call_runtime_continuation); | |
12400 } | |
12401 } | |
12402 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
12403 | |
12404 { | |
12405 IfBuilder return_or_call_runtime(this, | |
12406 &return_or_call_runtime_continuation); | |
12407 return_or_call_runtime.Then(); | |
12408 Push(receiver); | |
12409 return_or_call_runtime.Else(); | |
12410 Add<HPushArguments>(receiver, key); | |
12411 Push(Add<HCallRuntime>(call->name(), | |
12412 Runtime::FunctionForId(Runtime::kSetAdd), 2)); | |
12413 } | |
12414 | |
12415 return ast_context()->ReturnValue(Pop()); | |
12416 } | 12064 } |
12417 | 12065 |
12418 | 12066 |
12419 template <typename CollectionType> | 12067 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) { |
12420 void HOptimizedGraphBuilder::BuildJSCollectionDelete( | |
12421 CallRuntime* call, const Runtime::Function* c_function) { | |
12422 DCHECK(call->arguments()->length() == 2); | |
12423 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
12424 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
12425 HValue* key = Pop(); | |
12426 HValue* receiver = Pop(); | |
12427 | |
12428 NoObservableSideEffectsScope no_effects(this); | |
12429 | |
12430 HIfContinuation return_or_call_runtime_continuation( | |
12431 graph()->CreateBasicBlock(), graph()->CreateBasicBlock()); | |
12432 HIfContinuation got_string_hash; | |
12433 HValue* hash = | |
12434 BuildStringHashLoadIfIsStringAndHashComputed(key, &got_string_hash); | |
12435 IfBuilder string_checker(this, &got_string_hash); | |
12436 string_checker.Then(); | |
12437 { | |
12438 HValue* table = Add<HLoadNamedField>(receiver, nullptr, | |
12439 HObjectAccess::ForJSCollectionTable()); | |
12440 HValue* key_index = | |
12441 BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash); | |
12442 { | |
12443 IfBuilder if_found(this); | |
12444 if_found.If<HCompareNumericAndBranch>( | |
12445 key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE); | |
12446 if_found.Then(); | |
12447 { | |
12448 // If we're removing an element, we might need to shrink. | |
12449 // If we do need to shrink, we'll be bailing out to the runtime. | |
12450 HValue* num_elements = Add<HLoadNamedField>( | |
12451 table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfElements< | |
12452 CollectionType>()); | |
12453 num_elements = AddUncasted<HSub>(num_elements, graph()->GetConstant1()); | |
12454 num_elements->ClearFlag(HValue::kCanOverflow); | |
12455 | |
12456 HValue* num_buckets = Add<HLoadNamedField>( | |
12457 table, nullptr, HObjectAccess::ForOrderedHashTableNumberOfBuckets< | |
12458 CollectionType>()); | |
12459 // threshold is capacity >> 2; we simplify this to num_buckets >> 1 | |
12460 // since kLoadFactor is 2. | |
12461 STATIC_ASSERT(CollectionType::kLoadFactor == 2); | |
12462 HValue* threshold = | |
12463 AddUncasted<HShr>(num_buckets, graph()->GetConstant1()); | |
12464 | |
12465 IfBuilder if_need_not_shrink(this); | |
12466 if_need_not_shrink.If<HCompareNumericAndBranch>(num_elements, threshold, | |
12467 Token::GTE); | |
12468 if_need_not_shrink.Then(); | |
12469 { | |
12470 Add<HStoreKeyed>(table, key_index, graph()->GetConstantHole(), | |
12471 FAST_ELEMENTS); | |
12472 | |
12473 // For maps, also need to clear the value. | |
12474 if (CollectionType::kChainOffset > 1) { | |
12475 HValue* value_index = | |
12476 AddUncasted<HAdd>(key_index, graph()->GetConstant1()); | |
12477 value_index->ClearFlag(HValue::kCanOverflow); | |
12478 Add<HStoreKeyed>(table, value_index, graph()->GetConstantHole(), | |
12479 FAST_ELEMENTS); | |
12480 } | |
12481 STATIC_ASSERT(CollectionType::kChainOffset <= 2); | |
12482 | |
12483 HValue* num_deleted = Add<HLoadNamedField>( | |
12484 table, nullptr, | |
12485 HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
12486 CollectionType>()); | |
12487 num_deleted = AddUncasted<HAdd>(num_deleted, graph()->GetConstant1()); | |
12488 num_deleted->ClearFlag(HValue::kCanOverflow); | |
12489 Add<HStoreNamedField>( | |
12490 table, HObjectAccess::ForOrderedHashTableNumberOfElements< | |
12491 CollectionType>(), | |
12492 num_elements); | |
12493 Add<HStoreNamedField>( | |
12494 table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements< | |
12495 CollectionType>(), | |
12496 num_deleted); | |
12497 Push(graph()->GetConstantTrue()); | |
12498 } | |
12499 if_need_not_shrink.JoinContinuation( | |
12500 &return_or_call_runtime_continuation); | |
12501 } | |
12502 if_found.Else(); | |
12503 { | |
12504 // Not found, so we're done. | |
12505 Push(graph()->GetConstantFalse()); | |
12506 } | |
12507 } | |
12508 } | |
12509 string_checker.JoinContinuation(&return_or_call_runtime_continuation); | |
12510 | |
12511 { | |
12512 IfBuilder return_or_call_runtime(this, | |
12513 &return_or_call_runtime_continuation); | |
12514 return_or_call_runtime.Then(); | |
12515 return_or_call_runtime.Else(); | |
12516 Add<HPushArguments>(receiver, key); | |
12517 Push(Add<HCallRuntime>(call->name(), c_function, 2)); | |
12518 } | |
12519 | |
12520 return ast_context()->ReturnValue(Pop()); | |
12521 } | |
12522 | |
12523 | |
12524 void HOptimizedGraphBuilder::GenerateMapDelete(CallRuntime* call) { | |
12525 BuildJSCollectionDelete<OrderedHashMap>( | |
12526 call, Runtime::FunctionForId(Runtime::kMapDelete)); | |
12527 } | |
12528 | |
12529 | |
12530 void HOptimizedGraphBuilder::GenerateSetDelete(CallRuntime* call) { | |
12531 BuildJSCollectionDelete<OrderedHashSet>( | |
12532 call, Runtime::FunctionForId(Runtime::kSetDelete)); | |
12533 } | |
12534 | |
12535 | |
12536 void HOptimizedGraphBuilder::GenerateSetGetSize(CallRuntime* call) { | |
12537 DCHECK(call->arguments()->length() == 1); | 12068 DCHECK(call->arguments()->length() == 1); |
12538 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12069 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12539 HValue* receiver = Pop(); | 12070 HValue* receiver = Pop(); |
12540 HValue* table = Add<HLoadNamedField>(receiver, nullptr, | |
12541 HObjectAccess::ForJSCollectionTable()); | |
12542 HInstruction* result = New<HLoadNamedField>( | 12071 HInstruction* result = New<HLoadNamedField>( |
12543 table, nullptr, | 12072 receiver, nullptr, HObjectAccess::ForJSCollectionTable()); |
12544 HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashSet>()); | |
12545 return ast_context()->ReturnInstruction(result, call->id()); | 12073 return ast_context()->ReturnInstruction(result, call->id()); |
12546 } | 12074 } |
12547 | 12075 |
12548 | 12076 |
12549 void HOptimizedGraphBuilder::GenerateMapGetSize(CallRuntime* call) { | 12077 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) { |
12550 DCHECK(call->arguments()->length() == 1); | 12078 DCHECK(call->arguments()->length() == 1); |
12551 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12079 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12552 HValue* receiver = Pop(); | 12080 HValue* object = Pop(); |
12553 HValue* table = Add<HLoadNamedField>(receiver, nullptr, | |
12554 HObjectAccess::ForJSCollectionTable()); | |
12555 HInstruction* result = New<HLoadNamedField>( | 12081 HInstruction* result = New<HLoadNamedField>( |
12556 table, nullptr, | 12082 object, nullptr, HObjectAccess::ForStringHashField()); |
12557 HObjectAccess::ForOrderedHashTableNumberOfElements<OrderedHashMap>()); | |
12558 return ast_context()->ReturnInstruction(result, call->id()); | 12083 return ast_context()->ReturnInstruction(result, call->id()); |
12559 } | 12084 } |
12560 | 12085 |
12561 | 12086 |
12562 template <typename CollectionType> | 12087 template <typename CollectionType> |
12563 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() { | 12088 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() { |
12564 static const int kCapacity = CollectionType::kMinCapacity; | 12089 static const int kCapacity = CollectionType::kMinCapacity; |
12565 static const int kBucketCount = kCapacity / CollectionType::kLoadFactor; | 12090 static const int kBucketCount = kCapacity / CollectionType::kLoadFactor; |
12566 static const int kFixedArrayLength = CollectionType::kHashTableStartIndex + | 12091 static const int kFixedArrayLength = CollectionType::kHashTableStartIndex + |
12567 kBucketCount + | 12092 kBucketCount + |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13390 if (ShouldProduceTraceOutput()) { | 12915 if (ShouldProduceTraceOutput()) { |
13391 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12916 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13392 } | 12917 } |
13393 | 12918 |
13394 #ifdef DEBUG | 12919 #ifdef DEBUG |
13395 graph_->Verify(false); // No full verify. | 12920 graph_->Verify(false); // No full verify. |
13396 #endif | 12921 #endif |
13397 } | 12922 } |
13398 | 12923 |
13399 } } // namespace v8::internal | 12924 } } // namespace v8::internal |
OLD | NEW |