Revision: 21139
Author:   bmeu...@chromium.org
Date:     Mon May  5 11:03:14 2014 UTC
Log:      Don't add code dependencies eagerly for HCheckMaps.

Instead of adding code dependencies on stable during
graph creation, we now add them during code generation
for those HCheckMaps that survived dead code elimination.

R=svenpa...@chromium.org

Review URL: https://codereview.chromium.org/264973013
http://code.google.com/p/v8/source/detail?r=21139

Modified:
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-arm.h
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm64/lithium-arm64.cc
 /branches/bleeding_edge/src/arm64/lithium-arm64.h
 /branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/hydrogen-instructions.cc
 /branches/bleeding_edge/src/hydrogen-instructions.h
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/hydrogen.h
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/lithium-codegen.cc
 /branches/bleeding_edge/src/lithium-codegen.h
 /branches/bleeding_edge/src/lithium.cc
 /branches/bleeding_edge/src/lithium.h
 /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.cc
 /branches/bleeding_edge/src/mips/lithium-mips.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.cc
 /branches/bleeding_edge/src/x64/lithium-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.cc Mon May 5 11:03:14 2014 UTC
@@ -1976,15 +1976,12 @@


 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
-  LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) {
-    value = UseRegisterAtStart(instr->value());
-    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
-  }
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (!instr->CanOmitMapChecks()) {
-    result = AssignEnvironment(result);
-    if (instr->has_migration_target()) result = AssignPointerMap(result);
+  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
+  if (instr->HasMigrationTarget()) {
+    info()->MarkAsDeferredCalling();
+    result = AssignPointerMap(result);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-arm.h Mon May 5 11:03:14 2014 UTC
@@ -2375,7 +2375,7 @@

 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckMaps(LOperand* value) {
+  explicit LCheckMaps(LOperand* value = NULL) {
     inputs_[0] = value;
   }

=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon May 5 11:03:14 2014 UTC
@@ -5140,7 +5140,14 @@
     Register object_;
   };

-  if (instr->hydrogen()->CanOmitMapChecks()) return;
+  if (instr->hydrogen()->IsStabilityCheck()) {
+    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
+    for (int i = 0; i < maps->size(); ++i) {
+      AddStabilityDependency(maps->at(i).handle());
+    }
+    return;
+  }
+
   Register map_reg = scratch0();

   LOperand* input = instr->value();
@@ -5150,7 +5157,7 @@
   __ ldr(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));

   DeferredCheckMaps* deferred = NULL;
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
     __ bind(deferred->check_maps());
   }
@@ -5165,7 +5172,7 @@

   Handle<Map> map = maps->at(maps->size() - 1).handle();
   __ CompareMap(map_reg, map, &success);
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     __ b(ne, deferred->entry());
   } else {
     DeoptimizeIf(ne, instr->environment());
=======================================
--- /branches/bleeding_edge/src/arm64/lithium-arm64.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/arm64/lithium-arm64.cc Mon May 5 11:03:14 2014 UTC
@@ -1169,17 +1169,13 @@


 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
-  LOperand* value = NULL;
-  LOperand* temp = NULL;
-  if (!instr->CanOmitMapChecks()) {
-    value = UseRegisterAtStart(instr->value());
-    temp = TempRegister();
-    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
-  }
-  LInstruction* result = new(zone()) LCheckMaps(value, temp);
-  if (!instr->CanOmitMapChecks()) {
-    result = AssignEnvironment(result);
-    if (instr->has_migration_target()) result = AssignPointerMap(result);
+  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LOperand* temp = TempRegister();
+ LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value, temp));
+  if (instr->HasMigrationTarget()) {
+    info()->MarkAsDeferredCalling();
+    result = AssignPointerMap(result);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/arm64/lithium-arm64.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/arm64/lithium-arm64.h Mon May 5 11:03:14 2014 UTC
@@ -908,7 +908,7 @@

 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 1> {
  public:
-  explicit LCheckMaps(LOperand* value, LOperand* temp) {
+  LCheckMaps(LOperand* value = NULL, LOperand* temp = NULL) {
     inputs_[0] = value;
     temps_[0] = temp;
   }
=======================================
--- /branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc Mon May 5 11:03:14 2014 UTC
@@ -2115,9 +2115,11 @@
     Register object_;
   };

-  if (instr->hydrogen()->CanOmitMapChecks()) {
-    ASSERT(instr->value() == NULL);
-    ASSERT(instr->temp() == NULL);
+  if (instr->hydrogen()->IsStabilityCheck()) {
+    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
+    for (int i = 0; i < maps->size(); ++i) {
+      AddStabilityDependency(maps->at(i).handle());
+    }
     return;
   }

@@ -2127,7 +2129,7 @@
   __ Ldr(map_reg, FieldMemOperand(object, HeapObject::kMapOffset));

   DeferredCheckMaps* deferred = NULL;
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     deferred = new(zone()) DeferredCheckMaps(this, instr, object);
     __ Bind(deferred->check_maps());
   }
@@ -2143,7 +2145,7 @@
   __ CompareMap(map_reg, map);

   // We didn't match a map.
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     __ B(ne, deferred->entry());
   } else {
     DeoptimizeIf(ne, instr->environment());
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Apr 29 06:42:26 2014 UTC +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon May 5 11:03:14 2014 UTC
@@ -1042,7 +1042,7 @@
     Handle<Map> placeholder_map = isolate()->factory()->meta_map();
     HValue* global = Add<HConstant>(
         StoreGlobalStub::global_placeholder(isolate()));
-    Add<HCheckMaps>(global, placeholder_map, top_info());
+    Add<HCheckMaps>(global, placeholder_map);
   }

   HValue* cell = Add<HConstant>(placeholder_cell);
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.cc Mon May 5 11:03:14 2014 UTC
@@ -1675,7 +1675,27 @@
   for (int i = 1; i < maps()->size(); ++i) {
     stream->Add(",%p", *maps()->at(i).handle());
   }
-  stream->Add("]%s", CanOmitMapChecks() ? "(omitted)" : "");
+  stream->Add("]%s", IsStabilityCheck() ? "(stability-check)" : "");
+}
+
+
+HValue* HCheckMaps::Canonicalize() {
+  if (!IsStabilityCheck() && maps_are_stable() && value()->IsConstant()) {
+    HConstant* c_value = HConstant::cast(value());
+    if (c_value->HasObjectMap() && c_value->ObjectMapIsStable()) {
+      for (int i = 0; i < maps()->size(); ++i) {
+        if (c_value->ObjectMap() == maps()->at(i)) {
+          if (maps()->size() > 1) {
+            set_maps(new(block()->graph()->zone()) UniqueSet<Map>(
+                    maps()->at(i), block()->graph()->zone()));
+          }
+          MarkAsStabilityCheck();
+          break;
+        }
+      }
+    }
+  }
+  return this;
 }


@@ -2661,26 +2681,30 @@
 }


-HConstant::HConstant(Handle<Object> handle, Representation r)
-  : HTemplateInstruction<0>(HType::TypeFromValue(handle)),
-    object_(Unique<Object>::CreateUninitialized(handle)),
+HConstant::HConstant(Handle<Object> object, Representation r)
+  : HTemplateInstruction<0>(HType::TypeFromValue(object)),
+    object_(Unique<Object>::CreateUninitialized(object)),
+    object_map_(Handle<Map>::null()),
+    object_map_is_stable_(false),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
     has_external_reference_value_(false),
     is_not_in_new_space_(true),
