Improve memory usage of receiver type feedback.
authorvitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Aug 2011 14:23:37 +0000 (14:23 +0000)
committervitalyr@chromium.org <vitalyr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 22 Aug 2011 14:23:37 +0000 (14:23 +0000)
Some AST nodes (Property, Call, etc.) store either a list of receiver
types or a monomorphic receiver type. This patch merges the two fields
using a small pointer list. GetMonomorphicReceiverType() is now a
purely convenience function returning the first and only recorded
type.

This saves about 500K (of about 39M) on average when compiling V8
benchmark as measured by a simple patch adding a zone allocation
counter (https://gist.github.com/1149397).

R=kmillikin@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/ast.cc
src/ast.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/small-pointer-list.h
src/stub-cache.cc
src/stub-cache.h
src/type-info.cc
src/type-info.h
src/zone.h

index 3e6d856ce43cc60a9f587791572840e8a4c7b15c..7319abe6ddefc7625f68fc47a2f30fe96638ca0d 100644 (file)
@@ -139,8 +139,7 @@ Assignment::Assignment(Isolate* isolate,
       assignment_id_(GetNextId(isolate)),
       block_start_(false),
       block_end_(false),
-      is_monomorphic_(false),
-      receiver_types_(NULL) {
+      is_monomorphic_(false) {
   ASSERT(Token::IsAssignmentOp(op));
   if (is_compound()) {
     binary_operation_ =
@@ -652,6 +651,7 @@ bool CountOperation::IsInlineable() const {
 void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
   // Record type feedback from the oracle in the AST.
   is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
+  receiver_types_.Clear();
   if (key()->IsPropertyName()) {
     if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
       is_array_length_ = true;
@@ -664,16 +664,15 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
       Literal* lit_key = key()->AsLiteral();
       ASSERT(lit_key != NULL && lit_key->handle()->IsString());
       Handle<String> name = Handle<String>::cast(lit_key->handle());
-      ZoneMapList* types = oracle->LoadReceiverTypes(this, name);
-      receiver_types_ = types;
+      oracle->LoadReceiverTypes(this, name, &receiver_types_);
     }
   } else if (oracle->LoadIsBuiltin(this, Builtins::kKeyedLoadIC_String)) {
     is_string_access_ = true;
   } else if (is_monomorphic_) {
-    monomorphic_receiver_type_ = oracle->LoadMonomorphicReceiverType(this);
+    receiver_types_.Add(oracle->LoadMonomorphicReceiverType(this));
   } else if (oracle->LoadIsMegamorphicWithTypeInfo(this)) {
-    receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
-    oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
+    receiver_types_.Reserve(kMaxKeyedPolymorphism);
+    oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
   }
 }
 
@@ -682,30 +681,31 @@ void Assignment::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
   Property* prop = target()->AsProperty();
   ASSERT(prop != NULL);
   is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
+  receiver_types_.Clear();
   if (prop->key()->IsPropertyName()) {
     Literal* lit_key = prop->key()->AsLiteral();
     ASSERT(lit_key != NULL && lit_key->handle()->IsString());
     Handle<String> name = Handle<String>::cast(lit_key->handle());
-    ZoneMapList* types = oracle->StoreReceiverTypes(this, name);
-    receiver_types_ = types;
+    oracle->StoreReceiverTypes(this, name, &receiver_types_);
   } else if (is_monomorphic_) {
     // Record receiver type for monomorphic keyed stores.
-    monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
+    receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
   } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
-    receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
-    oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
+    receiver_types_.Reserve(kMaxKeyedPolymorphism);
+    oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
   }
 }
 
 
 void CountOperation::RecordTypeFeedback(TypeFeedbackOracle* oracle) {
   is_monomorphic_ = oracle->StoreIsMonomorphicNormal(this);
+  receiver_types_.Clear();
   if (is_monomorphic_) {
     // Record receiver type for monomorphic keyed stores.
-    monomorphic_receiver_type_ = oracle->StoreMonomorphicReceiverType(this);
+    receiver_types_.Add(oracle->StoreMonomorphicReceiverType(this));
   } else if (oracle->StoreIsMegamorphicWithTypeInfo(this)) {
-    receiver_types_ = new ZoneMapList(kMaxKeyedPolymorphism);
-    oracle->CollectKeyedReceiverTypes(this->id(), receiver_types_);
+    receiver_types_.Reserve(kMaxKeyedPolymorphism);
+    oracle->CollectKeyedReceiverTypes(this->id(), &receiver_types_);
   }
 }
 
@@ -789,15 +789,14 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
   Literal* key = property->key()->AsLiteral();
   ASSERT(key != NULL && key->handle()->IsString());
   Handle<String> name = Handle<String>::cast(key->handle());
-  receiver_types_ = oracle->CallReceiverTypes(this, name, call_kind);
+  receiver_types_.Clear();
+  oracle->CallReceiverTypes(this, name, call_kind, &receiver_types_);
 #ifdef DEBUG
   if (FLAG_enable_slow_asserts) {
-    if (receiver_types_ != NULL) {
-      int length = receiver_types_->length();
-      for (int i = 0; i < length; i++) {
-        Handle<Map> map = receiver_types_->at(i);
-        ASSERT(!map.is_null() && *map != NULL);
-      }
+    int length = receiver_types_.length();
+    for (int i = 0; i < length; i++) {
+      Handle<Map> map = receiver_types_.at(i);
+      ASSERT(!map.is_null() && *map != NULL);
     }
   }
 #endif
@@ -805,9 +804,9 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle,
   check_type_ = oracle->GetCallCheckType(this);
   if (is_monomorphic_) {
     Handle<Map> map;
-    if (receiver_types_ != NULL && receiver_types_->length() > 0) {
+    if (receiver_types_.length() > 0) {
       ASSERT(check_type_ == RECEIVER_MAP_CHECK);
-      map = receiver_types_->at(0);
+      map = receiver_types_.at(0);
     } else {
       ASSERT(check_type_ != RECEIVER_MAP_CHECK);
       holder_ = Handle<JSObject>(
index 4031b7d810037bf6141488e5b06bd2b09c054747..399d27894cd29b926d5e334f2c6b844751e468b3 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -33,6 +33,7 @@
 #include "factory.h"
 #include "jsregexp.h"
 #include "runtime.h"
+#include "small-pointer-list.h"
 #include "token.h"
 #include "variables.h"
 
@@ -207,6 +208,36 @@ class Statement: public AstNode {
 };
 
 
+class SmallMapList {
+ public:
+  SmallMapList() {}
+  explicit SmallMapList(int capacity) : list_(capacity) {}
+
+  void Reserve(int capacity) { list_.Reserve(capacity); }
+  void Clear() { list_.Clear(); }
+
+  bool is_empty() const { return list_.is_empty(); }
+  int length() const { return list_.length(); }
+
+  void Add(Handle<Map> handle) {
+    list_.Add(handle.location());
+  }
+
+  Handle<Map> at(int i) const {
+    return Handle<Map>(list_.at(i));
+  }
+
+  Handle<Map> first() const { return at(0); }
+  Handle<Map> last() const { return at(length() - 1); }
+
+ private:
+  // The list stores pointers to Map*, that is Map**, so it's GC safe.
+  SmallPointerList<Map*> list_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmallMapList);
+};
+
+
 class Expression: public AstNode {
  public:
   enum Context {
@@ -265,13 +296,15 @@ class Expression: public AstNode {
     UNREACHABLE();
     return false;
   }
-  virtual ZoneMapList* GetReceiverTypes() {
+  virtual SmallMapList* GetReceiverTypes() {
     UNREACHABLE();
     return NULL;
   }
-  virtual Handle<Map> GetMonomorphicReceiverType() {
-    UNREACHABLE();
-    return Handle<Map>();
+  Handle<Map> GetMonomorphicReceiverType() {
+    ASSERT(IsMonomorphic());
+    SmallMapList* types = GetReceiverTypes();
+    ASSERT(types != NULL && types->length() == 1);
+    return types->at(0);
   }
 
   unsigned id() const { return id_; }
@@ -1213,7 +1246,6 @@ class Property: public Expression {
         key_(key),
         pos_(pos),
         type_(type),
-        receiver_types_(NULL),
         is_monomorphic_(false),
         is_array_length_(false),
         is_string_length_(false),
@@ -1237,11 +1269,8 @@ class Property: public Expression {
   // Type feedback information.
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
-  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
+  virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
   virtual bool IsArrayLength() { return is_array_length_; }
-  virtual Handle<Map> GetMonomorphicReceiverType() {
-    return monomorphic_receiver_type_;
-  }
 
  private:
   Expression* obj_;
@@ -1249,13 +1278,12 @@ class Property: public Expression {
   int pos_;
   Type type_;
 
-  ZoneMapList* receiver_types_;
+  SmallMapList receiver_types_;
   bool is_monomorphic_ : 1;
   bool is_array_length_ : 1;
   bool is_string_length_ : 1;
   bool is_string_access_ : 1;
   bool is_function_prototype_ : 1;
-  Handle<Map> monomorphic_receiver_type_;
 };
 
 
@@ -1271,7 +1299,6 @@ class Call: public Expression {
         pos_(pos),
         is_monomorphic_(false),
         check_type_(RECEIVER_MAP_CHECK),
-        receiver_types_(NULL),
         return_id_(GetNextId(isolate)) {
   }
 
@@ -1285,7 +1312,7 @@ class Call: public Expression {
 
   void RecordTypeFeedback(TypeFeedbackOracle* oracle,
                           CallKind call_kind);
-  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
+  virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
   virtual bool IsMonomorphic() { return is_monomorphic_; }
   CheckType check_type() const { return check_type_; }
   Handle<JSFunction> target() { return target_; }
@@ -1310,7 +1337,7 @@ class Call: public Expression {
 
   bool is_monomorphic_;
   CheckType check_type_;
-  ZoneMapList* receiver_types_;
+  SmallMapList receiver_types_;
   Handle<JSFunction> target_;
   Handle<JSObject> holder_;
   Handle<JSGlobalPropertyCell> cell_;
@@ -1485,8 +1512,7 @@ class CountOperation: public Expression {
         expression_(expr),
         pos_(pos),
         assignment_id_(GetNextId(isolate)),
-        count_id_(GetNextId(isolate)),
-        receiver_types_(NULL) { }
+        count_id_(GetNextId(isolate)) {}
 
   DECLARE_NODE_TYPE(CountOperation)
 
@@ -1507,10 +1533,7 @@ class CountOperation: public Expression {
 
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
-  virtual Handle<Map> GetMonomorphicReceiverType() {
-    return monomorphic_receiver_type_;
-  }
-  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
+  virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
 
   // Bailout support.
   int AssignmentId() const { return assignment_id_; }
@@ -1524,8 +1547,7 @@ class CountOperation: public Expression {
   int pos_;
   int assignment_id_;
   int count_id_;
-  Handle<Map> monomorphic_receiver_type_;
-  ZoneMapList* receiver_types_;
+  SmallMapList receiver_types_;
 };
 
 
@@ -1673,10 +1695,7 @@ class Assignment: public Expression {
   // Type feedback information.
   void RecordTypeFeedback(TypeFeedbackOracle* oracle);
   virtual bool IsMonomorphic() { return is_monomorphic_; }
-  virtual ZoneMapList* GetReceiverTypes() { return receiver_types_; }
-  virtual Handle<Map> GetMonomorphicReceiverType() {
-    return monomorphic_receiver_type_;
-  }
+  virtual SmallMapList* GetReceiverTypes() { return &receiver_types_; }
 
   // Bailout support.
   int CompoundLoadId() const { return compound_load_id_; }
@@ -1695,8 +1714,7 @@ class Assignment: public Expression {
   bool block_end_;
 
   bool is_monomorphic_;
-  ZoneMapList* receiver_types_;
-  Handle<Map> monomorphic_receiver_type_;
+  SmallMapList receiver_types_;
 };
 
 
index 71c59b5d9ecf0a4c998a572ad4af6d15e793ef17..ec5affd6cf7c5a5a7b44886f8f8dcc21b3eb69d3 100644 (file)
@@ -1306,7 +1306,7 @@ void HLoadNamedField::PrintDataTo(StringStream* stream) {
 
 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context,
                                                        HValue* object,
-                                                       ZoneMapList* types,
+                                                       SmallMapList* types,
                                                        Handle<String> name)
     : types_(Min(types->length(), kMaxLoadPolymorphism)),
       name_(name),
index e7a9104e87f64800fbbd05ec3dcfeeff379449c3..1c3d7b204be3c1b7e8800f849a9461b5480ef5a8 100644 (file)
@@ -3405,12 +3405,12 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
  public:
   HLoadNamedFieldPolymorphic(HValue* context,
                              HValue* object,
-                             ZoneMapList* types,
+                             SmallMapList* types,
                              Handle<String> name);
 
   HValue* context() { return OperandAt(0); }
   HValue* object() { return OperandAt(1); }
-  ZoneMapList* types() { return &types_; }
+  SmallMapList* types() { return &types_; }
   Handle<String> name() { return name_; }
   bool need_generic() { return need_generic_; }
 
@@ -3428,7 +3428,7 @@ class HLoadNamedFieldPolymorphic: public HTemplateInstruction<2> {
   virtual bool DataEquals(HValue* value);
 
  private:
-  ZoneMapList types_;
+  SmallMapList types_;
   Handle<String> name_;
   bool need_generic_;
 };
index ca0aebbbb9bf936b3f7969b05ff823762648f311..570987d4940d66ad2a0e073317e75b565a05a515 100644 (file)
@@ -3395,7 +3395,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
   ASSERT(!name.is_null());
 
   LookupResult lookup;
-  ZoneMapList* types = expr->GetReceiverTypes();
+  SmallMapList* types = expr->GetReceiverTypes();
   bool is_monomorphic = expr->IsMonomorphic() &&
       ComputeStoredField(types->first(), name, &lookup);
 
@@ -3409,7 +3409,7 @@ HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
                                                      HValue* object,
                                                      HValue* value,
-                                                     ZoneMapList* types,
+                                                     SmallMapList* types,
                                                      Handle<String> name) {
   // TODO(ager): We should recognize when the prototype chains for different
   // maps are identical. In that case we can avoid repeatedly generating the
@@ -3500,7 +3500,7 @@ void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
     Handle<String> name = Handle<String>::cast(key->handle());
     ASSERT(!name.is_null());
 
-    ZoneMapList* types = expr->GetReceiverTypes();
+    SmallMapList* types = expr->GetReceiverTypes();
     LookupResult lookup;
 
     if (expr->IsMonomorphic()) {
@@ -3986,7 +3986,7 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
   *has_side_effects = false;
   AddInstruction(new(zone()) HCheckNonSmi(object));
   AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
-  ZoneMapList* maps = prop->GetReceiverTypes();
+  SmallMapList* maps = prop->GetReceiverTypes();
   bool todo_external_array = false;
 
   static const int kNumElementTypes = JSObject::kElementsKindCount;
@@ -4260,7 +4260,7 @@ void HGraphBuilder::VisitProperty(Property* expr) {
 
   } else if (expr->key()->IsPropertyName()) {
     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
-    ZoneMapList* types = expr->GetReceiverTypes();
+    SmallMapList* types = expr->GetReceiverTypes();
 
     HValue* obj = Pop();
     if (expr->IsMonomorphic()) {
@@ -4321,7 +4321,7 @@ void HGraphBuilder::AddCheckConstantFunction(Call* expr,
 
 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
                                                HValue* receiver,
-                                               ZoneMapList* types,
+                                               SmallMapList* types,
                                                Handle<String> name) {
   // TODO(ager): We should recognize when the prototype chains for different
   // maps are identical. In that case we can avoid repeatedly generating the
@@ -4849,13 +4849,14 @@ void HGraphBuilder::VisitCall(Call* expr) {
 
     Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
 
-    ZoneMapList* types = expr->GetReceiverTypes();
+    SmallMapList* types = expr->GetReceiverTypes();
 
     HValue* receiver =
         environment()->ExpressionStackAt(expr->arguments()->length());
     if (expr->IsMonomorphic()) {
-      Handle<Map> receiver_map =
-          (types == NULL) ? Handle<Map>::null() : types->first();
+      Handle<Map> receiver_map = (types == NULL || types->is_empty())
+          ? Handle<Map>::null()
+          : types->first();
       if (TryInlineBuiltinFunction(expr,
                                    receiver,
                                    receiver_map,
index 99225511c5c19c652413219f2779ccd749396114..c18ba5815345821dddc7507ba7d080314c6c00ef 100644 (file)
@@ -901,11 +901,11 @@ class HGraphBuilder: public AstVisitor {
   void HandlePolymorphicStoreNamedField(Assignment* expr,
                                         HValue* object,
                                         HValue* value,
-                                        ZoneMapList* types,
+                                        SmallMapList* types,
                                         Handle<String> name);
   void HandlePolymorphicCallNamed(Call* expr,
                                   HValue* receiver,
-                                  ZoneMapList* types,
+                                  SmallMapList* types,
                                   Handle<String> name);
   void HandleLiteralCompareTypeof(CompareOperation* compare_expr,
                                   Expression* expr,
index 6291d9ee8628d08492dc53ce30628b25066dfead..6c5ce890d2cb64fe8c437bf99c96efb144786357 100644 (file)
@@ -44,6 +44,31 @@ class SmallPointerList {
  public:
   SmallPointerList() : data_(kEmptyTag) {}
 
+  explicit SmallPointerList(int capacity) : data_(kEmptyTag) {
+    Reserve(capacity);
+  }
+
+  void Reserve(int capacity) {
+    if (capacity < 2) return;
+    if ((data_ & kTagMask) == kListTag) {
+      if (list()->capacity() >= capacity) return;
+      int old_length = list()->length();
+      list()->AddBlock(NULL, capacity - list()->capacity());
+      list()->Rewind(old_length);
+      return;
+    }
+    PointerList* list = new PointerList(capacity);
+    if ((data_ & kTagMask) == kSingletonTag) {
+      list->Add(single_value());
+    }
+    ASSERT(IsAligned(reinterpret_cast<intptr_t>(list), kPointerAlignment));
+    data_ = reinterpret_cast<intptr_t>(list) | kListTag;
+  }
+
+  void Clear() {
+    data_ = kEmptyTag;
+  }
+
   bool is_empty() const { return length() == 0; }
 
   int length() const {
index 79cd7a0d22725d277d3ad93939bb136285dc21af..13b0b633b16ed1d9c98a600c6ebc3638d9be8dce 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "api.h"
 #include "arguments.h"
+#include "ast.h"
 #include "code-stubs.h"
 #include "gdb-jit.h"
 #include "ic-inl.h"
@@ -1161,7 +1162,7 @@ void StubCache::Clear() {
 }
 
 
-void StubCache::CollectMatchingMaps(ZoneMapList* types,
+void StubCache::CollectMatchingMaps(SmallMapList* types,
                                     String* name,
                                     Code::Flags flags) {
   for (int i = 0; i < kPrimaryTableSize; i++) {
index ffe4241ec14c2a35028f714839a236b676c447b4..a97a4cdab2a880d4158df59fc67095a194c630c6 100644 (file)
@@ -46,8 +46,10 @@ namespace internal {
 // invalidate the cache whenever a prototype map is changed.  The stub
 // validates the map chain as in the mono-morphic case.
 
+class SmallMapList;
 class StubCache;
 
+
 class SCTableReference {
  public:
   Address address() const { return address_; }
@@ -294,7 +296,7 @@ class StubCache {
   void Clear();
 
   // Collect all maps that match the name and flags.
-  void CollectMatchingMaps(ZoneMapList* types,
+  void CollectMatchingMaps(SmallMapList* types,
                            String* name,
                            Code::Flags flags);
 
index e10c5f40e45e1769a58313f8a03adfda153e1d15..bdf7bc3c865338d017b07a6469ebddd18df5c48c 100644 (file)
@@ -159,23 +159,26 @@ Handle<Map> TypeFeedbackOracle::StoreMonomorphicReceiverType(Expression* expr) {
 }
 
 
-ZoneMapList* TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
-                                                   Handle<String> name) {
+void TypeFeedbackOracle::LoadReceiverTypes(Property* expr,
+                                           Handle<String> name,
+                                           SmallMapList* types) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL);
-  return CollectReceiverTypes(expr->id(), name, flags);
+  CollectReceiverTypes(expr->id(), name, flags, types);
 }
 
 
-ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
-                                                    Handle<String> name) {
+void TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
+                                            Handle<String> name,
+                                            SmallMapList* types) {
   Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL);
-  return CollectReceiverTypes(expr->id(), name, flags);
+  CollectReceiverTypes(expr->id(), name, flags, types);
 }
 
 
-ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
-                                                   Handle<String> name,
-                                                   CallKind call_kind) {
+void TypeFeedbackOracle::CallReceiverTypes(Call* expr,
+                                           Handle<String> name,
+                                           CallKind call_kind,
+                                           SmallMapList* types) {
   int arity = expr->arguments()->length();
 
   // Note: Currently we do not take string extra ic data into account
@@ -189,7 +192,7 @@ ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
                                                     OWN_MAP,
                                                     NOT_IN_LOOP,
                                                     arity);
-  return CollectReceiverTypes(expr->id(), name, flags);
+  CollectReceiverTypes(expr->id(), name, flags, types);
 }
 
 
@@ -391,36 +394,30 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) {
 }
 
 
-ZoneMapList* TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
-                                                      Handle<String> name,
-                                                      Code::Flags flags) {
+void TypeFeedbackOracle::CollectReceiverTypes(unsigned ast_id,
+                                              Handle<String> name,
+                                              Code::Flags flags,
+                                              SmallMapList* types) {
   Isolate* isolate = Isolate::Current();
   Handle<Object> object = GetInfo(ast_id);
-  if (object->IsUndefined() || object->IsSmi()) return NULL;
+  if (object->IsUndefined() || object->IsSmi()) return;
 
   if (*object == isolate->builtins()->builtin(Builtins::kStoreIC_GlobalProxy)) {
     // TODO(fschneider): We could collect the maps and signal that
     // we need a generic store (or load) here.
     ASSERT(Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC);
-    return NULL;
   } else if (object->IsMap()) {
-    ZoneMapList* types = new ZoneMapList(1);
     types->Add(Handle<Map>::cast(object));
-    return types;
   } else if (Handle<Code>::cast(object)->ic_state() == MEGAMORPHIC) {
-    ZoneMapList* types = new ZoneMapList(4);
+    types->Reserve(4);
     ASSERT(object->IsCode());
     isolate->stub_cache()->CollectMatchingMaps(types, *name, flags);
-    return types->length() > 0 ? types : NULL;
-  } else {
-    return NULL;
   }
 }
 
 
-void TypeFeedbackOracle::CollectKeyedReceiverTypes(
-    unsigned ast_id,
-    ZoneMapList* types) {
+void TypeFeedbackOracle::CollectKeyedReceiverTypes(unsigned ast_id,
+                                                   SmallMapList* types) {
   Handle<Object> object = GetInfo(ast_id);
   if (!object->IsCode()) return;
   Handle<Code> code = Handle<Code>::cast(object);
index dee4c34c929453e16d2f081927967ba171acf0fe..448e4c94e7ef9d6e2c334f90a7ff43b675e51020 100644 (file)
@@ -203,14 +203,16 @@ enum StringStubFeedback {
 
 // Forward declarations.
 class Assignment;
-class UnaryOperation;
 class BinaryOperation;
 class Call;
+class CaseClause;
 class CompareOperation;
-class CountOperation;
 class CompilationInfo;
+class CountOperation;
 class Property;
-class CaseClause;
+class SmallMapList;
+class UnaryOperation;
+
 
 class TypeFeedbackOracle BASE_EMBEDDED {
  public:
@@ -225,13 +227,18 @@ class TypeFeedbackOracle BASE_EMBEDDED {
   Handle<Map> LoadMonomorphicReceiverType(Property* expr);
   Handle<Map> StoreMonomorphicReceiverType(Expression* expr);
 
-  ZoneMapList* LoadReceiverTypes(Property* expr, Handle<String> name);
-  ZoneMapList* StoreReceiverTypes(Assignment* expr, Handle<String> name);
-  ZoneMapList* CallReceiverTypes(Call* expr,
-                                 Handle<String> name,
-                                 CallKind call_kind);
+  void LoadReceiverTypes(Property* expr,
+                         Handle<String> name,
+                         SmallMapList* types);
+  void StoreReceiverTypes(Assignment* expr,
+                          Handle<String> name,
+                          SmallMapList* types);
+  void CallReceiverTypes(Call* expr,
+                         Handle<String> name,
+                         CallKind call_kind,
+                         SmallMapList* types);
   void CollectKeyedReceiverTypes(unsigned ast_id,
-                                 ZoneMapList* types);
+                                 SmallMapList* types);
 
   CheckType GetCallCheckType(Call* expr);
   Handle<JSObject> GetPrototypeForPrimitiveCheck(CheckType check);
@@ -252,9 +259,10 @@ class TypeFeedbackOracle BASE_EMBEDDED {
   TypeInfo IncrementType(CountOperation* expr);
 
  private:
-  ZoneMapList* CollectReceiverTypes(unsigned ast_id,
-                                    Handle<String> name,
-                                    Code::Flags flags);
+  void CollectReceiverTypes(unsigned ast_id,
+                            Handle<String> name,
+                            Code::Flags flags,
+                            SmallMapList* types);
 
   void SetInfo(unsigned ast_id, Object* target);
 
index faad3b7ccd04a056663a69b4a548c3d8a4d9b449..4dfd01d3589b93434fd18acbef2406381b452b31 100644 (file)
@@ -200,10 +200,6 @@ class ZoneList: public List<T, ZoneListAllocationPolicy> {
 };
 
 
-// Introduce a convenience type for zone lists of map handles.
-typedef ZoneList<Handle<Map> > ZoneMapList;
-
-
 // ZoneScopes keep track of the current parsing and compilation
 // nesting and cleans up generated ASTs in the Zone when exiting the
 // outer-most scope.