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

Side by Side Diff: src/hydrogen.cc

Issue 16948005: Refactor turning polymorphic loads into monomorphic loads (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Also in compound assignment Created 7 years, 6 months 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 6298 matching lines...) Expand 10 before | Expand all | Expand 10 after
6309 if (ComputeLoadStoreField(map, name, &lookup, true)) { 6309 if (ComputeLoadStoreField(map, name, &lookup, true)) {
6310 AddCheckMapsWithTransitions(object, map); 6310 AddCheckMapsWithTransitions(object, map);
6311 return BuildStoreNamedField(object, name, value, map, &lookup); 6311 return BuildStoreNamedField(object, name, value, map, &lookup);
6312 } 6312 }
6313 6313
6314 // No luck, do a generic store. 6314 // No luck, do a generic store.
6315 return BuildStoreNamedGeneric(object, name, value); 6315 return BuildStoreNamedGeneric(object, name, value);
6316 } 6316 }
6317 6317
6318 6318
6319 bool HOptimizedGraphBuilder::HandlePolymorphicArrayLengthLoad( 6319 HInstruction* HOptimizedGraphBuilder::LoadPolymorphicAsMonomorphic(
Hannes Payer (out of office) 2013/06/13 15:26:36 Would it make more sense to name this method TryLo
Toon Verwaest 2013/06/13 16:33:58 Done.
6320 Property* expr, 6320 Property* expr,
6321 HValue* object, 6321 HValue* object,
6322 SmallMapList* types, 6322 SmallMapList* types,
6323 Handle<String> name) { 6323 Handle<String> name) {
6324 if (!name->Equals(isolate()->heap()->length_string())) return false;
6325
6326 for (int i = 0; i < types->length(); i++) {
6327 if (types->at(i)->instance_type() != JS_ARRAY_TYPE) return false;
6328 }
6329
6330 BuildCheckNonSmi(object);
6331
6332 HInstruction* typecheck =
6333 AddInstruction(HCheckMaps::New(object, types, zone()));
6334 HInstruction* instr = new(zone())
6335 HLoadNamedField(object, HObjectAccess::ForArrayLength(), typecheck);
6336
6337 instr->set_position(expr->position());
6338 ast_context()->ReturnInstruction(instr, expr->id());
6339 return true;
6340 }
6341
6342
6343 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
6344 HValue* object,
6345 SmallMapList* types,
6346 Handle<String> name) {
6347
6348 if (HandlePolymorphicArrayLengthLoad(expr, object, types, name))
6349 return;
6350
6351 BuildCheckNonSmi(object);
6352
6353 // Use monomorphic load if property lookup results in the same field index 6324 // Use monomorphic load if property lookup results in the same field index
6354 // for all maps. Requires special map check on the set of all handled maps. 6325 // for all maps. Requires special map check on the set of all handled maps.
6355 HInstruction* instr = NULL;
6356 LookupResult lookup(isolate()); 6326 LookupResult lookup(isolate());
6357 int count; 6327 int count;
6358 Representation representation = Representation::None(); 6328 Representation representation = Representation::None();
6359 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused. 6329 HObjectAccess access = HObjectAccess::ForMap(); // initial value unused.
6360 for (count = 0; 6330 for (count = 0;
6361 count < types->length() && count < kMaxLoadPolymorphism; 6331 count < types->length() && count < kMaxLoadPolymorphism;
6362 ++count) { 6332 ++count) {
6363 Handle<Map> map = types->at(count); 6333 Handle<Map> map = types->at(count);
6364 if (!ComputeLoadStoreField(map, name, &lookup, false)) break; 6334 if (!ComputeLoadStoreField(map, name, &lookup, false)) break;
6365 6335
(...skipping 10 matching lines...) Expand all
6376 break; 6346 break;
6377 } else if (access.offset() != new_access.offset()) { 6347 } else if (access.offset() != new_access.offset()) {
6378 // Offsets did not match. 6348 // Offsets did not match.
6379 break; 6349 break;
6380 } else if (access.IsInobject() != new_access.IsInobject()) { 6350 } else if (access.IsInobject() != new_access.IsInobject()) {
6381 // In-objectness did not match. 6351 // In-objectness did not match.
6382 break; 6352 break;
6383 } 6353 }
6384 } 6354 }
6385 6355
6386 if (count == types->length()) { 6356 if (count != types->length()) return NULL;
6387 // Everything matched; can use monomorphic load. 6357
6388 AddInstruction(HCheckMaps::New(object, types, zone())); 6358 // Everything matched; can use monomorphic load.
6389 instr = BuildLoadNamedField(object, access, representation); 6359 BuildCheckNonSmi(object);
6390 } else { 6360 AddInstruction(HCheckMaps::New(object, types, zone()));
6361 return BuildLoadNamedField(object, access, representation);
6362 }
6363
6364
6365 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
Hannes Payer (out of office) 2013/06/13 15:26:36 Can you move "Property* expr" to the next line?
Toon Verwaest 2013/06/13 16:33:58 Done.
6366 HValue* object,
6367 SmallMapList* types,
6368 Handle<String> name) {
6369
Hannes Payer (out of office) 2013/06/13 15:26:36 remove this newline
Toon Verwaest 2013/06/13 16:33:58 Done.
6370 HInstruction* instr = LoadPolymorphicAsMonomorphic(expr, object, types, name);
6371 if (instr == NULL) {
6391 // Something did not match; must use a polymorphic load. 6372 // Something did not match; must use a polymorphic load.
6373 BuildCheckNonSmi(object);
6392 HValue* context = environment()->LookupContext(); 6374 HValue* context = environment()->LookupContext();
6393 instr = new(zone()) HLoadNamedFieldPolymorphic( 6375 instr = new(zone()) HLoadNamedFieldPolymorphic(
6394 context, object, types, name, zone()); 6376 context, object, types, name, zone());
6395 } 6377 }
6396 6378
6397 instr->set_position(expr->position()); 6379 instr->set_position(expr->position());
6398 return ast_context()->ReturnInstruction(instr, expr->id()); 6380 return ast_context()->ReturnInstruction(instr, expr->id());
6399 } 6381 }
6400 6382
6401 6383
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
6676 return ast_context()->ReturnValue(Pop()); 6658 return ast_context()->ReturnValue(Pop());
6677 6659
6678 } else if (prop != NULL) { 6660 } else if (prop != NULL) {
6679 if (prop->key()->IsPropertyName()) { 6661 if (prop->key()->IsPropertyName()) {
6680 // Named property. 6662 // Named property.
6681 CHECK_ALIVE(VisitForValue(prop->obj())); 6663 CHECK_ALIVE(VisitForValue(prop->obj()));
6682 HValue* object = Top(); 6664 HValue* object = Top();
6683 6665
6684 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 6666 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
6685 Handle<Map> map; 6667 Handle<Map> map;
6686 HInstruction* load; 6668 HInstruction* load = NULL;
6669 SmallMapList* types = prop->GetReceiverTypes();
6687 bool monomorphic = prop->IsMonomorphic(); 6670 bool monomorphic = prop->IsMonomorphic();
6688 if (monomorphic) { 6671 if (monomorphic) {
6689 map = prop->GetReceiverTypes()->first(); 6672 map = types->first();
6690 // We can't generate code for a monomorphic dict mode load so 6673 // We can't generate code for a monomorphic dict mode load so
6691 // just pretend it is not monomorphic. 6674 // just pretend it is not monomorphic.
6692 if (map->is_dictionary_map()) monomorphic = false; 6675 if (map->is_dictionary_map()) monomorphic = false;
6693 } 6676 }
6694 if (monomorphic) { 6677 if (monomorphic) {
Hannes Payer (out of office) 2013/06/13 15:26:36 can you restructure the code monomorphic = fals
Toon Verwaest 2013/06/13 16:33:58 It kinda minimizes the number of branches. We shou
6695 Handle<JSFunction> getter; 6678 Handle<JSFunction> getter;
6696 Handle<JSObject> holder; 6679 Handle<JSObject> holder;
6697 if (LookupGetter(map, name, &getter, &holder)) { 6680 if (LookupGetter(map, name, &getter, &holder)) {
6698 load = BuildCallGetter(object, map, getter, holder); 6681 load = BuildCallGetter(object, map, getter, holder);
6699 } else { 6682 } else {
6700 load = BuildLoadNamedMonomorphic(object, name, prop, map); 6683 load = BuildLoadNamedMonomorphic(object, name, prop, map);
6701 } 6684 }
6702 } else { 6685 } else if (types != NULL && types->length() > 1) {
6703 load = BuildLoadNamedGeneric(object, name, prop); 6686 load = LoadPolymorphicAsMonomorphic(prop, object, types, name);
6704 } 6687 }
6688 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
6705 PushAndAdd(load); 6689 PushAndAdd(load);
6706 if (load->HasObservableSideEffects()) { 6690 if (load->HasObservableSideEffects()) {
6707 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); 6691 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
6708 } 6692 }
6709 6693
6710 CHECK_ALIVE(VisitForValue(expr->value())); 6694 CHECK_ALIVE(VisitForValue(expr->value()));
6711 HValue* right = Pop(); 6695 HValue* right = Pop();
6712 HValue* left = Pop(); 6696 HValue* left = Pop();
6713 6697
6714 HInstruction* instr = BuildBinaryOperation(operation, left, right); 6698 HInstruction* instr = BuildBinaryOperation(operation, left, right);
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
6960 return field; 6944 return field;
6961 } 6945 }
6962 6946
6963 6947
6964 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 6948 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
6965 HValue* object, 6949 HValue* object,
6966 Handle<String> name, 6950 Handle<String> name,
6967 Property* expr) { 6951 Property* expr) {
6968 if (expr->IsUninitialized()) { 6952 if (expr->IsUninitialized()) {
6969 AddSoftDeoptimize(); 6953 AddSoftDeoptimize();
6954 } else {
6955 // OS::DebugBreak();
Hannes Payer (out of office) 2013/06/13 15:26:36 I guess you do not need that anymore.
Toon Verwaest 2013/06/13 16:33:58 Done.
6970 } 6956 }
6971 HValue* context = environment()->LookupContext(); 6957 HValue* context = environment()->LookupContext();
6972 return new(zone()) HLoadNamedGeneric(context, object, name); 6958 return new(zone()) HLoadNamedGeneric(context, object, name);
6973 } 6959 }
6974 6960
6975 6961
6976 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 6962 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
6977 HValue* object, 6963 HValue* object,
6978 Handle<Map> map, 6964 Handle<Map> map,
6979 Handle<JSFunction> getter, 6965 Handle<JSFunction> getter,
(...skipping 2278 matching lines...) Expand 10 before | Expand all | Expand 10 after
9258 9244
9259 if (prop->key()->IsPropertyName()) { 9245 if (prop->key()->IsPropertyName()) {
9260 // Named property. 9246 // Named property.
9261 if (returns_original_input) Push(graph()->GetConstantUndefined()); 9247 if (returns_original_input) Push(graph()->GetConstantUndefined());
9262 9248
9263 CHECK_ALIVE(VisitForValue(prop->obj())); 9249 CHECK_ALIVE(VisitForValue(prop->obj()));
9264 HValue* object = Top(); 9250 HValue* object = Top();
9265 9251
9266 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 9252 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
9267 Handle<Map> map; 9253 Handle<Map> map;
9268 HInstruction* load; 9254 HInstruction* load = NULL;
9269 bool monomorphic = prop->IsMonomorphic(); 9255 bool monomorphic = prop->IsMonomorphic();
9256 SmallMapList* types = prop->GetReceiverTypes();
9270 if (monomorphic) { 9257 if (monomorphic) {
9271 map = prop->GetReceiverTypes()->first(); 9258 map = types->first();
9272 if (map->is_dictionary_map()) monomorphic = false; 9259 if (map->is_dictionary_map()) monomorphic = false;
9273 } 9260 }
9274 if (monomorphic) { 9261 if (monomorphic) {
Hannes Payer (out of office) 2013/06/13 15:26:36 can you restructure the code monomorphic = fals
Toon Verwaest 2013/06/13 16:33:58 Same thing here On 2013/06/13 15:26:36, Hannes Pa
9275 Handle<JSFunction> getter; 9262 Handle<JSFunction> getter;
9276 Handle<JSObject> holder; 9263 Handle<JSObject> holder;
9277 if (LookupGetter(map, name, &getter, &holder)) { 9264 if (LookupGetter(map, name, &getter, &holder)) {
9278 load = BuildCallGetter(object, map, getter, holder); 9265 load = BuildCallGetter(object, map, getter, holder);
9279 } else { 9266 } else {
9280 load = BuildLoadNamedMonomorphic(object, name, prop, map); 9267 load = BuildLoadNamedMonomorphic(object, name, prop, map);
9281 } 9268 }
9282 } else { 9269 } else if (types != NULL && types->length() > 1) {
9283 load = BuildLoadNamedGeneric(object, name, prop); 9270 load = LoadPolymorphicAsMonomorphic(prop, object, types, name);
9284 } 9271 }
9272 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop);
Hannes Payer (out of office) 2013/06/13 15:26:36 This sequence of code is exactly the same as in li
Toon Verwaest 2013/06/13 16:33:58 True, but lets do that in a different CL. On 2013
9285 PushAndAdd(load); 9273 PushAndAdd(load);
9286 if (load->HasObservableSideEffects()) { 9274 if (load->HasObservableSideEffects()) {
9287 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); 9275 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
9288 } 9276 }
9289 9277
9290 after = BuildIncrement(returns_original_input, expr); 9278 after = BuildIncrement(returns_original_input, expr);
9291 input = Pop(); 9279 input = Pop();
9292 9280
9293 HInstruction* store; 9281 HInstruction* store;
9294 if (!monomorphic || map->is_observed()) { 9282 if (!monomorphic || map->is_observed()) {
(...skipping 2319 matching lines...) Expand 10 before | Expand all | Expand 10 after
11614 } 11602 }
11615 } 11603 }
11616 11604
11617 #ifdef DEBUG 11605 #ifdef DEBUG
11618 if (graph_ != NULL) graph_->Verify(false); // No full verify. 11606 if (graph_ != NULL) graph_->Verify(false); // No full verify.
11619 if (allocator_ != NULL) allocator_->Verify(); 11607 if (allocator_ != NULL) allocator_->Verify();
11620 #endif 11608 #endif
11621 } 11609 }
11622 11610
11623 } } // namespace v8::internal 11611 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698