-    boolean_value_(handle->BooleanValue()),
+    boolean_value_(object->BooleanValue()),
     is_undetectable_(false),
     instance_type_(kUnknownInstanceType) {
-  if (handle->IsHeapObject()) {
-    Handle<HeapObject> heap_obj = Handle<HeapObject>::cast(handle);
-    Heap* heap = heap_obj->GetHeap();
-    is_not_in_new_space_ = !heap->InNewSpace(*handle);
-    instance_type_ = heap_obj->map()->instance_type();
-    is_undetectable_ = heap_obj->map()->is_undetectable();
+  if (object->IsHeapObject()) {
+    Isolate* isolate = Handle<HeapObject>::cast(object)->GetIsolate();
+    Handle<Map> map(Handle<HeapObject>::cast(object)->map(), isolate);
+    is_not_in_new_space_ = !isolate->heap()->InNewSpace(*object);
+    instance_type_ = map->instance_type();
+    is_undetectable_ = map->is_undetectable();
+    object_map_ = Unique<Map>::CreateImmovable(map);
+    object_map_is_stable_ = map->is_stable();
   }
-  if (handle->IsNumber()) {
-    double n = handle->Number();
+  if (object->IsNumber()) {
+    double n = object->Number();
     has_int32_value_ = IsInteger32(n);
     int32_value_ = DoubleToInt32(n);
     has_smi_value_ = has_int32_value_ && Smi::IsValid(int32_value_);
@@ -2702,6 +2726,8 @@
                      InstanceType instance_type)
   : HTemplateInstruction<0>(type),
     object_(unique),
+    object_map_(Handle<Map>::null()),
+    object_map_is_stable_(false),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
@@ -2721,6 +2747,8 @@
                      bool is_not_in_new_space,
                      Unique<Object> object)
   : object_(object),
+    object_map_(Handle<Map>::null()),
+    object_map_is_stable_(false),
     has_smi_value_(Smi::IsValid(integer_value)),
     has_int32_value_(true),
     has_double_value_(true),
@@ -2745,6 +2773,8 @@
                      bool is_not_in_new_space,
                      Unique<Object> object)
   : object_(object),
+    object_map_(Handle<Map>::null()),
+    object_map_is_stable_(false),
     has_int32_value_(IsInteger32(double_value)),
     has_double_value_(true),
     has_external_reference_value_(false),
@@ -2767,6 +2797,8 @@
 HConstant::HConstant(ExternalReference reference)
   : HTemplateInstruction<0>(HType::None()),
     object_(Unique<Object>(Handle<Object>::null())),
+    object_map_(Handle<Map>::null()),
+    object_map_is_stable_(false),
     has_smi_value_(false),
     has_int32_value_(false),
     has_double_value_(false),
@@ -3375,29 +3407,6 @@
     dependency()->PrintNameTo(stream);
   }
 }
-
-
-HCheckMaps* HCheckMaps::New(Zone* zone,
-                            HValue* context,
-                            HValue* value,
-                            Handle<Map> map,
-                            CompilationInfo* info,
-                            HValue* typecheck) {
- HCheckMaps* check_map = new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
-          Unique<Map>::CreateImmovable(map), zone), typecheck);
-  // TODO(bmeurer): Get rid of this shit!
-  if (map->CanOmitMapChecks() &&
-      value->IsConstant() &&
-      HConstant::cast(value)->HasMap(map)) {
-    // TODO(titzer): collect dependent map checks into a list.
-    check_map->omit_ = true;
-    if (map->CanTransition()) {
-      Map::AddDependentCompilationInfo(
-          map, DependentCode::kPrototypeCheckGroup, info);
-    }
-  }
-  return check_map;
-}


 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) {
@@ -3914,12 +3923,9 @@
       HInnerAllocatedObject::New(zone, context(), dominating_allocate_,
       dominating_allocate_->size(), type());
   free_space_instr->InsertBefore(this);
-  HConstant* filler_map = HConstant::New(
-      zone,
-      context(),
-      isolate()->factory()->free_space_map());
- filler_map->FinalizeUniqueness(); // TODO(titzer): should be init'd a'ready
-  filler_map->InsertAfter(free_space_instr);
+  HConstant* filler_map = HConstant::CreateAndInsertAfter(
+      zone, Unique<Map>::CreateImmovable(
+          isolate()->factory()->free_space_map()), free_space_instr);
   HInstruction* store_map = HStoreNamedField::New(zone, context(),
       free_space_instr, HObjectAccess::ForMap(), filler_map);
   store_map->SetFlag(HValue::kHasNoObservableSideEffects);
=======================================
--- /branches/bleeding_edge/src/hydrogen-instructions.h Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/hydrogen-instructions.h Mon May 5 11:03:14 2014 UTC
@@ -2744,8 +2744,10 @@
 class HCheckMaps V8_FINAL : public HTemplateInstruction<2> {
  public:
   static HCheckMaps* New(Zone* zone, HValue* context, HValue* value,
-                         Handle<Map> map, CompilationInfo* info,
-                         HValue* typecheck = NULL);
+                         Handle<Map> map, HValue* typecheck = NULL) {
+    return new(zone) HCheckMaps(value, new(zone) UniqueSet<Map>(
+            Unique<Map>::CreateImmovable(map), zone), typecheck);
+  }
   static HCheckMaps* New(Zone* zone, HValue* context,
                          HValue* value, SmallMapList* map_list,
                          HValue* typecheck = NULL) {
@@ -2756,7 +2758,14 @@
     return new(zone) HCheckMaps(value, maps, typecheck);
   }

-  bool CanOmitMapChecks() { return omit_; }
+  bool IsStabilityCheck() const { return is_stability_check_; }
+  void MarkAsStabilityCheck() {
+    has_migration_target_ = false;
+    is_stability_check_ = true;
+    ClearChangesFlag(kNewSpacePromotion);
+    ClearDependsOnFlag(kElementsKind);
+    ClearDependsOnFlag(kMaps);
+  }

virtual bool HasEscapingOperandAt(int index) V8_OVERRIDE { return false; } virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
@@ -2770,9 +2779,11 @@
   const UniqueSet<Map>* maps() const { return maps_; }
   void set_maps(const UniqueSet<Map>* maps) { maps_ = maps; }

-  bool has_migration_target() const {
-    return has_migration_target_;
-  }
+  bool maps_are_stable() const { return maps_are_stable_; }
+
+  bool HasMigrationTarget() const { return has_migration_target_; }
+
+  virtual HValue* Canonicalize() V8_OVERRIDE;

   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)

@@ -2787,7 +2798,8 @@
   // Clients should use one of the static New* methods above.
   HCheckMaps(HValue* value, const UniqueSet<Map>* maps, HValue* typecheck)
       : HTemplateInstruction<2>(value->type()), maps_(maps),
-        omit_(false), has_migration_target_(false) {
+        has_migration_target_(false), is_stability_check_(false),
+        maps_are_stable_(true) {
     ASSERT_NE(0, maps->size());
     SetOperandAt(0, value);
     // Use the object value for the dependency if NULL is passed.
@@ -2797,17 +2809,17 @@
     SetDependsOnFlag(kMaps);
     SetDependsOnFlag(kElementsKind);
     for (int i = 0; i < maps->size(); ++i) {
-      if (maps->at(i).handle()->is_migration_target()) {
-        SetChangesFlag(kNewSpacePromotion);
-        has_migration_target_ = true;
-        break;
-      }
+      Handle<Map> map = maps->at(i).handle();
+      if (map->is_migration_target()) has_migration_target_ = true;
+      if (!map->is_stable()) maps_are_stable_ = false;
     }
+    if (has_migration_target_) SetChangesFlag(kNewSpacePromotion);
   }

   const UniqueSet<Map>* maps_;
-  bool omit_ : 1;
   bool has_migration_target_ : 1;
+  bool is_stability_check_ : 1;
+  bool maps_are_stable_ : 1;
 };


@@ -3458,6 +3470,14 @@
         unique, Representation::Tagged(), HType::Tagged(),
         is_not_in_new_space, false, false, kUnknownInstanceType));
   }
