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 // 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |