Chromium Code Reviews| 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 12086 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12097 | 12097 |
| 12098 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { | 12098 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) { |
| 12099 DCHECK(call->arguments()->length() == 1); | 12099 DCHECK(call->arguments()->length() == 1); |
| 12100 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12100 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12101 HValue* value = Pop(); | 12101 HValue* value = Pop(); |
| 12102 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); | 12102 HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt); |
| 12103 return ast_context()->ReturnInstruction(result, call->id()); | 12103 return ast_context()->ReturnInstruction(result, call->id()); |
| 12104 } | 12104 } |
| 12105 | 12105 |
| 12106 | 12106 |
| 12107 template <typename CollectionType> | |
| 12108 HValue* HOptimizedGraphBuilder::BuildOrderedHashTableFindEntry(HValue* table, | |
| 12109 HValue* key, | |
| 12110 HValue* hash) { | |
| 12111 HValue* num_buckets = Add<HLoadKeyed>( | |
| 12112 table, Add<HConstant>(CollectionType::kNumberOfBucketsIndex), | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Why LoadKeyed here? Since the offset is constant,
adamk
2014/12/02 21:00:38
Done.
In my defense, I was following the code in
| |
| 12113 static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 12114 num_buckets->set_type(HType::Smi()); | |
| 12115 | |
| 12116 // Some things that won't change inside the loop | |
| 12117 HValue* not_found = Add<HConstant>(CollectionType::kNotFound); | |
| 12118 HValue* start_index = Add<HConstant>(CollectionType::kHashTableStartIndex); | |
| 12119 HValue* entry_size = Add<HConstant>(CollectionType::kEntrySize); | |
| 12120 HValue* chain_offset = Add<HConstant>(CollectionType::kChainOffset); | |
| 12121 HValue* key_start = AddUncasted<HAdd>(start_index, num_buckets); | |
| 12122 key_start->ClearFlag(HValue::kCanOverflow); | |
| 12123 | |
| 12124 // BuildHashToBucket | |
| 12125 HValue* mask = AddUncasted<HSub>(num_buckets, graph()->GetConstant1()); | |
| 12126 mask->ChangeRepresentation(Representation::Integer32()); | |
| 12127 mask->ClearFlag(HValue::kCanOverflow); | |
| 12128 | |
| 12129 HValue* bucket = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask); | |
| 12130 | |
| 12131 // BuildHashToEntry | |
| 12132 HValue* entry_index = AddUncasted<HAdd>(start_index, bucket); | |
| 12133 entry_index->ClearFlag(HValue::kCanOverflow); | |
| 12134 HValue* entry = | |
| 12135 Add<HLoadKeyed>(table, entry_index, static_cast<HValue*>(NULL), | |
| 12136 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
| 12137 entry->set_type(HType::Smi()); | |
| 12138 | |
| 12139 Push(entry); | |
| 12140 | |
| 12141 // LOOP | |
| 12142 LoopBuilder loop(this); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Nit: use RAII for Loop/IfBuilders
adamk
2014/12/02 21:00:38
Can you explain what you mean here? Do you mean yo
Dmitry Lomov (no reviews)
2014/12/02 21:26:27
Yes; sorry for being unclear; the pattern is:
{ If
adamk
2014/12/02 21:37:57
That works on IfBuilders, but LoopBuilder just has
| |
| 12143 loop.BeginBody(1); | |
| 12144 | |
| 12145 entry = Pop(); | |
| 12146 | |
| 12147 IfBuilder if_not_found(this); | |
| 12148 if_not_found.If<HCompareNumericAndBranch>(entry, not_found, Token::EQ); | |
| 12149 if_not_found.Then(); | |
| 12150 Push(entry); | |
| 12151 loop.Break(); | |
| 12152 if_not_found.End(); | |
| 12153 | |
| 12154 // BuildEntryToIndex | |
| 12155 HValue* key_index = AddUncasted<HMul>(entry, entry_size); | |
| 12156 key_index->ClearFlag(HValue::kCanOverflow); | |
| 12157 key_index = AddUncasted<HAdd>(key_index, key_start); | |
| 12158 key_index->ClearFlag(HValue::kCanOverflow); | |
| 12159 // BuildKeyAt | |
| 12160 HValue* candidate_key = | |
| 12161 Add<HLoadKeyed>(table, key_index, static_cast<HValue*>(NULL), | |
| 12162 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
| 12163 | |
| 12164 IfBuilder if_keys_equal(this); | |
| 12165 if_keys_equal.If<HIsStringAndBranch>(candidate_key); | |
| 12166 if_keys_equal.AndIf<HStringCompareAndBranch>(candidate_key, key, | |
| 12167 Token::EQ_STRICT); | |
| 12168 if_keys_equal.Then(); | |
| 12169 Push(key_index); | |
| 12170 loop.Break(); | |
| 12171 if_keys_equal.End(); | |
| 12172 | |
| 12173 // BuildChainAt | |
| 12174 HValue* chain_index = AddUncasted<HMul>(entry, entry_size); | |
| 12175 chain_index->ClearFlag(HValue::kCanOverflow); | |
| 12176 chain_index = AddUncasted<HAdd>(chain_index, key_start); | |
| 12177 chain_index->ClearFlag(HValue::kCanOverflow); | |
| 12178 chain_index = AddUncasted<HAdd>(chain_index, chain_offset); | |
| 12179 chain_index->ClearFlag(HValue::kCanOverflow); | |
| 12180 entry = Add<HLoadKeyed>(table, chain_index, static_cast<HValue*>(NULL), | |
| 12181 FAST_ELEMENTS, ALLOW_RETURN_HOLE); | |
| 12182 entry->set_type(HType::Smi()); | |
| 12183 Push(entry); | |
| 12184 | |
| 12185 loop.EndBody(); | |
| 12186 | |
| 12187 return Pop(); | |
| 12188 } | |
| 12189 | |
| 12190 | |
| 12191 void HOptimizedGraphBuilder::GenerateMapGet(CallRuntime* call) { | |
| 12192 DCHECK(call->arguments()->length() == 2); | |
| 12193 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12194 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
| 12195 HValue* key = Pop(); | |
| 12196 HValue* receiver = Pop(); | |
| 12197 | |
| 12198 NoObservableSideEffectsScope no_effects(this); | |
| 12199 | |
| 12200 HIfContinuation continuation; | |
| 12201 HValue* hash = | |
| 12202 BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation); | |
| 12203 IfBuilder string_checker(this, &continuation); | |
| 12204 string_checker.Then(); | |
| 12205 { | |
| 12206 HValue* table = Add<HLoadNamedField>( | |
| 12207 receiver, static_cast<HValue*>(NULL), | |
| 12208 HObjectAccess::ForObservableJSObjectOffset(JSCollection::kTableOffset)); | |
| 12209 HValue* key_index = | |
| 12210 BuildOrderedHashTableFindEntry<OrderedHashMap>(table, key, hash); | |
| 12211 IfBuilder if_found(this); | |
| 12212 if_found.If<HCompareNumericAndBranch>( | |
| 12213 key_index, Add<HConstant>(OrderedHashMap::kNotFound), Token::NE); | |
| 12214 if_found.Then(); | |
| 12215 { | |
| 12216 HValue* value_index = AddUncasted<HAdd>( | |
| 12217 key_index, Add<HConstant>(OrderedHashMap::kValueOffset)); | |
| 12218 value_index->ClearFlag(HValue::kCanOverflow); | |
| 12219 Push(Add<HLoadKeyed>(table, value_index, static_cast<HValue*>(NULL), | |
| 12220 FAST_ELEMENTS)); | |
| 12221 } | |
| 12222 if_found.Else(); | |
| 12223 Push(graph()->GetConstantUndefined()); | |
| 12224 if_found.End(); | |
| 12225 } | |
| 12226 string_checker.Else(); | |
| 12227 { | |
| 12228 Add<HPushArguments>(receiver, key); | |
| 12229 Push(Add<HCallRuntime>(isolate()->factory()->empty_string(), | |
| 12230 Runtime::FunctionForId(Runtime::kMapGet), 2)); | |
| 12231 } | |
| 12232 string_checker.End(); | |
| 12233 | |
| 12234 return ast_context()->ReturnValue(Pop()); | |
| 12235 } | |
| 12236 | |
| 12237 | |
| 12238 HValue* HOptimizedGraphBuilder::BuildStringHashLoadIfIsStringAndHashComputed( | |
| 12239 HValue* object, HIfContinuation* continuation) { | |
| 12240 IfBuilder string_checker(this); | |
| 12241 string_checker.If<HIsStringAndBranch>(object); | |
| 12242 string_checker.And(); | |
| 12243 HValue* hash = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL), | |
| 12244 HObjectAccess::ForStringHashField()); | |
| 12245 HValue* hash_not_computed_mask = Add<HConstant>(String::kHashNotComputedMask); | |
| 12246 HValue* hash_computed_test = | |
| 12247 AddUncasted<HBitwise>(Token::BIT_AND, hash, hash_not_computed_mask); | |
| 12248 string_checker.If<HCompareNumericAndBranch>( | |
| 12249 hash_computed_test, graph()->GetConstant0(), Token::EQ); | |
| 12250 string_checker.Then(); | |
| 12251 HValue* shifted_hash = | |
| 12252 AddUncasted<HShr>(hash, Add<HConstant>(String::kHashShift)); | |
| 12253 string_checker.CaptureContinuation(continuation); | |
| 12254 return shifted_hash; | |
| 12255 } | |
| 12256 | |
| 12257 | |
| 12258 template <typename CollectionType> | |
| 12259 void HOptimizedGraphBuilder::BuildJSCollectionHas( | |
| 12260 CallRuntime* call, const Runtime::Function* c_function) { | |
| 12261 DCHECK(call->arguments()->length() == 2); | |
| 12262 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12263 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | |
| 12264 HValue* key = Pop(); | |
| 12265 HValue* receiver = Pop(); | |
| 12266 | |
| 12267 NoObservableSideEffectsScope no_effects(this); | |
| 12268 | |
| 12269 HIfContinuation continuation; | |
| 12270 HValue* hash = | |
| 12271 BuildStringHashLoadIfIsStringAndHashComputed(key, &continuation); | |
| 12272 IfBuilder string_checker(this, &continuation); | |
| 12273 string_checker.Then(); | |
| 12274 { | |
| 12275 HValue* table = Add<HLoadNamedField>( | |
| 12276 receiver, static_cast<HValue*>(NULL), | |
| 12277 HObjectAccess::ForObservableJSObjectOffset(JSCollection::kTableOffset)); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Nit: Add HObjectAccess::ForJSCollectionTable()
adamk
2014/12/02 21:00:38
Done.
| |
| 12278 HValue* key_index = | |
| 12279 BuildOrderedHashTableFindEntry<CollectionType>(table, key, hash); | |
| 12280 IfBuilder if_found(this); | |
| 12281 if_found.If<HCompareNumericAndBranch>( | |
| 12282 key_index, Add<HConstant>(CollectionType::kNotFound), Token::NE); | |
| 12283 if_found.Then(); | |
| 12284 Push(graph()->GetConstantTrue()); | |
| 12285 if_found.Else(); | |
| 12286 Push(graph()->GetConstantFalse()); | |
| 12287 if_found.End(); | |
| 12288 } | |
| 12289 string_checker.Else(); | |
| 12290 { | |
| 12291 Add<HPushArguments>(receiver, key); | |
| 12292 Push( | |
| 12293 Add<HCallRuntime>(isolate()->factory()->empty_string(), c_function, 2)); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
nit: Please pass a name here.
I wonder why everyon
adamk
2014/12/02 21:00:39
Done.
| |
| 12294 } | |
| 12295 string_checker.End(); | |
| 12296 | |
| 12297 return ast_context()->ReturnValue(Pop()); | |
| 12298 } | |
| 12299 | |
| 12300 | |
| 12301 void HOptimizedGraphBuilder::GenerateMapHas(CallRuntime* call) { | |
| 12302 BuildJSCollectionHas<OrderedHashMap>( | |
| 12303 call, Runtime::FunctionForId(Runtime::kMapHas)); | |
| 12304 } | |
| 12305 | |
| 12306 | |
| 12307 void HOptimizedGraphBuilder::GenerateSetHas(CallRuntime* call) { | |
| 12308 BuildJSCollectionHas<OrderedHashSet>( | |
| 12309 call, Runtime::FunctionForId(Runtime::kSetHas)); | |
| 12310 } | |
| 12311 | |
| 12312 | |
| 12313 void HOptimizedGraphBuilder::GenerateSetGetSize(CallRuntime* call) { | |
| 12314 DCHECK(call->arguments()->length() == 1); | |
| 12315 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12316 HValue* receiver = Pop(); | |
| 12317 HValue* table = Add<HLoadNamedField>( | |
| 12318 receiver, static_cast<HValue*>(NULL), | |
| 12319 HObjectAccess::ForObservableJSObjectOffset(JSSet::kTableOffset)); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Nit: Add HObjectAccess::ForJSCollectionTable()
adamk
2014/12/02 21:00:38
Done.
| |
| 12320 HInstruction* result = New<HLoadKeyed>( | |
| 12321 table, Add<HConstant>(OrderedHashSet::kNumberOfElementsIndex), | |
| 12322 static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
| 12323 return ast_context()->ReturnInstruction(result, call->id()); | |
| 12324 } | |
| 12325 | |
| 12326 | |
| 12327 void HOptimizedGraphBuilder::GenerateMapGetSize(CallRuntime* call) { | |
| 12328 DCHECK(call->arguments()->length() == 1); | |
| 12329 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | |
| 12330 HValue* receiver = Pop(); | |
| 12331 HValue* table = Add<HLoadNamedField>( | |
| 12332 receiver, static_cast<HValue*>(NULL), | |
| 12333 HObjectAccess::ForObservableJSObjectOffset(JSMap::kTableOffset)); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Nit: Add HObjectAccess::ForJSCollectionTable()
adamk
2014/12/02 21:00:38
Done.
| |
| 12334 HInstruction* result = New<HLoadKeyed>( | |
| 12335 table, Add<HConstant>(OrderedHashMap::kNumberOfElementsIndex), | |
| 12336 static_cast<HValue*>(NULL), FAST_ELEMENTS); | |
|
Dmitry Lomov (no reviews)
2014/11/27 18:18:26
Why LoadKeyed here? Since the offset is constant,
adamk
2014/12/02 21:00:37
Done.
| |
| 12337 return ast_context()->ReturnInstruction(result, call->id()); | |
| 12338 } | |
| 12339 | |
| 12340 | |
| 12107 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 12341 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| 12108 DCHECK(call->arguments()->length() == 1); | 12342 DCHECK(call->arguments()->length() == 1); |
| 12109 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12343 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12110 HValue* value = Pop(); | 12344 HValue* value = Pop(); |
| 12111 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); | 12345 HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value); |
| 12112 return ast_context()->ReturnInstruction(result, call->id()); | 12346 return ast_context()->ReturnInstruction(result, call->id()); |
| 12113 } | 12347 } |
| 12114 | 12348 |
| 12115 | 12349 |
| 12116 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) { | 12350 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) { |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12776 if (ShouldProduceTraceOutput()) { | 13010 if (ShouldProduceTraceOutput()) { |
| 12777 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13011 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12778 } | 13012 } |
| 12779 | 13013 |
| 12780 #ifdef DEBUG | 13014 #ifdef DEBUG |
| 12781 graph_->Verify(false); // No full verify. | 13015 graph_->Verify(false); // No full verify. |
| 12782 #endif | 13016 #endif |
| 12783 } | 13017 } |
| 12784 | 13018 |
| 12785 } } // namespace v8::internal | 13019 } } // namespace v8::internal |
| OLD | NEW |