Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: src/hydrogen.cc

Issue 757143002: Optimize non-mutation Map and Set operations for String keys (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add lots more stuff Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698