+
+  static HConstant* CreateAndInsertAfter(Zone* zone,
+                                         Unique<Map> unique,
+                                         HInstruction* instruction) {
+    return instruction->Append(new(zone) HConstant(
+            unique, Representation::Tagged(), HType::Tagged(),
+            true, false, false, MAP_TYPE));
+  }

   Handle<Object> handle(Isolate* isolate) {
     if (object_.handle().is_null()) {
@@ -3470,12 +3490,6 @@
     ASSERT(has_int32_value_ || !object_.handle()->IsSmi());
     return object_.handle();
   }
-
-  bool HasMap(Handle<Map> map) {
-    Handle<Object> constant_object = handle(map->GetIsolate());
-    return constant_object->IsHeapObject() &&
-        Handle<HeapObject>::cast(constant_object)->map() == *map;
-  }

   bool IsSpecialDouble() const {
     return has_double_value_ &&
@@ -3560,6 +3574,16 @@
   bool BooleanValue() const { return boolean_value_; }
   bool IsUndetectable() const { return is_undetectable_; }
   InstanceType GetInstanceType() const { return instance_type_; }
+
+  bool HasObjectMap() const { return !object_map_.IsNull(); }
+  Unique<Map> ObjectMap() const {
+    ASSERT(HasObjectMap());
+    return object_map_;
+  }
+  bool ObjectMapIsStable() const {
+    ASSERT(HasObjectMap());
+    return object_map_is_stable_;
+  }

   virtual intptr_t Hashcode() V8_OVERRIDE {
     if (has_int32_value_) {
@@ -3653,6 +3677,10 @@
   // constant HeapObject.
   Unique<Object> object_;

+  // If this is a heap object, this points to the Map of the object.
+  Unique<Map> object_map_;
+  bool object_map_is_stable_ : 1;
+
   // We store the HConstant in the most specific form safely possible.
   // The two flags, has_int32_value_ and has_double_value_ tell us if
   // int32_value_ and double_value_ hold valid, safe representations
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Fri May  2 06:37:54 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Mon May  5 11:03:14 2014 UTC
@@ -1235,11 +1235,6 @@
   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   FinishExitCurrentBlock(New<HAbnormalExit>());
 }
-
-
-HValue* HGraphBuilder::BuildCheckMap(HValue* obj, Handle<Map> map) {
-  return Add<HCheckMaps>(obj, map, top_info());
-}


 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
@@ -2142,7 +2137,7 @@
   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
     HCheckMaps* check_cow_map = Add<HCheckMaps>(
-        elements, isolate()->factory()->fixed_array_map(), top_info());
+        elements, isolate()->factory()->fixed_array_map());
     check_cow_map->ClearDependsOnFlag(kElementsKind);
   }
   HInstruction* length = NULL;
@@ -2216,7 +2211,7 @@
                                             elements_kind, length);
       } else {
         HCheckMaps* check_cow_map = Add<HCheckMaps>(
-            elements, isolate()->factory()->fixed_array_map(), top_info());
+            elements, isolate()->factory()->fixed_array_map());
         check_cow_map->ClearDependsOnFlag(kElementsKind);
       }
     }
@@ -2684,7 +2679,7 @@
// the monomorphic map when the code is used as a template to generate a
       // new IC. For optimized functions, there is no sentinel map, the map
       // emitted below is the actual monomorphic map.
-      BuildCheckMap(value, type->Classes().Current());
+      Add<HCheckMaps>(value, type->Classes().Current());
     } else {
       if_nil.Deopt("Too many undetectable types");
     }
@@ -5136,7 +5131,7 @@
             } else {
               PropertyAccessInfo info(this, STORE, ToType(map), name);
               if (info.CanAccessMonomorphic()) {
-                HValue* checked_literal = BuildCheckMap(literal, map);
+                HValue* checked_literal = Add<HCheckMaps>(literal, map);
                 ASSERT(!info.lookup()->IsPropertyCallbacks());
                 store = BuildMonomorphicAccess(
                     &info, literal, checked_literal, value,
@@ -5263,7 +5258,7 @@

     // De-opt if elements kind changed from boilerplate_elements_kind.
     Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
-    literal = Add<HCheckMaps>(literal, map, top_info());
+    literal = Add<HCheckMaps>(literal, map);
   }

   // The array is expected in the bailout environment during computation
@@ -5316,7 +5311,7 @@
 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
                                                 Handle<Map> map) {
   BuildCheckHeapObject(object);
-  return Add<HCheckMaps>(object, map, top_info());
+  return Add<HCheckMaps>(object, map);
 }


@@ -5399,12 +5394,7 @@
     if (!info->field_maps()->is_empty()) {
       ASSERT(field_access.representation().IsHeapObject());
       BuildCheckHeapObject(value);
-      if (info->field_maps()->length() == 1) {
- // TODO(bmeurer): Also apply stable maps optimization to the else case!
-        value = BuildCheckMap(value, info->field_maps()->first());
-      } else {
-        value = Add<HCheckMaps>(value, info->field_maps());
-      }
+      value = Add<HCheckMaps>(value, info->field_maps());

// TODO(bmeurer): This is a dirty hack to avoid repeating the smi check
       // that was already performed by the HCheckHeapObject above in the
@@ -6358,8 +6348,7 @@
     Handle<Map> map,
     PropertyAccessType access_type,
     KeyedAccessStoreMode store_mode) {
-  HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(),
-                                               dependency);
+  HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
   if (dependency) {
     checked_object->ClearDependsOnFlag(kElementsKind);
   }
@@ -6838,19 +6827,9 @@
 }


-HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
-                                                   CompilationInfo* info) {
-  HConstant* constant_value = New<HConstant>(constant);
-  Handle<Map> map(constant->map(), info->isolate());
-
-  if (constant->map()->CanOmitMapChecks()) {
-    Map::AddDependentCompilationInfo(
-        map, DependentCode::kPrototypeCheckGroup, info);
-    return constant_value;
-  }
-
-  AddInstruction(constant_value);
-  HCheckMaps* check = Add<HCheckMaps>(constant_value, map, info);
+HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
+  HCheckMaps* check = Add<HCheckMaps>(
+      Add<HConstant>(constant), handle(constant->map()));
   check->ClearDependsOnFlag(kElementsKind);
   return check;
 }
@@ -6859,16 +6838,13 @@
HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype, Handle<JSObject> holder) {
   while (holder.is_null() || !prototype.is_identical_to(holder)) {
-    BuildConstantMapCheck(prototype, top_info());
+    BuildConstantMapCheck(prototype);
     Object* next_prototype = prototype->GetPrototype();
     if (next_prototype->IsNull()) return NULL;
     CHECK(next_prototype->IsJSObject());
     prototype = handle(JSObject::cast(next_prototype));
   }
-
- HInstruction* checked_object = BuildConstantMapCheck(prototype, top_info());
-  if (!checked_object->IsLinked()) AddInstruction(checked_object);
-  return checked_object;
+  return BuildConstantMapCheck(prototype);
 }


=======================================
--- /branches/bleeding_edge/src/hydrogen.h      Tue Apr 29 06:42:26 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.h      Mon May  5 11:03:14 2014 UTC
@@ -1298,7 +1298,6 @@
   HBasicBlock* CreateLoopHeaderBlock();

   HValue* BuildCheckHeapObject(HValue* object);
-  HValue* BuildCheckMap(HValue* obj, Handle<Map> map);
   HValue* BuildCheckString(HValue* string);
   HValue* BuildWrapReceiver(HValue* object, HValue* function);

@@ -1781,8 +1780,7 @@
                                     HValue* previous_object_size,
                                     HValue* payload);

-  HInstruction* BuildConstantMapCheck(Handle<JSObject> constant,
-                                      CompilationInfo* info);
+  HInstruction* BuildConstantMapCheck(Handle<JSObject> constant);
   HInstruction* BuildCheckPrototypeMaps(Handle<JSObject> prototype,
                                         Handle<JSObject> holder);

=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Mon May 5 11:03:14 2014 UTC
@@ -5594,14 +5594,20 @@
     Register object_;
   };

-  if (instr->hydrogen()->CanOmitMapChecks()) return;
+  if (instr->hydrogen()->IsStabilityCheck()) {
+    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
+    for (int i = 0; i < maps->size(); ++i) {
+      AddStabilityDependency(maps->at(i).handle());
+    }
+    return;
+  }

   LOperand* input = instr->value();
   ASSERT(input->IsRegister());
   Register reg = ToRegister(input);

   DeferredCheckMaps* deferred = NULL;
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
     __ bind(deferred->check_maps());
   }
