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