Index: src/type-info.cc |
=================================================================== |
--- src/type-info.cc (revision 10254) |
+++ src/type-info.cc (working copy) |
@@ -438,11 +438,45 @@ |
Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) { |
types->Reserve(4); |
ASSERT(object->IsCode()); |
- isolate_->stub_cache()->CollectMatchingMaps(types, *name, flags); |
+ isolate_->stub_cache()->CollectMatchingMaps(types, |
+ *name, |
+ flags, |
+ global_context_); |
} |
} |
+// Check if a map originates from a given global context. We use this |
+// information to filter out maps from different context to avoid |
+// retaining objects from different tabs in Chrome via optimized code. |
+bool TypeFeedbackOracle::CanRetainOtherContext(Map* map, |
+ Context* global_context) { |
+ Object* constructor = map->constructor(); |
+ ASSERT(constructor != NULL); |
+ while (!constructor->IsJSFunction()) { |
+ // If the constructor is not null or a JSFunction, we have to |
+ // conservatively assume that it may retain a global context. |
+ if (!constructor->IsNull()) return true; |
+ |
+ // If both, constructor and prototype are null, we conclude |
+ // that no global context will be retained by this map. |
+ if (map->prototype()->IsNull()) return false; |
+ |
+ map = JSObject::cast(map->prototype())->map(); |
+ constructor = map->constructor(); |
+ } |
+ JSFunction* function = JSFunction::cast(constructor); |
+ return CanRetainOtherContext(function, global_context); |
+} |
+ |
+ |
+bool TypeFeedbackOracle::CanRetainOtherContext(JSFunction* function, |
+ Context* global_context) { |
+ return function->context()->global() != global_context->global() |
+ && function->context()->global() != global_context->builtins(); |
+} |
+ |
+ |
static void AddMapIfMissing(Handle<Map> map, SmallMapList* list) { |
for (int i = 0; i < list->length(); ++i) { |
if (list->at(i).is_identical_to(map)) return; |
@@ -539,7 +573,12 @@ |
SetInfo(ast_id, Smi::FromInt(target->check_type())); |
} else { |
Object* map = target->FindFirstMap(); |
- SetInfo(ast_id, map == NULL ? static_cast<Object*>(target) : map); |
+ if (map == NULL) { |
+ SetInfo(ast_id, static_cast<Object*>(target)); |
+ } else if (!CanRetainOtherContext(Map::cast(map), |
+ *global_context_)) { |
+ SetInfo(ast_id, map); |
+ } |
} |
} else if (target->ic_state() == MEGAMORPHIC) { |
SetInfo(ast_id, target); |
@@ -565,7 +604,9 @@ |
if (target->major_key() == CodeStub::CallFunction && |
target->has_function_cache()) { |
Object* value = CallFunctionStub::GetCachedValue(reloc_entry.pc()); |
- if (value->IsJSFunction()) { |
+ if (value->IsJSFunction() && |
+ !CanRetainOtherContext(JSFunction::cast(value), |
+ *global_context_)) { |
SetInfo(ast_id, value); |
} |
} |