@@ -5616,7 +5622,7 @@

   Handle<Map> map = maps->at(maps->size() - 1).handle();
   __ CompareMap(reg, map);
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     __ j(not_equal, deferred->entry());
   } else {
     DeoptimizeIf(not_equal, instr->environment());
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Mon May 5 11:03:14 2014 UTC
@@ -2027,15 +2027,12 @@


 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
-  LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) {
-    value = UseRegisterAtStart(instr->value());
-    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
-  }
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (!instr->CanOmitMapChecks()) {
-    result = AssignEnvironment(result);
-    if (instr->has_migration_target()) result = AssignPointerMap(result);
+  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
+  if (instr->HasMigrationTarget()) {
+    info()->MarkAsDeferredCalling();
+    result = AssignPointerMap(result);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Mon May 5 11:03:14 2014 UTC
@@ -2399,7 +2399,7 @@

 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckMaps(LOperand* value) {
+  explicit LCheckMaps(LOperand* value = NULL) {
     inputs_[0] = value;
   }

=======================================
--- /branches/bleeding_edge/src/lithium-codegen.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/lithium-codegen.cc Mon May 5 11:03:14 2014 UTC
@@ -220,5 +220,11 @@
   if (map->is_deprecated()) return Abort(kMapBecameDeprecated);
   chunk_->AddDeprecationDependency(map);
 }
+
+
+void LCodeGenBase::AddStabilityDependency(Handle<Map> map) {
+  if (!map->is_stable()) return Abort(kMapBecameUnstable);
+  chunk_->AddStabilityDependency(map);
+}

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/lithium-codegen.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/lithium-codegen.h Mon May 5 11:03:14 2014 UTC
@@ -77,6 +77,7 @@

   // Methods for code dependencies.
   void AddDeprecationDependency(Handle<Map> map);
+  void AddStabilityDependency(Handle<Map> map);
 };


=======================================
--- /branches/bleeding_edge/src/lithium.cc      Fri May  2 06:37:54 2014 UTC
+++ /branches/bleeding_edge/src/lithium.cc      Mon May  5 11:03:14 2014 UTC
@@ -234,7 +234,8 @@
       instructions_(32, graph->zone()),
       pointer_maps_(8, graph->zone()),
       inlined_closures_(1, graph->zone()),
-      deprecation_dependencies_(MapLess(), MapAllocator(graph->zone())) {
+      deprecation_dependencies_(MapLess(), MapAllocator(graph->zone())),
+      stability_dependencies_(MapLess(), MapAllocator(graph->zone())) {
 }


@@ -381,6 +382,14 @@
     ASSERT(map->CanBeDeprecated());
     Map::AddDependentCode(map, DependentCode::kTransitionGroup, code);
   }
+
+  for (MapSet::const_iterator it = stability_dependencies_.begin(),
+       iend = stability_dependencies_.end(); it != iend; ++it) {
+    Handle<Map> map = *it;
+    ASSERT(map->is_stable());
+    ASSERT(map->CanTransition());
+    Map::AddDependentCode(map, DependentCode::kPrototypeCheckGroup, code);
+  }

   info_->CommitDependencies(code);
 }
=======================================
--- /branches/bleeding_edge/src/lithium.h       Fri May  2 06:37:54 2014 UTC
+++ /branches/bleeding_edge/src/lithium.h       Mon May  5 11:03:14 2014 UTC
@@ -651,6 +651,13 @@
     ASSERT(!info_->IsStub());
     deprecation_dependencies_.insert(map);
   }
+
+  void AddStabilityDependency(Handle<Map> map) {
+    ASSERT(map->is_stable());
+    if (!map->CanTransition()) return;
+    ASSERT(!info_->IsStub());
+    stability_dependencies_.insert(map);
+  }

   Zone* zone() const { return info_->zone(); }

@@ -680,6 +687,7 @@
   ZoneList<LPointerMap*> pointer_maps_;
   ZoneList<Handle<JSFunction> > inlined_closures_;
   MapSet deprecation_dependencies_;
+  MapSet stability_dependencies_;
 };


=======================================
--- /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/mips/lithium-codegen-mips.cc Mon May 5 11:03:14 2014 UTC
@@ -5164,7 +5164,14 @@
     Register object_;
   };

-  if (instr->hydrogen()->CanOmitMapChecks()) return;
+  if (instr->hydrogen()->IsStabilityCheck()) {
+    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
+    for (int i = 0; i < maps->size(); ++i) {
+      AddStabilityDependency(maps->at(i).handle());
+    }
+    return;
+  }
+
   Register map_reg = scratch0();
   LOperand* input = instr->value();
   ASSERT(input->IsRegister());
@@ -5172,7 +5179,7 @@
   __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));

   DeferredCheckMaps* deferred = NULL;
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
     __ bind(deferred->check_maps());
   }
