| 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 |