Revision: 9584
Author: [email protected]
Date: Tue Oct 11 09:02:45 2011
Log: Refactor and fix polymorphic KeyedStoreIC creation
Review URL: http://codereview.chromium.org/8233011
http://code.google.com/p/v8/source/detail?r=9584
Modified:
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/ic.h
/branches/bleeding_edge/src/mips/stub-cache-mips.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/stub-cache.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Oct 11 02:33:00
2011
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Oct 11 09:02:45
2011
@@ -3178,7 +3178,7 @@
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
+MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic(
MapList* receiver_maps,
CodeList* handler_ics) {
// ----------- S t a t e -------------
@@ -3274,64 +3274,10 @@
}
-MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition(
- Map* transitioned_map,
- Map* untransitioned_map_1,
- Map* untransitioned_map_2) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : key
- // -- r2 : receiver
- // -- lr : return address
- // -- r3 : scratch
- // -----------------------------------
-
- // The order of map occurrences in the generated code below is important.
- // Both IC code and Crankshaft rely on |transitioned_map| being the first
- // map in the stub.
-
- Code* notransition_stub;
- ElementsKind elements_kind = transitioned_map->elements_kind();
- bool is_js_array = transitioned_map->instance_type() == JS_ARRAY_TYPE;
- MaybeObject* maybe_stub =
- KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
- if (!maybe_stub->To(¬ransition_stub)) return maybe_stub;
-
- Label just_store, miss;
- __ JumpIfSmi(r2, &miss);
- __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
- // r3: receiver->map().
- __ mov(ip, Operand(Handle<Map>(transitioned_map)));
- __ cmp(r3, ip);
- __ b(eq, &just_store);
- ASSERT_NE(untransitioned_map_1, NULL);
- __ mov(ip, Operand(Handle<Map>(untransitioned_map_1)));
- __ cmp(r3, ip);
- Code* generic_stub = (strict_mode_ == kStrictMode)
- ?
isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
- : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
- __ Jump(Handle<Code>(generic_stub), RelocInfo::CODE_TARGET, eq);
- if (untransitioned_map_2 != NULL) {
- __ mov(ip, Operand(Handle<Map>(untransitioned_map_2)));
- __ cmp(r3, ip);
- __ Jump(Handle<Code>(generic_stub), RelocInfo::CODE_TARGET, eq);
- }
-
- __ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ Jump(ic, RelocInfo::CODE_TARGET);
-
- __ bind(&just_store);
- __ Jump(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL, MEGAMORPHIC);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
+MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
MapList* receiver_maps,
- CodeList* handler_ics) {
+ CodeList* handler_stubs,
+ MapList* transitioned_maps) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
@@ -3344,12 +3290,20 @@
int receiver_count = receiver_maps->length();
__ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
- for (int current = 0; current < receiver_count; ++current) {
- Handle<Map> map(receiver_maps->at(current));
- Handle<Code> code(handler_ics->at(current));
+ for (int i = 0; i < receiver_count; ++i) {
+ Handle<Map> map(receiver_maps->at(i));
+ Handle<Code> code(handler_stubs->at(i));
__ mov(ip, Operand(map));
__ cmp(r3, ip);
- __ Jump(code, RelocInfo::CODE_TARGET, eq);
+ if (transitioned_maps->at(i) == NULL) {
+ __ Jump(code, RelocInfo::CODE_TARGET, eq);
+ } else {
+ Label next_map;
+ __ b(eq, &next_map);
+ __ mov(r4, Operand(Handle<Map>(transitioned_maps->at(i))));
+ __ Jump(code, RelocInfo::CODE_TARGET, al);
+ __ bind(&next_map);
+ }
}
__ bind(&miss);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Oct 11 02:33:00
2011
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Oct 11 09:02:45
2011
@@ -2755,81 +2755,32 @@
}
-MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition(
- Map* transitioned_map,
- Map* untransitioned_map_1,
- Map* untransitioned_map_2) {
+MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
+ MapList* receiver_maps,
+ CodeList* handler_stubs,
+ MapList* transitioned_maps) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
-
- // The order of map occurrences in the generated code below is important.
- // Both IC code and Crankshaft rely on |transitioned_map| being the first
- // map in the stub.
-
- Code* notransition_stub;
- ElementsKind elements_kind = transitioned_map->elements_kind();
- bool is_jsarray = transitioned_map->instance_type() == JS_ARRAY_TYPE;
- MaybeObject* maybe_stub =
- KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode();
- if (!maybe_stub->To(¬ransition_stub)) return maybe_stub;
-
- Label just_store, miss;
+ Label miss;
__ JumpIfSmi(edx, &miss, Label::kNear);
- __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset));
+ __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
// ebx: receiver->map().
- __ cmp(ebx, Handle<Map>(transitioned_map));
- __ j(equal, &just_store);
- ASSERT_NE(untransitioned_map_1, NULL);
- __ cmp(ebx, Handle<Map>(untransitioned_map_1));
- // TODO(jkummerow): When we have specialized code to do the transition,
- // call that code here, then jump to just_store when the call returns.
- // <temporary: just use the generic stub>
- Code* generic_stub = (strict_mode_ == kStrictMode)
- ?
isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
- : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
- __ j(equal, Handle<Code>(generic_stub));
- // </temporary>
- if (untransitioned_map_2 != NULL) {
- __ cmp(ebx, Handle<Map>(untransitioned_map_2));
- // <temporary: see above, same here>
- __ j(equal, Handle<Code>(generic_stub));
- // </temporary>
- }
- __ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- __ bind(&just_store);
- __ jmp(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL, MEGAMORPHIC);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
- MapList* receiver_maps,
- CodeList* handler_ics) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : key
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- Label miss;
- __ JumpIfSmi(edx, &miss);
-
- Register map_reg = ebx;
- __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
- int receiver_count = receiver_maps->length();
- for (int current = 0; current < receiver_count; ++current) {
- Handle<Map> map(receiver_maps->at(current));
- __ cmp(map_reg, map);
- __ j(equal, Handle<Code>(handler_ics->at(current)));
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Handle<Map> map(receiver_maps->at(i));
+ __ cmp(edi, map);
+ if (transitioned_maps->at(i) == NULL) {
+ __ j(equal, Handle<Code>(handler_stubs->at(i)));
+ } else {
+ Label next_map;
+ __ j(not_equal, &next_map, Label::kNear);
+ __ mov(ebx, Immediate(Handle<Map>(transitioned_maps->at(i))));
+ __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET);
+ __ bind(&next_map);
+ }
}
__ bind(&miss);
Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
@@ -3269,7 +3220,7 @@
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
+MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic(
MapList* receiver_maps,
CodeList* handler_ics) {
// ----------- S t a t e -------------
=======================================
--- /branches/bleeding_edge/src/ic.cc Tue Oct 11 02:33:00 2011
+++ /branches/bleeding_edge/src/ic.cc Tue Oct 11 09:02:45 2011
@@ -1084,14 +1084,22 @@
}
-MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
+MaybeObject* KeyedLoadIC::ComputePolymorphicStub(
MapList* receiver_maps,
- CodeList* targets,
StrictModeFlag strict_mode) {
+ CodeList handler_ics(receiver_maps->length());
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Map* receiver_map(receiver_maps->at(i));
+ MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
+ receiver_map, strict_mode);
+ Code* cached_stub;
+ if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
+ handler_ics.Add(cached_stub);
+ }
Object* object;
KeyedLoadStubCompiler compiler;
- MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
- targets);
+ MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps,
+ &handler_ics);
if (!maybe_code->ToObject(&object)) return maybe_code;
isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
PROFILE(isolate(), CodeCreateEvent(
@@ -1625,13 +1633,16 @@
} else {
GetReceiverMapsForStub(target(), &target_receiver_maps);
}
- Map* new_map = receiver->map();
+ bool map_added =
+ AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map());
if (IsTransitionStubKind(stub_kind)) {
MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind);
+ Map* new_map = NULL;
if (!maybe_map->To(&new_map)) return maybe_map;
- }
- if (!AddOneReceiverMapIfMissing(&target_receiver_maps, new_map)) {
- // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
+ map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
new_map);
+ }
+ if (!map_added) {
+ // If the miss wasn't due to an unseen map, a polymorphic stub
// won't help, use the generic stub.
return generic_stub;
}
@@ -1652,13 +1663,8 @@
ASSERT(maybe_cached_stub->IsCode());
return Code::cast(maybe_cached_stub);
}
- MaybeObject* maybe_stub = NULL;
- if (IsTransitionStubKind(stub_kind)) {
- maybe_stub = ComputePolymorphicStubWithTransition(
- receiver, &target_receiver_maps, new_map, strict_mode);
- } else {
- maybe_stub = ComputePolymorphicStub(&target_receiver_maps,
strict_mode);
- }
+ MaybeObject* maybe_stub =
+ ComputePolymorphicStub(&target_receiver_maps, strict_mode);
Code* stub;
if (!maybe_stub->To(&stub)) return maybe_stub;
MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags,
stub);
@@ -1705,45 +1711,6 @@
}
return result;
}
-
-
-MaybeObject* KeyedIC::ComputePolymorphicStubWithTransition(
- JSObject* receiver,
- MapList* receiver_maps,
- Map* new_map,
- StrictModeFlag strict_mode) {
- Map* existing_transitionable_map = NULL;
- for (int i = 0; i < receiver_maps->length(); ++i) {
- Map* map = receiver_maps->at(i);
- if (map != receiver->map() && map != new_map) {
- existing_transitionable_map = map;
- break;
- }
- }
- KeyedStoreStubCompiler compiler(strict_mode);
- return compiler.CompileStoreElementWithTransition(
- new_map,
- receiver->map(),
- existing_transitionable_map);
-}
-
-
-MaybeObject* KeyedIC::ComputePolymorphicStub(
- MapList* receiver_maps,
- StrictModeFlag strict_mode) {
- // Collect MONOMORPHIC stubs for all target_receiver_maps.
- CodeList handler_ics(receiver_maps->length());
- for (int i = 0; i < receiver_maps->length(); ++i) {
- Map* receiver_map(receiver_maps->at(i));
- MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
- receiver_map, strict_mode);
- Code* cached_stub;
- if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
- handler_ics.Add(cached_stub);
- }
- // Build the MEGAMORPHIC stub.
- return ConstructMegamorphicStub(receiver_maps, &handler_ics,
strict_mode);
-}
MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver,
@@ -1768,14 +1735,88 @@
}
-MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
+// If |map| is contained in |maps_list|, returns |map|; otherwise returns
NULL.
+Map* GetMapIfPresent(Map* map, MapList* maps_list) {
+ for (int i = 0; i < maps_list->length(); ++i) {
+ if (maps_list->at(i) == map) return map;
+ }
+ return NULL;
+}
+
+
+// Returns the most generic transitioned map for |map| that's found in
+// |maps_list|, or NULL if no transitioned map for |map| is found at all.
+Map* GetTransitionedMap(Map* map, MapList* maps_list) {
+ ElementsKind elements_kind = map->elements_kind();
+ if (elements_kind == FAST_ELEMENTS) {
+ return NULL;
+ }
+ if (elements_kind == FAST_DOUBLE_ELEMENTS) {
+ bool dummy = true;
+ Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS,
&dummy);
+ if (fast_map == NULL) return NULL;
+ return GetMapIfPresent(fast_map, maps_list);
+ }
+ if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
+ bool dummy = true;
+ Map* double_map =
map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
+ &dummy);
+ // In the current implementation, if the DOUBLE map doesn't exist, the
+ // FAST map can't exist either.
+ if (double_map == NULL) return NULL;
+ Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS,
&dummy);
+ if (fast_map == NULL) {
+ return GetMapIfPresent(double_map, maps_list);
+ }
+ // Both double_map and fast_map are non-NULL. Return fast_map if it's
in
+ // maps_list, double_map otherwise.
+ Map* fast_map_present = GetMapIfPresent(fast_map, maps_list);
+ if (fast_map_present != NULL) return fast_map_present;
+ return GetMapIfPresent(double_map, maps_list);
+ }
+ return NULL;
+}
+
+
+MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
MapList* receiver_maps,
- CodeList* targets,
StrictModeFlag strict_mode) {
+ // TODO(yangguo): <remove>
+ Code* generic_stub = (strict_mode == kStrictMode)
+ ?
isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
+ : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
+ // </remove>
+
+ // Collect MONOMORPHIC stubs for all target_receiver_maps.
+ CodeList handler_ics(receiver_maps->length());
+ MapList transitioned_maps(receiver_maps->length());
+ for (int i = 0; i < receiver_maps->length(); ++i) {
+ Map* receiver_map(receiver_maps->at(i));
+ MaybeObject* maybe_cached_stub = NULL;
+ Map* transitioned_map = GetTransitionedMap(receiver_map,
receiver_maps);
+ if (transitioned_map != NULL) {
+ // TODO(yangguo): Enable this code!
+ // maybe_cached_stub = FastElementsConversionStub(
+ // receiver_map->elements_kind(), // original elements_kind
+ // transitioned_map->elements_kind(),
+ // receiver_map->instance_type() == JS_ARRAY_TYPE, //
is_js_array
+ // strict_mode_).TryGetCode();
+ // TODO(yangguo): <remove>
+ maybe_cached_stub = generic_stub;
+ // </remove>
+ } else {
+ maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
+ receiver_map, strict_mode);
+ }
+ Code* cached_stub;
+ if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
+ handler_ics.Add(cached_stub);
+ transitioned_maps.Add(transitioned_map);
+ }
Object* object;
KeyedStoreStubCompiler compiler(strict_mode);
- MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
- targets);
+ MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
+ receiver_maps, &handler_ics, &transitioned_maps);
if (!maybe_code->ToObject(&object)) return maybe_code;
isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
PROFILE(isolate(), CodeCreateEvent(
=======================================
--- /branches/bleeding_edge/src/ic.h Tue Oct 11 02:33:00 2011
+++ /branches/bleeding_edge/src/ic.h Tue Oct 11 09:02:45 2011
@@ -368,31 +368,21 @@
StrictModeFlag strict_mode,
Code* default_stub);
- virtual MaybeObject* ConstructMegamorphicStub(
- MapList* receiver_maps,
- CodeList* targets,
- StrictModeFlag strict_mode) = 0;
-
- private:
- void GetReceiverMapsForStub(Code* stub, MapList* result);
+ virtual MaybeObject* ComputePolymorphicStub(MapList* receiver_maps,
+ StrictModeFlag strict_mode)
= 0;
MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
Map* receiver_map,
StrictModeFlag strict_mode);
+ private:
+ void GetReceiverMapsForStub(Code* stub, MapList* result);
+
MaybeObject* ComputeMonomorphicStub(JSObject* receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
Code* default_stub);
- MaybeObject* ComputePolymorphicStubWithTransition(JSObject* receiver,
- MapList* receiver_maps,
- Map* new_map,
- StrictModeFlag
strict_mode);
-
- MaybeObject* ComputePolymorphicStub(MapList* receiver_maps,
- StrictModeFlag strict_mode);
-
MaybeObject* ComputeTransitionedMap(JSObject* receiver, StubKind
stub_kind);
static bool IsTransitionStubKind(StubKind stub_kind) {
@@ -440,9 +430,8 @@
protected:
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
- virtual MaybeObject* ConstructMegamorphicStub(
+ virtual MaybeObject* ComputePolymorphicStub(
MapList* receiver_maps,
- CodeList* targets,
StrictModeFlag strict_mode);
virtual Code* string_stub() {
@@ -591,9 +580,8 @@
protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
- virtual MaybeObject* ConstructMegamorphicStub(
+ virtual MaybeObject* ComputePolymorphicStub(
MapList* receiver_maps,
- CodeList* targets,
StrictModeFlag strict_mode);
private:
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Thu Sep 22 04:30:04
2011
+++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Tue Oct 11 09:02:45
2011
@@ -3130,7 +3130,7 @@
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
+MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic(
MapList* receiver_maps,
CodeList* handler_ics) {
// ----------- S t a t e -------------
=======================================
--- /branches/bleeding_edge/src/objects.cc Tue Oct 11 04:35:04 2011
+++ /branches/bleeding_edge/src/objects.cc Tue Oct 11 09:02:45 2011
@@ -2163,15 +2163,16 @@
}
-// Returns the contents of |map|'s descriptor array for the given string
-// (which might be NULL). |safe_to_add_transition| is set to false and NULL
-// is returned if adding transitions is not allowed.
-static Object* GetDescriptorContents(Map* map,
- String* sentinel_name,
- bool* safe_to_add_transition) {
+String* Map::elements_transition_sentinel_name() {
+ return GetHeap()->empty_symbol();
+}
+
+
+Object* Map::GetDescriptorContents(String* sentinel_name,
+ bool* safe_to_add_transition) {
// Get the cached index for the descriptors lookup, or find and cache it.
- DescriptorArray* descriptors = map->instance_descriptors();
- DescriptorLookupCache* cache =
map->GetIsolate()->descriptor_lookup_cache();
+ DescriptorArray* descriptors = instance_descriptors();
+ DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
int index = cache->Lookup(descriptors, sentinel_name);
if (index == DescriptorLookupCache::kAbsent) {
index = descriptors->Search(sentinel_name);
@@ -2190,31 +2191,20 @@
}
-// Returns the map that |original_map| transitions to if its elements_kind
-// is changed to |elements_kind|, or NULL if no such map is cached yet.
-// |safe_to_add_transitions| is set to false if adding transitions is not
-// allowed.
-static Map* LookupElementsTransitionMap(Map* original_map,
- ElementsKind elements_kind,
- String* sentinel_name,
- bool* safe_to_add_transition) {
+Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
+ bool* safe_to_add_transition) {
// Special case: indirect SMI->FAST transition (cf. comment in
// AddElementsTransition()).
- if (original_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
+ if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
elements_kind == FAST_ELEMENTS) {
- Map* double_map = LookupElementsTransitionMap(
- original_map,
- FAST_DOUBLE_ELEMENTS,
- sentinel_name,
- safe_to_add_transition);
+ Map* double_map =
this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
+
safe_to_add_transition);
if (double_map == NULL) return double_map;
- return LookupElementsTransitionMap(double_map,
- FAST_ELEMENTS,
- sentinel_name,
- safe_to_add_transition);
+ return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
+ safe_to_add_transition);
}
Object* descriptor_contents = GetDescriptorContents(
- original_map, sentinel_name, safe_to_add_transition);
+ elements_transition_sentinel_name(), safe_to_add_transition);
if (descriptor_contents != NULL) {
Map* maybe_transition_map =
GetElementsTransitionMapFromDescriptor(descriptor_contents,
@@ -2226,41 +2216,34 @@
}
-// Adds an entry to |original_map|'s descriptor array for a transition to
-// |transitioned_map| when its elements_kind is changed to |elements_kind|,
-// using |sentinel_name| as key for the entry.
-static MaybeObject* AddElementsTransition(Map* original_map,
- ElementsKind elements_kind,
- Map* transitioned_map,
- String* sentinel_name) {
+MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
+ Map* transitioned_map) {
// The map transition graph should be a tree, therefore the transition
// from SMI to FAST elements is not done directly, but by going through
// DOUBLE elements first.
- if (original_map->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
+ if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
elements_kind == FAST_ELEMENTS) {
bool safe_to_add = true;
- Map* double_map = LookupElementsTransitionMap(
- original_map, FAST_DOUBLE_ELEMENTS, sentinel_name, &safe_to_add);
+ Map* double_map = this->LookupElementsTransitionMap(
+ FAST_DOUBLE_ELEMENTS, &safe_to_add);
// This method is only called when safe_to_add_transition has been
found
// to be true earlier.
ASSERT(safe_to_add);
if (double_map == NULL) {
- MaybeObject* maybe_map = original_map->CopyDropTransitions();
+ MaybeObject* maybe_map = this->CopyDropTransitions();
if (!maybe_map->To(&double_map)) return maybe_map;
double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
- MaybeObject* maybe_double_transition = AddElementsTransition(
- original_map, FAST_DOUBLE_ELEMENTS, double_map, sentinel_name);
+ MaybeObject* maybe_double_transition = this->AddElementsTransition(
+ FAST_DOUBLE_ELEMENTS, double_map);
if (maybe_double_transition->IsFailure()) return
maybe_double_transition;
}
- return AddElementsTransition(
- double_map, FAST_ELEMENTS, transitioned_map, sentinel_name);
+ return double_map->AddElementsTransition(FAST_ELEMENTS,
transitioned_map);
}
- DescriptorArray* descriptors = original_map->instance_descriptors();
bool safe_to_add_transition = true;
Object* descriptor_contents = GetDescriptorContents(
- original_map, sentinel_name, &safe_to_add_transition);
+ elements_transition_sentinel_name(), &safe_to_add_transition);
// This method is only called when safe_to_add_transition has been found
// to be true earlier.
ASSERT(safe_to_add_transition);
@@ -2272,24 +2255,22 @@
return maybe_new_contents;
}
- ElementsTransitionDescriptor desc(sentinel_name, new_contents);
+ ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
+ new_contents);
Object* new_descriptors;
MaybeObject* maybe_new_descriptors =
- descriptors->CopyInsert(&desc, KEEP_TRANSITIONS);
+ instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
return maybe_new_descriptors;
}
- descriptors = DescriptorArray::cast(new_descriptors);
- original_map->set_instance_descriptors(descriptors);
- return original_map;
+ set_instance_descriptors(DescriptorArray::cast(new_descriptors));
+ return this;
}
MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) {
- Heap* current_heap = GetHeap();
Map* current_map = map();
ElementsKind from_kind = current_map->elements_kind();
- String* elements_transition_sentinel_name = current_heap->empty_symbol();
if (from_kind == to_kind) return current_map;
@@ -2309,9 +2290,8 @@
if (safe_to_add_transition) {
// It's only safe to manipulate the descriptor array if it would be
// safe to add a transition.
- Map* maybe_transition_map = LookupElementsTransitionMap(
- current_map, to_kind, elements_transition_sentinel_name,
- &safe_to_add_transition);
+ Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
+ to_kind, &safe_to_add_transition);
if (maybe_transition_map != NULL) {
return maybe_transition_map;
}
@@ -2334,8 +2314,8 @@
(GetIsolate()->context()->global_context()->object_function()->map() !=
map());
if (allow_map_transition) {
- MaybeObject* maybe_transition = AddElementsTransition(
- current_map, to_kind, new_map, elements_transition_sentinel_name);
+ MaybeObject* maybe_transition =
+ current_map->AddElementsTransition(to_kind, new_map);
if (maybe_transition->IsFailure()) return maybe_transition;
}
return new_map;
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Oct 11 01:41:19 2011
+++ /branches/bleeding_edge/src/objects.h Tue Oct 11 09:02:45 2011
@@ -4269,6 +4269,24 @@
bool EquivalentTo(Map* other) {
return EquivalentToForNormalization(other, KEEP_INOBJECT_PROPERTIES);
}
+
+ // Returns the contents of this map's descriptor array for the given
string.
+ // May return NULL. |safe_to_add_transition| is set to false and NULL
+ // is returned if adding transitions is not allowed.
+ Object* GetDescriptorContents(String* sentinel_name,
+ bool* safe_to_add_transitions);
+
+ // Returns the map that this map transitions to if its elements_kind
+ // is changed to |elements_kind|, or NULL if no such map is cached yet.
+ // |safe_to_add_transitions| is set to false if adding transitions is not
+ // allowed.
+ Map* LookupElementsTransitionMap(ElementsKind elements_kind,
+ bool* safe_to_add_transition);
+
+ // Adds an entry to this map's descriptor array for a transition to
+ // |transitioned_map| when its elements_kind is changed to |
elements_kind|.
+ MaybeObject* AddElementsTransition(ElementsKind elements_kind,
+ Map* transitioned_map);
// Dispatched behavior.
#ifdef OBJECT_PRINT
@@ -4387,6 +4405,7 @@
kSize> BodyDescriptor;
private:
+ String* elements_transition_sentinel_name();
DISALLOW_IMPLICIT_CONSTRUCTORS(Map);
};
=======================================
--- /branches/bleeding_edge/src/stub-cache.h Tue Oct 11 02:33:00 2011
+++ /branches/bleeding_edge/src/stub-cache.h Tue Oct 11 09:02:45 2011
@@ -641,7 +641,7 @@
MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);
- MUST_USE_RESULT MaybeObject* CompileLoadMegamorphic(
+ MUST_USE_RESULT MaybeObject* CompileLoadPolymorphic(
MapList* receiver_maps,
CodeList* handler_ics);
@@ -700,14 +700,10 @@
MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map);
- MUST_USE_RESULT MaybeObject* CompileStoreElementWithTransition(
- Map* transitioned_map,
- Map* untransitioned_map_1,
- Map* untransitioned_map_2 = NULL);
-
- MUST_USE_RESULT MaybeObject* CompileStoreMegamorphic(
+ MUST_USE_RESULT MaybeObject* CompileStorePolymorphic(
MapList* receiver_maps,
- CodeList* handler_ics);
+ CodeList* handler_stubs,
+ MapList* transitioned_maps);
static void GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array,
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Oct 11 02:33:00
2011
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Oct 11 09:02:45
2011
@@ -2603,59 +2603,10 @@
}
-MaybeObject* KeyedStoreStubCompiler::CompileStoreElementWithTransition(
- Map* transitioned_map,
- Map* untransitioned_map_1,
- Map* untransitioned_map_2) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : key
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
-
- // The order of map occurrences in the generated code below is important.
- // Both IC code and Crankshaft rely on |transitioned_map| being the first
- // map in the stub.
-
- Code* notransition_stub;
- ElementsKind elements_kind = transitioned_map->elements_kind();
- bool is_js_array = transitioned_map->instance_type() == JS_ARRAY_TYPE;
- MaybeObject* maybe_stub =
- KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
- if (!maybe_stub->To(¬ransition_stub)) return maybe_stub;
-
- Label just_store, miss;
- __ JumpIfSmi(rdx, &miss, Label::kNear);
- __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
- // rbx: receiver->map().
- __ Cmp(rbx, Handle<Map>(transitioned_map));
- __ j(equal, &just_store);
- ASSERT_NE(untransitioned_map_1, NULL);
- __ Cmp(rbx, Handle<Map>(untransitioned_map_1));
- Code* generic_stub = (strict_mode_ == kStrictMode)
- ?
isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
- : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
- __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET);
- if (untransitioned_map_2 != NULL) {
- __ Cmp(rbx, Handle<Map>(untransitioned_map_2));
- __ j(equal, Handle<Code>(generic_stub), RelocInfo::CODE_TARGET);
- }
- __ bind(&miss);
- Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
- __ jmp(ic, RelocInfo::CODE_TARGET);
-
- __ bind(&just_store);
- __ jmp(Handle<Code>(notransition_stub), RelocInfo::CODE_TARGET);
-
- // Return the generated code.
- return GetCode(NORMAL, NULL, MEGAMORPHIC);
-}
-
-
-MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
+MaybeObject* KeyedStoreStubCompiler::CompileStorePolymorphic(
MapList* receiver_maps,
- CodeList* handler_ics) {
+ CodeList* handler_stubs,
+ MapList* transitioned_maps) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
@@ -2663,18 +2614,25 @@
// -- rsp[0] : return address
// -----------------------------------
Label miss;
- __ JumpIfSmi(rdx, &miss);
-
- Register map_reg = rbx;
- __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
+ __ JumpIfSmi(rdx, &miss, Label::kNear);
+
+ __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
int receiver_count = receiver_maps->length();
- for (int current = 0; current < receiver_count; ++current) {
+ for (int i = 0; i < receiver_count; ++i) {
// Check map and tail call if there's a match
- Handle<Map> map(receiver_maps->at(current));
- __ Cmp(map_reg, map);
- __ j(equal,
- Handle<Code>(handler_ics->at(current)),
- RelocInfo::CODE_TARGET);
+ Handle<Map> map(receiver_maps->at(i));
+ __ Cmp(rdi, map);
+ if (transitioned_maps->at(i) == NULL) {
+ __ j(equal, Handle<Code>(handler_stubs->at(i)),
RelocInfo::CODE_TARGET);
+ } else {
+ Label next_map;
+ __ j(not_equal, &next_map, Label::kNear);
+ __ movq(rbx,
+ Handle<Map>(transitioned_maps->at(i)),
+ RelocInfo::EMBEDDED_OBJECT);
+ __ jmp(Handle<Code>(handler_stubs->at(i)), RelocInfo::CODE_TARGET);
+ __ bind(&next_map);
+ }
}
__ bind(&miss);
@@ -3110,7 +3068,7 @@
}
-MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
+MaybeObject* KeyedLoadStubCompiler::CompileLoadPolymorphic(
MapList* receiver_maps,
CodeList* handler_ics) {
// ----------- S t a t e -------------
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev