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

Unified Diff: src/objects.cc

Issue 35413006: Correct handling of arrays with callbacks in the prototype chain. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: A few test updates and simpler prototype updating. Created 7 years, 2 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 side-by-side diff with in-line comments
Download patch
« src/ic.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 2f84975d6fa77d9ecf1e3f0aa9aaa9378027f24f..d2b988acf6d2ecd0c99ba6816b32bfee49190462 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2923,6 +2923,25 @@ Handle<Object> JSReceiver::SetPropertyWithDefinedSetter(
}
+bool JSReceiver::MayHaveIndexedCallbacksInPrototypeChain() {
+ Heap* heap = GetHeap();
+ for (Object* pt = GetPrototype();
+ pt != heap->null_value();
+ pt = pt->GetPrototype(GetIsolate())) {
+ if (pt->IsJSProxy()) {
+ // Be conservative, don't walk into proxies.
+ return true;
+ }
+
+ if (JSObject::cast(pt)->map()->has_element_callbacks()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
uint32_t index,
Object* value,
@@ -6204,12 +6223,14 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
Handle<Object> structure,
PropertyAttributes attributes) {
Heap* heap = object->GetHeap();
+ Handle<Map> old_map(object->map());
PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
// Normalize elements to make this operation simple.
Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
ASSERT(object->HasDictionaryElements() ||
object->HasDictionaryArgumentsElements());
+ bool map_changed = object->map() != *old_map;
// Update the dictionary with the new CALLBACKS property.
dictionary = SeededNumberDictionary::Set(dictionary, index, structure,
@@ -6231,6 +6252,34 @@ void JSObject::SetElementCallback(Handle<JSObject> object,
} else {
object->set_elements(*dictionary);
}
+
+ if (!object->map()->has_element_callbacks()) {
+ if (!map_changed) {
+ Handle<Map> new_map = Map::Copy(handle(object->map()));
+ object->set_map(*new_map);
+ }
+ object->map()->set_has_element_callbacks(true);
danno 2013/10/23 12:22:11 This isn't quite right. You might "pollute" normal
+ }
+
+ // If we are the array prototype object, rebuild the cache.
+ Isolate* isolate = object->GetIsolate();
+ if (isolate->initial_array_prototype().is_identical_to(object)) {
+ // Install the initial map, new_ek_map in the function prototype for
danno 2013/10/23 12:22:11 Is this comment correct?
+ // array.
+ Handle<JSFunction> array_function(
+ isolate->global_context()->array_function(), isolate);
+ JSFunction::SetPrototype(array_function, object);
danno 2013/10/23 12:22:11 You are "rebuilding the cache" by side effect, whi
+ } else if (isolate->initial_object_prototype().is_identical_to(object)) {
+ Handle<JSFunction> object_function(
+ isolate->global_context()->object_function(), isolate);
+ JSFunction::SetPrototype(object_function, object);
+ }
+
+ // TODO(mvstanton): With a dependency group we can avoid the need to
+ // deoptimize code that doesn't depend on the changed maps. Address this
+ // in a follow-up checkin.
+ Deoptimizer::DeoptimizeAll(object->GetIsolate());
danno 2013/10/23 12:22:11 Oh, *the humanity* Are you sure it can't be in thi
+ object->GetHeap()->ClearAllKeyedStoreICs();
}
@@ -10560,6 +10609,16 @@ void Code::ReplaceNthCell(int n, Cell* replace_with) {
void Code::ClearInlineCaches() {
+ ClearInlineCaches(NULL);
+}
+
+
+void Code::ClearInlineCaches(Code::Kind kind) {
+ ClearInlineCaches(&kind);
+}
+
+
+void Code::ClearInlineCaches(Code::Kind* kind) {
int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
@@ -10568,7 +10627,9 @@ void Code::ClearInlineCaches() {
RelocInfo* info = it.rinfo();
Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
if (target->is_inline_cache_stub()) {
- IC::Clear(this->GetIsolate(), info->pc());
+ if (kind == NULL || *kind == target->kind()) {
+ IC::Clear(this->GetIsolate(), info->pc());
+ }
}
}
}
@@ -12738,8 +12799,11 @@ MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
if (from_kind == to_kind) return this;
- MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
- if (maybe_failure->IsFailure()) return maybe_failure;
+ // Don't update the site if to_kind isn't fast
+ if (IsFastElementsKind(to_kind)) {
+ MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
+ if (maybe_failure->IsFailure()) return maybe_failure;
+ }
Isolate* isolate = GetIsolate();
if (elements() == isolate->heap()->empty_fixed_array() ||
« src/ic.cc ('K') | « src/objects.h ('k') | src/objects-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698