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 3985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3996 | 3996 |
3997 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, | 3997 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, |
3998 literals, | 3998 literals, |
3999 expr->pattern(), | 3999 expr->pattern(), |
4000 expr->flags(), | 4000 expr->flags(), |
4001 expr->literal_index()); | 4001 expr->literal_index()); |
4002 return ast_context()->ReturnInstruction(instr, expr->id()); | 4002 return ast_context()->ReturnInstruction(instr, expr->id()); |
4003 } | 4003 } |
4004 | 4004 |
4005 | 4005 |
| 4006 static bool CanInlinePropertyAccess(Map* type) { |
| 4007 return !type->is_dictionary_map() && !type->has_named_interceptor(); |
| 4008 } |
| 4009 |
| 4010 |
4006 static void LookupInPrototypes(Handle<Map> map, | 4011 static void LookupInPrototypes(Handle<Map> map, |
4007 Handle<String> name, | 4012 Handle<String> name, |
4008 LookupResult* lookup) { | 4013 LookupResult* lookup) { |
4009 while (map->prototype()->IsJSObject()) { | 4014 while (map->prototype()->IsJSObject()) { |
4010 Handle<JSObject> holder(JSObject::cast(map->prototype())); | 4015 Handle<JSObject> holder(JSObject::cast(map->prototype())); |
4011 if (!holder->HasFastProperties()) break; | |
4012 map = Handle<Map>(holder->map()); | 4016 map = Handle<Map>(holder->map()); |
| 4017 if (!CanInlinePropertyAccess(*map)) break; |
4013 map->LookupDescriptor(*holder, *name, lookup); | 4018 map->LookupDescriptor(*holder, *name, lookup); |
4014 if (lookup->IsFound()) return; | 4019 if (lookup->IsFound()) return; |
4015 } | 4020 } |
4016 lookup->NotFound(); | 4021 lookup->NotFound(); |
4017 } | 4022 } |
4018 | 4023 |
4019 | 4024 |
4020 // Tries to find a JavaScript accessor of the given name in the prototype chain | 4025 // Tries to find a JavaScript accessor of the given name in the prototype chain |
4021 // starting at the given map. Return true iff there is one, including the | 4026 // starting at the given map. Return true iff there is one, including the |
4022 // corresponding AccessorPair plus its holder (which could be null when the | 4027 // corresponding AccessorPair plus its holder (which could be null when the |
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4390 return ast_context()->ReturnValue(Pop()); | 4395 return ast_context()->ReturnValue(Pop()); |
4391 } | 4396 } |
4392 | 4397 |
4393 | 4398 |
4394 // Sets the lookup result and returns true if the load/store can be inlined. | 4399 // Sets the lookup result and returns true if the load/store can be inlined. |
4395 static bool ComputeLoadStoreField(Handle<Map> type, | 4400 static bool ComputeLoadStoreField(Handle<Map> type, |
4396 Handle<String> name, | 4401 Handle<String> name, |
4397 LookupResult* lookup, | 4402 LookupResult* lookup, |
4398 bool is_store) { | 4403 bool is_store) { |
4399 ASSERT(!is_store || !type->is_observed()); | 4404 ASSERT(!is_store || !type->is_observed()); |
4400 if (type->has_named_interceptor()) { | 4405 if (!CanInlinePropertyAccess(*type)) { |
4401 lookup->InterceptorResult(NULL); | 4406 lookup->NotFound(); |
4402 return false; | 4407 return false; |
4403 } | 4408 } |
4404 // If we directly find a field, the access can be inlined. | 4409 // If we directly find a field, the access can be inlined. |
4405 type->LookupDescriptor(NULL, *name, lookup); | 4410 type->LookupDescriptor(NULL, *name, lookup); |
4406 if (lookup->IsField()) return true; | 4411 if (lookup->IsField()) return true; |
4407 | 4412 |
4408 // For a load, we are out of luck if there is no such field. | 4413 // For a load, we are out of luck if there is no such field. |
4409 if (!is_store) return false; | 4414 if (!is_store) return false; |
4410 | 4415 |
4411 // 2nd chance: A store into a non-existent field can still be inlined if we | 4416 // 2nd chance: A store into a non-existent field can still be inlined if we |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4534 } | 4539 } |
4535 | 4540 |
4536 // No luck, do a generic store. | 4541 // No luck, do a generic store. |
4537 return BuildStoreNamedGeneric(object, name, value); | 4542 return BuildStoreNamedGeneric(object, name, value); |
4538 } | 4543 } |
4539 | 4544 |
4540 | 4545 |
4541 static bool CanLoadPropertyFromPrototype(Handle<Map> map, | 4546 static bool CanLoadPropertyFromPrototype(Handle<Map> map, |
4542 Handle<Name> name, | 4547 Handle<Name> name, |
4543 LookupResult* lookup) { | 4548 LookupResult* lookup) { |
4544 if (map->has_named_interceptor()) return false; | 4549 if (!CanInlinePropertyAccess(*map)) return false; |
4545 if (map->is_dictionary_map()) return false; | |
4546 map->LookupDescriptor(NULL, *name, lookup); | 4550 map->LookupDescriptor(NULL, *name, lookup); |
4547 if (lookup->IsFound()) return false; | 4551 if (lookup->IsFound()) return false; |
4548 return true; | 4552 return true; |
4549 } | 4553 } |
4550 | 4554 |
4551 | 4555 |
4552 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( | 4556 HInstruction* HOptimizedGraphBuilder::TryLoadPolymorphicAsMonomorphic( |
4553 Property* expr, | 4557 Property* expr, |
4554 HValue* object, | 4558 HValue* object, |
4555 SmallMapList* types, | 4559 SmallMapList* types, |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4627 // polymorphic loads where the property is sometimes found in the prototype | 4631 // polymorphic loads where the property is sometimes found in the prototype |
4628 // chain. | 4632 // chain. |
4629 static bool PrototypeChainCanNeverResolve( | 4633 static bool PrototypeChainCanNeverResolve( |
4630 Handle<Map> map, Handle<String> name) { | 4634 Handle<Map> map, Handle<String> name) { |
4631 Isolate* isolate = map->GetIsolate(); | 4635 Isolate* isolate = map->GetIsolate(); |
4632 Object* current = map->prototype(); | 4636 Object* current = map->prototype(); |
4633 while (current != isolate->heap()->null_value()) { | 4637 while (current != isolate->heap()->null_value()) { |
4634 if (current->IsJSGlobalProxy() || | 4638 if (current->IsJSGlobalProxy() || |
4635 current->IsGlobalObject() || | 4639 current->IsGlobalObject() || |
4636 !current->IsJSObject() || | 4640 !current->IsJSObject() || |
4637 JSObject::cast(current)->map()->has_named_interceptor() || | 4641 !CanInlinePropertyAccess(JSObject::cast(current)->map()) || |
4638 JSObject::cast(current)->IsAccessCheckNeeded() || | 4642 JSObject::cast(current)->IsAccessCheckNeeded()) { |
4639 !JSObject::cast(current)->HasFastProperties()) { | |
4640 return false; | 4643 return false; |
4641 } | 4644 } |
4642 | 4645 |
4643 LookupResult lookup(isolate); | 4646 LookupResult lookup(isolate); |
4644 Map* map = JSObject::cast(current)->map(); | 4647 Map* map = JSObject::cast(current)->map(); |
4645 map->LookupDescriptor(NULL, *name, &lookup); | 4648 map->LookupDescriptor(NULL, *name, &lookup); |
4646 if (lookup.IsFound()) return false; | 4649 if (lookup.IsFound()) return false; |
4647 if (!lookup.IsCacheable()) return false; | 4650 if (!lookup.IsCacheable()) return false; |
4648 current = JSObject::cast(current)->GetPrototype(); | 4651 current = JSObject::cast(current)->GetPrototype(); |
4649 } | 4652 } |
(...skipping 14 matching lines...) Expand all Loading... |
4664 } | 4667 } |
4665 | 4668 |
4666 // Something did not match; must use a polymorphic load. | 4669 // Something did not match; must use a polymorphic load. |
4667 int count = 0; | 4670 int count = 0; |
4668 HBasicBlock* join = NULL; | 4671 HBasicBlock* join = NULL; |
4669 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { | 4672 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) { |
4670 Handle<Map> map = types->at(i); | 4673 Handle<Map> map = types->at(i); |
4671 LookupResult lookup(isolate()); | 4674 LookupResult lookup(isolate()); |
4672 if (ComputeLoadStoreField(map, name, &lookup, false) || | 4675 if (ComputeLoadStoreField(map, name, &lookup, false) || |
4673 (lookup.IsCacheable() && | 4676 (lookup.IsCacheable() && |
4674 !map->is_dictionary_map() && | 4677 CanInlinePropertyAccess(*map) && |
4675 !map->has_named_interceptor() && | |
4676 (lookup.IsConstant() || | 4678 (lookup.IsConstant() || |
4677 (!lookup.IsFound() && | 4679 (!lookup.IsFound() && |
4678 PrototypeChainCanNeverResolve(map, name))))) { | 4680 PrototypeChainCanNeverResolve(map, name))))) { |
4679 if (count == 0) { | 4681 if (count == 0) { |
4680 BuildCheckHeapObject(object); | 4682 BuildCheckHeapObject(object); |
4681 join = graph()->CreateBasicBlock(); | 4683 join = graph()->CreateBasicBlock(); |
4682 } | 4684 } |
4683 ++count; | 4685 ++count; |
4684 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4686 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
4685 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4687 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4990 Literal* key = prop->key()->AsLiteral(); | 4992 Literal* key = prop->key()->AsLiteral(); |
4991 Handle<String> name = Handle<String>::cast(key->value()); | 4993 Handle<String> name = Handle<String>::cast(key->value()); |
4992 ASSERT(!name.is_null()); | 4994 ASSERT(!name.is_null()); |
4993 | 4995 |
4994 HInstruction* instr = NULL; | 4996 HInstruction* instr = NULL; |
4995 SmallMapList* types = expr->GetReceiverTypes(); | 4997 SmallMapList* types = expr->GetReceiverTypes(); |
4996 bool monomorphic = expr->IsMonomorphic(); | 4998 bool monomorphic = expr->IsMonomorphic(); |
4997 Handle<Map> map; | 4999 Handle<Map> map; |
4998 if (monomorphic) { | 5000 if (monomorphic) { |
4999 map = types->first(); | 5001 map = types->first(); |
5000 if (map->is_dictionary_map()) monomorphic = false; | 5002 monomorphic = CanInlinePropertyAccess(*map); |
5001 } | 5003 } |
5002 if (monomorphic) { | 5004 if (monomorphic) { |
5003 Handle<JSFunction> setter; | 5005 Handle<JSFunction> setter; |
5004 Handle<JSObject> holder; | 5006 Handle<JSObject> holder; |
5005 if (LookupSetter(map, name, &setter, &holder)) { | 5007 if (LookupSetter(map, name, &setter, &holder)) { |
5006 AddCheckConstantFunction(holder, object, map); | 5008 AddCheckConstantFunction(holder, object, map); |
5007 // Don't try to inline if the result_value is different from the | 5009 // Don't try to inline if the result_value is different from the |
5008 // store_value. That case isn't handled yet by the inlining. | 5010 // store_value. That case isn't handled yet by the inlining. |
5009 if (result_value == store_value && | 5011 if (result_value == store_value && |
5010 FLAG_inline_accessors && | 5012 FLAG_inline_accessors && |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5131 | 5133 |
5132 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 5134 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
5133 Handle<Map> map; | 5135 Handle<Map> map; |
5134 HInstruction* load = NULL; | 5136 HInstruction* load = NULL; |
5135 SmallMapList* types = prop->GetReceiverTypes(); | 5137 SmallMapList* types = prop->GetReceiverTypes(); |
5136 bool monomorphic = prop->IsMonomorphic(); | 5138 bool monomorphic = prop->IsMonomorphic(); |
5137 if (monomorphic) { | 5139 if (monomorphic) { |
5138 map = types->first(); | 5140 map = types->first(); |
5139 // We can't generate code for a monomorphic dict mode load so | 5141 // We can't generate code for a monomorphic dict mode load so |
5140 // just pretend it is not monomorphic. | 5142 // just pretend it is not monomorphic. |
5141 if (map->is_dictionary_map()) monomorphic = false; | 5143 monomorphic = CanInlinePropertyAccess(*map); |
5142 } | 5144 } |
5143 if (monomorphic) { | 5145 if (monomorphic) { |
5144 Handle<JSFunction> getter; | 5146 Handle<JSFunction> getter; |
5145 Handle<JSObject> holder; | 5147 Handle<JSObject> holder; |
5146 if (LookupGetter(map, name, &getter, &holder)) { | 5148 if (LookupGetter(map, name, &getter, &holder)) { |
5147 load = BuildCallGetter(object, map, getter, holder); | 5149 load = BuildCallGetter(object, map, getter, holder); |
5148 } else { | 5150 } else { |
5149 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 5151 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
5150 } | 5152 } |
5151 } else if (types != NULL && types->length() > 1) { | 5153 } else if (types != NULL && types->length() > 1) { |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5889 | 5891 |
5890 } else if (expr->key()->IsPropertyName()) { | 5892 } else if (expr->key()->IsPropertyName()) { |
5891 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 5893 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
5892 SmallMapList* types = expr->GetReceiverTypes(); | 5894 SmallMapList* types = expr->GetReceiverTypes(); |
5893 HValue* object = Top(); | 5895 HValue* object = Top(); |
5894 | 5896 |
5895 Handle<Map> map; | 5897 Handle<Map> map; |
5896 bool monomorphic = false; | 5898 bool monomorphic = false; |
5897 if (expr->IsMonomorphic()) { | 5899 if (expr->IsMonomorphic()) { |
5898 map = types->first(); | 5900 map = types->first(); |
5899 monomorphic = !map->is_dictionary_map(); | 5901 monomorphic = CanInlinePropertyAccess(*map); |
5900 } else if (object->HasMonomorphicJSObjectType()) { | 5902 } else if (object->HasMonomorphicJSObjectType()) { |
5901 map = object->GetMonomorphicJSObjectMap(); | 5903 map = object->GetMonomorphicJSObjectMap(); |
5902 monomorphic = !map->is_dictionary_map(); | 5904 monomorphic = CanInlinePropertyAccess(*map); |
5903 } | 5905 } |
5904 if (monomorphic) { | 5906 if (monomorphic) { |
5905 Handle<JSFunction> getter; | 5907 Handle<JSFunction> getter; |
5906 Handle<JSObject> holder; | 5908 Handle<JSObject> holder; |
5907 if (LookupGetter(map, name, &getter, &holder)) { | 5909 if (LookupGetter(map, name, &getter, &holder)) { |
5908 AddCheckConstantFunction(holder, Top(), map); | 5910 AddCheckConstantFunction(holder, Top(), map); |
5909 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; | 5911 if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return; |
5910 Add<HPushArgument>(Pop()); | 5912 Add<HPushArgument>(Pop()); |
5911 instr = new(zone()) HCallConstantFunction(getter, 1); | 5913 instr = new(zone()) HCallConstantFunction(getter, 1); |
5912 } else { | 5914 } else { |
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7575 CHECK_ALIVE(VisitForValue(prop->obj())); | 7577 CHECK_ALIVE(VisitForValue(prop->obj())); |
7576 HValue* object = Top(); | 7578 HValue* object = Top(); |
7577 | 7579 |
7578 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 7580 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
7579 Handle<Map> map; | 7581 Handle<Map> map; |
7580 HInstruction* load = NULL; | 7582 HInstruction* load = NULL; |
7581 bool monomorphic = prop->IsMonomorphic(); | 7583 bool monomorphic = prop->IsMonomorphic(); |
7582 SmallMapList* types = prop->GetReceiverTypes(); | 7584 SmallMapList* types = prop->GetReceiverTypes(); |
7583 if (monomorphic) { | 7585 if (monomorphic) { |
7584 map = types->first(); | 7586 map = types->first(); |
7585 if (map->is_dictionary_map()) monomorphic = false; | 7587 monomorphic = CanInlinePropertyAccess(*map); |
7586 } | 7588 } |
7587 if (monomorphic) { | 7589 if (monomorphic) { |
7588 Handle<JSFunction> getter; | 7590 Handle<JSFunction> getter; |
7589 Handle<JSObject> holder; | 7591 Handle<JSObject> holder; |
7590 if (LookupGetter(map, name, &getter, &holder)) { | 7592 if (LookupGetter(map, name, &getter, &holder)) { |
7591 load = BuildCallGetter(object, map, getter, holder); | 7593 load = BuildCallGetter(object, map, getter, holder); |
7592 } else { | 7594 } else { |
7593 load = BuildLoadNamedMonomorphic(object, name, prop, map); | 7595 load = BuildLoadNamedMonomorphic(object, name, prop, map); |
7594 } | 7596 } |
7595 } else if (types != NULL && types->length() > 1) { | 7597 } else if (types != NULL && types->length() > 1) { |
(...skipping 2143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9739 if (ShouldProduceTraceOutput()) { | 9741 if (ShouldProduceTraceOutput()) { |
9740 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9742 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9741 } | 9743 } |
9742 | 9744 |
9743 #ifdef DEBUG | 9745 #ifdef DEBUG |
9744 graph_->Verify(false); // No full verify. | 9746 graph_->Verify(false); // No full verify. |
9745 #endif | 9747 #endif |
9746 } | 9748 } |
9747 | 9749 |
9748 } } // namespace v8::internal | 9750 } } // namespace v8::internal |
OLD | NEW |