Commit ae6e6a68 authored by ulan@chromium.org's avatar ulan@chromium.org

Handlify KeyedIC::ComputeStub.

BUG=
TEST=

Review URL: http://codereview.chromium.org/8356041

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9741 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 9b0626b5
...@@ -971,36 +971,30 @@ void LoadIC::UpdateCaches(LookupResult* lookup, ...@@ -971,36 +971,30 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
} }
MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck(
bool is_js_array, bool is_js_array,
ElementsKind elements_kind) { ElementsKind elements_kind) {
return KeyedLoadElementStub(elements_kind).TryGetCode(); return KeyedLoadElementStub(elements_kind).GetCode();
} }
MaybeObject* KeyedLoadIC::ComputePolymorphicStub( Handle<Code> KeyedLoadIC::ComputePolymorphicStub(
MapList* receiver_maps, MapHandleList* receiver_maps,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
CodeList handler_ics(receiver_maps->length()); CodeHandleList handler_ics(receiver_maps->length());
for (int i = 0; i < receiver_maps->length(); ++i) { for (int i = 0; i < receiver_maps->length(); ++i) {
Map* receiver_map(receiver_maps->at(i)); Handle<Map> receiver_map = receiver_maps->at(i);
MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( Handle<Code> cached_stub = ComputeMonomorphicStubWithoutMapCheck(
receiver_map, strict_mode); receiver_map, strict_mode);
Code* cached_stub;
if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
handler_ics.Add(cached_stub); handler_ics.Add(cached_stub);
} }
Object* object;
HandleScope scope(isolate());
KeyedLoadStubCompiler compiler(isolate()); KeyedLoadStubCompiler compiler(isolate());
MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps, Handle<Code> code = compiler.CompileLoadPolymorphic(
&handler_ics); receiver_maps, &handler_ics);
if (!maybe_code->ToObject(&object)) return maybe_code;
isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
PROFILE(isolate(), CodeCreateEvent( PROFILE(isolate(),
Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0));
Code::cast(object), 0)); return code;
return object;
} }
...@@ -1034,8 +1028,7 @@ MaybeObject* KeyedLoadIC::Load(State state, ...@@ -1034,8 +1028,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
name->Equals(isolate()->heap()->length_symbol())) { name->Equals(isolate()->heap()->length_symbol())) {
Handle<String> string = Handle<String>::cast(object); Handle<String> string = Handle<String>::cast(object);
Handle<Code> code = Handle<Code> code =
isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
string);
ASSERT(!code.is_null()); ASSERT(!code.is_null());
set_target(*code); set_target(*code);
TRACE_IC("KeyedLoadIC", name, state, target()); TRACE_IC("KeyedLoadIC", name, state, target());
...@@ -1420,10 +1413,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ...@@ -1420,10 +1413,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
} }
static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
Map* new_receiver_map) { Handle<Map> new_receiver_map) {
ASSERT(!new_receiver_map.is_null());
for (int current = 0; current < receiver_maps->length(); ++current) { for (int current = 0; current < receiver_maps->length(); ++current) {
if (receiver_maps->at(current) == new_receiver_map) { if (!receiver_maps->at(current).is_null() &&
receiver_maps->at(current).is_identical_to(new_receiver_map)) {
return false; return false;
} }
} }
...@@ -1432,22 +1427,23 @@ static bool AddOneReceiverMapIfMissing(MapList* receiver_maps, ...@@ -1432,22 +1427,23 @@ static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
} }
void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) { void KeyedIC::GetReceiverMapsForStub(Handle<Code> stub,
MapHandleList* result) {
ASSERT(stub->is_inline_cache_stub()); ASSERT(stub->is_inline_cache_stub());
if (!string_stub().is_null() && stub == *string_stub()) { if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
return result->Add(isolate()->heap()->string_map()); return result->Add(isolate()->factory()->string_map());
} else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) { } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
if (stub->ic_state() == MONOMORPHIC) { if (stub->ic_state() == MONOMORPHIC) {
result->Add(Map::cast(stub->FindFirstMap())); result->Add(Handle<Map>(stub->FindFirstMap()));
} else { } else {
ASSERT(stub->ic_state() == MEGAMORPHIC); ASSERT(stub->ic_state() == MEGAMORPHIC);
AssertNoAllocation no_allocation; AssertNoAllocation no_allocation;
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
for (RelocIterator it(stub, mask); !it.done(); it.next()) { for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo(); RelocInfo* info = it.rinfo();
Object* object = info->target_object(); Handle<Object> object(info->target_object());
ASSERT(object->IsMap()); ASSERT(object->IsMap());
AddOneReceiverMapIfMissing(result, Map::cast(object)); AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
} }
} }
} }
...@@ -1458,33 +1454,13 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver, ...@@ -1458,33 +1454,13 @@ Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
StubKind stub_kind, StubKind stub_kind,
StrictModeFlag strict_mode, StrictModeFlag strict_mode,
Handle<Code> generic_stub) { Handle<Code> generic_stub) {
CALL_HEAP_FUNCTION(isolate(),
ComputeStub(*receiver,
stub_kind,
strict_mode,
*generic_stub),
Code);
}
MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
Code* generic_stub) {
State ic_state = target()->ic_state(); State ic_state = target()->ic_state();
if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
!IsTransitionStubKind(stub_kind)) { !IsTransitionStubKind(stub_kind)) {
Code* monomorphic_stub; return ComputeMonomorphicStub(
MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, receiver, stub_kind, strict_mode, generic_stub);
stub_kind,
strict_mode,
generic_stub);
if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
return monomorphic_stub;
} }
ASSERT(target() != generic_stub); ASSERT(target() != *generic_stub);
// Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
// via megamorphic stubs, since they don't have a map in their relocation info // via megamorphic stubs, since they don't have a map in their relocation info
...@@ -1495,18 +1471,17 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, ...@@ -1495,18 +1471,17 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
// Determine the list of receiver maps that this call site has seen, // Determine the list of receiver maps that this call site has seen,
// adding the map that was just encountered. // adding the map that was just encountered.
MapList target_receiver_maps; MapHandleList target_receiver_maps;
Handle<Map> receiver_map(receiver->map());
if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
target_receiver_maps.Add(receiver->map()); target_receiver_maps.Add(receiver_map);
} else { } else {
GetReceiverMapsForStub(target(), &target_receiver_maps); GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
} }
bool map_added = bool map_added =
AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map()); AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
if (IsTransitionStubKind(stub_kind)) { if (IsTransitionStubKind(stub_kind)) {
MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind); Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
Map* new_map = NULL;
if (!maybe_map->To(&new_map)) return maybe_map;
map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map); map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
} }
if (!map_added) { if (!map_added) {
...@@ -1521,32 +1496,25 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, ...@@ -1521,32 +1496,25 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
return generic_stub; return generic_stub;
} }
PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); Handle<PolymorphicCodeCache> cache =
Code::Flags flags = Code::ComputeFlags(this->kind(), isolate()->factory()->polymorphic_code_cache();
MEGAMORPHIC, Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode);
strict_mode); Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); if (probe->IsCode()) return Handle<Code>::cast(probe);
// If there is a cached stub, use it.
if (!maybe_cached_stub->IsUndefined()) { Handle<Code> stub =
ASSERT(maybe_cached_stub->IsCode());
return Code::cast(maybe_cached_stub);
}
MaybeObject* maybe_stub =
ComputePolymorphicStub(&target_receiver_maps, strict_mode); ComputePolymorphicStub(&target_receiver_maps, strict_mode);
Code* stub; PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
if (!maybe_stub->To(&stub)) return maybe_stub;
MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub);
if (maybe_update->IsFailure()) return maybe_update;
return stub; return stub;
} }
MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
Map* receiver_map, Handle<Map> receiver_map,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
if ((receiver_map->instance_type() & kNotStringTag) == 0) { if ((receiver_map->instance_type() & kNotStringTag) == 0) {
ASSERT(!string_stub().is_null()); ASSERT(!string_stub().is_null());
return *string_stub(); return string_stub();
} else { } else {
ASSERT(receiver_map->has_dictionary_elements() || ASSERT(receiver_map->has_dictionary_elements() ||
receiver_map->has_fast_elements() || receiver_map->has_fast_elements() ||
...@@ -1560,85 +1528,78 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( ...@@ -1560,85 +1528,78 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
} }
MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver, Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<JSObject> receiver,
StubKind stub_kind, StubKind stub_kind,
StrictModeFlag strict_mode, StrictModeFlag strict_mode,
Code* generic_stub) { Handle<Code> generic_stub) {
Code* result = NULL;
if (receiver->HasFastElements() || if (receiver->HasFastElements() ||
receiver->HasFastSmiOnlyElements() || receiver->HasFastSmiOnlyElements() ||
receiver->HasExternalArrayElements() || receiver->HasExternalArrayElements() ||
receiver->HasFastDoubleElements() || receiver->HasFastDoubleElements() ||
receiver->HasDictionaryElements()) { receiver->HasDictionaryElements()) {
MaybeObject* maybe_stub = return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( receiver, stub_kind, strict_mode);
receiver, stub_kind, strict_mode);
if (!maybe_stub->To(&result)) return maybe_stub;
} else { } else {
result = generic_stub; return generic_stub;
} }
return result;
} }
MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver, Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
StubKind stub_kind) { StubKind stub_kind) {
switch (stub_kind) { switch (stub_kind) {
case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT: case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT: case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
return receiver->GetElementsTransitionMap(FAST_ELEMENTS); return JSObject::GetElementsTransitionMap(receiver, FAST_ELEMENTS);
break;
case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE: case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return Handle<Map>::null();
} }
} }
MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck( Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck(
bool is_js_array, bool is_js_array,
ElementsKind elements_kind) { ElementsKind elements_kind) {
return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); return KeyedStoreElementStub(is_js_array, elements_kind).GetCode();
} }
MaybeObject* KeyedStoreIC::ComputePolymorphicStub( Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
MapList* receiver_maps, StrictModeFlag strict_mode) {
StrictModeFlag strict_mode) {
// Collect MONOMORPHIC stubs for all target_receiver_maps. // Collect MONOMORPHIC stubs for all target_receiver_maps.
CodeList handler_ics(receiver_maps->length()); CodeHandleList handler_ics(receiver_maps->length());
MapList transitioned_maps(receiver_maps->length()); MapHandleList transitioned_maps(receiver_maps->length());
for (int i = 0; i < receiver_maps->length(); ++i) { for (int i = 0; i < receiver_maps->length(); ++i) {
Map* receiver_map(receiver_maps->at(i)); Handle<Map> receiver_map(receiver_maps->at(i));
MaybeObject* maybe_cached_stub = NULL; Handle<Code> cached_stub;
Map* transitioned_map = receiver_map->FindTransitionedMap(receiver_maps); Handle<Map> transitioned_map =
if (transitioned_map != NULL) { receiver_map->FindTransitionedMap(receiver_maps);
maybe_cached_stub = ElementsTransitionAndStoreStub( if (!transitioned_map.is_null()) {
cached_stub = ElementsTransitionAndStoreStub(
receiver_map->elements_kind(), // original elements_kind receiver_map->elements_kind(), // original elements_kind
transitioned_map->elements_kind(), transitioned_map->elements_kind(),
receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
strict_mode).TryGetCode(); strict_mode).GetCode();
} else { } else {
maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
receiver_map, strict_mode); strict_mode);
} }
Code* cached_stub; ASSERT(!cached_stub.is_null());
if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
handler_ics.Add(cached_stub); handler_ics.Add(cached_stub);
transitioned_maps.Add(transitioned_map); transitioned_maps.Add(transitioned_map);
} }
Object* object;
HandleScope scope(isolate());
KeyedStoreStubCompiler compiler(isolate(), strict_mode); KeyedStoreStubCompiler compiler(isolate(), strict_mode);
MaybeObject* maybe_code = compiler.CompileStorePolymorphic( Handle<Code> code = compiler.CompileStorePolymorphic(
receiver_maps, &handler_ics, &transitioned_maps); receiver_maps, &handler_ics, &transitioned_maps);
if (!maybe_code->ToObject(&object)) return maybe_code;
isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
PROFILE(isolate(), CodeCreateEvent( PROFILE(isolate(),
Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0));
Code::cast(object), 0)); return code;
return object;
} }
......
...@@ -365,7 +365,7 @@ class KeyedIC: public IC { ...@@ -365,7 +365,7 @@ class KeyedIC: public IC {
explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {} explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
virtual ~KeyedIC() {} virtual ~KeyedIC() {}
virtual MaybeObject* GetElementStubWithoutMapCheck( virtual Handle<Code> GetElementStubWithoutMapCheck(
bool is_js_array, bool is_js_array,
ElementsKind elements_kind) = 0; ElementsKind elements_kind) = 0;
...@@ -381,27 +381,23 @@ class KeyedIC: public IC { ...@@ -381,27 +381,23 @@ class KeyedIC: public IC {
StrictModeFlag strict_mode, StrictModeFlag strict_mode,
Handle<Code> default_stub); Handle<Code> default_stub);
MaybeObject* ComputeStub(JSObject* receiver, virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
StubKind stub_kind,
StrictModeFlag strict_mode,
Code* default_stub);
virtual MaybeObject* ComputePolymorphicStub(MapList* receiver_maps,
StrictModeFlag strict_mode) = 0; StrictModeFlag strict_mode) = 0;
MaybeObject* ComputeMonomorphicStubWithoutMapCheck( Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
Map* receiver_map, Handle<Map> receiver_map,
StrictModeFlag strict_mode); StrictModeFlag strict_mode);
private: private:
void GetReceiverMapsForStub(Code* stub, MapList* result); void GetReceiverMapsForStub(Handle<Code> stub, MapHandleList* result);
MaybeObject* ComputeMonomorphicStub(JSObject* receiver, Handle<Code> ComputeMonomorphicStub(Handle<JSObject> receiver,
StubKind stub_kind, StubKind stub_kind,
StrictModeFlag strict_mode, StrictModeFlag strict_mode,
Code* default_stub); Handle<Code> default_stub);
MaybeObject* ComputeTransitionedMap(JSObject* receiver, StubKind stub_kind); Handle<Map> ComputeTransitionedMap(Handle<JSObject> receiver,
StubKind stub_kind);
static bool IsTransitionStubKind(StubKind stub_kind) { static bool IsTransitionStubKind(StubKind stub_kind) {
return stub_kind > STORE_NO_TRANSITION; return stub_kind > STORE_NO_TRANSITION;
...@@ -441,16 +437,15 @@ class KeyedLoadIC: public KeyedIC { ...@@ -441,16 +437,15 @@ class KeyedLoadIC: public KeyedIC {
static const int kSlowCaseBitFieldMask = static const int kSlowCaseBitFieldMask =
(1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor); (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
virtual MaybeObject* GetElementStubWithoutMapCheck( virtual Handle<Code> GetElementStubWithoutMapCheck(
bool is_js_array, bool is_js_array,
ElementsKind elements_kind); ElementsKind elements_kind);
protected: protected:
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; } virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
virtual MaybeObject* ComputePolymorphicStub( virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
MapList* receiver_maps, StrictModeFlag strict_mode);
StrictModeFlag strict_mode);
virtual Handle<Code> string_stub() { virtual Handle<Code> string_stub() {
return isolate()->builtins()->KeyedLoadIC_String(); return isolate()->builtins()->KeyedLoadIC_String();
...@@ -585,16 +580,15 @@ class KeyedStoreIC: public KeyedIC { ...@@ -585,16 +580,15 @@ class KeyedStoreIC: public KeyedIC {
static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm); static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm); static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
virtual MaybeObject* GetElementStubWithoutMapCheck( virtual Handle<Code> GetElementStubWithoutMapCheck(
bool is_js_array, bool is_js_array,
ElementsKind elements_kind); ElementsKind elements_kind);
protected: protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; } virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
virtual MaybeObject* ComputePolymorphicStub( virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
MapList* receiver_maps, StrictModeFlag strict_mode);
StrictModeFlag strict_mode);
private: private:
// Update the inline cache. // Update the inline cache.
......
...@@ -236,6 +236,19 @@ int SortedListBSearch(const List<T>& list, T elem) { ...@@ -236,6 +236,19 @@ int SortedListBSearch(const List<T>& list, T elem) {
return SortedListBSearch<T>(list, elem, PointerValueCompare<T>); return SortedListBSearch<T>(list, elem, PointerValueCompare<T>);
} }
template <class T>
List<T*>* UnwrapHandleList(List<T*>* destination, List<Handle<T> >* source) {
ASSERT(destination->is_empty());
int length = source->length();
for (int i = 0; i < length; ++i) {
Handle<T> handle = source->at(i);
destination->Add(handle.is_null() ? NULL : *handle);
}
return destination;
}
} } // namespace v8::internal } } // namespace v8::internal
#endif // V8_LIST_INL_H_ #endif // V8_LIST_INL_H_
...@@ -165,8 +165,11 @@ class List { ...@@ -165,8 +165,11 @@ class List {
class Map; class Map;
class Code; class Code;
template<typename T> class Handle;
typedef List<Map*> MapList; typedef List<Map*> MapList;
typedef List<Code*> CodeList; typedef List<Code*> CodeList;
typedef List<Handle<Map> > MapHandleList;
typedef List<Handle<Code> > CodeHandleList;
// Perform binary search for an element in an already sorted // Perform binary search for an element in an already sorted
// list. Returns the index of the element of -1 if it was not found. // list. Returns the index of the element of -1 if it was not found.
...@@ -176,6 +179,15 @@ int SortedListBSearch( ...@@ -176,6 +179,15 @@ int SortedListBSearch(
template <typename T> template <typename T>
int SortedListBSearch(const List<T>& list, T elem); int SortedListBSearch(const List<T>& list, T elem);
// Unwraps each handle in the source list to a pointer at
// the corresponding position in the destination list.
// Returns the destination list.
// Both list must have the same length.
template <class T>
List<T*>* UnwrapHandleList(List<T*>* destination, List<Handle<T> >* source);
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -2190,6 +2190,14 @@ static bool ContainsMap(MapList* maps_list, Map* map) { ...@@ -2190,6 +2190,14 @@ static bool ContainsMap(MapList* maps_list, Map* map) {
} }
Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
MapList raw_candidates(candidates->length());
Map* result = FindTransitionedMap(UnwrapHandleList(&raw_candidates,
candidates));
return (result == NULL) ? Handle<Map>::null() : Handle<Map>(result);
}
Map* Map::FindTransitionedMap(MapList* candidates) { Map* Map::FindTransitionedMap(MapList* candidates) {
ElementsKind elms_kind = elements_kind(); ElementsKind elms_kind = elements_kind();
if (elms_kind == FAST_DOUBLE_ELEMENTS) { if (elms_kind == FAST_DOUBLE_ELEMENTS) {
...@@ -2397,6 +2405,15 @@ MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind, ...@@ -2397,6 +2405,15 @@ MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
} }
Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
ElementsKind to_kind) {
Isolate* isolate = object->GetIsolate();
CALL_HEAP_FUNCTION(isolate,
object->GetElementsTransitionMap(to_kind),
Map);
}
MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) { MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) {
Map* current_map = map(); Map* current_map = map();
ElementsKind from_kind = current_map->elements_kind(); ElementsKind from_kind = current_map->elements_kind();
...@@ -5124,6 +5141,19 @@ void CodeCacheHashTable::RemoveByIndex(int index) { ...@@ -5124,6 +5141,19 @@ void CodeCacheHashTable::RemoveByIndex(int index) {
} }
void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
MapHandleList* maps,
Code::Flags flags,
Handle<Code> code) {
Isolate* isolate = cache->GetIsolate();
List<Map*> raw_maps(maps->length());
CALL_HEAP_FUNCTION_VOID(
isolate,
(raw_maps.Clear(),
cache->Update(UnwrapHandleList(&raw_maps, maps), flags, *code)));
}
MaybeObject* PolymorphicCodeCache::Update(MapList* maps, MaybeObject* PolymorphicCodeCache::Update(MapList* maps,
Code::Flags flags, Code::Flags flags,
Code* code) { Code* code) {
...@@ -5152,6 +5182,13 @@ MaybeObject* PolymorphicCodeCache::Update(MapList* maps, ...@@ -5152,6 +5182,13 @@ MaybeObject* PolymorphicCodeCache::Update(MapList* maps,
} }
Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
Code::Flags flags) {
List<Map*> raw_maps(maps->length());
return Handle<Object>(Lookup(UnwrapHandleList(&raw_maps, maps), flags));
}
Object* PolymorphicCodeCache::Lookup(MapList* maps, Code::Flags flags) { Object* PolymorphicCodeCache::Lookup(MapList* maps, Code::Flags flags) {
if (!cache()->IsUndefined()) { if (!cache()->IsUndefined()) {
PolymorphicCodeCacheHashTable* hash_table = PolymorphicCodeCacheHashTable* hash_table =
......
...@@ -1800,6 +1800,8 @@ class JSObject: public JSReceiver { ...@@ -1800,6 +1800,8 @@ class JSObject: public JSReceiver {
// Returns a new map with all transitions dropped from the object's current // Returns a new map with all transitions dropped from the object's current
// map and the ElementsKind set. // map and the ElementsKind set.
static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
ElementsKind to_kind);
MUST_USE_RESULT MaybeObject* GetElementsTransitionMap( MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
ElementsKind elements_kind); ElementsKind elements_kind);
...@@ -4355,10 +4357,12 @@ class Map: public HeapObject { ...@@ -4355,10 +4357,12 @@ class Map: public HeapObject {
Map* transitioned_map); Map* transitioned_map);
// Returns the transitioned map for this map with the most generic // Returns the transitioned map for this map with the most generic
// elements_kind that's found in |candidates|, or NULL if no match is // elements_kind that's found in |candidates|, or null handle if no match is
// found at all. // found at all.
Handle<Map> FindTransitionedMap(MapHandleList* candidates);
Map* FindTransitionedMap(MapList* candidates); Map* FindTransitionedMap(MapList* candidates);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
inline void MapPrint() { inline void MapPrint() {
...@@ -5859,9 +5863,18 @@ class PolymorphicCodeCache: public Struct { ...@@ -5859,9 +5863,18 @@ class PolymorphicCodeCache: public Struct {
public: public:
DECL_ACCESSORS(cache, Object) DECL_ACCESSORS(cache, Object)
static void Update(Handle<PolymorphicCodeCache> cache,
MapHandleList* maps,
Code::Flags flags,
Handle<Code> code);
MUST_USE_RESULT MaybeObject* Update(MapList* maps, MUST_USE_RESULT MaybeObject* Update(MapList* maps,
Code::Flags flags, Code::Flags flags,
Code* code); Code* code);
// Returns an undefined value if the entry is not found.
Handle<Object> Lookup(MapHandleList* maps, Code::Flags flags);
Object* Lookup(MapList* maps, Code::Flags flags); Object* Lookup(MapList* maps, Code::Flags flags);
static inline PolymorphicCodeCache* cast(Object* obj); static inline PolymorphicCodeCache* cast(Object* obj);
......
...@@ -542,8 +542,23 @@ Handle<Code> StubCache::ComputeStoreField(Handle<String> name, ...@@ -542,8 +542,23 @@ Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
} }
MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement( Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(Handle<Map> map) {
JSObject* receiver, CALL_HEAP_FUNCTION(isolate(),
(set_failure(NULL), CompileLoadElement(*map)),
Code);
}
Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(Handle<Map> map) {
CALL_HEAP_FUNCTION(isolate(),
(set_failure(NULL),
CompileStoreElement(*map)),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadOrStoreElement(
Handle<JSObject> receiver,
KeyedIC::StubKind stub_kind, KeyedIC::StubKind stub_kind,
StrictModeFlag strict_mode) { StrictModeFlag strict_mode) {
Code::Flags flags = Code::Flags flags =
...@@ -552,62 +567,92 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement( ...@@ -552,62 +567,92 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
: Code::KEYED_STORE_IC, : Code::KEYED_STORE_IC,
NORMAL, NORMAL,
strict_mode); strict_mode);
String* name = NULL; Handle<String> name;
switch (stub_kind) { switch (stub_kind) {
case KeyedIC::LOAD: case KeyedIC::LOAD:
name = isolate()->heap()->KeyedLoadElementMonomorphic_symbol(); name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
break; break;
case KeyedIC::STORE_NO_TRANSITION: case KeyedIC::STORE_NO_TRANSITION:
name = isolate()->heap()->KeyedStoreElementMonomorphic_symbol(); name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
Object* maybe_code = receiver->map()->FindInCodeCache(name, flags); Handle<Map> receiver_map(receiver->map());
if (!maybe_code->IsUndefined()) return Code::cast(maybe_code); Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
Map* receiver_map = receiver->map(); Handle<Code> code;
MaybeObject* maybe_new_code = NULL;
switch (stub_kind) { switch (stub_kind) {
case KeyedIC::LOAD: { case KeyedIC::LOAD: {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_); KeyedLoadStubCompiler compiler(isolate_);
maybe_new_code = compiler.CompileLoadElement(receiver_map); code = compiler.CompileLoadElement(receiver_map);
break; break;
} }
case KeyedIC::STORE_NO_TRANSITION: { case KeyedIC::STORE_NO_TRANSITION: {
HandleScope scope(isolate_);
KeyedStoreStubCompiler compiler(isolate_, strict_mode); KeyedStoreStubCompiler compiler(isolate_, strict_mode);
maybe_new_code = compiler.CompileStoreElement(receiver_map); code = compiler.CompileStoreElement(receiver_map);
break; break;
} }
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
} }
Code* code = NULL;
if (!maybe_new_code->To(&code)) return maybe_new_code; ASSERT(!code.is_null());
if (stub_kind == KeyedIC::LOAD) { if (stub_kind == KeyedIC::LOAD) {
PROFILE(isolate_, PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
Code::cast(code), 0));
} else { } else {
PROFILE(isolate_, PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
Code::cast(code), 0));
}
ASSERT(code->IsCode());
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
} }
JSObject::UpdateMapCodeCache(receiver, name, code);
return code; return code;
} }
Handle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs) {
MapList raw_receiver_maps(receiver_maps->length());
CodeList raw_handler_stubs(handler_stubs->length());
CALL_HEAP_FUNCTION(
isolate(),
(set_failure(NULL),
raw_receiver_maps.Clear(),
raw_handler_stubs.Clear(),
CompileLoadPolymorphic(UnwrapHandleList(&raw_receiver_maps,
receiver_maps),
UnwrapHandleList(&raw_handler_stubs,
handler_stubs))),
Code);
}
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
MapList raw_receiver_maps(receiver_maps->length());
CodeList raw_handler_stubs(handler_stubs->length());
MapList raw_transitioned_maps(transitioned_maps->length());
CALL_HEAP_FUNCTION(
isolate(),
(set_failure(NULL),
raw_receiver_maps.Clear(),
raw_handler_stubs.Clear(),
raw_transitioned_maps.Clear(),
CompileStorePolymorphic(UnwrapHandleList(&raw_receiver_maps,
receiver_maps),
UnwrapHandleList(&raw_handler_stubs,
handler_stubs),
UnwrapHandleList(&raw_transitioned_maps,
transitioned_maps))),
Code);
}
Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) {
return (strict_mode == kStrictMode) return (strict_mode == kStrictMode)
? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
......
...@@ -168,10 +168,9 @@ class StubCache { ...@@ -168,10 +168,9 @@ class StubCache {
Handle<Map> transition, Handle<Map> transition,
StrictModeFlag strict_mode); StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreElement( Handle<Code> ComputeKeyedLoadOrStoreElement(Handle<JSObject> receiver,
JSObject* receiver, KeyedIC::StubKind stub_kind,
KeyedIC::StubKind stub_kind, StrictModeFlag strict_mode);
StrictModeFlag strict_mode);
// --- // ---
...@@ -687,8 +686,13 @@ class KeyedLoadStubCompiler: public StubCompiler { ...@@ -687,8 +686,13 @@ class KeyedLoadStubCompiler: public StubCompiler {
MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name); MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map); MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);
Handle<Code> CompileLoadPolymorphic(MapHandleList* receiver_maps,
CodeHandleList* handler_ics);
MUST_USE_RESULT MaybeObject* CompileLoadPolymorphic( MUST_USE_RESULT MaybeObject* CompileLoadPolymorphic(
MapList* receiver_maps, MapList* receiver_maps,
CodeList* handler_ics); CodeList* handler_ics);
...@@ -769,8 +773,14 @@ class KeyedStoreStubCompiler: public StubCompiler { ...@@ -769,8 +773,14 @@ class KeyedStoreStubCompiler: public StubCompiler {
Map* transition, Map* transition,
String* name); String* name);
Handle<Code> CompileStoreElement(Handle<Map> receiver_map);
MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map); MUST_USE_RESULT MaybeObject* CompileStoreElement(Map* receiver_map);
Handle<Code> CompileStorePolymorphic(MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps);
MUST_USE_RESULT MaybeObject* CompileStorePolymorphic( MUST_USE_RESULT MaybeObject* CompileStorePolymorphic(
MapList* receiver_maps, MapList* receiver_maps,
CodeList* handler_stubs, CodeList* handler_stubs,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment