Handlify KeyedIC::ComputeStub.
authorulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 21 Oct 2011 11:42:54 +0000 (11:42 +0000)
committerulan@chromium.org <ulan@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 21 Oct 2011 11:42:54 +0000 (11:42 +0000)
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

src/ic.cc
src/ic.h
src/list-inl.h
src/list.h
src/objects.cc
src/objects.h
src/stub-cache.cc
src/stub-cache.h

index 5f779b1..55d2d0b 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -971,36 +971,30 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
 }
 
 
-MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck(
+Handle<Code> KeyedLoadIC::GetElementStubWithoutMapCheck(
     bool is_js_array,
     ElementsKind elements_kind) {
-  return KeyedLoadElementStub(elements_kind).TryGetCode();
+  return KeyedLoadElementStub(elements_kind).GetCode();
 }
 
 
-MaybeObject* KeyedLoadIC::ComputePolymorphicStub(
-    MapList* receiver_maps,
+Handle<Code> KeyedLoadIC::ComputePolymorphicStub(
+    MapHandleList* receiver_maps,
     StrictModeFlag strict_mode) {
-  CodeList handler_ics(receiver_maps->length());
+  CodeHandleList 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(
+    Handle<Map> receiver_map = receiver_maps->at(i);
+    Handle<Code> 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;
-  HandleScope scope(isolate());
   KeyedLoadStubCompiler compiler(isolate());
-  MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps,
-                                                            &handler_ics);
-  if (!maybe_code->ToObject(&object)) return maybe_code;
+  Handle<Code> code = compiler.CompileLoadPolymorphic(
+      receiver_maps, &handler_ics);
   isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
-  PROFILE(isolate(), CodeCreateEvent(
-      Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
-      Code::cast(object), 0));
-  return object;
+  PROFILE(isolate(),
+          CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0));
+  return code;
 }
 
 
@@ -1034,8 +1028,7 @@ MaybeObject* KeyedLoadIC::Load(State state,
           name->Equals(isolate()->heap()->length_symbol())) {
         Handle<String> string = Handle<String>::cast(object);
         Handle<Code> code =
-            isolate()->stub_cache()->ComputeKeyedLoadStringLength(name,
-                                                                  string);
+            isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
         ASSERT(!code.is_null());
         set_target(*code);
         TRACE_IC("KeyedLoadIC", name, state, target());
@@ -1420,10 +1413,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
 }
 
 
-static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
-                                       Map* new_receiver_map) {
+static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
+                                       Handle<Map> new_receiver_map) {
+  ASSERT(!new_receiver_map.is_null());
   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;
     }
   }
@@ -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());
-  if (!string_stub().is_null() && stub == *string_stub()) {
-    return result->Add(isolate()->heap()->string_map());
+  if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
+    return result->Add(isolate()->factory()->string_map());
   } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
     if (stub->ic_state() == MONOMORPHIC) {
-      result->Add(Map::cast(stub->FindFirstMap()));
+      result->Add(Handle<Map>(stub->FindFirstMap()));
     } else {
       ASSERT(stub->ic_state() == MEGAMORPHIC);
       AssertNoAllocation no_allocation;
       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();
-        Object* object = info->target_object();
+        Handle<Object> object(info->target_object());
         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,
                                   StubKind stub_kind,
                                   StrictModeFlag strict_mode,
                                   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();
   if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) &&
       !IsTransitionStubKind(stub_kind)) {
-    Code* monomorphic_stub;
-    MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
-                                                     stub_kind,
-                                                     strict_mode,
-                                                     generic_stub);
-    if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
-
-    return monomorphic_stub;
+    return ComputeMonomorphicStub(
+        receiver, stub_kind, strict_mode, generic_stub);
   }
-  ASSERT(target() != generic_stub);
+  ASSERT(target() != *generic_stub);
 
   // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
   // via megamorphic stubs, since they don't have a map in their relocation info
@@ -1495,18 +1471,17 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
 
   // Determine the list of receiver maps that this call site has seen,
   // 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) {
-    target_receiver_maps.Add(receiver->map());
+    target_receiver_maps.Add(receiver_map);
   } else {
-    GetReceiverMapsForStub(target(), &target_receiver_maps);
+    GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
   }
   bool map_added =
-      AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map());
+      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;
+    Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
     map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
   }
   if (!map_added) {
@@ -1521,32 +1496,25 @@ MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
     return generic_stub;
   }
 
