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

Side by Side Diff: src/hydrogen.cc

Issue 23614011: Fix interceptor handling in crankshaft. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 3 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 | « no previous file | test/cctest/test-api.cc » ('j') | 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 3985 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698