@@ -5185,7 +5192,7 @@
   }
   Handle<Map> map = maps->at(maps->size() - 1).handle();
   // Do the CompareMap() directly within the Branch() and DeoptimizeIf().
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     __ Branch(deferred->entry(), ne, map_reg, Operand(map));
   } else {
     DeoptimizeIf(ne, instr->environment(), map_reg, Operand(map));
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/mips/lithium-mips.cc Mon May 5 11:03:14 2014 UTC
@@ -1926,15 +1926,12 @@


 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
-  LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) {
-    value = UseRegisterAtStart(instr->value());
-    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
-  }
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (!instr->CanOmitMapChecks()) {
-    result = AssignEnvironment(result);
-    if (instr->has_migration_target()) result = AssignPointerMap(result);
+  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
+  if (instr->HasMigrationTarget()) {
+    info()->MarkAsDeferredCalling();
+    result = AssignPointerMap(result);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/mips/lithium-mips.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/mips/lithium-mips.h Mon May 5 11:03:14 2014 UTC
@@ -2330,7 +2330,7 @@

 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckMaps(LOperand* value) {
+  explicit LCheckMaps(LOperand* value = NULL) {
     inputs_[0] = value;
   }

=======================================
--- /branches/bleeding_edge/src/objects.h       Mon May  5 09:57:45 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Mon May  5 11:03:14 2014 UTC
@@ -1157,6 +1157,7 @@
V(kLookupVariableInCountOperation, \ "Lookup variable in count operation") \ V(kMapBecameDeprecated, "Map became deprecated") \ + V(kMapBecameUnstable, "Map became unstable") \ V(kMapIsNoLongerInEax, "Map is no longer in eax") \ V(kModuleDeclaration, "Module declaration") \ V(kModuleLiteral, "Module literal") \
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon May 5 06:53:19 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Mon May 5 11:03:14 2014 UTC
@@ -5013,14 +5013,20 @@
     Register object_;
   };

-  if (instr->hydrogen()->CanOmitMapChecks()) return;
+  if (instr->hydrogen()->IsStabilityCheck()) {
+    const UniqueSet<Map>* maps = instr->hydrogen()->maps();
+    for (int i = 0; i < maps->size(); ++i) {
+      AddStabilityDependency(maps->at(i).handle());
+    }
+    return;
+  }

   LOperand* input = instr->value();
   ASSERT(input->IsRegister());
   Register reg = ToRegister(input);

   DeferredCheckMaps* deferred = NULL;
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
     __ bind(deferred->check_maps());
   }
@@ -5035,7 +5041,7 @@

   Handle<Map> map = maps->at(maps->size() - 1).handle();
   __ CompareMap(reg, map);
-  if (instr->hydrogen()->has_migration_target()) {
+  if (instr->hydrogen()->HasMigrationTarget()) {
     __ j(not_equal, deferred->entry());
   } else {
     DeoptimizeIf(not_equal, instr->environment());
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.cc Mon May 5 11:03:14 2014 UTC
@@ -1935,15 +1935,12 @@


 LInstruction* LChunkBuilder::DoCheckMaps(HCheckMaps* instr) {
-  LOperand* value = NULL;
-  if (!instr->CanOmitMapChecks()) {
-    value = UseRegisterAtStart(instr->value());
-    if (instr->has_migration_target()) info()->MarkAsDeferredCalling();
-  }
-  LInstruction* result = new(zone()) LCheckMaps(value);
-  if (!instr->CanOmitMapChecks()) {
-    result = AssignEnvironment(result);
-    if (instr->has_migration_target()) result = AssignPointerMap(result);
+  if (instr->IsStabilityCheck()) return new(zone()) LCheckMaps;
+  LOperand* value = UseRegisterAtStart(instr->value());
+  LInstruction* result = AssignEnvironment(new(zone()) LCheckMaps(value));
+  if (instr->HasMigrationTarget()) {
+    info()->MarkAsDeferredCalling();
+    result = AssignPointerMap(result);
   }
   return result;
 }
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Fri May 2 08:08:23 2014 UTC +++ /branches/bleeding_edge/src/x64/lithium-x64.h Mon May 5 11:03:14 2014 UTC
@@ -2338,7 +2338,7 @@

 class LCheckMaps V8_FINAL : public LTemplateInstruction<0, 1, 0> {
  public:
-  explicit LCheckMaps(LOperand* value) {
+  explicit LCheckMaps(LOperand* value = NULL) {
     inputs_[0] = value;
   }

--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to