-  PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache();
-  Code::Flags flags = Code::ComputeFlags(this->kind(),
-                                         MEGAMORPHIC,
-                                         strict_mode);
-  Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags);
-  // If there is a cached stub, use it.
-  if (!maybe_cached_stub->IsUndefined()) {
-    ASSERT(maybe_cached_stub->IsCode());
-    return Code::cast(maybe_cached_stub);
-  }
-  MaybeObject* maybe_stub =
+  Handle<PolymorphicCodeCache> cache =
+      isolate()->factory()->polymorphic_code_cache();
+  Code::Flags flags = Code::ComputeFlags(kind(), MEGAMORPHIC, strict_mode);
+  Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
+  if (probe->IsCode()) return Handle<Code>::cast(probe);
+
+  Handle<Code> 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);
-  if (maybe_update->IsFailure()) return maybe_update;
+  PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
   return stub;
 }
 
 
-MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
-    Map* receiver_map,
+Handle<Code> KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
+    Handle<Map> receiver_map,
     StrictModeFlag strict_mode) {
   if ((receiver_map->instance_type() & kNotStringTag) == 0) {
     ASSERT(!string_stub().is_null());
-    return *string_stub();
+    return string_stub();
   } else {
     ASSERT(receiver_map->has_dictionary_elements() ||
            receiver_map->has_fast_elements() ||
@@ -1560,85 +1528,78 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
 }
 
 
-MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
+Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<JSObject> receiver,
                                              StubKind stub_kind,
                                              StrictModeFlag strict_mode,
-                                             Code* generic_stub) {
-  Code* result = NULL;
+                                             Handle<Code> generic_stub) {
   if (receiver->HasFastElements() ||
       receiver->HasFastSmiOnlyElements() ||
       receiver->HasExternalArrayElements() ||
       receiver->HasFastDoubleElements() ||
       receiver->HasDictionaryElements()) {
-    MaybeObject* maybe_stub =
-        isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
-            receiver, stub_kind, strict_mode);
-    if (!maybe_stub->To(&result)) return maybe_stub;
+    return isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
+        receiver, stub_kind, strict_mode);
   } else {
-    result = generic_stub;
+    return generic_stub;
   }
-  return result;
 }
 
 
-MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver,
-                                             StubKind stub_kind) {
+Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
+                                            StubKind stub_kind) {
   switch (stub_kind) {
     case KeyedIC::STORE_TRANSITION_SMI_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:
-      return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
+      return JSObject::GetElementsTransitionMap(receiver, FAST_DOUBLE_ELEMENTS);
+      break;
     default:
       UNREACHABLE();
-      return NULL;
+      return Handle<Map>::null();
   }
 }
 
 
-MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck(
+Handle<Code> KeyedStoreIC::GetElementStubWithoutMapCheck(
     bool is_js_array,
     ElementsKind elements_kind) {
-  return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
+  return KeyedStoreElementStub(is_js_array, elements_kind).GetCode();
 }
 
 
-MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
-    MapList* receiver_maps,
-    StrictModeFlag strict_mode) {
+Handle<Code> KeyedStoreIC::ComputePolymorphicStub(MapHandleList* receiver_maps,
+                                                  StrictModeFlag strict_mode) {
   // Collect MONOMORPHIC stubs for all target_receiver_maps.
-  CodeList handler_ics(receiver_maps->length());
-  MapList transitioned_maps(receiver_maps->length());
+  CodeHandleList handler_ics(receiver_maps->length());
+  MapHandleList 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 = receiver_map->FindTransitionedMap(receiver_maps);
-    if (transitioned_map != NULL) {
-      maybe_cached_stub = ElementsTransitionAndStoreStub(
+    Handle<Map> receiver_map(receiver_maps->at(i));
+    Handle<Code> cached_stub;
+    Handle<Map> transitioned_map =
+        receiver_map->FindTransitionedMap(receiver_maps);
+    if (!transitioned_map.is_null()) {
+      cached_stub = ElementsTransitionAndStoreStub(
           receiver_map->elements_kind(),  // original elements_kind
           transitioned_map->elements_kind(),
           receiver_map->instance_type() == JS_ARRAY_TYPE,  // is_js_array
-          strict_mode).TryGetCode();
+          strict_mode).GetCode();
     } else {
-      maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
-          receiver_map, strict_mode);
+      cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
+                                                          strict_mode);
     }
-    Code* cached_stub;
-    if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
+    ASSERT(!cached_stub.is_null());
     handler_ics.Add(cached_stub);
     transitioned_maps.Add(transitioned_map);
   }
-  Object* object;
-  HandleScope scope(isolate());
   KeyedStoreStubCompiler compiler(isolate(), strict_mode);
-  MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
+  Handle<Code> 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(
-      Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
-      Code::cast(object), 0));
-  return object;
+  PROFILE(isolate(),
+          CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0));
+  return code;
 }
 
 
