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 |