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

Side by Side Diff: src/hydrogen.cc

Issue 18918002: Turn polymorphic calls using the same prototype monomorphic. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 5 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 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 4923 matching lines...) Expand 10 before | Expand all | Expand 10 after
4934 if (ComputeLoadStoreField(map, name, &lookup, true)) { 4934 if (ComputeLoadStoreField(map, name, &lookup, true)) {
4935 AddCheckMapsWithTransitions(object, map); 4935 AddCheckMapsWithTransitions(object, map);
4936 return BuildStoreNamedField(object, name, value, map, &lookup); 4936 return BuildStoreNamedField(object, name, value, map, &lookup);
4937 } 4937 }
4938 4938
4939 // No luck, do a generic store. 4939 // No luck, do a generic store.
4940 return BuildStoreNamedGeneric(object, name, value); 4940 return BuildStoreNamedGeneric(object, name, value);
4941 } 4941 }
4942 4942
4943 4943
4944 static bool CanLoadPropertyFromPrototype(Handle<Map> map,
4945 Handle<Name> name,
4946 LookupResult* lookup) {
4947 if (map->has_named_interceptor()) return false;
4948 if (map->is_dictionary_map()) return false;
4949 map->LookupDescriptor(NULL, *name, lookup);
4950 if (lookup->IsFound()) return false;
4951 return true;
4952 }
4953
4954
4944 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( 4955 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic(
4945 Property* expr, 4956 Property* expr,
4946 HValue* object, 4957 HValue* object,
4947 SmallMapList* types, 4958 SmallMapList* types,
4948 Handle<String> name) { 4959 Handle<String> name) {
4949 // Use monomorphic load if property lookup results in the same field index 4960 // Use monomorphic load if property lookup results in the same field index
4950 // for all maps. Requires special map check on the set of all handled maps. 4961 // for all maps. Requires special map check on the set of all handled maps.
4951 if (types->length() > kMaxLoadPolymorphism) return NULL; 4962 if (types->length() > kMaxLoadPolymorphism) return NULL;
4952 4963
4953 LookupResult lookup(isolate()); 4964 LookupResult lookup(isolate());
(...skipping 29 matching lines...) Expand all
4983 BuildCheckHeapObject(object); 4994 BuildCheckHeapObject(object);
4984 AddInstruction(HCheckMaps::New(object, types, zone())); 4995 AddInstruction(HCheckMaps::New(object, types, zone()));
4985 return BuildLoadNamedField(object, access, representation); 4996 return BuildLoadNamedField(object, access, representation);
4986 } 4997 }
4987 4998
4988 if (count != 0) return NULL; 4999 if (count != 0) return NULL;
4989 5000
4990 // Second chance: the property is on the prototype and all maps have the 5001 // Second chance: the property is on the prototype and all maps have the
4991 // same prototype. 5002 // same prototype.
4992 Handle<Map> map(types->at(0)); 5003 Handle<Map> map(types->at(0));
4993 if (map->has_named_interceptor()) return NULL; 5004 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return NULL;
4994 if (map->is_dictionary_map()) return NULL;
4995 5005
4996 Handle<Object> prototype(map->prototype(), isolate()); 5006 Handle<Object> prototype(map->prototype(), isolate());
4997 for (count = 1; count < types->length(); ++count) { 5007 for (count = 1; count < types->length(); ++count) {
4998 Handle<Map> test_map(types->at(count)); 5008 Handle<Map> test_map(types->at(count));
4999 // Ensure the property is on the prototype, not the object itself. 5009 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return NULL;
5000 if (map->has_named_interceptor()) return NULL;
5001 if (test_map->is_dictionary_map()) return NULL;
5002 test_map->LookupDescriptor(NULL, *name, &lookup);
5003 if (lookup.IsFound()) return NULL;
5004 if (test_map->prototype() != *prototype) return NULL; 5010 if (test_map->prototype() != *prototype) return NULL;
5005 } 5011 }
5006 5012
5007 LookupInPrototypes(map, name, &lookup); 5013 LookupInPrototypes(map, name, &lookup);
5008 if (!lookup.IsField()) return NULL; 5014 if (!lookup.IsField()) return NULL;
5009 5015
5010 BuildCheckHeapObject(object); 5016 BuildCheckHeapObject(object);
5011 AddInstruction(HCheckMaps::New(object, types, zone())); 5017 AddInstruction(HCheckMaps::New(object, types, zone()));
5012 Handle<JSObject> holder(lookup.holder()); 5018 Handle<JSObject> holder(lookup.holder());
5013 Handle<Map> holder_map(holder->map()); 5019 Handle<Map> holder_map(holder->map());
(...skipping 1337 matching lines...) Expand 10 before | Expand all | Expand 10 after
6351 6357
6352 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) { 6358 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
6353 int diff = lhs.ticks() - rhs.ticks(); 6359 int diff = lhs.ticks() - rhs.ticks();
6354 if (diff != 0) return diff > 0; 6360 if (diff != 0) return diff > 0;
6355 diff = lhs.ast_length() - rhs.ast_length(); 6361 diff = lhs.ast_length() - rhs.ast_length();
6356 if (diff != 0) return diff < 0; 6362 if (diff != 0) return diff < 0;
6357 return lhs.src_length() < rhs.src_length(); 6363 return lhs.src_length() < rhs.src_length();
6358 } 6364 }
6359 6365
6360 6366
6367 bool HOptimizedGraphBuilder::TryCallPolymorphicAsMonomorphic(
6368 Call* expr,
6369 HValue* receiver,
6370 SmallMapList* types,
6371 Handle<String> name) {
6372 if (types->length() > kMaxCallPolymorphism) return false;
6373
6374 Handle<Map> map(types->at(0));
6375 LookupResult lookup(isolate());
6376 if (!CanLoadPropertyFromPrototype(map, name, &lookup)) return false;
6377
6378 Handle<Object> prototype(map->prototype(), isolate());
6379 for (int count = 1; count < types->length(); ++count) {
6380 Handle<Map> test_map(types->at(count));
6381 if (!CanLoadPropertyFromPrototype(test_map, name, &lookup)) return false;
6382 if (test_map->prototype() != *prototype) return false;
6383 }
6384
6385 if (!expr->ComputeTarget(map, name)) return false;
6386
6387 BuildCheckHeapObject(receiver);
6388 AddInstruction(HCheckMaps::New(receiver, types, zone()));
6389 AddCheckPrototypeMaps(expr->holder(), map);
6390 if (FLAG_trace_inlining) {
6391 Handle<JSFunction> caller = current_info()->closure();
6392 SmartArrayPointer<char> caller_name =
6393 caller->shared()->DebugName()->ToCString();
6394 PrintF("Trying to inline the polymorphic call to %s from %s\n",
6395 *name->ToCString(), *caller_name);
6396 }
6397
6398 if (!TryInlineCall(expr)) {
6399 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6400 HCallConstantFunction* call =
6401 new(zone()) HCallConstantFunction(expr->target(), argument_count);
6402 call->set_position(expr->position());
6403 PreProcessCall(call);
6404 AddInstruction(call);
6405 if (!ast_context()->IsEffect()) Push(call);
mvstanton 2013/07/10 12:48:14 Could you explain what is happening with this ast_
Toon Verwaest 2013/07/10 13:04:03 This is boilerplate code that's all over. I'll jus
6406 AddSimulate(expr->id(), REMOVABLE_SIMULATE);
6407 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
6408 }
6409
6410 return true;
6411 }
6412
6413
6361 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed( 6414 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
6362 Call* expr, 6415 Call* expr,
6363 HValue* receiver, 6416 HValue* receiver,
6364 SmallMapList* types, 6417 SmallMapList* types,
6365 Handle<String> name) { 6418 Handle<String> name) {
6366 // TODO(ager): We should recognize when the prototype chains for different 6419 if (TryCallPolymorphicAsMonomorphic(expr, receiver, types, name)) return;
6367 // maps are identical. In that case we can avoid repeatedly generating the 6420
6368 // same prototype map checks.
6369 int argument_count = expr->arguments()->length() + 1; // Includes receiver. 6421 int argument_count = expr->arguments()->length() + 1; // Includes receiver.
6370 HBasicBlock* join = NULL; 6422 HBasicBlock* join = NULL;
6371 FunctionSorter order[kMaxCallPolymorphism]; 6423 FunctionSorter order[kMaxCallPolymorphism];
6372 int ordered_functions = 0; 6424 int ordered_functions = 0;
6373 6425
6374 Handle<Map> initial_string_map( 6426 Handle<Map> initial_string_map(
6375 isolate()->native_context()->string_function()->initial_map()); 6427 isolate()->native_context()->string_function()->initial_map());
6376 Handle<Map> string_marker_map( 6428 Handle<Map> string_marker_map(
6377 JSObject::cast(initial_string_map->prototype())->map()); 6429 JSObject::cast(initial_string_map->prototype())->map());
6378 Handle<Map> initial_number_map( 6430 Handle<Map> initial_number_map(
(...skipping 3795 matching lines...) Expand 10 before | Expand all | Expand 10 after
10174 if (ShouldProduceTraceOutput()) { 10226 if (ShouldProduceTraceOutput()) {
10175 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); 10227 isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
10176 } 10228 }
10177 10229
10178 #ifdef DEBUG 10230 #ifdef DEBUG
10179 graph_->Verify(false); // No full verify. 10231 graph_->Verify(false); // No full verify.
10180 #endif 10232 #endif
10181 } 10233 }
10182 10234
10183 } } // namespace v8::internal 10235 } } // 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