index d707b72..3fc593d 100644 (file)
--- a/src/ic.h
+++ b/src/ic.h
@@ -365,7 +365,7 @@ class KeyedIC: public IC {
   explicit KeyedIC(Isolate* isolate) : IC(NO_EXTRA_FRAME, isolate) {}
   virtual ~KeyedIC() {}
 
-  virtual MaybeObject* GetElementStubWithoutMapCheck(
+  virtual Handle<Code> GetElementStubWithoutMapCheck(
       bool is_js_array,
       ElementsKind elements_kind) = 0;
 
@@ -381,27 +381,23 @@ class KeyedIC: public IC {
                            StrictModeFlag strict_mode,
                            Handle<Code> default_stub);
 
-  MaybeObject* ComputeStub(JSObject* receiver,
-                           StubKind stub_kind,
-                           StrictModeFlag strict_mode,
-                           Code* default_stub);
-
-  virtual MaybeObject* ComputePolymorphicStub(MapList* receiver_maps,
+  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
                                               StrictModeFlag strict_mode) = 0;
 
-  MaybeObject* ComputeMonomorphicStubWithoutMapCheck(
-      Map* receiver_map,
+  Handle<Code> ComputeMonomorphicStubWithoutMapCheck(
+      Handle<Map> receiver_map,
       StrictModeFlag strict_mode);
 
  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,
                                       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) {
     return stub_kind > STORE_NO_TRANSITION;
@@ -441,16 +437,15 @@ class KeyedLoadIC: public KeyedIC {
   static const int kSlowCaseBitFieldMask =
       (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor);
 
-  virtual MaybeObject* GetElementStubWithoutMapCheck(
+  virtual Handle<Code> GetElementStubWithoutMapCheck(
       bool is_js_array,
       ElementsKind elements_kind);
 
  protected:
   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
 
-  virtual MaybeObject* ComputePolymorphicStub(
-      MapList* receiver_maps,
-      StrictModeFlag strict_mode);
+  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
+                                              StrictModeFlag strict_mode);
 
   virtual Handle<Code> string_stub() {
     return isolate()->builtins()->KeyedLoadIC_String();
@@ -585,16 +580,15 @@ class KeyedStoreIC: public KeyedIC {
   static void GenerateTransitionElementsSmiToDouble(MacroAssembler* masm);
   static void GenerateTransitionElementsDoubleToObject(MacroAssembler* masm);
 
-  virtual MaybeObject* GetElementStubWithoutMapCheck(
+  virtual Handle<Code> GetElementStubWithoutMapCheck(
       bool is_js_array,
       ElementsKind elements_kind);
 
  protected:
   virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
 
-  virtual MaybeObject* ComputePolymorphicStub(
-      MapList* receiver_maps,
-      StrictModeFlag strict_mode);
+  virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
+                                              StrictModeFlag strict_mode);
 
   private:
   // Update the inline cache.
index 5b5179d..34fa027 100644 (file)
@@ -236,6 +236,19 @@ int SortedListBSearch(const List<T>& list, T elem) {
   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
 
 #endif  // V8_LIST_INL_H_
index 0558709..0b605e9 100644 (file)
@@ -165,8 +165,11 @@ class List {
 
 class Map;
 class Code;
+template<typename T> class Handle;
 typedef List<Map*> MapList;
 typedef List<Code*> CodeList;
+typedef List<Handle<Map> > MapHandleList;
+typedef List<Handle<Code> > CodeHandleList;
 
 // Perform binary search for an element in an already sorted
 // list. Returns the index of the element of -1 if it was not found.
@@ -176,6 +179,15 @@ int SortedListBSearch(
 template <typename T>
 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
 
 
index 7e36ee7..8db40f0 100644 (file)
@@ -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) {
   ElementsKind elms_kind = elements_kind();
   if (elms_kind == FAST_DOUBLE_ELEMENTS) {
@@ -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) {
   Map* current_map = map();
   ElementsKind from_kind = current_map->elements_kind();
@@ -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,
                                           Code::Flags flags,
                                           Code* code) {
@@ -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) {
   if (!cache()->IsUndefined()) {
     PolymorphicCodeCacheHashTable* hash_table =
index a9afef0..87613f0 100644 (file)
@@ -1800,6 +1800,8 @@ class JSObject: public JSReceiver {
 
   // Returns a new map with all transitions dropped from the object's current
   // map and the ElementsKind set.
+  static Handle<Map> GetElementsTransitionMap(Handle<JSObject> object,
+                                              ElementsKind to_kind);
   MUST_USE_RESULT MaybeObject* GetElementsTransitionMap(
       ElementsKind elements_kind);
 
@@ -4355,10 +4357,12 @@ class Map: public HeapObject {
                                      Map* transitioned_map);
 
   // 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.
+  Handle<Map> FindTransitionedMap(MapHandleList* candidates);
   Map* FindTransitionedMap(MapList* candidates);
 
+
   // Dispatched behavior.
 #ifdef OBJECT_PRINT
   inline void MapPrint() {
@@ -5859,9 +5863,18 @@ class PolymorphicCodeCache: public Struct {
  public:
   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,
                                       Code::Flags flags,
                                       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);
 
   static inline PolymorphicCodeCache* cast(Object* obj);
index a84cb9f..bebee71 100644 (file)
@@ -542,8 +542,23 @@ Handle<Code> StubCache::ComputeStoreField(Handle<String> name,
 }
 
 
-MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
-    JSObject* receiver,
+Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(Handle<Map> map) {
+  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,
     StrictModeFlag strict_mode) {
   Code::Flags flags =
@@ -552,62 +567,92 @@ MaybeObject* StubCache::ComputeKeyedLoadOrStoreElement(
                                      : Code::KEYED_STORE_IC,
           NORMAL,
           strict_mode);
-  String* name = NULL;
+  Handle<String> name;
   switch (stub_kind) {
     case KeyedIC::LOAD:
-      name = isolate()->heap()->KeyedLoadElementMonomorphic_symbol();
+      name = isolate()->factory()->KeyedLoadElementMonomorphic_symbol();
       break;
     case KeyedIC::STORE_NO_TRANSITION:
-      name = isolate()->heap()->KeyedStoreElementMonomorphic_symbol();
+      name = isolate()->factory()->KeyedStoreElementMonomorphic_symbol();
       break;
     default:
       UNREACHABLE();
       break;
   }
-  Object* maybe_code = receiver->map()->FindInCodeCache(name, flags);
-  if (!maybe_code->IsUndefined()) return Code::cast(maybe_code);
+  Handle<Map> receiver_map(receiver->map());
+  Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags));
+  if (probe->IsCode()) return Handle<Code>::cast(probe);
 
-  Map* receiver_map = receiver->map();
-  MaybeObject* maybe_new_code = NULL;
+  Handle<Code> code;
   switch (stub_kind) {
     case KeyedIC::LOAD: {
-      HandleScope scope(isolate_);
       KeyedLoadStubCompiler compiler(isolate_);
-      maybe_new_code = compiler.CompileLoadElement(receiver_map);
+      code = compiler.CompileLoadElement(receiver_map);
       break;
     }
     case KeyedIC::STORE_NO_TRANSITION: {
-      HandleScope scope(isolate_);
       KeyedStoreStubCompiler compiler(isolate_, strict_mode);
-      maybe_new_code = compiler.CompileStoreElement(receiver_map);
+      code = compiler.CompileStoreElement(receiver_map);
       break;
     }
     default:
       UNREACHABLE();
       break;
   }
-  Code* code = NULL;
-  if (!maybe_new_code->To(&code)) return maybe_new_code;
+
+  ASSERT(!code.is_null());
 
   if (stub_kind == KeyedIC::LOAD) {
-    PROFILE(isolate_,
-            CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
-                            Code::cast(code), 0));
+    PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0));
   } else {
-    PROFILE(isolate_,
-            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;
+    PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0));
   }
+  JSObject::UpdateMapCodeCache(receiver, name, 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) {
   return (strict_mode == kStrictMode)
       ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict()
index a12e8a9..3545b44 100644 (file)
@@ -168,10 +168,9 @@ class StubCache {
                                       Handle<Map> transition,
                                       StrictModeFlag strict_mode);
 
-  MUST_USE_RESULT MaybeObject* ComputeKeyedLoadOrStoreElement(
-      JSObject* receiver,
-      KeyedIC::StubKind stub_kind,
-      StrictModeFlag strict_mode);
+  Handle<Code> ComputeKeyedLoadOrStoreElement(Handle<JSObject> receiver,
+                                              KeyedIC::StubKind stub_kind,
+                                              StrictModeFlag strict_mode);
 
   // ---
 
@@ -687,8 +686,13 @@ class KeyedLoadStubCompiler: public StubCompiler {
 
   MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
 
+  Handle<Code> CompileLoadElement(Handle<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(
       MapList* receiver_maps,
       CodeList* handler_ics);
@@ -769,8 +773,14 @@ class KeyedStoreStubCompiler: public StubCompiler {
                                                  Map* transition,
                                                  String* name);
 
+  Handle<Code> CompileStoreElement(Handle<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(
       MapList* receiver_maps,
       CodeList* handler_stubs,